[MPlayer-dev-eng] [RFC] h264 ES parser problems

Reimar Döffinger Reimar.Doeffinger at stud.uni-karlsruhe.de
Sat Sep 17 11:24:06 CEST 2005


Hi,
An improved version, and I will go through what it does step by step
referencing the spec, since I saw I made wrong assumptions in the past.
I am using the prepublished version from March 2005.

On p. 74, in 7.4.1.2.3 it says:
"The first of any of the following NAL units after the last VCL NAL unit
of a primary coded picture specifies the start of a new access unit".
My code will not check the "after the last...of a primary coded
picture", for that a lot of logic would be needed. Also it seems bogus
to me, since what is the sense of an access unit delimiter if you have
to do some extra checks to find out if it has any meaning at all?
The NALs listed then are, numbers in ():

access unit delimiter (9, optional)
sequence parameter set (7, optional)
picture parameter set (8, optional)
SEI (6, optional)
14-18 (optional)
"first VCL NAL unit of a primary coded picture (always present)"
VCL NALs are in the range of 1-5, but due to the specifics given later I
will exclude those that do not contain a slice header.

Next there are some comments on the order of these NALs (p. 75):
"When an access unit delimiter NAL unit is present, it shall be the
first NAL unit. There shall be at most one access unit delimiter NAL
unit in any access unit".
This means this type can be safely used for detection.

"When any SEI NAL units are present, they shall precede the primary
codec picture"
So if we find one after a VCL NAL this should mean a new access unit,
right?

"When an end of sequence NAL unit is present, it shall follow the
primary coded picture and all redundant coded pictures (if any) and all
coded slice of any auxiliary coded picture without partitioning NAL
units (if any)."
Sounds like it should be good enough for us to detect an end?? This is
NAL nr. 10 btw.

Since NALs nr. 7 and 8 (as a NOTE further down says) can appear
anywhere, they are not used anymore for detection. And since there is
no info on 14-18, I removed the check for those as well.

Now to the "first VCL NAL unit of a primary coded picture".
The correct detection is described in 7.4.1.2.4, e.g.:
"Any coded slice NAL unit or coded slice data partition A NAL unit of
the primary coded picture of the current access unit shall be different
from any coded slice NAL unit or codec slice data partition A NAL unit
of the primary coded picture of the previous access unit in one or more
of the following ways"
Since it does not say what to do with them anywhere I assume that "slice
data partition B"(3) and "slice data partition C"(4) NAL units can not be the
"first VCL NAL unit of a primary coded picture".

Now on to the heart of our detection, 7.4.1.2.5 "Order of VCL NAL units
and association to coded pictures", p.76.
"Otherwise (arbitrary slice order is not allowed), the order of coded
slice of an IDR picture NAL units shall be in the order of increasing
macroblock address for the first macroblock of each coded slice slice of
an IDR picture NAL unit."
Something similar is said about non-IDR pictures. So if we assume strict
slice ordering, we should be able to detect first VCL NAL via the
macroblock address, if all the picture is encoded it should be 0.
The first entry of the slice header (7.3.3, p. 57) is first_mb_in_slice,
which is specified to be ue(v), i.e. "unsigned integer Exp-Golomb-coded
syntax element with the left bit first" (7.2, p.49).
Now the table in 9.1 (p. 200) show that if the first bit is set, the
value is 0, which is what we are looking for.

Do you agree with my conclusions (and code)? And have much fun reading
specs :-P

Greetings,
Reimar Döffinger
-------------- next part --------------
Index: libmpdemux/demuxer.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/demuxer.h,v
retrieving revision 1.83
diff -u -r1.83 demuxer.h
--- libmpdemux/demuxer.h	3 Sep 2005 08:58:34 -0000	1.83
+++ libmpdemux/demuxer.h	17 Sep 2005 09:24:25 -0000
@@ -257,6 +257,9 @@
 int demux_read_data(demux_stream_t *ds,unsigned char* mem,int len);
 int demux_read_data_pack(demux_stream_t *ds,unsigned char* mem,int len);
 
+#define demux_peekc(ds) (\
+     (likely(ds->buffer_pos<ds->buffer_size)) ? ds->buffer[ds->buffer_pos] \
+     :((unlikely(!ds_fill_buffer(ds)))? (-1) : ds->buffer[ds->buffer_pos] ) )
 #if 1
 #define demux_getc(ds) (\
      (likely(ds->buffer_pos<ds->buffer_size)) ? ds->buffer[ds->buffer_pos++] \
Index: libmpdemux/video.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/video.c,v
retrieving revision 1.53
diff -u -r1.53 video.c
--- libmpdemux/video.c	26 Aug 2005 22:53:59 -0000	1.53
+++ libmpdemux/video.c	17 Sep 2005 09:24:27 -0000
@@ -517,6 +517,7 @@
             ((demuxer->file_format==DEMUXER_TYPE_MPEG_PS) && (sh_video->format==0x10000005))
   ){
       //
+        int in_picture = 0;
         while(videobuf_len<VIDEOBUFFER_SIZE-MAX_VIDEO_PACKET_SIZE){
           int i=sync_video_packet(d_video);
           int pos = videobuf_len+4;
@@ -532,7 +533,23 @@
             if(!i) return -1;
             if(!read_video_packet(d_video)) return -1; // EOF
           }
-          if((i&~0x60) == 0x101 || (i&~0x60) == 0x102 || (i&~0x60) == 0x105) break;
+
+          // here starts the access unit end detection code
+          if((i&~0x60) == 0x101 || (i&~0x60) == 0x102 || (i&~0x60) == 0x105)
+            // found VCL NAL with slice header i.e. start of current primary coded
+            // picture, so start scanning for the end now
+            in_picture = 1;
+          if (in_picture) {
+            i = sync_video_packet(d_video) & ~0x60; // code of next packet
+            if(i == 0x106 || i == 0x109) break; // SEI or access unit delim.
+            if(i == 0x101 || i == 0x102 || i == 0x105) {
+              // assuming arbitrary slice ordering is not allowed, the
+              // first_mb_in_slice (golomb encoded) value should be 0 then
+              // for the first VCL NAL in a picture
+              if (demux_peekc(d_video) & 0x80)
+                break;
+            }
+          }
         }
 	*start=videobuffer; in_size=videobuf_len;
 	videobuf_len=0;


More information about the MPlayer-dev-eng mailing list