[MPlayer-dev-eng] MPlayer MPEG4 Seeking Bug (and patch)

Ingo Brückl ib at wupperonline.de
Thu Apr 14 11:06:33 CEST 2011


Carl Eugen Hoyos wrote on Sun, 3 Apr 2011 21:25:46 +0000 (UTC):

> Thank you. Unfortunately, the patch got mangled (-/+). Any reason you
> cannot use svn diff? And please just remove lines, do not just comment
> them out.

To not let this patch get lost due to formal inapplicability, here it is in
a form that should be acceptable.

I tried to use Andyz' words for the patch's description and only added some
'glue' where necessary.

In the patch I revised the comments into a form which I think is usual for
code comments.

Unfortunately, I cannot judge his patch so that is for somebody else.

Ingo
-------------- next part --------------
The seek behaviour with MPEG4 is quite poor. Major distortion of the image
is present for several seconds after seeking forward 10 seconds or selecting
a random position.

After specifying that the frame (i==0x1B6) is a VOP (Video Object Plane), it
could be differential compression frame (B) or predicted frame (P) or a
actual full picture (IDR, Immediate Decoder Refresh, keyframe). During
seeking we only want IDR (keyframes), otherwise distortion will be large
until the next keyframe.

The spec says that the higher 2 bits from this byte determine the frame type:

  VOP_CODING_TYPE (binary)   Coding method
  00...                      intra-coded (I)
  01...                      predictive-coded (P)
  10...                      bidirectionally-predictive-coded (B)
  11...                      sprite (S)

Set peek_nal_descriptor whenever getting data to be able to determine the
frame type, but don't mess up the state of the stream, so use demux_peekc.

Patch by Andyz Smith, andyzsmith yahoo com.


Index: libmpdemux/demux_mpg.c
===================================================================
--- libmpdemux/demux_mpg.c	(revision 33255)
+++ libmpdemux/demux_mpg.c	(working copy)
@@ -978,9 +978,7 @@
           } else
           if(sh_video->format == 0x10000004) {	//mpeg4
             if(i==0x1B6) {			//vop (frame) startcode
-	      int pos = videobuf_len;
-	      if(!read_video_packet(d_video)) break; // EOF
-	      if((videobuffer[pos+4] & 0x3F) == 0) break;	//I-frame
+	      if ((peek_nal_descriptor & 0xc0) == 0) break;	//I-frame (IDR, keyframe)
 	    }
           } else if(sh_video->format == 0x10000005){	//h264
             if((i & ~0x60) == 0x105) break;
Index: libmpdemux/parse_es.c
===================================================================
--- libmpdemux/parse_es.c	(revision 33255)
+++ libmpdemux/parse_es.c	(working copy)
@@ -37,6 +37,7 @@
 int next_nal = -1;
 ///! legacy variable, 4 if stream is synced, 0 if not
 int videobuf_code_len=0;
+int peek_nal_descriptor = -1;    // lookahead for MPEG4 frame detection

 #define MAX_SYNCLEN (10 * 1024 * 1024)
 // sync video stream, and returns next packet code
@@ -49,6 +50,7 @@
       goto eof_out;
     }
     next_nal = demux_getc(ds);
+    peek_nal_descriptor = demux_peekc(ds);
     if (next_nal < 0)
       goto eof_out;
     videobuf_code_len = 4;
@@ -93,6 +95,7 @@

   // Save next packet code:
   next_nal = demux_getc(ds);
+  peek_nal_descriptor = demux_peekc(ds);
   if (next_nal < 0)
     goto eof_out;
   videobuf_code_len=4;
Index: libmpdemux/parse_es.h
===================================================================
--- libmpdemux/parse_es.h	(revision 33255)
+++ libmpdemux/parse_es.h	(working copy)
@@ -30,6 +30,7 @@
 extern int videobuf_len;
 extern unsigned char videobuf_code[4];
 extern int videobuf_code_len;
+extern int peek_nal_descriptor;    // lookahead for MPEG4 frame detection

 // sync video stream, and returns next packet code
 int sync_video_packet(demux_stream_t *ds);


More information about the MPlayer-dev-eng mailing list