mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-29 18:08:08 +00:00
[android] Verifying the actual flag required on hardware access
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user