diff options
| author | Carl Hetherington <cth@carlh.net> | 2022-02-15 22:47:48 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2022-02-17 09:59:26 +0100 |
| commit | 80430058f5eefb55147218a85225adeb6b616f4d (patch) | |
| tree | 7566946921785c596c0b4be66fbd0e9adb449ec7 /src/lib/ffmpeg_decoder.cc | |
| parent | c3ce1bf707fb5308f4b96cb96ed6e8d29335a319 (diff) | |
Try to handle EAGAIN from avcodec_send_packet() properly.
The docs say on EAGAIN we should call avcodec_receive_frame()
and then re-send the same packet again. This should do that.
This is a fix for errors trigged by the accompanying test.
Diffstat (limited to 'src/lib/ffmpeg_decoder.cc')
| -rw-r--r-- | src/lib/ffmpeg_decoder.cc | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index b2a1bbbe0..d49878217 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -533,24 +533,30 @@ FFmpegDecoder::decode_and_process_video_packet (AVPacket* packet) auto context = video_codec_context(); - int r = avcodec_send_packet (context, packet); - if (r < 0) { - LOG_WARNING("avcodec_send_packet returned %1 for a video packet", r); - } - - while (true) { - r = avcodec_receive_frame (context, _video_frame); - if (r == AVERROR(EAGAIN) || r == AVERROR_EOF || (r < 0 && !packet)) { - /* More input is required, no more frames are coming, or we are flushing and there was - * some error which we just want to ignore. - */ - return false; - } else if (r < 0) { - throw DecodeError (N_("avcodec_receive_frame"), N_("FFmpeg::decode_and_process_video_packet"), r); + bool pending = false; + do { + int r = avcodec_send_packet (context, packet); + if (r < 0) { + LOG_WARNING("avcodec_send_packet returned %1 for a video packet", r); } - process_video_frame (); - } + /* EAGAIN means we should call avcodec_receive_frame and then re-send the same packet */ + pending = r == AVERROR(EAGAIN); + + while (true) { + r = avcodec_receive_frame (context, _video_frame); + if (r == AVERROR(EAGAIN) || r == AVERROR_EOF || (r < 0 && !packet)) { + /* More input is required, no more frames are coming, or we are flushing and there was + * some error which we just want to ignore. + */ + return false; + } else if (r < 0) { + throw DecodeError (N_("avcodec_receive_frame"), N_("FFmpeg::decode_and_process_video_packet"), r); + } + + process_video_frame (); + } + } while (pending); return true; } |
