diff --git a/app/streaming/video/ffmpeg.cpp b/app/streaming/video/ffmpeg.cpp index 478fbeeb..c4c9bc5c 100644 --- a/app/streaming/video/ffmpeg.cpp +++ b/app/streaming/video/ffmpeg.cpp @@ -491,6 +491,8 @@ bool FFmpegVideoDecoder::completeInitialization(const AVCodec* decoder, enum AVP } m_RequiredPixelFormat = requiredFormat; + m_OriginalVideoWidth = params->width; + m_OriginalVideoHeight = params->height; m_StreamFps = params->frameRate; m_VideoFormat = params->videoFormat; m_CurrentTestMode = testMode; @@ -1892,6 +1894,32 @@ void FFmpegVideoDecoder::decoderThreadProc() } } + // Some encoders (like RDNA3's AV1 encoder) include excess padding and expect us + // to crop it off. If we find our received frame looks close to our requested + // size (where "close" is arbitrarily defined as "within 64 pixels") then just + // crop the video to our requested size instead. + if (frame->width != m_OriginalVideoWidth || frame->height != m_OriginalVideoHeight) { + int cropWidth = frame->width - m_OriginalVideoWidth; + int cropHeight = frame->height - m_OriginalVideoHeight; + + if (cropWidth >= 0 && cropWidth < 64 && cropHeight >= 0 && cropHeight < 64) { + if (m_FramesOut == 1) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Cropping incoming frames from (%d, %d) to (%d, %d)", + frame->width, + frame->height, + m_OriginalVideoWidth, + m_OriginalVideoHeight); + } + + // We assume that all padding is added to the right and bottom. + // This is true for the known affected encoders. + frame->crop_right = cropWidth; + frame->crop_bottom = cropHeight; + av_frame_apply_cropping(frame, 0); + } + } + // Reset failed decodes count if we reached this far m_ConsecutiveFailedDecodes = 0; diff --git a/app/streaming/video/ffmpeg.h b/app/streaming/video/ffmpeg.h index ac5faca0..111df338 100644 --- a/app/streaming/video/ffmpeg.h +++ b/app/streaming/video/ffmpeg.h @@ -124,6 +124,8 @@ private: int m_LastFrameNumber; int m_StreamFps; + int m_OriginalVideoWidth; + int m_OriginalVideoHeight; int m_VideoFormat; bool m_NeedsSpsFixup; bool m_TestOnly;