summaryrefslogtreecommitdiff
path: root/src/video_core/host1x/codecs/decoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/host1x/codecs/decoder.cpp')
-rwxr-xr-xsrc/video_core/host1x/codecs/decoder.cpp105
1 files changed, 48 insertions, 57 deletions
diff --git a/src/video_core/host1x/codecs/decoder.cpp b/src/video_core/host1x/codecs/decoder.cpp
index 49a601969..69371f610 100755
--- a/src/video_core/host1x/codecs/decoder.cpp
+++ b/src/video_core/host1x/codecs/decoder.cpp
@@ -9,63 +9,54 @@
namespace Tegra {
-Decoder::Decoder(Host1x::Host1x& host1x_, s32 id_, const Host1x::NvdecCommon::NvdecRegisters& regs_,
- Host1x::FrameQueue& frame_queue_)
+ Decoder::Decoder(Host1x::Host1x& host1x_, s32 id_, const Host1x::NvdecCommon::NvdecRegisters& regs_,
+ Host1x::FrameQueue& frame_queue_)
: host1x(host1x_), memory_manager{host1x.GMMU()}, regs{regs_}, id{id_}, frame_queue{
- frame_queue_} {}
-
-Decoder::~Decoder() = default;
-
-void Decoder::Decode() {
- if (!initialized) {
- return;
- }
-
- const auto packet_data = ComposeFrame();
- // Send assembled bitstream to decoder.
- if (!decode_api.SendPacket(packet_data)) {
- return;
- }
-
- // Only receive/store visible frames.
- if (vp9_hidden_frame) {
- return;
- }
-
- // Receive output frames from decoder.
- auto frame = decode_api.ReceiveFrame();
-
- if (IsInterlaced()) {
- auto [luma_top, luma_bottom, chroma_top, chroma_bottom] = GetInterlacedOffsets();
- auto frame_copy = frame;
-
- if (!frame.get()) {
- LOG_ERROR(HW_GPU,
- "Nvdec {} dailed to decode interlaced frame for top 0x{:X} bottom 0x{:X}", id,
- luma_top, luma_bottom);
+ frame_queue_} {}
+
+ Decoder::~Decoder() = default;
+
+ void Decoder::Decode() {
+ if (!initialized) {
+ return;
+ }
+
+ const auto packet_data = ComposeFrame();
+
+ // Capture the state needed for queuing BEFORE sending the packet
+ // and potentially yielding. The main `regs` and `current_context` can be
+ // overwritten by the time FFmpeg returns a frame.
+ const bool is_interlaced_frame = IsInterlaced();
+ const auto interlaced_offsets = GetInterlacedOffsets();
+ const auto progressive_offsets = GetProgressiveOffsets();
+
+ // Send assembled bitstream to decoder.
+ if (!decode_api.SendPacket(packet_data)) {
+ return;
+ }
+
+ // Only process visible frames.
+ if (vp9_hidden_frame) {
+ return;
+ }
+
+ // Receive output frames from decoder.
+ // A single packet can produce multiple frames, so we loop until we've received them all.
+ while (true) {
+ auto frame = decode_api.ReceiveFrame();
+ if (!frame) { // No more frames available for now.
+ break;
+ }
+
+ if (is_interlaced_frame) {
+ auto [luma_top, luma_bottom, chroma_top, chroma_bottom] = interlaced_offsets;
+ auto frame_copy = frame;
+ frame_queue.PushDecodeOrder(id, luma_top, std::move(frame));
+ frame_queue.PushDecodeOrder(id, luma_bottom, std::move(frame_copy));
+ } else {
+ auto [luma_offset, chroma_offset] = progressive_offsets;
+ frame_queue.PushDecodeOrder(id, luma_offset, std::move(frame));
+ }
+ }
}
-
- if (UsingDecodeOrder()) {
- frame_queue.PushDecodeOrder(id, luma_top, std::move(frame));
- frame_queue.PushDecodeOrder(id, luma_bottom, std::move(frame_copy));
- } else {
- frame_queue.PushPresentOrder(id, luma_top, std::move(frame));
- frame_queue.PushPresentOrder(id, luma_bottom, std::move(frame_copy));
- }
- } else {
- auto [luma_offset, chroma_offset] = GetProgressiveOffsets();
-
- if (!frame.get()) {
- LOG_ERROR(HW_GPU, "Nvdec {} failed to decode progressive frame for luma 0x{:X}", id,
- luma_offset);
- }
-
- if (UsingDecodeOrder()) {
- frame_queue.PushDecodeOrder(id, luma_offset, std::move(frame));
- } else {
- frame_queue.PushPresentOrder(id, luma_offset, std::move(frame));
- }
- }
-}
-
} // namespace Tegra