Parse NAL units in H264 parser.
authorIvan Schreter <schreter@gmx.net>
Sat, 21 Feb 2009 19:56:50 +0000 (19:56 +0000)
committerCarl Eugen Hoyos <cehoyos@rainbow.studorg.tuwien.ac.at>
Sat, 21 Feb 2009 19:56:50 +0000 (19:56 +0000)
Patch by Ivan Schreter, schreter gmx net

Originally committed as revision 17488 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/h264_parser.c

index a04fd21..e00c15b 100644 (file)
@@ -27,6 +27,8 @@
 
 #include "parser.h"
 #include "h264_parser.h"
+#include "h264data.h"
+#include "golomb.h"
 
 #include <assert.h>
 
@@ -96,6 +98,73 @@ found:
     return i-(state&5);
 }
 
+/*!
+ * Parse NAL units of found picture and decode some basic information.
+ *
+ * @param s parser context.
+ * @param avctx codec context.
+ * @param buf buffer with field/frame data.
+ * @param buf_size size of the buffer.
+ */
+static inline int parse_nal_units(AVCodecParserContext *s,
+                                  AVCodecContext *avctx,
+                                  const uint8_t *buf, int buf_size)
+{
+    H264Context *h = s->priv_data;
+    const uint8_t *buf_end = buf + buf_size;
+    unsigned int slice_type;
+    int state;
+    const uint8_t *ptr;
+
+    /* set some sane default values */
+    s->pict_type = FF_I_TYPE;
+
+    h->s.avctx= avctx;
+
+    for(;;) {
+        int src_length, dst_length, consumed;
+        buf = ff_find_start_code(buf, buf_end, &state);
+        if(buf >= buf_end)
+            break;
+        --buf;
+        src_length = buf_end - buf;
+        switch (state & 0x1f) {
+        case NAL_SLICE:
+        case NAL_IDR_SLICE:
+            // Do not walk the whole buffer just to decode slice header
+            if (src_length > 20)
+                src_length = 20;
+            break;
+        }
+        ptr= ff_h264_decode_nal(h, buf, &dst_length, &consumed, src_length);
+        if (ptr==NULL || dst_length < 0)
+            break;
+
+        init_get_bits(&h->s.gb, ptr, 8*dst_length);
+        switch(h->nal_unit_type) {
+        case NAL_SPS:
+            ff_h264_decode_seq_parameter_set(h);
+            break;
+        case NAL_PPS:
+            ff_h264_decode_picture_parameter_set(h, h->s.gb.size_in_bits);
+            break;
+        case NAL_SEI:
+            ff_h264_decode_sei(h);
+            break;
+        case NAL_IDR_SLICE:
+        case NAL_SLICE:
+            get_ue_golomb(&h->s.gb);  // skip first_mb_in_slice
+            slice_type = get_ue_golomb_31(&h->s.gb);
+            s->pict_type = golomb_to_pict_type[slice_type % 5];
+            return 0; /* no need to evaluate the rest */
+        }
+        buf += consumed;
+    }
+    /* didn't find a picture! */
+    av_log(h->s.avctx, AV_LOG_ERROR, "missing picture in access unit\n");
+    return -1;
+}
+
 static int h264_parse(AVCodecParserContext *s,
                       AVCodecContext *avctx,
                       const uint8_t **poutbuf, int *poutbuf_size,
@@ -120,6 +189,8 @@ static int h264_parse(AVCodecParserContext *s,
             assert(pc->last_index + next >= 0 );
             ff_h264_find_frame_end(h, &pc->buffer[pc->last_index + next], -next); //update state
         }
+
+        parse_nal_units(s, avctx, buf, buf_size);
     }
 
     *poutbuf = buf;