From 66a30c66f3f2534f551f3b2e0f4c91c6751ab67a Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 16 Jan 2026 01:08:51 -0600 Subject: [PATCH] Use EOS to force decoder test frame output --- app/streaming/video/ffmpeg.cpp | 61 ++++++++++++++++------------------ 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/app/streaming/video/ffmpeg.cpp b/app/streaming/video/ffmpeg.cpp index c4c9bc5c..d1e10e2b 100644 --- a/app/streaming/video/ffmpeg.cpp +++ b/app/streaming/video/ffmpeg.cpp @@ -664,6 +664,27 @@ bool FFmpegVideoDecoder::completeInitialization(const AVCodec* decoder, enum AVP return false; } + // Most FFmpeg decoders process input using a "push" model. + // We'll see those fail here if the format is not supported. + err = avcodec_send_packet(m_VideoDecoderCtx, m_Pkt); + if (err < 0) { + char errorstring[512]; + av_strerror(err, errorstring, sizeof(errorstring)); + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Test decode failed (avcodec_send_packet): %s", errorstring); + return false; + } + + // Signal EOS to force the decoder to immediately output the frame + err = avcodec_send_packet(m_VideoDecoderCtx, nullptr); + if (err < 0) { + char errorstring[512]; + av_strerror(err, errorstring, sizeof(errorstring)); + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Test flush failed (avcodec_send_packet): %s", errorstring); + return false; + } + AVFrame* frame = av_frame_alloc(); if (!frame) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, @@ -671,35 +692,17 @@ bool FFmpegVideoDecoder::completeInitialization(const AVCodec* decoder, enum AVP return false; } - // Some decoders won't output on the first frame, so we'll submit - // a few test frames if we get an EAGAIN error. - for (int retries = 0; retries < 5; retries++) { - // Most FFmpeg decoders process input using a "push" model. - // We'll see those fail here if the format is not supported. - err = avcodec_send_packet(m_VideoDecoderCtx, m_Pkt); - if (err < 0) { - av_frame_free(&frame); - char errorstring[512]; - av_strerror(err, errorstring, sizeof(errorstring)); + err = avcodec_receive_frame(m_VideoDecoderCtx, frame); + if (err == 0) { + // Allow the renderer to do any validation it wants on this frame + if (!m_FrontendRenderer->testRenderFrame(frame)) { SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Test decode failed (avcodec_send_packet): %s", errorstring); + "Test decode failed (testRenderFrame)"); + av_frame_free(&frame); return false; } - - // A few FFmpeg decoders (h264_mmal) process here using a "pull" model. - // Those decoders will fail here if the format is not supported. - err = avcodec_receive_frame(m_VideoDecoderCtx, frame); - if (err == AVERROR(EAGAIN)) { - // Wait a little while to let the hardware work - SDL_Delay(100); - } - else { - // Done! - break; - } } - - if (err < 0) { + else if (err < 0) { char errorstring[512]; av_strerror(err, errorstring, sizeof(errorstring)); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, @@ -708,14 +711,6 @@ bool FFmpegVideoDecoder::completeInitialization(const AVCodec* decoder, enum AVP return false; } - // Allow the renderer to do any validation it wants on this frame - if (!m_FrontendRenderer->testRenderFrame(frame)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Test decode failed (testRenderFrame)"); - av_frame_free(&frame); - return false; - } - av_frame_free(&frame); // Flush the codec to prepare for the real stream if we're