codecparsers: h264: Add an h.264 bitstream parsing library
authorThibault Saunier <thibault.saunier@collabora.com>
Fri, 29 Jul 2011 08:56:15 +0000 (10:56 +0200)
committerEdward Hervey <edward.hervey@collabora.co.uk>
Fri, 2 Sep 2011 13:46:02 +0000 (15:46 +0200)
docs/libs/gst-plugins-bad-libs-docs.sgml
docs/libs/gst-plugins-bad-libs-sections.txt
docs/libs/gst-plugins-bad-libs.types
gst-libs/gst/codecparsers/Makefile.am
gst-libs/gst/codecparsers/gsth264parser.c [new file with mode: 0644]
gst-libs/gst/codecparsers/gsth264parser.h [new file with mode: 0644]
tests/check/Makefile.am
tests/check/libs/h264parser.c [new file with mode: 0644]

index d1113bc..b31d641 100644 (file)
@@ -28,6 +28,7 @@
         <filename>gstreamer-plugins-bad-&GST_MAJORMINOR;.pc</filename> and adding
         <filename>-lgscodeparsers-&GST_MAJORMINOR;</filename> to the library flags.
       </para>
+      <xi:include href="xml/gsth264parser.xml" />
       <xi:include href="xml/gstmpegvideoparser.xml" />
     </chapter>
   </part>
index a09929c..251d453 100644 (file)
@@ -1,5 +1,49 @@
 # codecparsers
 <SECTION>
+<FILE>gsth264parser</FILE>
+<TITLE>h264parser</TITLE>
+<INCLUDE>gst/codecparsers/gsth264parser.h</INCLUDE>
+GST_H264_MAX_SPS_COUNT
+GST_H264_MAX_PPS_COUNT
+GST_H264_IS_P_SLICE
+GST_H264_IS_B_SLICE
+GST_H264_IS_I_SLICE
+GST_H264_IS_SP_SLICE
+GST_H264_IS_SI_SLICE
+GstH264NalUnitType
+GstH264ParserResult
+GstH264SEIPayloadType
+GstH264SEIPicStructType
+GstH264SliceType
+GstH264NalParser
+GstH264NalUnit
+GstH264SPS
+GstH264PPS
+GstH264HRDParams
+GstH264VUIParams
+GstH264DecRefPicMarking
+GstH264RefPicMarking
+GstH264PredWeightTable
+GstH264SliceHdr
+GstH264ClockTimestamp
+GstH264PicTiming
+GstH264BufferingPeriod
+GstH264SEIMessage
+gst_h264_parser_identify_nalu
+gst_h264_parser_identify_nalu_avc
+gst_h264_parser_parse_nal
+gst_h264_parser_parse_slice_hdr
+gst_h264_parser_parse_sps
+gst_h264_parser_parse_pps
+gst_h264_parser_parse_sei
+gst_h264_nal_parser_new
+gst_h264_parse_sps
+gst_h264_parse_pps
+<SUBSECTION Standard>
+<SUBSECTION Private>
+</SECTION>
+
+<SECTION>
 <FILE>gstmpegvideoparser</FILE>
 <TITLE>mpegvideoparser</TITLE>
 <INCLUDE>gst/codecparsers/gstmpegvideoparser.h</INCLUDE>
index 4ca1a2b..4932157 100644 (file)
@@ -1,3 +1,4 @@
 #include <gst/gst.h>
 
+#include <gst/codecparsers/gsth264parser.h>
 #include <gst/codecparsers/gstmpegvideoparser.h>
index 86a7b16..7fa44f1 100644 (file)
@@ -1,12 +1,13 @@
 lib_LTLIBRARIES = libgstcodecparsers-@GST_MAJORMINOR@.la
 
-libgstcodecparsers_@GST_MAJORMINOR@_la_SOURCES = gstmpegvideoparser.c
+libgstcodecparsers_@GST_MAJORMINOR@_la_SOURCES = \
+       gstmpegvideoparser.c gsth264parser.c
 
 libgstcodecparsers_@GST_MAJORMINOR@includedir = \
        $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/codecparsers
 
 libgstcodecparsers_@GST_MAJORMINOR@include_HEADERS = \
-       gstmpegvideoparser.h
+       gstmpegvideoparser.h gsth264parser.h
 
 libgstcodecparsers_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_CFLAGS)
 libgstcodecparsers_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS)
diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c
new file mode 100644 (file)
index 0000000..bdd2899
--- /dev/null
@@ -0,0 +1,1808 @@
+/* Gstreamer
+ * Copyright (C) <2011> Intel Corporation
+ * Copyright (C) <2011> Collabora Ltd.
+ * Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
+ *
+ * Some bits C-c,C-v'ed and s/4/3 from h264parse and videoparsers/h264parse.c:
+ *    Copyright (C) <2010> Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+ *    Copyright (C) <2010> Collabora Multimedia
+ *    Copyright (C) <2010> Nokia Corporation
+ *
+ *    (C) 2005 Michal Benes <michal.benes@itonis.tv>
+ *    (C) 2008 Wim Taymans <wim.taymans@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gsth264parser
+ * @short_description: Convenience library for h264 video
+ * bitstream parsing.
+ *
+ * It offers you basic parsing in AVC mode or not. Tp identify Nals in a bitstream and
+ * parse its basic headers, you should call:
+ * <itemizedlist>
+ *   <listitem>
+ *      gst_h264_parser_identify_nalu to identify the following nalu in not AVC bitstreams
+ *   </listitem>
+ *   <listitem>
+ *      gst_h264_parser_identify_nalu_avc to identify the following nalu in AVC bitstreams
+ *   </listitem>
+ * </itemizedlist>
+ *
+ * Then, depending on the #GstH264NalUnitType of the newly parsed #GstH264NalUnit, you should
+ * call the differents functions to parse the struct.
+ *
+ * Note: You should always call gst_h264_parser_parse_nal if you don't actually need
+ * #GstH264NalUnitType to be parsed for your personnal use. This, to guarantee that the
+ * #GstH264NalParser is always up to date.
+ *
+ * For more details about the structures, look at the ISO specifications.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "gsth264parser.h"
+
+#include <gst/base/gstbytereader.h>
+#include <gst/base/gstbitreader.h>
+#include <string.h>
+
+GST_DEBUG_CATEGORY (h264_parser_debug);
+#define GST_CAT_DEFAULT h264_parser_debug
+
+/**** Default scaling_lists according to Table 7-2 *****/
+const guint8 default_4x4_intra[16] = {
+  6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32,
+  32, 37, 37, 42
+};
+
+const guint8 default_4x4_inter[16] = {
+  10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27,
+  27, 30, 30, 34
+};
+
+const guint8 default_8x8_intra[64] = {
+  6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18,
+  18, 18, 18, 23, 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27,
+  27, 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, 31, 33,
+  33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42
+};
+
+const guint8 default_8x8_inter[64] = {
+  9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19,
+  19, 19, 19, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24,
+  24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, 27, 28,
+  28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35
+};
+
+const guint8 zigzag_8x8[64] = {
+  0, 1, 8, 16, 9, 2, 3, 10,
+  17, 24, 32, 25, 18, 11, 4, 5,
+  12, 19, 26, 33, 40, 48, 41, 34,
+  27, 20, 13, 6, 7, 14, 21, 28,
+  35, 42, 49, 56, 57, 50, 43, 36,
+  29, 22, 15, 23, 30, 37, 44, 51,
+  58, 59, 52, 45, 38, 31, 39, 46,
+  53, 60, 61, 54, 47, 55, 62, 63
+};
+
+const guint8 zigzag_4x4[16] = {
+  0, 1, 4, 8,
+  5, 2, 3, 6,
+  9, 12, 13, 10,
+  7, 11, 14, 15,
+};
+
+/****** Nal parser ******/
+
+typedef struct
+{
+  const guint8 *data;
+  guint size;
+
+  guint byte;                   /* Byte position */
+  guint bits_in_cache;          /* bitpos in the cache of next bit */
+  guint8 first_byte;
+  guint64 cache;                /* cached bytes */
+} NalReader;
+
+static void
+nal_reader_init (NalReader * nr, const guint8 * data, guint size)
+{
+  nr->data = data;
+  nr->size = size;
+
+  nr->byte = 0;
+  nr->bits_in_cache = 0;
+  /* fill with something other than 0 to detect emulation prevention bytes */
+  nr->first_byte = 0xff;
+  nr->cache = 0xff;
+}
+
+static gboolean
+nal_reader_read (NalReader * nr, guint nbits)
+{
+  if (G_UNLIKELY (nr->byte * 8 + (nbits - nr->bits_in_cache) > nr->size * 8)) {
+    GST_DEBUG ("Can not read %u bits, bits in cache %u, Byte * 8 %u, size in "
+        "bits %u", nbits, nr->bits_in_cache, nr->byte * 8, nr->size * 8);
+    return FALSE;
+  }
+
+  while (nr->bits_in_cache < nbits) {
+    guint8 byte;
+    gboolean check_three_byte;
+
+    check_three_byte = TRUE;
+  next_byte:
+    if (G_UNLIKELY (nr->byte >= nr->size))
+      return FALSE;
+
+    byte = nr->data[nr->byte++];
+
+    /* check if the byte is a emulation_prevention_three_byte */
+    if (check_three_byte && byte == 0x03 && nr->first_byte == 0x00 &&
+        ((nr->cache & 0xff) == 0)) {
+      /* next byte goes unconditionally to the cache, even if it's 0x03 */
+      check_three_byte = FALSE;
+      goto next_byte;
+    }
+    nr->cache = (nr->cache << 8) | nr->first_byte;
+    nr->first_byte = byte;
+    nr->bits_in_cache += 8;
+  }
+
+  return TRUE;
+}
+
+static inline gboolean
+nal_reader_skip (NalReader * nr, guint nbits)
+{
+  g_return_val_if_fail (nr != NULL, FALSE);
+
+  if (G_UNLIKELY (!nal_reader_read (nr, nbits)))
+    return FALSE;
+
+  nr->bits_in_cache -= nbits;
+
+  return TRUE;
+}
+
+static inline gboolean
+nal_reader_skip_to_byte (NalReader * nr)
+{
+  g_return_val_if_fail (nr != NULL, FALSE);
+
+  if (nr->bits_in_cache == 0) {
+    if (G_LIKELY ((nr->size - nr->byte) > 0))
+      nr->byte++;
+    else
+      return FALSE;
+  }
+
+  nr->bits_in_cache = 0;
+
+  return TRUE;
+}
+
+static inline guint
+nal_reader_get_pos (const NalReader * nr)
+{
+  return nr->byte * 8 - nr->bits_in_cache;
+}
+
+static inline guint
+nal_reader_get_remaining (const NalReader * nr)
+{
+  return (nr->size - nr->byte) * 8 + nr->bits_in_cache;
+}
+
+#define GST_NAL_READER_READ_BITS(bits) \
+static gboolean \
+nal_reader_get_bits_uint##bits (NalReader *nr, guint##bits *val, guint nbits) \
+{ \
+  guint shift; \
+  \
+  g_return_val_if_fail (nr != NULL, FALSE); \
+  g_return_val_if_fail (val != NULL, FALSE); \
+  g_return_val_if_fail (nbits <= bits, FALSE); \
+  \
+  if (!nal_reader_read (nr, nbits)) \
+    return FALSE; \
+  \
+  /* bring the required bits down and truncate */ \
+  shift = nr->bits_in_cache - nbits; \
+  *val = nr->first_byte >> shift; \
+  \
+  *val |= nr->cache << (8 - shift); \
+  /* mask out required bits */ \
+  if (nbits < bits) \
+    *val &= ((guint##bits)1 << nbits) - 1; \
+  \
+  nr->bits_in_cache = shift; \
+  \
+  return TRUE; \
+} \
+
+GST_NAL_READER_READ_BITS (8);
+GST_NAL_READER_READ_BITS (16);
+GST_NAL_READER_READ_BITS (32);
+
+#define GST_NAL_READER_PEAK_BITS(bits) \
+static gboolean \
+nal_reader_peek_bits_uint##bits (const NalReader *nr, guint##bits *val, guint nbits) \
+{ \
+  NalReader tmp; \
+  \
+  g_return_val_if_fail (nr != NULL, FALSE); \
+  tmp = *nr; \
+  return nal_reader_get_bits_uint##bits (&tmp, val, nbits); \
+}
+
+GST_NAL_READER_PEAK_BITS (8);
+
+static gboolean
+nal_reader_get_ue (NalReader * nr, guint32 * val)
+{
+  guint i = 0;
+  guint8 bit;
+  guint32 value;
+
+  if (G_UNLIKELY (!nal_reader_get_bits_uint8 (nr, &bit, 1))) {
+
+    return FALSE;
+  }
+
+  while (bit == 0) {
+    i++;
+    if G_UNLIKELY
+      ((!nal_reader_get_bits_uint8 (nr, &bit, 1)))
+          return FALSE;
+  }
+
+  g_return_val_if_fail (i <= 32, FALSE);
+
+  if (G_UNLIKELY (!nal_reader_get_bits_uint32 (nr, &value, i)))
+    return FALSE;
+
+  *val = (1 << i) - 1 + value;
+
+  return TRUE;
+}
+
+static gboolean
+nal_reader_get_se (NalReader * nr, gint32 * val)
+{
+  guint32 value;
+
+  if (G_UNLIKELY (!nal_reader_get_ue (nr, &value)))
+    return FALSE;
+
+  if (value % 2)
+    *val = (value / 2) + 1;
+  else
+    *val = -(value / 2);
+
+  return TRUE;
+}
+
+#define CHECK_ALLOWED(val, min, max) { \
+  if (val < min || val > max) { \
+    GST_WARNING ("value not in allowed range. value: %d, range %d-%d", \
+                     val, min, max); \
+    goto error; \
+  } \
+}
+
+#define READ_UINT8(nr, val, nbits) { \
+  if (!nal_reader_get_bits_uint8 (nr, &val, nbits)) { \
+    GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
+    goto error; \
+  } \
+}
+
+#define READ_UINT16(nr, val, nbits) { \
+  if (!nal_reader_get_bits_uint16 (nr, &val, nbits)) { \
+  GST_WARNING ("failed to read uint16, nbits: %d", nbits); \
+    goto error; \
+  } \
+}
+
+#define READ_UINT32(nr, val, nbits) { \
+  if (!nal_reader_get_bits_uint32 (nr, &val, nbits)) { \
+  GST_WARNING ("failed to read uint32, nbits: %d", nbits); \
+    goto error; \
+  } \
+}
+
+#define READ_UINT64(nr, val, nbits) { \
+  if (!nal_reader_get_bits_uint64 (nr, &val, nbits)) { \
+    GST_WARNING ("failed to read uint32, nbits: %d", nbits); \
+    goto error; \
+  } \
+}
+
+#define READ_UE(nr, val) { \
+  if (!nal_reader_get_ue (nr, &val)) { \
+    GST_WARNING ("failed to read UE"); \
+    goto error; \
+  } \
+}
+
+#define READ_UE_ALLOWED(nr, val, min, max) { \
+  guint32 tmp; \
+  READ_UE (nr, tmp); \
+  CHECK_ALLOWED (tmp, min, max); \
+  val = tmp; \
+}
+
+#define READ_SE(nr, val) { \
+  if (!nal_reader_get_se (nr, &val)) { \
+    GST_WARNING ("failed to read SE"); \
+    goto error; \
+  } \
+}
+
+#define READ_SE_ALLOWED(nr, val, min, max) { \
+  gint32 tmp; \
+  READ_SE (nr, tmp); \
+  CHECK_ALLOWED (tmp, min, max); \
+  val = tmp; \
+}
+
+/***********  end of nal parser ***************/
+
+/*****  Utils ****/
+#define EXTENDED_SAR 255
+
+static GstH264SPS *
+gst_h264_parser_get_sps (GstH264NalParser * nalparser, guint8 sps_id)
+{
+  GstH264SPS *sps;
+
+  sps = &nalparser->sps[sps_id];
+
+  if (sps->valid)
+    return sps;
+
+  return NULL;
+}
+
+static GstH264PPS *
+gst_h264_parser_get_pps (GstH264NalParser * nalparser, guint8 pps_id)
+{
+  GstH264PPS *pps;
+
+  pps = &nalparser->pps[pps_id];
+
+  if (pps->valid)
+    return pps;
+
+  return NULL;
+}
+
+static inline void
+set_nalu_datas (GstH264NalUnit * nalu)
+{
+  guint8 *data = nalu->data + nalu->offset;
+
+  nalu->type = (data[0] & 0x1f);
+  nalu->ref_idc = (data[0] & 0x60) >> 5;
+  nalu->idr_pic_flag = (nalu->type == 5 ? 1 : 0);
+
+  GST_DEBUG ("Nal type %u, ref_idc %u", nalu->type, nalu->ref_idc);
+}
+
+static inline gint
+scan_for_start_codes (const guint8 * data, guint size)
+{
+  GstByteReader br;
+  gst_byte_reader_init (&br, data, size);
+
+  /* NALU not empty, so we can at least expect 1 (even 2) bytes following sc */
+  return gst_byte_reader_masked_scan_uint32 (&br, 0xffffff00, 0x00000100,
+      0, size);
+}
+
+static gboolean
+gst_h264_parser_more_data (NalReader * nr)
+{
+  guint remaining;
+
+  remaining = nal_reader_get_remaining (nr);
+  if (remaining == 0)
+    return FALSE;
+
+  if (remaining <= 8) {
+    guint8 rbsp_stop_one_bit;
+
+    if (!nal_reader_peek_bits_uint8 (nr, &rbsp_stop_one_bit, 1))
+      return FALSE;
+
+    if (rbsp_stop_one_bit == 1) {
+      guint8 zero_bits;
+
+      if (remaining == 1)
+        return FALSE;
+
+      if (!nal_reader_peek_bits_uint8 (nr, &zero_bits, remaining))
+        return FALSE;
+
+      if ((zero_bits - (1 << (remaining - 1))) == 0)
+        return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+/****** Parsing functions *****/
+
+static gboolean
+gst_h264_parse_hrd_parameters (GstH264HRDParams * hrd, NalReader * nr)
+{
+  guint sched_sel_idx;
+
+  GST_DEBUG ("parsing \"HRD Parameters\"");
+
+  READ_UE_ALLOWED (nr, hrd->cpb_cnt_minus1, 0, 31);
+  READ_UINT8 (nr, hrd->bit_rate_scale, 4);
+  READ_UINT8 (nr, hrd->cpb_size_scale, 4);
+
+  for (sched_sel_idx = 0; sched_sel_idx <= hrd->cpb_cnt_minus1; sched_sel_idx++) {
+    READ_UE (nr, hrd->bit_rate_value_minus1[sched_sel_idx]);
+    READ_UE (nr, hrd->cpb_size_value_minus1[sched_sel_idx]);
+  }
+
+  READ_UINT8 (nr, hrd->initial_cpb_removal_delay_length_minus1, 5);
+  READ_UINT8 (nr, hrd->cpb_removal_delay_length_minus1, 5);
+  READ_UINT8 (nr, hrd->dpb_output_delay_length_minus1, 5);
+  READ_UINT8 (nr, hrd->time_offset_length, 5);
+
+  return TRUE;
+
+error:
+  GST_WARNING ("error parsing \"HRD Parameters\"");
+  return FALSE;
+}
+
+static gboolean
+gst_h264_parse_vui_parameters (GstH264SPS * sps, NalReader * nr)
+{
+  GstH264VUIParams *vui = &sps->vui_parameters;
+
+  GST_DEBUG ("parsing \"VUI Parameters\"");
+
+  /* set default values for fields that might not be present in the bitstream
+     and have valid defaults */
+  vui->aspect_ratio_idc = 0;
+  vui->video_format = 5;
+  vui->video_full_range_flag = 0;
+  vui->colour_primaries = 2;
+  vui->transfer_characteristics = 2;
+  vui->matrix_coefficients = 2;
+  vui->chroma_sample_loc_type_top_field = 0;
+  vui->chroma_sample_loc_type_bottom_field = 0;
+  vui->low_delay_hrd_flag = 0;
+
+  READ_UINT8 (nr, vui->aspect_ratio_info_present_flag, 1);
+  if (vui->aspect_ratio_info_present_flag) {
+    READ_UINT8 (nr, vui->aspect_ratio_idc, 8);
+    if (vui->aspect_ratio_idc == EXTENDED_SAR) {
+      READ_UINT16 (nr, vui->sar_width, 16);
+      READ_UINT16 (nr, vui->sar_height, 16);
+    }
+  }
+
+  READ_UINT8 (nr, vui->overscan_info_present_flag, 1);
+  if (vui->overscan_info_present_flag)
+    READ_UINT8 (nr, vui->overscan_appropriate_flag, 1);
+
+  READ_UINT8 (nr, vui->video_signal_type_present_flag, 1);
+  if (vui->video_signal_type_present_flag) {
+
+    READ_UINT8 (nr, vui->video_format, 3);
+    READ_UINT8 (nr, vui->video_full_range_flag, 1);
+    READ_UINT8 (nr, vui->colour_description_present_flag, 1);
+    if (vui->colour_description_present_flag) {
+      READ_UINT8 (nr, vui->colour_primaries, 8);
+      READ_UINT8 (nr, vui->transfer_characteristics, 8);
+      READ_UINT8 (nr, vui->matrix_coefficients, 8);
+    }
+  }
+
+  READ_UINT8 (nr, vui->chroma_loc_info_present_flag, 1);
+  if (vui->chroma_loc_info_present_flag) {
+    READ_UE_ALLOWED (nr, vui->chroma_sample_loc_type_top_field, 0, 5);
+    READ_UE_ALLOWED (nr, vui->chroma_sample_loc_type_bottom_field, 0, 5);
+  }
+
+  READ_UINT8 (nr, vui->timing_info_present_flag, 1);
+  if (vui->timing_info_present_flag) {
+    READ_UINT32 (nr, vui->num_units_in_tick, 32);
+    if (vui->num_units_in_tick == 0)
+      GST_WARNING ("num_units_in_tick = 0 detected in stream "
+          "(incompliant to H.264 E.2.1).");
+
+    READ_UINT32 (nr, vui->time_scale, 32);
+    if (vui->time_scale == 0)
+      GST_WARNING ("time_scale = 0 detected in stream "
+          "(incompliant to H.264 E.2.1).");
+
+    READ_UINT8 (nr, vui->fixed_frame_rate_flag, 1);
+  }
+
+  READ_UINT8 (nr, vui->nal_hrd_parameters_present_flag, 1);
+  if (vui->nal_hrd_parameters_present_flag) {
+    if (!gst_h264_parse_hrd_parameters (&vui->nal_hrd_parameters, nr))
+      goto error;
+  }
+
+  READ_UINT8 (nr, vui->vcl_hrd_parameters_present_flag, 1);
+  if (vui->vcl_hrd_parameters_present_flag) {
+    if (!gst_h264_parse_hrd_parameters (&vui->vcl_hrd_parameters, nr))
+      goto error;
+  }
+
+  if (vui->nal_hrd_parameters_present_flag ||
+      vui->vcl_hrd_parameters_present_flag)
+    READ_UINT8 (nr, vui->low_delay_hrd_flag, 1);
+
+  READ_UINT8 (nr, vui->pic_struct_present_flag, 1);
+  READ_UINT8 (nr, vui->bitstream_restriction_flag, 1);
+  if (vui->bitstream_restriction_flag) {
+    READ_UINT8 (nr, vui->motion_vectors_over_pic_boundaries_flag, 1);
+    READ_UE (nr, vui->max_bytes_per_pic_denom);
+    READ_UE_ALLOWED (nr, vui->max_bits_per_mb_denom, 0, 16);
+    READ_UE_ALLOWED (nr, vui->log2_max_mv_length_horizontal, 0, 16);
+    READ_UE_ALLOWED (nr, vui->log2_max_mv_length_vertical, 0, 16);
+    READ_UE_ALLOWED (nr, vui->log2_max_mv_length_vertical, 0, 16);
+    READ_UE (nr, vui->num_reorder_frames);
+    READ_UE (nr, vui->max_dec_frame_buffering);
+  }
+
+  return TRUE;
+
+error:
+  GST_WARNING ("error parsing \"VUI Parameters\"");
+  return FALSE;
+}
+
+static gboolean
+gst_h264_parser_parse_scaling_list (NalReader * nr,
+    guint8 scaling_lists_4x4[6][16], guint8 scaling_lists_8x8[6][64],
+    const guint8 fallback_4x4_inter[16], const guint8 fallback_4x4_intra[16],
+    const guint8 fallback_8x8_inter[64], const guint8 fallback_8x8_intra[64],
+    guint8 n_lists)
+{
+  guint i;
+
+  GST_DEBUG ("parsing scaling lists");
+
+  for (i = 0; i < 12; i++) {
+    gboolean use_default = FALSE;
+
+    if (i < n_lists) {
+      guint8 scaling_list_present_flag;
+
+      READ_UINT8 (nr, scaling_list_present_flag, 1);
+      if (scaling_list_present_flag) {
+        guint8 *scaling_list;
+        const guint8 *scan;
+        guint size;
+        guint j;
+        guint8 last_scale, next_scale;
+
+        if (i < 6) {
+          scaling_list = scaling_lists_4x4[i];
+          scan = zigzag_4x4;
+          size = 16;
+        } else {
+          scaling_list = scaling_lists_8x8[i - 6];
+          scan = zigzag_8x8;
+          size = 64;
+        }
+
+        last_scale = 8;
+        next_scale = 8;
+        for (j = 0; j < size; j++) {
+          if (next_scale != 0) {
+            gint32 delta_scale;
+
+            READ_SE (nr, delta_scale);
+            next_scale = (last_scale + delta_scale) & 0xff;
+          }
+          if (j == 0 && next_scale == 0) {
+            use_default = TRUE;
+            break;
+          }
+          last_scale = scaling_list[scan[j]] =
+              (next_scale == 0) ? last_scale : next_scale;
+        }
+      } else
+        use_default = TRUE;
+    } else
+      use_default = TRUE;
+
+    if (use_default) {
+      switch (i) {
+        case 0:
+          memcpy (scaling_lists_4x4[0], fallback_4x4_intra, 16);
+          break;
+        case 1:
+          memcpy (scaling_lists_4x4[1], scaling_lists_4x4[0], 16);
+          break;
+        case 2:
+          memcpy (scaling_lists_4x4[2], scaling_lists_4x4[1], 16);
+          break;
+        case 3:
+          memcpy (scaling_lists_4x4[3], fallback_4x4_inter, 16);
+          break;
+        case 4:
+          memcpy (scaling_lists_4x4[4], scaling_lists_4x4[3], 16);
+          break;
+        case 5:
+          memcpy (scaling_lists_4x4[5], scaling_lists_4x4[4], 16);
+          break;
+        case 6:
+          memcpy (scaling_lists_8x8[0], fallback_8x8_intra, 64);
+          break;
+        case 7:
+          memcpy (scaling_lists_8x8[1], fallback_8x8_inter, 64);
+          break;
+        case 8:
+          memcpy (scaling_lists_8x8[2], scaling_lists_8x8[0], 64);
+          break;
+        case 9:
+          memcpy (scaling_lists_8x8[3], scaling_lists_8x8[1], 64);
+          break;
+        case 10:
+          memcpy (scaling_lists_8x8[4], scaling_lists_8x8[2], 64);
+          break;
+        case 11:
+          memcpy (scaling_lists_8x8[5], scaling_lists_8x8[3], 64);
+          break;
+
+        default:
+          break;
+      }
+    }
+  }
+
+  return TRUE;
+
+error:
+  GST_WARNING ("error parsing scaling lists");
+  return FALSE;
+}
+
+static gboolean
+slice_parse_ref_pic_list_reordering (GstH264SliceHdr * slice, NalReader * nr)
+{
+  GST_DEBUG ("parsing \"Reference picture list reordering\"");
+
+  if (!(slice->type == GST_H264_I_SLICE) && !(slice->type == GST_H264_SI_SLICE)) {
+    guint8 ref_pic_list_reordering_flag_l0;
+    guint32 reordering_of_pic_nums_idc;
+
+    READ_UINT8 (nr, ref_pic_list_reordering_flag_l0, 1);
+    if (ref_pic_list_reordering_flag_l0)
+      do {
+        READ_UE (nr, reordering_of_pic_nums_idc);
+        if (reordering_of_pic_nums_idc == 0 || reordering_of_pic_nums_idc == 1) {
+          guint32 abs_diff_pic_num_minus1 G_GNUC_UNUSED;
+
+          READ_UE_ALLOWED (nr, abs_diff_pic_num_minus1, 0,
+              slice->max_pic_num - 1);
+        } else if (reordering_of_pic_nums_idc == 2) {
+          guint32 long_term_pic_num;
+
+          READ_UE (nr, long_term_pic_num);
+        }
+      } while (reordering_of_pic_nums_idc != 3);
+  }
+
+  if (slice->type == GST_H264_B_SLICE) {
+    guint8 ref_pic_list_reordering_flag_l1;
+    guint32 reordering_of_pic_nums_idc;
+
+    READ_UINT8 (nr, ref_pic_list_reordering_flag_l1, 1);
+    if (ref_pic_list_reordering_flag_l1)
+      do {
+        READ_UE (nr, reordering_of_pic_nums_idc);
+        if (reordering_of_pic_nums_idc == 0 || reordering_of_pic_nums_idc == 1) {
+          guint32 abs_diff_num_minus1;
+
+          READ_UE (nr, abs_diff_num_minus1);
+        } else if (reordering_of_pic_nums_idc == 2) {
+          guint32 long_term_pic_num;
+
+          READ_UE (nr, long_term_pic_num);
+        }
+      } while (reordering_of_pic_nums_idc != 3);
+  }
+
+  return TRUE;
+
+error:
+  GST_WARNING ("error parsing \"Reference picture list reordering\"");
+  return FALSE;
+}
+
+static gboolean
+gst_h264_slice_parse_dec_ref_pic_marking (GstH264SliceHdr * slice,
+    GstH264NalUnit * nalu, NalReader * nr)
+{
+  GstH264DecRefPicMarking *dec_ref_pic_m;
+
+  GST_DEBUG ("parsing \"Decoded reference picture marking\"");
+
+  dec_ref_pic_m = &slice->dec_ref_pic_marking;
+
+  if (nalu->idr_pic_flag) {
+    READ_UINT8 (nr, dec_ref_pic_m->no_output_of_prior_pics_flag, 1);
+    READ_UINT8 (nr, dec_ref_pic_m->long_term_reference_flag, 1);
+  } else {
+    READ_UINT8 (nr, dec_ref_pic_m->adaptive_ref_pic_marking_mode_flag, 1);
+    if (dec_ref_pic_m->adaptive_ref_pic_marking_mode_flag) {
+      guint32 mem_mgmt_ctrl_op;
+      GstH264RefPicMarking *refpicmarking;
+
+      dec_ref_pic_m->n_ref_pic_marking = 0;
+      while (1) {
+        refpicmarking =
+            &dec_ref_pic_m->ref_pic_marking[dec_ref_pic_m->n_ref_pic_marking];
+
+        READ_UE (nr, mem_mgmt_ctrl_op);
+        if (mem_mgmt_ctrl_op == 0)
+          break;
+
+        refpicmarking->memory_management_control_operation = mem_mgmt_ctrl_op;
+
+        if (mem_mgmt_ctrl_op == 1 || mem_mgmt_ctrl_op == 3)
+          READ_UE (nr, refpicmarking->difference_of_pic_nums_minus1);
+
+        if (mem_mgmt_ctrl_op == 2)
+          READ_UE (nr, refpicmarking->long_term_pic_num);
+
+        if (mem_mgmt_ctrl_op == 3 || mem_mgmt_ctrl_op == 6)
+          READ_UE (nr, refpicmarking->long_term_frame_idx);
+
+        if (mem_mgmt_ctrl_op == 4)
+          READ_UE (nr, refpicmarking->max_long_term_frame_idx_plus1);
+
+        dec_ref_pic_m->n_ref_pic_marking++;
+      }
+    }
+  }
+
+  return TRUE;
+
+error:
+  GST_WARNING ("error parsing \"Decoded reference picture marking\"");
+  return FALSE;
+}
+
+static gboolean
+gst_h264_slice_parse_pred_weight_table (GstH264SliceHdr * slice,
+    NalReader * nr, guint8 chroma_array_type)
+{
+  GstH264PredWeightTable *p;
+  gint i;
+
+  GST_DEBUG ("parsing \"Prediction weight table\"");
+
+  p = &slice->pred_weight_table;
+
+  READ_UE_ALLOWED (nr, p->luma_log2_weight_denom, 0, 7);
+  /* set default values */
+  default_luma_weight = 1 << p->luma_log2_weight_denom;
+  for (i = 0; i < G_N_ELEMENTS (p->luma_weight_l0); i++)
+    p->luma_weight_l0[i] = default_luma_weight;
+  memset (p->luma_offset_l0, 0, sizeof (p->luma_offset_l0));
+  if (GST_H264_IS_B_SLICE (slice)) {
+    for (i = 0; i < G_N_ELEMENTS (p->luma_weight_l1); i++)
+      p->luma_weight_l1[i] = default_luma_weight;
+    memset (p->luma_offset_l1, 0, sizeof (p->luma_offset_l1));
+  }
+
+  if (chroma_array_type != 0) {
+    READ_UE_ALLOWED (nr, p->chroma_log2_weight_denom, 0, 7);
+    /* set default values */
+    default_chroma_weight = 1 << p->chroma_log2_weight_denom;
+    for (i = 0; i < G_N_ELEMENTS (p->chroma_weight_l0); i++) {
+      p->chroma_weight_l0[i][0] = default_chroma_weight;
+      p->chroma_weight_l0[i][1] = default_chroma_weight;
+    }
+    memset (p->chroma_offset_l0, 0, sizeof (p->chroma_offset_l0));
+    if (GST_H264_IS_B_SLICE (slice)) {
+      for (i = 0; i < G_N_ELEMENTS (p->chroma_weight_l1); i++) {
+        p->chroma_weight_l1[i][0] = default_chroma_weight;
+        p->chroma_weight_l1[i][1] = default_chroma_weight;
+      }
+      memset (p->chroma_offset_l1, 0, sizeof (p->chroma_offset_l1));
+    }
+  }
+
+  for (i = 0; i <= slice->num_ref_idx_l0_active_minus1; i++) {
+    guint8 luma_weight_l0_flag;
+
+    READ_UINT8 (nr, luma_weight_l0_flag, 1);
+    if (luma_weight_l0_flag) {
+      READ_SE_ALLOWED (nr, p->luma_weight_l0[i], -128, 127);
+      READ_SE_ALLOWED (nr, p->luma_offset_l0[i], -128, 127);
+    }
+    if (chroma_array_type != 0) {
+      guint8 chroma_weight_l0_flag;
+      gint j;
+
+      READ_UINT8 (nr, chroma_weight_l0_flag, 1);
+      if (chroma_weight_l0_flag) {
+        for (j = 0; j < 2; j++) {
+          READ_SE_ALLOWED (nr, p->chroma_weight_l0[i][j], -128, 127);
+          READ_SE_ALLOWED (nr, p->chroma_offset_l0[i][j], -128, 127);
+        }
+      }
+    }
+  }
+
+  if (GST_H264_IS_B_SLICE (slice)) {
+    for (i = 0; i <= slice->num_ref_idx_l1_active_minus1; i++) {
+      guint8 luma_weight_l1_flag;
+
+      READ_UINT8 (nr, luma_weight_l1_flag, 1);
+      if (luma_weight_l1_flag) {
+        READ_SE_ALLOWED (nr, p->luma_weight_l1[i], -128, 127);
+        READ_SE_ALLOWED (nr, p->luma_offset_l1[i], -128, 127);
+      }
+      if (chroma_array_type != 0) {
+        guint8 chroma_weight_l1_flag;
+        gint j;
+
+        READ_UINT8 (nr, chroma_weight_l1_flag, 1);
+        if (chroma_weight_l1_flag) {
+          for (j = 0; j < 2; j++) {
+            READ_SE_ALLOWED (nr, p->chroma_weight_l1[i][j], -128, 127);
+            READ_SE_ALLOWED (nr, p->chroma_offset_l1[i][j], -128, 127);
+          }
+        }
+      }
+    }
+  }
+
+  return TRUE;
+
+error:
+  GST_WARNING ("error parsing \"Prediction weight table\"");
+  return FALSE;
+}
+
+static gboolean
+gst_h264_parser_parse_buffering_period (GstH264NalParser * nalparser,
+    GstH264BufferingPeriod * per, NalReader * nr)
+{
+  GstH264SPS *sps;
+  guint8 sps_id;
+
+  GST_DEBUG ("parsing \"Buffering period\"");
+
+  READ_UE_ALLOWED (nr, sps_id, 0, GST_H264_MAX_SPS_COUNT);
+  sps = gst_h264_parser_get_sps (nalparser, sps_id);
+  if (!sps) {
+    GST_WARNING ("couldn't find associated sequence parameter set with id: %d",
+        sps_id);
+    return GST_H264_PARSER_BROKEN_LINK;
+  }
+  per->sps = sps;
+
+  if (sps->vui_parameters_present_flag) {
+    GstH264VUIParams *vui = &sps->vui_parameters;
+
+    if (vui->nal_hrd_parameters_present_flag) {
+      GstH264HRDParams *hrd = &vui->nal_hrd_parameters;
+      guint8 sched_sel_idx;
+
+      for (sched_sel_idx = 0; sched_sel_idx <= hrd->cpb_cnt_minus1;
+          sched_sel_idx++) {
+        READ_UINT8 (nr, per->nal_initial_cpb_removal_delay[sched_sel_idx], 5);
+        READ_UINT8 (nr,
+            per->nal_initial_cpb_removal_delay_offset[sched_sel_idx], 5);
+      }
+    }
+
+    if (vui->vcl_hrd_parameters_present_flag) {
+      GstH264HRDParams *hrd = &vui->vcl_hrd_parameters;
+      guint8 sched_sel_idx;
+
+      for (sched_sel_idx = 0; sched_sel_idx <= hrd->cpb_cnt_minus1;
+          sched_sel_idx++) {
+        READ_UINT8 (nr, per->vcl_initial_cpb_removal_delay[sched_sel_idx], 5);
+        READ_UINT8 (nr,
+            per->vcl_initial_cpb_removal_delay_offset[sched_sel_idx], 5);
+      }
+    }
+  }
+
+  return GST_H264_PARSER_OK;
+
+error:
+  GST_WARNING ("error parsing \"Buffering period\"");
+  return GST_H264_PARSER_ERROR;
+}
+
+static gboolean
+gst_h264_parse_clock_timestamp (GstH264ClockTimestamp * tim,
+    GstH264VUIParams * vui, NalReader * nr)
+{
+  guint8 full_timestamp_flag;
+  guint8 time_offset_length;
+
+  GST_DEBUG ("parsing \"Clock timestamp\"");
+
+  /* defalt values */
+  tim->time_offset = 0;
+
+  READ_UINT8 (nr, tim->ct_type, 2);
+  READ_UINT8 (nr, tim->nuit_field_based_flag, 1);
+  READ_UINT8 (nr, tim->counting_type, 5);
+  READ_UINT8 (nr, full_timestamp_flag, 1);
+  READ_UINT8 (nr, tim->discontinuity_flag, 1);
+  READ_UINT8 (nr, tim->cnt_dropped_flag, 1);
+  READ_UINT8 (nr, tim->n_frames, 8);
+
+  if (full_timestamp_flag) {
+    tim->seconds_flag = TRUE;
+    READ_UINT8 (nr, tim->seconds_value, 6);
+
+    tim->minutes_flag = TRUE;
+    READ_UINT8 (nr, tim->minutes_value, 6);
+
+    tim->hours_flag = TRUE;
+    READ_UINT8 (nr, tim->hours_value, 5);
+  } else {
+    READ_UINT8 (nr, tim->seconds_flag, 1);
+    if (tim->seconds_flag) {
+      READ_UINT8 (nr, tim->seconds_value, 6);
+      READ_UINT8 (nr, tim->minutes_flag, 1);
+      if (tim->minutes_flag) {
+        READ_UINT8 (nr, tim->minutes_value, 6);
+        READ_UINT8 (nr, tim->hours_flag, 1);
+        if (tim->hours_flag)
+          READ_UINT8 (nr, tim->hours_value, 5);
+      }
+    }
+  }
+
+  time_offset_length = 0;
+  if (vui->nal_hrd_parameters_present_flag)
+    time_offset_length = vui->nal_hrd_parameters.time_offset_length;
+  else if (vui->vcl_hrd_parameters_present_flag)
+    time_offset_length = vui->vcl_hrd_parameters.time_offset_length;
+
+  if (time_offset_length > 0)
+    READ_UINT32 (nr, tim->time_offset, time_offset_length);
+
+error:
+  GST_WARNING ("error parsing \"Clock timestamp\"");
+  return FALSE;
+}
+
+static gboolean
+gst_h264_parser_parse_pic_timing (GstH264NalParser * nalparser,
+    GstH264PicTiming * tim, NalReader * nr)
+{
+  GST_DEBUG ("parsing \"Picture timing\"");
+  if (!nalparser->last_sps || !nalparser->last_sps->valid) {
+    GST_WARNING ("didn't get the associated sequence paramater set for the "
+        "current access unit");
+    goto error;
+  }
+
+  /* default values */
+  memset (tim->clock_timestamp_flag, 0, 3);
+
+  if (nalparser->last_sps->vui_parameters_present_flag) {
+    GstH264VUIParams *vui = &nalparser->last_sps->vui_parameters;
+
+    if (vui->nal_hrd_parameters_present_flag) {
+      READ_UINT32 (nr, tim->cpb_removal_delay,
+          vui->nal_hrd_parameters.cpb_removal_delay_length_minus1 + 1);
+      READ_UINT32 (nr, tim->dpb_output_delay,
+          vui->nal_hrd_parameters.dpb_output_delay_length_minus1 + 1);
+    } else if (vui->nal_hrd_parameters_present_flag) {
+      READ_UINT32 (nr, tim->cpb_removal_delay,
+          vui->vcl_hrd_parameters.cpb_removal_delay_length_minus1 + 1);
+      READ_UINT32 (nr, tim->dpb_output_delay,
+          vui->vcl_hrd_parameters.dpb_output_delay_length_minus1 + 1);
+    }
+
+    if (vui->pic_struct_present_flag) {
+      const guint8 num_clock_ts_table[9] = {
+        1, 1, 1, 2, 2, 3, 3, 2, 3
+      };
+      guint8 num_clock_num_ts;
+      guint i;
+
+      READ_UINT8 (nr, tim->pic_struct, 4);
+      CHECK_ALLOWED (tim->pic_struct, 0, 8);
+
+      num_clock_num_ts = num_clock_ts_table[tim->pic_struct];
+      for (i = 0; i < num_clock_num_ts; i++) {
+        READ_UINT8 (nr, tim->clock_timestamp_flag[i], 1);
+        if (tim->clock_timestamp_flag[i]) {
+          if (!gst_h264_parse_clock_timestamp (&tim->clock_timestamp[i], vui,
+                  nr))
+            goto error;
+        }
+      }
+    }
+  }
+
+  return GST_H264_PARSER_OK;
+
+error:
+  GST_WARNING ("error parsing \"Picture timing\"");
+  return GST_H264_PARSER_ERROR;
+}
+
+/******** API *************/
+
+/**
+ * gst_h264_nal_parser_new:
+ *
+ * Creates a nez #GstH264NalParser
+ *
+ * Returns: a new #GstH264NalParser
+ */
+GstH264NalParser *
+gst_h264_nal_parser_new (void)
+{
+  GstH264NalParser *nalparser;
+
+  nalparser = g_malloc0 (sizeof (GstH264NalParser));
+  GST_DEBUG_CATEGORY_INIT (h264_parser_debug, "codecparsers_h264", 0,
+      "h264 parser library");
+
+  return nalparser;
+}
+
+/**
+ * gst_h264_parser_identify_nalu:
+ * @nalparser: a #GstH264NalParser
+ * @data: The data to parse
+ * @offset: the offset from which to parse  @data
+ * @size: the size of @data
+ * @nalu: The #GstH264NalUnit where to store parsed nal headers
+ *
+ * Parses the buffer and set @nalu from the next nalu data from @data
+ *
+ * Returns: a #GstH264ParserResult
+ */
+GstH264ParserResult
+gst_h264_parser_identify_nalu (GstH264NalParser * nalparser,
+    const guint8 * data, guint offset, gsize size, GstH264NalUnit * nalu)
+{
+  gint off1, off2;
+
+  if (size - 4 <= offset) {
+    GST_DEBUG ("Can't parse,  buffer is to small size %u, offset %u", size,
+        offset);
+    return GST_H264_PARSER_ERROR;
+  }
+
+  off1 = scan_for_start_codes (data + offset, size - offset);
+
+  if (off1 < 0) {
+    GST_DEBUG ("No start code prefix in this buffer");
+    return GST_H264_PARSER_NO_NAL;
+  }
+
+  if (offset + off1 == size - 1) {
+    GST_DEBUG ("Missing data to identify nal unit");
+
+    return GST_H264_PARSER_ERROR;
+  }
+
+  nalu->valid = TRUE;
+  nalu->sc_offset = offset + off1;
+  /* sc might have 2 or 3 0-bytes */
+  if (nalu->sc_offset > 0 && data[nalu->sc_offset - 1] == 00)
+    nalu->sc_offset--;
+
+  nalu->offset = offset + off1 + 3;
+  nalu->data = (guint8 *) data;
+  set_nalu_datas (nalu);
+
+  off2 = scan_for_start_codes (data + nalu->offset, size - nalu->offset);
+  if (off2 < 0) {
+    GST_DEBUG ("Nal start %d, No end found", nalu->offset);
+
+    return GST_H264_PARSER_NO_NAL_END;
+  }
+
+  if (off2 > 0 && data[nalu->offset + off2 - 1] == 00)
+    off2--;
+
+  nalu->size = off2;
+  if (nalu->size < 2)
+    return GST_H264_PARSER_BROKEN_DATA;
+
+  GST_DEBUG ("Complete nal found. Off: %d, Size: %d", nalu->offset, nalu->size);
+  return GST_H264_PARSER_OK;
+}
+
+/**
+ * gst_h264_parser_identify_nalu_avc:
+ * @data: The data to parse, must be the beging of the Nal unit
+ * @size: the size of @data
+ * @nal_length_size: the size in bytes of the AVC nal length prefix.
+ * @nalu: The #GstH264NalUnit where to store parsed nal headers
+ *
+ * Parses the data and sets @nalu from @data.
+ *
+ * Returns: a #GstH264ParserResult
+ */
+GstH264ParserResult
+gst_h264_parser_identify_nalu_avc (GstH264NalParser * nalparser,
+    const guint8 * data, guint offset, gsize size, guint8 nal_length_size,
+    GstH264NalUnit * nalu)
+{
+  GstBitReader br;
+
+  size = size - offset;
+  gst_bit_reader_init (&br, data + offset, size);
+
+  gst_bit_reader_get_bits_uint32 (&br, &nalu->size, nal_length_size * 8);
+  nalu->sc_offset = offset;
+  nalu->offset = offset + nal_length_size;
+
+  if (size < nalu->size + nal_length_size) {
+    nalu->size = 0;
+
+    return GST_H264_PARSER_NO_NAL_END;
+  }
+
+  nalu->data = (guint8 *) data;
+
+  set_nalu_datas (nalu);
+
+  if (nalu->size < 2)
+    return GST_H264_PARSER_BROKEN_DATA;
+
+  nalu->valid = TRUE;
+
+  return GST_H264_PARSER_OK;
+}
+
+GstH264ParserResult
+gst_h264_parser_parse_nal (GstH264NalParser * nalparser, GstH264NalUnit * nalu)
+{
+  GstH264SPS sps;
+  GstH264PPS pps;
+
+  switch (nalu->type) {
+    case GST_H264_NAL_SPS:
+      return gst_h264_parser_parse_sps (nalparser, nalu, &sps, FALSE);
+      break;
+    case GST_H264_NAL_PPS:
+      return gst_h264_parser_parse_pps (nalparser, nalu, &pps);
+  }
+
+  return GST_H264_PARSER_OK;
+}
+
+/**
+ * gst_h264_parser_parse_sps:
+ * @nalparser: a #GstH264NalParser
+ * @nalu: The #GST_H264_NAL_SPS #GstH264NalUnit you want to parse
+ * @slice: The #GstH264SPS to set.
+ * @parse_vui_params: Whether to parse the vui_params or not
+ *
+ * Parses the @data, and sets the @sps.
+ *
+ * Returns: a #GstH264ParserResult
+ */
+GstH264ParserResult
+gst_h264_parser_parse_sps (GstH264NalParser * nalparser, GstH264NalUnit * nalu,
+    GstH264SPS * sps, gboolean parse_vui_params)
+{
+  GstH264ParserResult res = gst_h264_parse_sps (nalu, sps, parse_vui_params);
+
+  if (res == GST_H264_PARSER_OK) {
+    GST_DEBUG ("adding sequence parameter set with id: %d to array", sps->id);
+
+    nalparser->sps[sps->id] = *sps;
+    nalparser->last_sps = &nalparser->sps[sps->id];
+  }
+
+
+
+  return res;
+}
+
+/**
+ * gst_h264_parse_sps:
+ * @nalu: The #GST_H264_NAL_SPS #GstH264NalUnit you want to parse
+ * @slice: The #GstH264SPS to set.
+ * @parse_vui_params: Whether to parse the vui_params or not
+ *
+ * Parses the @data, and sets the @sps.
+ *
+ * Returns: a #GstH264ParserResult
+ */
+GstH264ParserResult
+gst_h264_parse_sps (GstH264NalUnit * nalu, GstH264SPS * sps,
+    gboolean parse_vui_params)
+{
+  NalReader nr;
+  gint width, height;
+  guint8 frame_cropping_flag;
+  guint subwc[] = { 1, 2, 2, 1 };
+  guint subhc[] = { 1, 2, 1, 1 };
+  GstH264VUIParams *vui = NULL;
+
+  GST_DEBUG ("parsing SPS");
+  nal_reader_init (&nr, nalu->data + nalu->offset + 1, nalu->size);
+
+  /* set default values for fields that might not be present in the bitstream
+     and have valid defaults */
+  sps->chroma_format_idc = 1;
+  sps->separate_colour_plane_flag = 0;
+  sps->bit_depth_luma_minus8 = 0;
+  sps->bit_depth_chroma_minus8 = 0;
+  memset (sps->scaling_lists_4x4, 16, 96);
+  memset (sps->scaling_lists_8x8, 16, 384);
+  sps->mb_adaptive_frame_field_flag = 0;
+  sps->frame_crop_left_offset = 0;
+  sps->frame_crop_right_offset = 0;
+  sps->frame_crop_top_offset = 0;
+  sps->frame_crop_bottom_offset = 0;
+
+  READ_UINT8 (&nr, sps->profile_idc, 8);
+  READ_UINT8 (&nr, sps->constraint_set0_flag, 1);
+  READ_UINT8 (&nr, sps->constraint_set1_flag, 1);
+  READ_UINT8 (&nr, sps->constraint_set2_flag, 1);
+  READ_UINT8 (&nr, sps->constraint_set3_flag, 1);
+
+  /* skip reserved_zero_4bits */
+  if (!nal_reader_skip (&nr, 4))
+    goto error;
+
+  READ_UINT8 (&nr, sps->level_idc, 8);
+
+  READ_UE_ALLOWED (&nr, sps->id, 0, GST_H264_MAX_SPS_COUNT);
+
+  if (sps->profile_idc == 100 || sps->profile_idc == 110 ||
+      sps->profile_idc == 122 || sps->profile_idc == 244 ||
+      sps->profile_idc == 44 || sps->profile_idc == 83 ||
+      sps->profile_idc == 86) {
+    READ_UE_ALLOWED (&nr, sps->chroma_format_idc, 0, 3);
+    if (sps->chroma_format_idc == 3)
+      READ_UINT8 (&nr, sps->separate_colour_plane_flag, 1);
+
+    READ_UE_ALLOWED (&nr, sps->bit_depth_luma_minus8, 0, 6);
+    READ_UE_ALLOWED (&nr, sps->bit_depth_chroma_minus8, 0, 6);
+    READ_UINT8 (&nr, sps->qpprime_y_zero_transform_bypass_flag, 1);
+
+    READ_UINT8 (&nr, sps->scaling_matrix_present_flag, 1);
+    if (sps->scaling_matrix_present_flag) {
+      guint8 n_lists;
+
+      n_lists = (sps->chroma_format_idc != 3) ? 8 : 12;
+      if (!gst_h264_parser_parse_scaling_list (&nr,
+              sps->scaling_lists_4x4, sps->scaling_lists_8x8,
+              default_4x4_inter, default_4x4_intra,
+              default_8x8_inter, default_8x8_intra, n_lists))
+        goto error;
+    }
+  }
+
+  READ_UE_ALLOWED (&nr, sps->log2_max_frame_num_minus4, 0, 12);
+
+  sps->max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4);
+
+  READ_UE_ALLOWED (&nr, sps->pic_order_cnt_type, 0, 2);
+  if (sps->pic_order_cnt_type == 0) {
+    READ_UE_ALLOWED (&nr, sps->log2_max_pic_order_cnt_lsb_minus4, 0, 12);
+  } else if (sps->pic_order_cnt_type == 1) {
+    guint i;
+
+    READ_UINT8 (&nr, sps->delta_pic_order_always_zero_flag, 1);
+    READ_SE (&nr, sps->offset_for_non_ref_pic);
+    READ_SE (&nr, sps->offset_for_top_to_bottom_field);
+    READ_UE_ALLOWED (&nr, sps->num_ref_frames_in_pic_order_cnt_cycle, 0, 255);
+
+    for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++)
+      READ_SE (&nr, sps->offset_for_ref_frame[i]);
+  }
+
+  READ_UE (&nr, sps->num_ref_frames);
+  READ_UINT8 (&nr, sps->gaps_in_frame_num_value_allowed_flag, 1);
+  READ_UE (&nr, sps->pic_width_in_mbs_minus1);
+  READ_UE (&nr, sps->pic_height_in_map_units_minus1);
+  READ_UINT8 (&nr, sps->frame_mbs_only_flag, 1);
+
+  if (!sps->frame_mbs_only_flag)
+    READ_UINT8 (&nr, sps->mb_adaptive_frame_field_flag, 1);
+
+  READ_UINT8 (&nr, sps->direct_8x8_inference_flag, 1);
+  READ_UINT8 (&nr, frame_cropping_flag, 1);
+  if (frame_cropping_flag) {
+    READ_UE (&nr, sps->frame_crop_left_offset);
+    READ_UE (&nr, sps->frame_crop_right_offset);
+    READ_UE (&nr, sps->frame_crop_top_offset);
+    READ_UE (&nr, sps->frame_crop_bottom_offset);
+  }
+
+  READ_UINT8 (&nr, sps->vui_parameters_present_flag, 1);
+  if (sps->vui_parameters_present_flag && parse_vui_params) {
+    if (!gst_h264_parse_vui_parameters (sps, &nr))
+      goto error;
+    vui = &sps->vui_parameters;
+  }
+
+  /* calculate ChromaArrayType */
+  if (sps->separate_colour_plane_flag)
+    sps->chroma_array_type = 0;
+  else
+    sps->chroma_array_type = sps->chroma_format_idc;
+
+  /* Calculate  width and height */
+  width = (sps->pic_width_in_mbs_minus1 + 1);
+  width *= 16;
+  height = (sps->pic_height_in_map_units_minus1 + 1);
+  height *= 16 * (2 - sps->frame_mbs_only_flag);
+  GST_LOG ("initial width=%d, height=%d", width, height);
+
+  width -= (sps->frame_crop_left_offset + sps->frame_crop_right_offset)
+      * subwc[sps->chroma_format_idc];
+  height -= (sps->frame_crop_top_offset + sps->frame_crop_bottom_offset
+      * subhc[sps->chroma_format_idc] * (2 - sps->frame_mbs_only_flag));
+  if (width < 0 || height < 0) {
+    GST_WARNING ("invalid width/height in SPS");
+    return FALSE;
+  }
+  GST_LOG ("final width=%u, height=%u", width, height);
+  sps->width = width;
+  sps->height = height;
+
+  /* derive framerate */
+  /* FIXME verify / also handle other cases */
+  GST_LOG ("Framerate: %u %u %u %u", parse_vui_params,
+      vui->fixed_frame_rate_flag, sps->frame_mbs_only_flag,
+      vui->pic_struct_present_flag);
+
+  if (parse_vui_params && vui->fixed_frame_rate_flag &&
+      sps->frame_mbs_only_flag && !vui->pic_struct_present_flag) {
+    sps->fps_num = vui->time_scale;
+    sps->fps_den = vui->num_units_in_tick;
+    /* picture is a frame = 2 fields */
+    sps->fps_den *= 2;
+    GST_LOG ("framerate %d/%d", sps->fps_num, sps->fps_den);
+  }
+
+  sps->valid = TRUE;
+
+  return GST_H264_PARSER_OK;
+
+error:
+  GST_WARNING ("error parsing \"Sequence parameter set\"");
+
+  return GST_H264_PARSER_ERROR;
+}
+
+/**
+ * gst_h264_parse_pps:
+ * @nalparser: a #GstH264NalParser
+ * @data: the data to parse
+ * @size: the size of @data
+ * @nalu: The #GST_H264_NAL_PPS #GstH264NalUnit you want to parse
+ * @slice: The #GstH264PPS to set.
+ *
+ * Parses the @data, and sets the @pps.
+ *
+ * Returns: a #GstH264ParserResult
+ */
+GstH264ParserResult
+gst_h264_parse_pps (GstH264NalParser * nalparser, GstH264NalUnit * nalu,
+    GstH264PPS * pps)
+{
+  NalReader nr;
+  GstH264SPS *sps;
+  gint sps_id;
+  guint8 pic_scaling_matrix_present_flag;
+  gint qp_bd_offset;
+
+  GST_DEBUG ("parsing PPS");
+
+  nal_reader_init (&nr, nalu->data + nalu->offset + 1, nalu->size);
+
+  READ_UE_ALLOWED (&nr, pps->id, 0, GST_H264_MAX_PPS_COUNT);
+  READ_UE_ALLOWED (&nr, sps_id, 0, GST_H264_MAX_SPS_COUNT);
+
+  sps = gst_h264_parser_get_sps (nalparser, sps_id);
+  if (!sps) {
+    GST_WARNING ("couldn't find associated sequence parameter set with id: %d",
+        sps_id);
+    return GST_H264_PARSER_BROKEN_LINK;
+  }
+  pps->sequence = sps;
+  qp_bd_offset = 6 * (sps->bit_depth_luma_minus8 +
+      sps->separate_colour_plane_flag);
+
+  /* set default values for fields that might not be present in the bitstream
+     and have valid defaults */
+  pps->slice_group_id = NULL;
+  pps->transform_8x8_mode_flag = 0;
+  memcpy (&pps->scaling_lists_4x4, &sps->scaling_lists_4x4, 96);
+  memcpy (&pps->scaling_lists_8x8, &sps->scaling_lists_8x8, 384);
+
+  READ_UINT8 (&nr, pps->entropy_coding_mode_flag, 1);
+  READ_UINT8 (&nr, pps->pic_order_present_flag, 1);
+  READ_UE_ALLOWED (&nr, pps->num_slice_groups_minus1, 0, 7);
+  if (pps->num_slice_groups_minus1 > 0) {
+    READ_UE_ALLOWED (&nr, pps->slice_group_map_type, 0, 6);
+
+    if (pps->slice_group_map_type == 0) {
+      gint i;
+
+      for (i = 0; i <= pps->num_slice_groups_minus1; i++)
+        READ_UE (&nr, pps->run_length_minus1[i]);
+    } else if (pps->slice_group_map_type == 2) {
+      gint i;
+
+      for (i = 0; i <= pps->num_slice_groups_minus1; i++) {
+        READ_UE (&nr, pps->top_left[i]);
+        READ_UE (&nr, pps->bottom_right[i]);
+      }
+    } else if (pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) {
+      READ_UINT8 (&nr, pps->slice_group_change_direction_flag, 1);
+      READ_UE (&nr, pps->slice_group_change_rate_minus1);
+    } else if (pps->slice_group_map_type == 6) {
+      gint bits;
+      gint i;
+
+      READ_UE (&nr, pps->pic_size_in_map_units_minus1);
+      bits = g_bit_storage (pps->num_slice_groups_minus1);
+
+      pps->slice_group_id =
+          g_new (guint8, pps->pic_size_in_map_units_minus1 + 1);
+      for (i = 0; i <= pps->pic_size_in_map_units_minus1; i++)
+        READ_UINT8 (&nr, pps->slice_group_id[i], bits);
+    }
+  }
+
+  READ_UE_ALLOWED (&nr, pps->num_ref_idx_l0_active_minus1, 0, 31);
+  READ_UE_ALLOWED (&nr, pps->num_ref_idx_l1_active_minus1, 0, 31);
+  READ_UINT8 (&nr, pps->weighted_pred_flag, 1);
+  READ_UINT8 (&nr, pps->weighted_bipred_idc, 2);
+  READ_SE_ALLOWED (&nr, pps->pic_init_qp_minus26, -(26 + qp_bd_offset), 25);
+  READ_SE_ALLOWED (&nr, pps->pic_init_qs_minus26, -26, 25);
+  READ_SE_ALLOWED (&nr, pps->chroma_qp_index_offset, -12, 12);
+  pps->second_chroma_qp_index_offset = pps->chroma_qp_index_offset;
+  READ_UINT8 (&nr, pps->deblocking_filter_control_present_flag, 1);
+  READ_UINT8 (&nr, pps->constrained_intra_pred_flag, 1);
+  READ_UINT8 (&nr, pps->redundant_pic_cnt_present_flag, 1);
+
+  if (!gst_h264_parser_more_data (&nr))
+    goto done;
+
+  READ_UINT8 (&nr, pps->transform_8x8_mode_flag, 1);
+
+  READ_UINT8 (&nr, pic_scaling_matrix_present_flag, 1);
+  if (pic_scaling_matrix_present_flag) {
+    guint8 n_lists;
+
+    n_lists = 6 + ((sps->chroma_format_idc != 3) ? 2 : 6) *
+        pps->transform_8x8_mode_flag;
+
+    if (sps->scaling_matrix_present_flag) {
+      if (!gst_h264_parser_parse_scaling_list (&nr,
+              pps->scaling_lists_4x4, pps->scaling_lists_8x8,
+              sps->scaling_lists_4x4[0], sps->scaling_lists_4x4[3],
+              sps->scaling_lists_8x8[0], sps->scaling_lists_8x8[3], n_lists))
+        goto error;
+    } else {
+      if (!gst_h264_parser_parse_scaling_list (&nr,
+              pps->scaling_lists_4x4, pps->scaling_lists_8x8,
+              default_4x4_inter, default_4x4_intra,
+              default_8x8_inter, default_8x8_intra, n_lists))
+        goto error;
+    }
+  }
+
+  /* FIXME For some reson second_chroma_qp_index_offset is not always present */
+  if (G_UNLIKELY (nr.byte * 8 + (8 - nr.bits_in_cache) > nr.size * 8))
+    READ_SE_ALLOWED (&nr, pps->second_chroma_qp_index_offset, -12, 12);
+
+  pps->valid = TRUE;
+
+done:
+  return GST_H264_PARSER_OK;
+
+error:
+  GST_WARNING ("error parsing \"Picture parameter set\"");
+  return GST_H264_PARSER_ERROR;
+}
+
+/**
+ * gst_h264_parser_parse_pps:
+ * @nalparser: a #GstH264NalParser
+ * @data: the data to parse
+ * @size: the size of @data
+ * @nalu: The #GST_H264_NAL_PPS #GstH264NalUnit you want to parse
+ * @slice: The #GstH264PPS to set.
+ *
+ * Parses the @data, and sets the @pps.
+ *
+ * Returns: a #GstH264ParserResult
+ */
+GstH264ParserResult
+gst_h264_parser_parse_pps (GstH264NalParser * nalparser,
+    GstH264NalUnit * nalu, GstH264PPS * pps)
+{
+  GstH264ParserResult res = gst_h264_parse_pps (nalparser, nalu, pps);
+
+  if (res == GST_H264_PARSER_OK) {
+    GST_DEBUG ("adding picture parameter set with id: %d to array", pps->id);
+
+    nalparser->pps[pps->id] = *pps;
+    nalparser->last_pps = &nalparser->pps[pps->id];
+  }
+
+  return res;
+}
+
+/**
+ * gst_h264_parser_parse_slice_hdr:
+ * @nalu: The #GST_H264_NAL_SLICE #GstH264NalUnit you want to parse
+ * @slice: The #GstH264SliceHdr to set.
+ * @parse_pred_weight_table: Whether to parse the pred_weight_table or not
+ * @parse_dec_ref_pic_marking: Whether to parse the dec_ref_pic_marking or not
+ *
+ * Parses the @data, and sets the @slice.
+ *
+ * Returns: a #GstH264ParserResult
+ */
+GstH264ParserResult
+gst_h264_parser_parse_slice_hdr (GstH264NalParser * nalparser,
+    GstH264NalUnit * nalu, GstH264SliceHdr * slice,
+    gboolean parse_pred_weight_table, gboolean parse_dec_ref_pic_marking)
+{
+  NalReader nr;
+  gint pps_id;
+  GstH264PPS *pps;
+  GstH264SPS *sps;
+
+  if (!nalu->size) {
+    GST_DEBUG ("Invalid Nal Unit");
+    return GST_H264_PARSER_ERROR;
+  }
+
+
+  nal_reader_init (&nr, nalu->data + nalu->offset + 1, nalu->size);
+
+  READ_UE (&nr, slice->first_mb_in_slice);
+  READ_UE (&nr, slice->type);
+
+  GST_DEBUG ("parsing \"Slice header\", slice type %u", slice->type);
+
+  READ_UE_ALLOWED (&nr, pps_id, 0, GST_H264_MAX_PPS_COUNT);
+  pps = gst_h264_parser_get_pps (nalparser, pps_id);
+
+  if (!pps) {
+    GST_WARNING ("couldn't find associated picture parameter set with id: %d",
+        pps_id);
+
+    return GST_H264_PARSER_BROKEN_LINK;
+  }
+
+  slice->pps = pps;
+  sps = pps->sequence;
+  if (!sps) {
+    GST_WARNING ("couldn't find associated sequence parameter set with id: %d",
+        pps->id);
+    return GST_H264_PARSER_BROKEN_LINK;
+  }
+
+  /* set default values for fields that might not be present in the bitstream
+     and have valid defaults */
+  slice->field_pic_flag = 0;
+  slice->bottom_field_flag = 0;
+  slice->delta_pic_order_cnt_bottom = 0;
+  slice->delta_pic_order_cnt[0] = 0;
+  slice->delta_pic_order_cnt[1] = 0;
+  slice->redundant_pic_cnt = 0;
+  slice->num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_active_minus1;
+  slice->num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_active_minus1;
+  slice->disable_deblocking_filter_idc = 0;
+  slice->slice_alpha_c0_offset_div2 = 0;
+
+  if (sps->separate_colour_plane_flag)
+    READ_UINT8 (&nr, slice->colour_plane_id, 2);
+
+  READ_UINT16 (&nr, slice->frame_num, sps->log2_max_frame_num_minus4 + 4);
+
+  if (!sps->frame_mbs_only_flag) {
+    READ_UINT8 (&nr, slice->field_pic_flag, 1);
+    if (slice->field_pic_flag)
+      READ_UINT8 (&nr, slice->bottom_field_flag, 1);
+  }
+
+  /* calculate MaxPicNum */
+  if (slice->field_pic_flag)
+    slice->max_pic_num = sps->max_frame_num;
+  else
+    slice->max_pic_num = 2 * sps->max_frame_num;
+
+  if (nalu->type == 5)
+    READ_UE_ALLOWED (&nr, slice->idr_pic_id, 0, G_MAXUINT16);
+
+  if (sps->pic_order_cnt_type == 0) {
+    READ_UINT16 (&nr, slice->pic_order_cnt_lsb,
+        sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
+
+    if (pps->pic_order_present_flag && !slice->field_pic_flag)
+      READ_SE (&nr, slice->delta_pic_order_cnt_bottom);
+  }
+
+  if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) {
+    READ_SE (&nr, slice->delta_pic_order_cnt[0]);
+    if (pps->pic_order_present_flag && !slice->field_pic_flag)
+      READ_SE (&nr, slice->delta_pic_order_cnt[1]);
+  }
+
+  if (pps->redundant_pic_cnt_present_flag)
+    READ_UE_ALLOWED (&nr, slice->redundant_pic_cnt, 0, G_MAXINT8);
+
+  if (GST_H264_IS_B_SLICE (slice))
+    READ_UINT8 (&nr, slice->direct_spatial_mv_pred_flag, 1);
+
+  if (GST_H264_IS_P_SLICE (slice) || GST_H264_IS_SP_SLICE (slice) ||
+      GST_H264_IS_B_SLICE (slice)) {
+    guint8 num_ref_idx_active_override_flag;
+
+    READ_UINT8 (&nr, num_ref_idx_active_override_flag, 1);
+    if (num_ref_idx_active_override_flag) {
+      READ_UE_ALLOWED (&nr, slice->num_ref_idx_l0_active_minus1, 0, 31);
+
+      if (GST_H264_IS_B_SLICE (slice))
+        READ_UE_ALLOWED (&nr, slice->num_ref_idx_l1_active_minus1, 0, 31);
+    }
+  }
+
+  if (!slice_parse_ref_pic_list_reordering (slice, &nr))
+    goto error;
+
+  if ((pps->weighted_pred_flag && (GST_H264_IS_P_SLICE (slice)
+              || GST_H264_IS_SP_SLICE (slice)))
+      || (pps->weighted_bipred_idc == 1 && GST_H264_IS_B_SLICE (slice))) {
+    if (!gst_h264_slice_parse_pred_weight_table (slice, &nr,
+            sps->chroma_array_type))
+      goto error;
+  }
+
+  if (nalu->ref_idc != 0) {
+    if (!gst_h264_slice_parse_dec_ref_pic_marking (slice, nalu, &nr))
+      goto error;
+  }
+
+  if (pps->entropy_coding_mode_flag && !GST_H264_IS_I_SLICE (slice) &&
+      !GST_H264_IS_SI_SLICE (slice))
+    READ_UE_ALLOWED (&nr, slice->cabac_init_idc, 0, 2);
+
+  READ_SE_ALLOWED (&nr, slice->slice_qp_delta, -87, 77);
+
+  if (GST_H264_IS_SP_SLICE (slice) || GST_H264_IS_SI_SLICE (slice)) {
+    guint8 sp_for_switch_flag;
+
+    if (GST_H264_IS_SP_SLICE (slice))
+      READ_UINT8 (&nr, sp_for_switch_flag, 1);
+    READ_SE_ALLOWED (&nr, slice->slice_qs_delta, -51, 51);
+  }
+
+  if (pps->deblocking_filter_control_present_flag) {
+    READ_UE_ALLOWED (&nr, slice->disable_deblocking_filter_idc, 0, 2);
+    if (slice->disable_deblocking_filter_idc != 1) {
+      READ_SE_ALLOWED (&nr, slice->slice_alpha_c0_offset_div2, -6, 6);
+      READ_SE_ALLOWED (&nr, slice->slice_beta_offset_div2, -6, 6);
+    }
+  }
+
+  if (pps->num_slice_groups_minus1 > 0 &&
+      pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) {
+    /* Ceil(Log2(PicSizeInMapUnits / SliceGroupChangeRate + 1))  [7-33] */
+    guint32 PicWidthInMbs = sps->pic_width_in_mbs_minus1 + 1;
+    guint32 PicHeightInMapUnits = sps->pic_height_in_map_units_minus1 + 1;
+    guint32 PicSizeInMapUnits = PicWidthInMbs * PicHeightInMapUnits;
+    guint32 SliceGroupChangeRate = pps->slice_group_change_rate_minus1 + 1;
+    const guint n = ceil_log2 (PicSizeInMapUnits / SliceGroupChangeRate + 1);
+    READ_UINT16 (&nr, slice->slice_group_change_cycle, n);
+  }
+
+  slice->header_size = nal_reader_get_pos (&nr);
+
+  return GST_H264_PARSER_OK;
+
+error:
+  GST_WARNING ("error parsing \"Slice header\"");
+  return GST_H264_PARSER_ERROR;
+}
+
+/**
+ * gst_h264_parser_parse_sei:
+ * @nalparser: a #GstH264NalParser
+ * @nalu: The #GST_H264_NAL_SEI #GstH264NalUnit you want to parse
+ * @slice: The #GstH264SEIMessage to set.
+ *
+ * Parses the @data, and sets the @pps.
+ *
+ * Returns: a #GstH264ParserResult
+ */
+GstH264ParserResult
+gst_h264_parser_parse_sei (GstH264NalParser * nalparser, GstH264NalUnit * nalu,
+    GstH264SEIMessage * sei)
+{
+  NalReader nr;
+
+  guint32 payloadSize;
+  guint8 payload_type_byte, payload_size_byte;
+  guint remaining, payload_size;
+  gboolean res;
+
+  GST_DEBUG ("parsing \"Sei message\"");
+
+  nal_reader_init (&nr, nalu->data + nalu->offset + 1, nalu->size);
+
+  sei->payloadType = 0;
+  do {
+    READ_UINT8 (&nr, payload_type_byte, 8);
+    sei->payloadType += payload_type_byte;
+  } while (payload_type_byte == 0xff);
+
+  payloadSize = 0;
+  do {
+    READ_UINT8 (&nr, payload_size_byte, 8);
+    payloadSize += payload_size_byte;
+  }
+  while (payload_size_byte == 0xff);
+
+  remaining = nal_reader_get_remaining (&nr) * 8;
+  payload_size = payloadSize < remaining ? payloadSize : remaining;
+
+  GST_DEBUG ("SEI message received: payloadType  %u, payloadSize = %u bytes",
+      sei->payloadType, payload_size);
+
+  if (sei->payloadType == GST_H264_SEI_BUF_PERIOD) {
+    /* Set the nal reader size properly */
+    nr.size = payload_size;
+    res = gst_h264_parser_parse_buffering_period (nalparser,
+        &sei->buffering_period, &nr);
+  } else if (sei->payloadType == GST_H264_SEI_PIC_TIMING) {
+    /* Set the nal reader size properly */
+    nr.size = payload_size;
+    res = gst_h264_parser_parse_pic_timing (nalparser, &sei->pic_timing, &nr);
+  } else
+    res = GST_H264_PARSER_OK;
+
+  return res;
+
+error:
+  GST_WARNING ("error parsing \"Sei message\"");
+  return GST_H264_PARSER_ERROR;
+}
diff --git a/gst-libs/gst/codecparsers/gsth264parser.h b/gst-libs/gst/codecparsers/gsth264parser.h
new file mode 100644 (file)
index 0000000..c7fae95
--- /dev/null
@@ -0,0 +1,657 @@
+/* Gstreamer
+ * Copyright (C) <2011> Intel Corporation
+ * Copyright (C) <2011> Collabora Ltd.
+ * Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
+ *
+ * Some bits C-c,C-v'ed and s/4/3 from h264parse and videoparsers/h264parse.c:
+ *    Copyright (C) <2010> Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+ *    Copyright (C) <2010> Collabora Multimedia
+ *    Copyright (C) <2010> Nokia Corporation
+ *
+ *    (C) 2005 Michal Benes <michal.benes@itonis.tv>
+ *    (C) 2008 Wim Taymans <wim.taymans@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_H264_PARSER_H__
+#define __GST_H264_PARSER_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_H264_MAX_SPS_COUNT   32
+#define GST_H264_MAX_PPS_COUNT   256
+
+#define GST_H264_IS_P_SLICE(slice)  (((slice)->type % 5) == GST_H264_P_SLICE)
+#define GST_H264_IS_B_SLICE(slice)  (((slice)->type % 5) == GST_H264_B_SLICE)
+#define GST_H264_IS_I_SLICE(slice)  (((slice)->type % 5) == GST_H264_I_SLICE)
+#define GST_H264_IS_SP_SLICE(slice) (((slice)->type % 5) == GST_H264_SP_SLICE)
+#define GST_H264_IS_SI_SLICE(slice) (((slice)->type % 5) == GST_H264_SI_SLICE)
+
+/**
+ * GstH264NalUnitType:
+ * @GST_H264_NAL_UNKNOWN: Unkonw nal type
+ * @GST_H264_NAL_SLICE: Slice nal
+ * @GST_H264_NAL_SLICE_DPA: DPA slice nal
+ * @GST_H264_NAL_SLICE_DPB: DPB slice nal
+ * @GST_H264_NAL_SLICE_DPC: DPC slice nal
+ * @GST_H264_NAL_SLICE_IDR: DPR slice nal
+ * @GST_H264_NAL_SEI: Supplemental enhancement information nal unit
+ * @GST_H264_NAL_SPS: Sequence parameter set nal unit
+ * @GST_H264_NAL_PPS: Picture parameter set nal unit
+ * @GST_H264_NAL_AU_DELIMITER: Access unit delimiter nal unit
+ * @GST_H264_NAL_SEQ_END: End of sequence nal unit
+ * @GST_H264_NAL_STREAM_END: End of stream nal unit
+ * @GST_H264_NAL_FILTER_DATA: Filler data na lunit
+ *
+ * Indicates the type of H264 Nal Units
+ */
+typedef enum
+{
+  GST_H264_NAL_UNKNOWN      = 0,
+  GST_H264_NAL_SLICE        = 1,
+  GST_H264_NAL_SLICE_DPA    = 2,
+  GST_H264_NAL_SLICE_DPB    = 3,
+  GST_H264_NAL_SLICE_DPC    = 4,
+  GST_H264_NAL_SLICE_IDR    = 5,
+  GST_H264_NAL_SEI          = 6,
+  GST_H264_NAL_SPS          = 7,
+  GST_H264_NAL_PPS          = 8,
+  GST_H264_NAL_AU_DELIMITER = 9,
+  GST_H264_NAL_SEQ_END      = 10,
+  GST_H264_NAL_STREAM_END   = 11,
+  GST_H264_NAL_FILLER_DATA  = 12
+} GstH264NalUnitType;
+
+/**
+ * GstH264ParserResult:
+ * @GST_H264_PARSER_OK: The parsing succeded
+ * @GST_H264_PARSER_BROKEN_DATA: The data we parsed where broken
+ * @GST_H264_PARSER_BROKEN_LINK: The link to a needed struct for the parsing couldn't be found
+ * @GST_H264_PARSER_ERROR: An error accured when parsing
+ * @GST_H264_PARSER_NO_NAL: No nal found during the parsing
+ * @GST_H264_PARSER_NO_NAL_END: Start of the nal found, not the end.
+ *
+ * Information about how the parsing of a H264 elements went.
+ */
+typedef enum
+{
+  GST_H264_PARSER_OK,
+  GST_H264_PARSER_BROKEN_DATA,
+  GST_H264_PARSER_BROKEN_LINK,
+  GST_H264_PARSER_ERROR,
+  GST_H264_PARSER_NO_NAL,
+  GST_H264_PARSER_NO_NAL_END
+} GstH264ParserResult;
+
+/**
+ * GstH264SEIPayloadType:
+ * @GST_H264_SEI_BUF_PERIOD: The Sei Message contains a buffering period message
+ * @GST_H264_SEI_PIC_TIMING: The Sei Message contains a picture timing message
+ * ...
+ *
+ * The type of the SEI message information
+ */
+typedef enum
+{
+  GST_H264_SEI_BUF_PERIOD = 0,
+  GST_H264_SEI_PIC_TIMING = 1
+      /* and more...  */
+} GstH264SEIPayloadType;
+
+/**
+ * GstH264SEIPicStructType:
+ * @GST_H264_SEI_PIC_STRUCT_FRAME: Picture is a frame
+ * @GST_H264_SEI_PIC_STRUCT_TOP_FIELD: Top field of frame
+ * @GST_H264_SEI_PIC_STRUCT_BOTTOM_FIELD: Botom field of frame
+ * @GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM: Top bottom field of frame
+ * @GST_H264_SEI_PIC_STRUCT_BOTTOM_TOP: bottom top field of frame
+ * @GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: top bottom top field of frame
+ * @GST_H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: bottom top bottom field of frame
+ * @GST_H264_SEI_PIC_STRUCT_FRAME_DOUBLING: indicates that the frame should
+ *  be displayed two times consecutively
+ * @GST_H264_SEI_PIC_STRUCT_FRAME_TRIPLING: indicates that the frame should be
+ *  displayed three times consecutively
+ *
+ * SEI pic_struct type
+ */
+typedef enum
+{
+  GST_H264_SEI_PIC_STRUCT_FRAME             = 0,
+  GST_H264_SEI_PIC_STRUCT_TOP_FIELD         = 1,
+  GST_H264_SEI_PIC_STRUCT_BOTTOM_FIELD      = 2,
+  GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM        = 3,
+  GST_H264_SEI_PIC_STRUCT_BOTTOM_TOP        = 4,
+  GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP    = 5,
+  GST_H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM = 6,
+  GST_H264_SEI_PIC_STRUCT_FRAME_DOUBLING    = 7,
+  GST_H264_SEI_PIC_STRUCT_FRAME_TRIPLING    = 8
+} GstH264SEIPicStructType;
+
+typedef enum
+{
+  GST_H264_P_SLICE    = 0,
+  GST_H264_B_SLICE    = 1,
+  GST_H264_I_SLICE    = 2,
+  GST_H264_SP_SLICE   = 3,
+  GST_H264_SI_SLICE   = 4,
+  GST_H264_S_P_SLICE  = 5,
+  GST_H264_S_B_SLICE  = 6,
+  GST_H264_S_I_SLICE  = 7,
+  GST_H264_S_SP_SLICE = 8,
+  GST_H264_S_SI_SLICE = 9
+} GstH264SliceType;
+
+typedef struct _GstH264NalParser        GstH264NalParser;
+
+typedef struct _GstH264NalUnit          GstH264NalUnit;
+
+typedef struct _GstH264SPS              GstH264SPS;
+typedef struct _GstH264PPS              GstH264PPS;
+typedef struct _GstH264HRDParams        GstH264HRDParams;
+typedef struct _GstH264VUIParams        GstH264VUIParams;
+
+typedef struct _GstH264DecRefPicMarking GstH264DecRefPicMarking;
+typedef struct _GstH264RefPicMarking    GstH264RefPicMarking;
+typedef struct _GstH264PredWeightTable  GstH264PredWeightTable;
+typedef struct _GstH264SliceHdr         GstH264SliceHdr;
+
+typedef struct _GstH264ClockTimestamp   GstH264ClockTimestamp;
+typedef struct _GstH264PicTiming        GstH264PicTiming;
+typedef struct _GstH264BufferingPeriod  GstH264BufferingPeriod;
+typedef struct _GstH264SEIMessage       GstH264SEIMessage;
+
+/**
+ * GstH264NalUnit:
+ * @ref_idc: not equal to 0 specifies that the content of the NAL unit contains a sequence
+ *  parameter set, a sequence * parameter set extension, a subset sequence parameter set, a
+ *  picture parameter set, a slice of a reference picture, a slice data partition of a
+ *  reference picture, or a prefix NAL unit preceding a slice of a reference picture.
+ * @type: A #GstH264NalUnitType
+ * @idr_pic_flag: calculated idr_pic_flag
+ * @size: The size of the nal unit starting from @offset
+ * @offset: The offset of the actual start of the nal unit
+ * @sc_offset:The offset of the start code of the nal unit
+ * @valid: If the nal unit is valid, which mean it has
+ * already been parsed
+ * @data: The data from which the Nalu has been parsed
+ *
+ * Structure defining the Nal unit headers
+ */
+struct _GstH264NalUnit
+{
+  guint16 ref_idc;
+  guint16 type;
+
+  /* calculated values */
+  guint8 idr_pic_flag;
+  guint size;
+  guint offset;
+  guint sc_offset;
+  gboolean valid;
+
+  guint8 *data;
+};
+
+/**
+ * GstH264HRDParams:
+ * @cpb_cnt_minus1: plus 1 specifies the number of alternative
+ *    CPB specifications in the bitstream
+ * @bit_rate_scale: specifies the maximum input bit rate of the
+ * SchedSelIdx-th CPB
+ * @cpb_size_scale: specifies the CPB size of the SchedSelIdx-th CPB
+ * @guint32 bit_rate_value_minus1: specifies the maximum input bit rate for the
+ * SchedSelIdx-th CPB
+ * @cpb_size_value_minus1: is used together with cpb_size_scale to specify the
+ * SchedSelIdx-th CPB size
+ * @cbr_flag: Specifies if running in itermediate bitrate mode or constant
+ * @initial_cpb_removal_delay_length_minus1: specifies the length in bits of
+ * the cpb_removal_delay syntax element
+ * @cpb_removal_delay_length_minus1: specifies the length in bits of the
+ * dpb_output_delay syntax element
+ * @dpb_output_delay_length_minus1: >0 specifies the length in bits of the time_offset syntax element.
+ * =0 specifies that the time_offset syntax element is not present
+ * @time_offset_length: Length of the time offset
+ *
+ * Defines the HRD parameters
+ */
+struct _GstH264HRDParams
+{
+  guint8 cpb_cnt_minus1;
+  guint8 bit_rate_scale;
+  guint8 cpb_size_scale;
+
+  guint32 bit_rate_value_minus1[32];
+  guint32 cpb_size_value_minus1[32];
+  guint8 cbr_flag[32];
+
+  guint8 initial_cpb_removal_delay_length_minus1;
+  guint8 cpb_removal_delay_length_minus1;
+  guint8 dpb_output_delay_length_minus1;
+  guint8 time_offset_length;
+};
+
+/**
+ * GstH264VUIParams:
+ * @aspect_ratio_info_present_flag: %TRUE specifies that aspect_ratio_idc is present.
+ *  %FALSE specifies that aspect_ratio_idc is not present
+ * @aspect_ratio_idc specifies the value of the sample aspect ratio of the luma samples
+ * @sar_width indicates the horizontal size of the sample aspect ratio
+ * @sar_height indicates the vertical size of the sample aspect ratio
+ * @overscan_info_present_flag: %TRUE overscan_appropriate_flag is present %FALSE otherwize
+ * @overscan_appropriate_flag: %TRUE indicates that the cropped decoded pictures
+ *  output are suitable for display using overscan. %FALSE the cropped decoded pictures
+ *  output contain visually important information
+ * @video_signal_type_present_flag: %TRUE specifies that video_format, video_full_range_flag and
+ *  colour_description_present_flag are present.
+ * @video_format: indicates the representation of the picture
+ * @video_full_range_flag: indicates the black level and range of the luma and chroma signals
+ * @colour_description_present_flag: %TRUE specifies that colour_primaries,
+ *  transfer_characteristics and matrix_coefficients are present
+ * @colour_primaries: indicates the chromaticity coordinates of the source primaries
+ * @transfer_characteristics: indicates the opto-electronic transfer characteristic
+ * @matrix_coefficients: describes the matrix coefficients used in deriving luma and chroma signals
+ * @chroma_loc_info_present_flag: %TRUE specifies that chroma_sample_loc_type_top_field and
+ *  chroma_sample_loc_type_bottom_field are present, %FALSE otherwize
+ * @chroma_sample_loc_type_top_field: specify the location of chroma for top field
+ * @chroma_sample_loc_type_bottom_field specify the location of chroma for bottom field
+ * @timing_info_present_flag: %TRUE specifies that num_units_in_tick,
+ *  time_scale and fixed_frame_rate_flag are present in the bitstream
+ * @num_units_in_tick: is the number of time units of a clock operating at the frequency time_scale Hz
+ * time_scale: is the number of time units that pass in one second
+ * @fixed_frame_rate_flag: %TRUE indicates that the temporal distance between the HRD output times
+ *  of any two consecutive pictures in output order is constrained as specified in the spec, %FALSE
+ *  otherwize.
+ * @nal_hrd_parameters_present_flag: %TRUE if nal hrd parameters present in the bitstream
+ * @vcl_hrd_parameters_present_flag: %TRUE if nal vlc hrd parameters present in the bitstream
+ * @low_delay_hrd_flag: specifies the HRD operational mode
+ * @pic_struct_present_flag: %TRUE specifies that picture timing SEI messages are present or not
+ * @bitstream_restriction_flag: %TRUE specifies that the following coded video sequence bitstream restriction
+ * parameters are present
+ * @motion_vectors_over_pic_boundaries_flag: %FALSE indicates that no sample outside the
+ *  picture boundaries and no sample at a fractional sample position, %TRUE indicates that one or more
+ *  samples outside picture boundaries may be used in inter prediction
+ * @max_bytes_per_pic_denom: indicates a number of bytes not exceeded by the sum of the sizes of
+ *  the VCL NAL units associated with any coded picture in the coded video sequence.
+ * @max_bits_per_mb_denom: indicates the maximum number of coded bits of macroblock_layer()
+ * @log2_max_mv_length_horizontal: indicate the maximum absolute value of a decoded horizontal
+ * motion vector component
+ * @log2_max_mv_length_vertical: indicate the maximum absolute value of a decoded vertical
+ *  motion vector component
+ * @num_reorder_frames: indicates the maximum number of frames, complementary field pairs,
+ *  or non-paired fields that precede any frame,
+ * @max_dec_frame_buffering: specifies the required size of the HRD decoded picture buffer in
+ *  units of frame buffers.
+ *
+ * The structure representing the VUI parameters.
+ */
+struct _GstH264VUIParams
+{
+  guint8 aspect_ratio_info_present_flag;
+  guint8 aspect_ratio_idc;
+  /* if aspect_ratio_idc == 255 */
+  guint16 sar_width;
+  guint16 sar_height;
+
+  guint8 overscan_info_present_flag;
+  /* if overscan_info_present_flag */
+  guint8 overscan_appropriate_flag;
+
+  guint8 video_signal_type_present_flag;
+  guint8 video_format;
+  guint8 video_full_range_flag;
+  guint8 colour_description_present_flag;
+  guint8 colour_primaries;
+  guint8 transfer_characteristics;
+  guint8 matrix_coefficients;
+
+  guint8 chroma_loc_info_present_flag;
+  guint8 chroma_sample_loc_type_top_field;
+  guint8 chroma_sample_loc_type_bottom_field;
+
+  guint8 timing_info_present_flag;
+  /* if timing_info_present_flag */
+  guint32 num_units_in_tick;
+  guint32 time_scale;
+  guint8 fixed_frame_rate_flag;
+
+  guint8 nal_hrd_parameters_present_flag;
+  /* if nal_hrd_parameters_present_flag */
+  GstH264HRDParams nal_hrd_parameters;
+
+  guint8 vcl_hrd_parameters_present_flag;
+  /* if nal_hrd_parameters_present_flag */
+  GstH264HRDParams vcl_hrd_parameters;
+
+  guint8 low_delay_hrd_flag;
+  guint8 pic_struct_present_flag;
+
+  guint8 bitstream_restriction_flag;
+  /*  if bitstream_restriction_flag */
+  guint8 motion_vectors_over_pic_boundaries_flag;
+  guint32 max_bytes_per_pic_denom;
+  guint32 max_bits_per_mb_denom;
+  guint32 log2_max_mv_length_horizontal;
+  guint32 log2_max_mv_length_vertical;
+  guint32 num_reorder_frames;
+  guint32 max_dec_frame_buffering;
+};
+
+/**
+ * GstH264SPS:
+ * @id: The ID of the sequence parameter set
+ * @profile_idc: indicate the profile to which the coded video sequence conforms
+ *
+ *
+ */
+struct _GstH264SPS
+{
+  gint id;
+
+  guint8 profile_idc;
+  guint8 constraint_set0_flag;
+  guint8 constraint_set1_flag;
+  guint8 constraint_set2_flag;
+  guint8 constraint_set3_flag;
+  guint8 level_idc;
+
+  guint8 chroma_format_idc;
+  guint8 separate_colour_plane_flag;
+  guint8 bit_depth_luma_minus8;
+  guint8 bit_depth_chroma_minus8;
+  guint8 qpprime_y_zero_transform_bypass_flag;
+
+  guint8 scaling_matrix_present_flag;
+  guint8 scaling_lists_4x4[6][16];
+  guint8 scaling_lists_8x8[6][64];
+
+  guint8 log2_max_frame_num_minus4;
+  guint8 pic_order_cnt_type;
+
+  /* if pic_order_cnt_type == 0 */
+  guint8 log2_max_pic_order_cnt_lsb_minus4;
+
+  /* else if pic_order_cnt_type == 1 */
+  guint8 delta_pic_order_always_zero_flag;
+  gint32 offset_for_non_ref_pic;
+  gint32 offset_for_top_to_bottom_field;
+  guint8 num_ref_frames_in_pic_order_cnt_cycle;
+  gint32 offset_for_ref_frame[255];
+
+  guint32 num_ref_frames;
+  guint8 gaps_in_frame_num_value_allowed_flag;
+  guint32 pic_width_in_mbs_minus1;
+  guint32 pic_height_in_map_units_minus1;
+  guint8 frame_mbs_only_flag;
+
+  guint8 mb_adaptive_frame_field_flag;
+
+  guint8 direct_8x8_inference_flag;
+
+  guint8 frame_cropping_flag;
+
+  /* if frame_cropping_flag */
+  guint32 frame_crop_left_offset;
+  guint32 frame_crop_right_offset;
+  guint32 frame_crop_top_offset;
+  guint32 frame_crop_bottom_offset;
+
+  guint8 vui_parameters_present_flag;
+  /* if vui_parameters_present_flag */
+ GstH264VUIParams vui_parameters;
+
+  /* calculated values */
+  guint8 chroma_array_type;
+  guint32 max_frame_num;
+  gint width, height;
+  gint fps_num, fps_den;
+  gboolean valid;
+};
+
+struct _GstH264PPS
+{
+  gint id;
+
+  GstH264SPS *sequence;
+
+  guint8 entropy_coding_mode_flag;
+  guint8 pic_order_present_flag;
+
+  guint32 num_slice_groups_minus1;
+
+  /* if num_slice_groups_minus1 > 0 */
+  guint8 slice_group_map_type;
+  /* and if slice_group_map_type == 0 */
+  guint32 run_length_minus1[8];
+  /* or if slice_group_map_type == 2 */
+  guint32 top_left[8];
+  guint32 bottom_right[8];
+  /* or if slice_group_map_type == (3, 4, 5) */
+  guint8 slice_group_change_direction_flag;
+  guint32 slice_group_change_rate_minus1;
+  /* or if slice_group_map_type == 6 */
+  guint32 pic_size_in_map_units_minus1;
+  guint8 *slice_group_id;
+
+  guint8 num_ref_idx_l0_active_minus1;
+  guint8 num_ref_idx_l1_active_minus1;
+  guint8 weighted_pred_flag;
+  guint8 weighted_bipred_idc;
+  gint8 pic_init_qp_minus26;
+  gint8 pic_init_qs_minus26;
+  gint8 chroma_qp_index_offset;
+  guint8 deblocking_filter_control_present_flag;
+  guint8 constrained_intra_pred_flag;
+  guint8 redundant_pic_cnt_present_flag;
+
+  guint8 transform_8x8_mode_flag;
+
+  guint8 scaling_lists_4x4[6][16];
+  guint8 scaling_lists_8x8[6][64];
+
+  guint8 second_chroma_qp_index_offset;
+
+  gboolean valid;
+};
+
+struct _GstH264PredWeightTable
+{
+  guint8 luma_log2_weight_denom;
+  guint8 chroma_log2_weight_denom;
+
+  guint8 luma_weight_l0[32];
+  guint8 luma_offset_l0[32];
+
+  /* if seq->ChromaArrayType != 0 */
+  guint8 chroma_weight_l0[32][2];
+  guint8 chroma_offset_l0[32][2];
+
+  /* if slice->slice_type % 5 == 1 */
+  guint8 luma_weight_l1[32];
+  guint8 luma_offset_l1[32];
+  /* and if seq->ChromaArrayType != 0 */
+  guint8 chroma_weight_l1[32][2];
+  guint8 chroma_offset_l1[32][2];
+};
+
+struct _GstH264RefPicMarking
+{
+  guint8 memory_management_control_operation;
+
+  guint32 difference_of_pic_nums_minus1;
+  guint32 long_term_pic_num;
+  guint32 long_term_frame_idx;
+  guint32 max_long_term_frame_idx_plus1;
+};
+
+struct _GstH264DecRefPicMarking
+{
+  /* if slice->nal_unit.IdrPicFlag */
+  guint8 no_output_of_prior_pics_flag;
+  guint8 long_term_reference_flag;
+
+  guint8 adaptive_ref_pic_marking_mode_flag;
+  GstH264RefPicMarking ref_pic_marking[10];
+  guint8 n_ref_pic_marking;
+};
+
+
+struct _GstH264SliceHdr
+{
+  guint32 first_mb_in_slice;
+  guint32 type;
+  GstH264PPS *pps;
+
+  /* if seq->separate_colour_plane_flag */
+  guint8 colour_plane_id;
+
+  guint16 frame_num;
+
+  guint8 field_pic_flag;
+  guint8 bottom_field_flag;
+
+  /* if nal_unit.type == 5 */
+  guint16 idr_pic_id;
+
+  /* if seq->pic_order_cnt_type == 0 */
+  guint16 pic_order_cnt_lsb;
+  /* if seq->pic_order_present_flag && !field_pic_flag */
+  gint32 delta_pic_order_cnt_bottom;
+
+  gint32 delta_pic_order_cnt[2];
+  guint8 redundant_pic_cnt;
+
+  /* if slice_type == B_SLICE */
+  guint8 direct_spatial_mv_pred_flag;
+
+  guint8 num_ref_idx_l0_active_minus1;
+  guint8 num_ref_idx_l1_active_minus1;
+
+  GstH264PredWeightTable pred_weight_table;
+  /* if nal_unit.ref_idc != 0 */
+  GstH264DecRefPicMarking dec_ref_pic_marking;
+
+  /* calculated values */
+  guint32 max_pic_num;
+  gboolean valid;
+};
+
+
+struct _GstH264ClockTimestamp
+{
+  guint8 ct_type;
+  guint8 nuit_field_based_flag;
+  guint8 counting_type;
+  guint8 discontinuity_flag;
+  guint8 cnt_dropped_flag;
+  guint8 n_frames;
+
+  guint8 seconds_flag;
+  guint8 seconds_value;
+
+  guint8 minutes_flag;
+  guint8 minutes_value;
+
+  guint8 hours_flag;
+  guint8 hours_value;
+
+  guint32 time_offset;
+};
+
+struct _GstH264PicTiming
+{
+  guint32 cpb_removal_delay;
+  guint32 dpb_output_delay;
+
+  guint8 pic_struct_present_flag;
+  /* if pic_struct_present_flag */
+  guint8 pic_struct;
+
+  guint8 clock_timestamp_flag[3];
+  GstH264ClockTimestamp clock_timestamp[3];
+};
+
+struct _GstH264BufferingPeriod
+{
+  GstH264SPS *sps;
+
+  /* seq->vui_parameters->nal_hrd_parameters_present_flag */
+  guint8 nal_initial_cpb_removal_delay[32];
+  guint8 nal_initial_cpb_removal_delay_offset[32];
+
+  /* seq->vui_parameters->vcl_hrd_parameters_present_flag */
+  guint8 vcl_initial_cpb_removal_delay[32];
+  guint8 vcl_initial_cpb_removal_delay_offset[32];
+};
+
+struct _GstH264SEIMessage
+{
+  GstH264SEIPayloadType payloadType;
+
+  union {
+    GstH264BufferingPeriod buffering_period;
+    GstH264PicTiming pic_timing;
+    /* ... could implement more */
+  };
+};
+
+/* Opaque structure */
+struct _GstH264NalParser
+{
+  GstH264SPS sps[GST_H264_MAX_SPS_COUNT];
+  GstH264PPS pps[GST_H264_MAX_PPS_COUNT];
+  GstH264SPS *last_sps;
+  GstH264PPS *last_pps;
+};
+
+GstH264NalParser *gst_h264_nal_parser_new             (void);
+
+GstH264ParserResult gst_h264_parser_identify_nalu     (GstH264NalParser *nalparser,
+                                                       const guint8 *data, guint offset,
+                                                       gsize size, GstH264NalUnit *nalu);
+
+GstH264ParserResult gst_h264_parser_identify_nalu_avc (GstH264NalParser *nalparser, const guint8 *data,
+                                                       guint offset, gsize size, guint8 nal_length_size,
+                                                       GstH264NalUnit *nalu);
+
+GstH264ParserResult gst_h264_parser_parse_nal         (GstH264NalParser *nalparser,
+                                                       GstH264NalUnit *nalu);
+
+GstH264ParserResult gst_h264_parser_parse_slice_hdr   (GstH264NalParser *nalparser, GstH264NalUnit *nalu,
+                                                       GstH264SliceHdr *slice, gboolean parse_pred_weight_table,
+                                                       gboolean parse_dec_ref_pic_marking);
+
+GstH264ParserResult gst_h264_parser_parse_sps         (GstH264NalParser *nalparser, GstH264NalUnit *nalu,
+                                                       GstH264SPS *sps, gboolean parse_vui_params);
+
+GstH264ParserResult gst_h264_parser_parse_pps         (GstH264NalParser *nalparser,
+                                                       GstH264NalUnit *nalu, GstH264PPS *pps);
+
+GstH264ParserResult gst_h264_parser_parse_sei         (GstH264NalParser *nalparser,
+                                                       GstH264NalUnit *nalu, GstH264SEIMessage *sei);
+
+void gst_h264_nal_parser_free                         (GstH264NalParser *nalparser);
+
+GstH264ParserResult gst_h264_parse_sps                (GstH264NalUnit *nalu,
+                                                       GstH264SPS *sps, gboolean parse_vui_params);
+
+GstH264ParserResult gst_h264_parse_pps                (GstH264NalParser *nalparser,
+                                                       GstH264NalUnit *nalu, GstH264PPS *pps);
+
+G_END_DECLS
+#endif
index 8528eb2..47bd813 100644 (file)
@@ -184,6 +184,7 @@ check_PROGRAMS = \
        $(check_mimic) \
        elements/rtpmux \
        libs/mpegvideoparser \
+       libs/h264parser \
        $(check_schro) \
        $(check_vp8) \
         elements/viewfinderbin \
@@ -224,6 +225,15 @@ libs_mpegvideoparser_LDADD = \
        $(GST_PLUGINS_BAD_LIBS) -lgstcodecparsers-@GST_MAJORMINOR@ \
        $(GST_BASE_LIBS) $(GST_LIBS) $(LDADD)
 
+libs_h264parser_CFLAGS = \
+       $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
+       $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS)
+
+libs_h264parser_LDADD = \
+       $(top_builddir)/gst-libs/gst/codecparsers/libgstcodecparsers-@GST_MAJORMINOR@.la \
+       $(GST_PLUGINS_BAD_LIBS) -lgstcodecparsers-@GST_MAJORMINOR@ \
+       $(GST_BASE_LIBS) $(GST_LIBS) $(LDADD)
+
 elements_voaacenc_CFLAGS = \
        $(GST_PLUGINS_BASE_CFLAGS) \
        $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS)
diff --git a/tests/check/libs/h264parser.c b/tests/check/libs/h264parser.c
new file mode 100644 (file)
index 0000000..3bc8c49
--- /dev/null
@@ -0,0 +1,182 @@
+/* Gstreamer
+ * Copyright (C) <2011> Intel Corporation
+ * Copyright (C) <2011> Collabora Ltd.
+ * Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <gst/check/gstcheck.h>
+#include <gst/codecparsers/gsth264parser.h>
+
+static guint8 slice_dpa[] = {
+  0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x03, 0x00,
+  0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0a, 0x00,
+  0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00,
+  0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00,
+  0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x1c, 0x00,
+  0x1d, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00,
+  0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x00,
+  0x29, 0x00, 0x2a, 0x00, 0x2b, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x2e, 0x00,
+  0x2f, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00,
+  0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00,
+  0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x40, 0x00,
+  0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00,
+  0x47, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00,
+  0x4d, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x51, 0x00, 0x52, 0x00,
+  0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, 0x58, 0x00,
+  0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x5c, 0x00, 0x5d, 0x00, 0x5e, 0x00,
+  0x5f, 0x00, 0x60, 0x00, 0x61, 0x01, 0x04, 0x00, 0xc4, 0x00, 0xa6, 0x00,
+  0xc5, 0x00, 0xab, 0x00, 0x82, 0x00, 0xc2, 0x00, 0xd8, 0x00, 0xc6, 0x00,
+  0xe4, 0x00, 0xbe, 0x00, 0xb0, 0x00, 0xe6, 0x00, 0xb6, 0x00, 0xb7, 0x00,
+  0xb4, 0x00, 0xb5, 0x00, 0x87, 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xd9, 0x00,
+  0x8c, 0x00, 0xe5, 0x00, 0xbf, 0x00, 0xb1, 0x00, 0xe7, 0x00, 0xbb, 0x00,
+  0xa3, 0x00, 0x84, 0x00, 0x85, 0x00, 0xbd, 0x00, 0x96, 0x00, 0xe8, 0x00,
+  0x86, 0x00, 0x8e, 0x00, 0x8b, 0x00, 0x9d, 0x00, 0xa9, 0x00, 0x8a, 0x01,
+  0x05, 0x00, 0x83, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0x8d, 0x00, 0x97, 0x00,
+  0x88, 0x00, 0xde, 0x00, 0xf1, 0x00, 0x9e, 0x00, 0xaa, 0x00, 0xf5, 0x00,
+  0xf4, 0x00, 0xf6, 0x00, 0xa2, 0x00, 0xad, 0x00, 0xc9, 0x00, 0xc7, 0x00,
+  0xae, 0x00, 0x62, 0x00, 0x63, 0x00, 0x90, 0x00, 0x64, 0x00, 0xcb, 0x00,
+  0x65, 0x00, 0xc8, 0x00, 0xca, 0x00, 0xcf, 0x00, 0xcc, 0x00, 0xcd, 0x00,
+  0xce, 0x00, 0xe9, 0x00, 0x66, 0x00, 0xd3, 0x00, 0xd0, 0x00, 0xd1, 0x00,
+  0xaf, 0x00, 0x67, 0x00, 0x91, 0x00, 0xd6, 0x00, 0xd4, 0x00, 0xd5, 0x00,
+  0x68, 0x00, 0xeb, 0x00, 0xed, 0x00, 0x89, 0x00, 0x6a, 0x00, 0x69, 0x00,
+  0x6b, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0x6e, 0x00, 0xa0, 0x00, 0x6f, 0x00,
+  0x71, 0x00, 0x70, 0x00, 0x72, 0x00, 0x73, 0x00, 0x75, 0x00, 0x74, 0x00,
+  0x76, 0x00, 0x77, 0x00, 0xea, 0x00, 0x78, 0x00, 0x7a, 0x00, 0x79, 0x00,
+  0x7b, 0x00, 0x7d, 0x00, 0x7c, 0x00, 0xa1, 0x00, 0x7f, 0x00, 0x7e, 0x00,
+  0x80, 0x00, 0x81, 0x00, 0xec, 0x00, 0xee, 0x00, 0xba, 0x01, 0x06, 0x00,
+  0xef, 0x00, 0xe1, 0x00, 0xe0, 0x00, 0xdc, 0x01, 0x07, 0x01, 0x08, 0x01,
+  0x09, 0x01, 0x0a, 0x01, 0x0b, 0x01, 0x0c, 0x00, 0xdb, 0x00, 0xe2, 0x01,
+  0x0d, 0x01, 0x0e, 0x01, 0x0f, 0x01, 0x10, 0x01, 0x11, 0x01, 0x12, 0x00,
+  0xdf, 0x01, 0x13, 0x01, 0x14, 0x01, 0x15, 0x01, 0x16, 0x01, 0x17, 0x00,
+  0xfd, 0x00, 0xff, 0x01, 0x18, 0x01, 0x19, 0x01, 0x1a, 0x01, 0x1b, 0x01,
+  0x1c, 0x01, 0x1d, 0x01, 0x1e, 0x01, 0x1f, 0x01, 0x20, 0x01, 0x21, 0x01,
+  0x22, 0x01, 0x23, 0x01, 0x24, 0x01, 0x25, 0x01, 0x26, 0x00, 0xfe, 0x01,
+  0x00, 0x01, 0x27, 0x01, 0x28, 0x01, 0x29, 0x01, 0x2a, 0x01, 0x2b, 0x01,
+  0x2c, 0x01, 0x2d, 0x01, 0x2e, 0x01, 0x2f, 0x01, 0x30, 0x01, 0x31, 0x00,
+  0xe3, 0x00, 0xd7, 0x01, 0x32, 0x00, 0xf8, 0x00, 0xf9, 0x01, 0x33, 0x01,
+  0x34, 0x01, 0x35, 0x01, 0x36, 0x01, 0x37, 0x01, 0x38, 0x01, 0x39, 0x01,
+  0x3a, 0x01, 0x3b, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0x3e, 0x01, 0x3f, 0x01,
+  0x40, 0x01, 0x41, 0x01, 0x42, 0x01, 0x43, 0x01, 0x44, 0x01, 0x45, 0x01,
+  0x46, 0x01, 0x47, 0x01, 0x48, 0x01, 0x49, 0x01, 0x4a, 0x01, 0x4b, 0x01,
+  0x4c, 0x00, 0x08, 0x05, 0x2e, 0x6e, 0x75, 0x6c, 0x6c, 0x0c, 0x76, 0x69,
+  0x73, 0x69, 0x62, 0x6c, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x04, 0x45,
+  0x75, 0x72, 0x6f, 0x06, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x0a, 0x62,
+  0x75, 0x6c, 0x6c, 0x65, 0x74, 0x6d, 0x61, 0x74, 0x68, 0x06, 0x53, 0x61,
+  0x63, 0x75, 0x74, 0x65, 0x06, 0x54, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06,
+  0x5a, 0x61, 0x63, 0x75, 0x74, 0x65, 0x06, 0x73, 0x61, 0x63, 0x75, 0x74,
+  0x65, 0x06, 0x74, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x7a, 0x61, 0x63,
+  0x75, 0x74, 0x65, 0x07, 0x41, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x07,
+  0x61, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x0c, 0x73, 0x63, 0x6f, 0x6d,
+  0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x53, 0x63, 0x6f,
+  0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0a, 0x5a, 0x64,
+  0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x06, 0x4c, 0x63, 0x61,
+  0x72, 0x6f, 0x6e, 0x06, 0x6c, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x0a, 0x7a,
+  0x64, 0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x06, 0x52, 0x61,
+  0x63, 0x75, 0x74, 0x65, 0x06, 0x41, 0x62, 0x72, 0x65, 0x76, 0x65, 0x06,
+  0x4c, 0x61, 0x63, 0x75, 0x74, 0x65, 0x07, 0x45, 0x6f, 0x67, 0x6f, 0x6e,
+  0x65, 0x6b, 0x06, 0x45, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x44, 0x63,
+  0x61, 0x72, 0x6f, 0x6e, 0x07, 0x44, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e,
+  0x06, 0x4e, 0x61, 0x63, 0x75, 0x74, 0x65, 0x06, 0x4e, 0x63, 0x61, 0x72,
+  0x6f, 0x6e, 0x0d, 0x4f, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75, 0x6d,
+  0x6c, 0x61, 0x75, 0x74, 0x06, 0x52, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x05,
+  0x55, 0x72, 0x69, 0x6e, 0x67, 0x09, 0x6e, 0x75, 0x6e, 0x67, 0x61, 0x64,
+  0x65, 0x73, 0x68, 0x0d, 0x55, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75,
+  0x6d, 0x6c, 0x61, 0x75, 0x74, 0x0c, 0x54, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+  0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x06, 0x72, 0x61, 0x63, 0x75, 0x74,
+  0x65, 0x06, 0x61, 0x62, 0x72, 0x65, 0x76, 0x65, 0x06, 0x6c, 0x61, 0x63,
+  0x75, 0x74, 0x65, 0x07, 0x65, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x06,
+  0x65, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x64, 0x63, 0x61, 0x72, 0x6f,
+  0x6e, 0x07, 0x64, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x06, 0x6e, 0x61,
+  0x63, 0x75, 0x74, 0x65, 0x06, 0x6e, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x0d,
+  0x6f, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75, 0x6d, 0x6c, 0x61, 0x75,
+  0x74, 0x06, 0x72, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x05, 0x75, 0x72, 0x69,
+  0x6e, 0x67, 0x0d, 0x75, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75, 0x6d,
+  0x6c, 0x61, 0x75, 0x74, 0x0c, 0x74, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61,
+  0x63, 0x63, 0x65, 0x6e, 0x74, 0x0a, 0x49, 0x64, 0x6f, 0x74, 0x61, 0x63,
+  0x63, 0x65, 0x6e, 0x74, 0x0c, 0x52, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61,
+  0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+  0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x07, 0x49, 0x6f, 0x67, 0x6f, 0x6e,
+  0x65, 0x6b, 0x07, 0x41, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x07, 0x45,
+  0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x0a, 0x45, 0x64, 0x6f, 0x74, 0x61,
+  0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x47, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+  0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x4b, 0x63, 0x6f, 0x6d, 0x6d,
+  0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x07, 0x49, 0x6d, 0x61, 0x63,
+  0x72, 0x6f, 0x6e, 0x0c, 0x4c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63,
+  0x63, 0x65, 0x6e, 0x74, 0x0c, 0x4e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61,
+  0x63, 0x63, 0x65, 0x6e, 0x74, 0x07, 0x4f, 0x6d, 0x61, 0x63, 0x72, 0x6f,
+  0x6e, 0x07, 0x55, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x07, 0x55, 0x6d,
+  0x61, 0x63, 0x72, 0x6f, 0x6e, 0x07, 0x69, 0x6f, 0x67, 0x6f, 0x6e, 0x65,
+  0x6b, 0x07, 0x61, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x07, 0x65, 0x6d,
+  0x61, 0x63, 0x72, 0x6f, 0x6e, 0x0a, 0x65, 0x64, 0x6f, 0x74, 0x61, 0x63,
+  0x63, 0x65, 0x6e, 0x74, 0x0c, 0x67, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61,
+  0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x6b, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+  0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x07, 0x69, 0x6d, 0x61, 0x63, 0x72,
+  0x6f, 0x6e, 0x0c, 0x6c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63,
+  0x65, 0x6e, 0x74, 0x0c, 0x6e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63,
+  0x63, 0x65, 0x6e, 0x74, 0x07, 0x6f, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e,
+  0x07, 0x75, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x07, 0x75, 0x6d, 0x61,
+  0x63, 0x72, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02
+};
+
+GST_START_TEST (test_h264_parse_slice_dpa)
+{
+  GstH264ParserResult res;
+  GstH264NalUnit nalu;
+
+  GstH264NalParser *parser = gst_h264_nal_parser_new ();
+
+  res = gst_h264_parser_identify_nalu (parser, slice_dpa, 0,
+      sizeof (slice_dpa), &nalu);
+
+  assert_equals_int (res, GST_H264_PARSER_OK);
+  assert_equals_int (nalu.type, GST_H264_NAL_SLICE_DPA);
+
+  g_free (parser);
+}
+
+GST_END_TEST;
+
+static Suite *
+h264parser_suite (void)
+{
+  Suite *s = suite_create ("H264 Parser library");
+
+  TCase *tc_chain = tcase_create ("general");
+
+  suite_add_tcase (s, tc_chain);
+  tcase_add_test (tc_chain, test_h264_parse_slice_dpa);
+
+  return s;
+}
+
+int
+main (int argc, char **argv)
+{
+  int nf;
+
+  Suite *s = h264parser_suite ();
+
+  SRunner *sr = srunner_create (s);
+
+  gst_check_init (&argc, &argv);
+
+  srunner_run_all (sr, CK_NORMAL);
+  nf = srunner_ntests_failed (sr);
+  srunner_free (sr);
+
+  return nf;
+}