diff options
Diffstat (limited to 'src/video_core/host1x/codecs')
| -rw-r--r-- | src/video_core/host1x/codecs/decoder.cpp | 66 | ||||
| -rw-r--r-- | src/video_core/host1x/codecs/decoder.h | 8 | ||||
| -rw-r--r-- | src/video_core/host1x/codecs/h264.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/host1x/codecs/vp8.cpp | 1 | ||||
| -rw-r--r-- | src/video_core/host1x/codecs/vp9.cpp | 1 |
5 files changed, 45 insertions, 35 deletions
diff --git a/src/video_core/host1x/codecs/decoder.cpp b/src/video_core/host1x/codecs/decoder.cpp index c75059db6f..1d6d3e8af6 100644 --- a/src/video_core/host1x/codecs/decoder.cpp +++ b/src/video_core/host1x/codecs/decoder.cpp @@ -20,58 +20,54 @@ Decoder::Decoder(Host1x::Host1x& host1x_, s32 id_, const Host1x::NvdecCommon::Nv Decoder::~Decoder() = default; -void Decoder::Decode() { - if (!initialized) { +void Decoder::SetFrameDimensions(s32 width, s32 height) { + if (width <= 0 || height <= 0) { + frame_dimensions.reset(); return; } + frame_dimensions = FFmpeg::FrameDimensions{width, height}; +} - const auto packet_data = ComposeFrame(); - // Send assembled bitstream to decoder. - if (!decode_api.SendPacket(packet_data)) { +void Decoder::Decode() { + if (!initialized) { return; } - // Only receive/store visible frames. - if (vp9_hidden_frame) { - return; + const auto packet_data = ComposeFrame(); + FFmpeg::FrameOffsets offsets{}; + offsets.hidden = vp9_hidden_frame; + offsets.interlaced = IsInterlaced(); + if (offsets.interlaced) { + std::tie(offsets.luma, offsets.luma_bottom, std::ignore, std::ignore) = + GetInterlacedOffsets(); + } else { + std::tie(offsets.luma, std::ignore) = GetProgressiveOffsets(); } - // Receive output frames from decoder. - auto frame = decode_api.ReceiveFrame(); - - if (!frame) { + // Send assembled bitstream to decoder. + if (!decode_api.SendPacket(packet_data, offsets, GetFrameDimensions())) { return; } - if (IsInterlaced()) { - auto [luma_top, luma_bottom, chroma_top, chroma_bottom] = GetInterlacedOffsets(); - auto frame_copy = frame; - - if (!frame.get()) { - LOG_ERROR(HW_GPU, - "Nvdec {} failed to decode interlaced frame for top {:#X} bottom 0x{:X}", id, - luma_top, luma_bottom); - } - + auto push = [&](u64 luma, std::shared_ptr<FFmpeg::Frame> frame) { if (UsingDecodeOrder()) { - host1x.frame_queue.PushDecodeOrder(id, luma_top, std::move(frame)); - host1x.frame_queue.PushDecodeOrder(id, luma_bottom, std::move(frame_copy)); + host1x.frame_queue.PushDecodeOrder(id, luma, std::move(frame)); } else { - host1x.frame_queue.PushPresentOrder(id, luma_top, std::move(frame)); - host1x.frame_queue.PushPresentOrder(id, luma_bottom, std::move(frame_copy)); + host1x.frame_queue.PushPresentOrder(id, luma, std::move(frame)); } - } else { - auto [luma_offset, chroma_offset] = GetProgressiveOffsets(); + }; - if (!frame.get()) { - LOG_ERROR(HW_GPU, "Nvdec {} failed to decode progressive frame for luma {:#X}", id, - luma_offset); + while (auto result = decode_api.ReceiveFrame()) { + auto& [frame, frame_offsets] = *result; + if (!frame) { + continue; } - - if (UsingDecodeOrder()) { - host1x.frame_queue.PushDecodeOrder(id, luma_offset, std::move(frame)); + if (frame_offsets.interlaced) { + auto frame_copy = frame; + push(frame_offsets.luma, std::move(frame)); + push(frame_offsets.luma_bottom, std::move(frame_copy)); } else { - host1x.frame_queue.PushPresentOrder(id, luma_offset, std::move(frame)); + push(frame_offsets.luma, std::move(frame)); } } } diff --git a/src/video_core/host1x/codecs/decoder.h b/src/video_core/host1x/codecs/decoder.h index 9fca89aa40..2cc6d8dce6 100644 --- a/src/video_core/host1x/codecs/decoder.h +++ b/src/video_core/host1x/codecs/decoder.h @@ -10,6 +10,7 @@ #include <mutex> #include <optional> #include <string_view> +#include <tuple> #include <ankerl/unordered_dense.h> #include <queue> @@ -46,12 +47,19 @@ protected: virtual std::tuple<u64, u64, u64, u64> GetInterlacedOffsets() = 0; virtual bool IsInterlaced() = 0; + void SetFrameDimensions(s32 width, s32 height); + + std::optional<FFmpeg::FrameDimensions> GetFrameDimensions() const { + return frame_dimensions; + } + FFmpeg::DecodeApi decode_api; Host1x::Host1x& host1x; const Host1x::NvdecCommon::NvdecRegisters& regs; s32 id; bool initialized : 1 = false; bool vp9_hidden_frame : 1 = false; + std::optional<FFmpeg::FrameDimensions> frame_dimensions; }; } // namespace Tegra diff --git a/src/video_core/host1x/codecs/h264.cpp b/src/video_core/host1x/codecs/h264.cpp index f439ac3828..e3a6f5d182 100644 --- a/src/video_core/host1x/codecs/h264.cpp +++ b/src/video_core/host1x/codecs/h264.cpp @@ -52,6 +52,10 @@ bool H264::IsInterlaced() { std::span<const u8> H264::ComposeFrame() { host1x.gmmu_manager.ReadBlock(regs.picture_info_offset.Address(), ¤t_context, sizeof(H264DecoderContext)); + const auto& params = current_context.h264_parameter_set; + SetFrameDimensions(static_cast<s32>(params.pic_width_in_mbs) * 16, + static_cast<s32>(params.frame_height_in_mbs) * 16); + const s64 frame_number = current_context.h264_parameter_set.frame_number.Value(); if (!is_first_frame && frame_number != 0) { frame_scratch.resize_destructive(current_context.stream_len); diff --git a/src/video_core/host1x/codecs/vp8.cpp b/src/video_core/host1x/codecs/vp8.cpp index 00fe6e4499..33d781816a 100644 --- a/src/video_core/host1x/codecs/vp8.cpp +++ b/src/video_core/host1x/codecs/vp8.cpp @@ -35,6 +35,7 @@ std::tuple<u64, u64, u64, u64> VP8::GetInterlacedOffsets() { std::span<const u8> VP8::ComposeFrame() { host1x.gmmu_manager.ReadBlock(regs.picture_info_offset.Address(), ¤t_context, sizeof(VP8PictureInfo)); + SetFrameDimensions(current_context.frame_width, current_context.frame_height); const bool is_key_frame = current_context.key_frame == 1u; const auto bitstream_size = size_t(current_context.vld_buffer_size); diff --git a/src/video_core/host1x/codecs/vp9.cpp b/src/video_core/host1x/codecs/vp9.cpp index 1085e08939..dcc6261e5c 100644 --- a/src/video_core/host1x/codecs/vp9.cpp +++ b/src/video_core/host1x/codecs/vp9.cpp @@ -841,6 +841,7 @@ std::span<const u8> VP9::ComposeFrame() { { Vp9FrameContainer curr_frame = GetCurrentFrame(); current_frame_info = curr_frame.info; + SetFrameDimensions(current_frame_info.frame_size.width, current_frame_info.frame_size.height); bitstream = std::move(curr_frame.bit_stream); } // The uncompressed header routine sets PrevProb parameters needed for the compressed header |
