[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