aboutsummaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
authorJonas <baguettegamerofficial2020@gmail.com>2026-11-03 05:47:42 +0600
committerJonas <baguettegamerofficial2020@gmail.com>2026-11-03 05:55:03 +0600
commit873cae5569e9f0069a73f24ab5e4ffd0799b02e7 (patch)
treebe8c37b01c91ba58937c87791532ea1019c603b9 /src/video_core
parent031e58e93046726446538a0efeebd56f7b5dc184 (diff)
nx2: video decoder: copy NV12 frames from a GPU decoder without swscale
FFmpeg 6.1's swscale leaves the chroma plane of an NV12 to NV12 copy at zero, so movies decoded on the host GPU (Mario Kart World's pre-race movie, Hyrule Warriors' cutscenes) showed green. CPU-decoded frames (YUV420P) were not affected.
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/host1x/nx2_video_decoder.cpp14
1 files changed, 14 insertions, 0 deletions
diff --git a/src/video_core/host1x/nx2_video_decoder.cpp b/src/video_core/host1x/nx2_video_decoder.cpp
index 87265ee6f6..86869ad5e2 100644
--- a/src/video_core/host1x/nx2_video_decoder.cpp
+++ b/src/video_core/host1x/nx2_video_decoder.cpp
@@ -226,6 +226,20 @@ void Nx2VideoDecoder::Render(const Nx2Picture& picture, Nx2PictureFormat format,
const AVPixelFormat target = format == Nx2PictureFormat::Nv12 ? AV_PIX_FMT_NV12
: format == Nx2PictureFormat::Rgba8 ? AV_PIX_FMT_RGBA
: AV_PIX_FMT_BGRA;
+ // Frames copied back from a host GPU decoder are already NV12. Copy them as they are:
+ // FFmpeg 6.1's swscale leaves the chroma plane of an NV12 to NV12 copy at zero, which shows
+ // the movies green.
+ if (target == AV_PIX_FMT_NV12 && f->format == AV_PIX_FMT_NV12 &&
+ static_cast<u32>(f->width) == width && static_cast<u32>(f->height) == height) {
+ for (u32 y = 0; y < height; ++y) {
+ std::memcpy(out.data() + y * pitch, f->data[0] + y * f->linesize[0], width);
+ }
+ for (u32 y = 0; y < (height + 1) / 2; ++y) {
+ std::memcpy(out.data() + chroma_offset + y * pitch, f->data[1] + y * f->linesize[1],
+ width);
+ }
+ return;
+ }
impl->scaler = sws_getCachedContext(impl->scaler, f->width, f->height,
static_cast<AVPixelFormat>(f->format),
static_cast<int>(width), static_cast<int>(height), target,