changeset 34772:d32f75f79517

Decode last frames for codecs with delay. Previously they would get lost, which would be particularly extreme when decoding with frame multithreading and lots of threads.
author reimar
date Sun, 15 Apr 2012 15:01:09 +0000
parents 83febd56b681
children 37af463fd7fc
files libmpcodecs/vd_ffmpeg.c libmpcodecs/vd_mpegpes.c libmpcodecs/vd_zrmjpeg.c mencoder.c mplayer.c
diffstat 5 files changed, 33 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/libmpcodecs/vd_ffmpeg.c	Sun Apr 15 13:12:56 2012 +0000
+++ b/libmpcodecs/vd_ffmpeg.c	Sun Apr 15 15:01:09 2012 +0000
@@ -731,7 +731,7 @@
     int dr1= ctx->do_dr1;
     AVPacket pkt;
 
-    if(len<=0) return NULL; // skipped frame
+    if(data && len<=0) return NULL; // skipped frame
 
 //ffmpeg interlace (mpeg2) bug have been fixed. no need of -noslices
     if (!dr1)
@@ -755,6 +755,7 @@
             avctx->skip_idct = AVDISCARD_ALL;
     }
 
+    if (data)
     mp_msg(MSGT_DECVIDEO, MSGL_DBG2, "vd_ffmpeg data: %04x, %04x, %04x, %04x\n",
            ((int *)data)[0], ((int *)data)[1], ((int *)data)[2], ((int *)data)[3]);
     av_init_packet(&pkt);
--- a/libmpcodecs/vd_mpegpes.c	Sun Apr 15 13:12:56 2012 +0000
+++ b/libmpcodecs/vd_mpegpes.c	Sun Apr 15 15:01:09 2012 +0000
@@ -61,6 +61,8 @@
     mp_mpeg_header_t picture;
     const unsigned char *d = data;
 
+    if (len <= 0 && !data) return NULL; // delay flush
+
     if(len>10 && !d[0] && !d[1] && d[2]==1 && d[3]==0xB3) {
         float old_aspect = sh->aspect;
         int oldw = sh->disp_w, oldh = sh->disp_h;
--- a/libmpcodecs/vd_zrmjpeg.c	Sun Apr 15 13:12:56 2012 +0000
+++ b/libmpcodecs/vd_zrmjpeg.c	Sun Apr 15 15:01:09 2012 +0000
@@ -232,6 +232,8 @@
 	mp_image_t* mpi;
 	vd_zrmjpeg_ctx_t *ctx = sh->context;
 
+	if (len <= 0 && !data) return NULL; // delay flush
+
 	if (!ctx->vo_initialized) {
 		ctx->preferred_csp = guess_mjpeg_type(data, len, sh->disp_h);
 		if (ctx->preferred_csp == 0) return NULL;
--- a/mencoder.c	Sun Apr 15 13:12:56 2012 +0000
+++ b/mencoder.c	Sun Apr 15 15:01:09 2012 +0000
@@ -232,6 +232,7 @@
     int in_size;
     float frame_time;
     int already_read;
+    int flush;
 } s_frame_data;
 
 static edl_record_ptr edl_records = NULL; ///< EDL entries memory area
@@ -433,6 +434,11 @@
 
         if (!frame_data->already_read) { // when called after fixdelay, a frame is already read
             frame_data->in_size = video_read_frame(sh_video, &frame_data->frame_time, &frame_data->start, force_fps);
+            frame_data->flush = frame_data->in_size < 0 && d_video->eof;
+            if (frame_data->flush) {
+                frame_data->in_size = 0;
+                frame_data->start = NULL;
+            }
             if(frame_data->in_size<0) return 2;
             sh_video->timer += frame_data->frame_time;
         }
@@ -454,6 +460,8 @@
             void *decoded_frame = decode_video(sh_video, frame_data->start, frame_data->in_size, !softskip, MP_NOPTS_VALUE, NULL);
 	    if (decoded_frame)
 		filter_video(sh_video, decoded_frame, MP_NOPTS_VALUE);
+	    else if (frame_data->flush)
+		return 2;
         }
 
         if (print_info) mp_msg(MSGT_MENCODER, MSGL_STATUS,
@@ -1392,6 +1400,11 @@
 
     if (!frame_data.already_read) {
         frame_data.in_size=video_read_frame(sh_video,&frame_data.frame_time,&frame_data.start,force_fps);
+        frame_data.flush = frame_data.in_size < 0 && d_video->eof;
+        if (frame_data.flush) {
+            frame_data.in_size = 0;
+            frame_data.start = NULL;
+        }
         sh_video->timer+=frame_data.frame_time;
     }
     frame_data.frame_time /= playback_speed;
@@ -1469,6 +1482,8 @@
                       ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) != CONTROL_TRUE);
     void *decoded_frame = decode_video(sh_video,frame_data.start,frame_data.in_size,
                                        drop_frame, MP_NOPTS_VALUE, NULL);
+    if (frame_data.flush && !decoded_frame)
+        at_eof = 1;
     if (did_seek && sh_video->pts != MP_NOPTS_VALUE) {
         did_seek = 0;
         sub_offset = sh_video->pts;
--- a/mplayer.c	Sun Apr 15 13:12:56 2012 +0000
+++ b/mplayer.c	Sun Apr 15 15:01:09 2012 +0000
@@ -1798,6 +1798,7 @@
         if (in_size < 0) {
             // try to extract last frames in case of decoder lag
             in_size = 0;
+            start   = NULL;
             pts     = MP_NOPTS_VALUE;
             hit_eof = 1;
         }
@@ -2425,6 +2426,7 @@
         int full_frame;
 
         do {
+            int flush;
             current_module = "video_read_frame";
             frame_time     = sh_video->next_frame_time;
             in_size = video_read_frame(sh_video, &sh_video->next_frame_time,
@@ -2441,6 +2443,11 @@
                 mpctx->stream->eof = 0;
             } else
 #endif
+            flush = in_size < 0 && mpctx->d_video->eof;
+            if (flush) {
+                start = NULL;
+                in_size = 0;
+            }
             if (in_size < 0)
                 return -1;
             if (in_size > max_framesize)
@@ -2450,12 +2457,15 @@
 #ifdef CONFIG_DVDNAV
             full_frame    = 1;
             decoded_frame = mp_dvdnav_restore_smpi(&in_size, &start, decoded_frame);
+#endif
             // still frame has been reached, no need to decode
-            if (in_size > 0 && !decoded_frame)
-#endif
+            if ((in_size > 0 || flush) && !decoded_frame)
             decoded_frame = decode_video(sh_video, start, in_size, drop_frame,
                                          sh_video->pts, &full_frame);
 
+            if (flush && !decoded_frame)
+                return -1;
+
             if (full_frame) {
                 sh_video->timer += frame_time;
                 if (mpctx->sh_audio)