diff --git a/app/streaming/video/ffmpeg.cpp b/app/streaming/video/ffmpeg.cpp index d66de359..3c328971 100644 --- a/app/streaming/video/ffmpeg.cpp +++ b/app/streaming/video/ffmpeg.cpp @@ -661,27 +661,6 @@ 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, @@ -689,17 +668,35 @@ bool FFmpegVideoDecoder::completeInitialization(const AVCodec* decoder, enum AVP return false; } - 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 (testRenderFrame)"); + // 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)); + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Test decode failed (avcodec_send_packet): %s", errorstring); 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; + } } - else if (err < 0) { + + if (err < 0) { char errorstring[512]; av_strerror(err, errorstring, sizeof(errorstring)); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, @@ -708,6 +705,14 @@ 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