Try to handle EAGAIN from avcodec_send_packet() properly.
[dcpomatic.git] / src / lib / ffmpeg_decoder.cc
index b2a1bbbe0eba06b00a3be8d1721f83dab6bfdab9..d49878217338fb40e29eab6892b62d44c788ef9d 100644 (file)
@@ -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;
 }