[android] Verifying the actual flag required on hardware access

This commit is contained in:
CamilleLaVey
2026-07-07 20:08:10 -04:00
parent a1b7cd51b4
commit d1f41a91ec
14 changed files with 252 additions and 71 deletions
+37 -41
View File
@@ -20,58 +20,54 @@ Decoder::Decoder(Host1x::Host1x& host1x_, s32 id_, const Host1x::NvdecCommon::Nv
Decoder::~Decoder() = default;
void Decoder::SetFrameDimensions(s32 width, s32 height) {
if (width <= 0 || height <= 0) {
frame_dimensions.reset();
return;
}
frame_dimensions = FFmpeg::FrameDimensions{width, height};
}
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 (!frame) {
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);
}
if (UsingDecodeOrder()) {
host1x.frame_queue.PushDecodeOrder(id, luma_top, std::move(frame));
host1x.frame_queue.PushDecodeOrder(id, luma_bottom, std::move(frame_copy));
} else {
host1x.frame_queue.PushPresentOrder(id, luma_top, std::move(frame));
host1x.frame_queue.PushPresentOrder(id, luma_bottom, std::move(frame_copy));
}
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 {
auto [luma_offset, chroma_offset] = GetProgressiveOffsets();
std::tie(offsets.luma, std::ignore) = GetProgressiveOffsets();
}
if (!frame.get()) {
LOG_ERROR(HW_GPU, "Nvdec {} failed to decode progressive frame for luma {:#X}", id,
luma_offset);
}
// Send assembled bitstream to decoder.
if (!decode_api.SendPacket(packet_data, offsets, GetFrameDimensions())) {
return;
}
auto push = [&](u64 luma, std::shared_ptr<FFmpeg::Frame> frame) {
if (UsingDecodeOrder()) {
host1x.frame_queue.PushDecodeOrder(id, luma_offset, std::move(frame));
host1x.frame_queue.PushDecodeOrder(id, luma, std::move(frame));
} else {
host1x.frame_queue.PushPresentOrder(id, luma_offset, std::move(frame));
host1x.frame_queue.PushPresentOrder(id, luma, std::move(frame));
}
};
while (auto result = decode_api.ReceiveFrame()) {
auto& [frame, frame_offsets] = *result;
if (frame_offsets.hidden || !frame) {
continue;
}
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 {
push(frame_offsets.luma, std::move(frame));
}
}
}
+8
View File
@@ -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
+4
View File
@@ -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);
+1
View File
@@ -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);
+1
View File
@@ -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