aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/host1x/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/host1x/codecs')
-rw-r--r--src/video_core/host1x/codecs/decoder.cpp66
-rw-r--r--src/video_core/host1x/codecs/decoder.h8
-rw-r--r--src/video_core/host1x/codecs/h264.cpp4
-rw-r--r--src/video_core/host1x/codecs/vp8.cpp1
-rw-r--r--src/video_core/host1x/codecs/vp9.cpp1
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(), &current_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(), &current_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