codecs: gstvp9{decoder|statefulparser}: optionally parse compressed headers
authorDaniel Almeida <daniel.almeida@collabora.com>
Thu, 8 Apr 2021 13:38:55 +0000 (10:38 -0300)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Mon, 29 Nov 2021 17:41:19 +0000 (17:41 +0000)
Rework gstvp9{decoder|statefulparser} to optionally parse compressed headers.
The information in these headers might be needed for accelerators
downstream, so optionally parse them if downstream requests it.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1012>

subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp9decoder.c
subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp9decoder.h
subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp9statefulparser.c
subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp9statefulparser.h

index f6f36d9..a0e9ecb 100644 (file)
@@ -339,8 +339,9 @@ gst_vp9_decoder_handle_frame (GstVideoDecoder * decoder,
     goto error;
   }
 
-  pres = gst_vp9_stateful_parser_parse_frame_header (priv->parser, &frame_hdr,
-      map.data, map.size);
+  pres =
+      gst_vp9_stateful_parser_parse_uncompressed_frame_header (priv->parser,
+      &frame_hdr, map.data, map.size);
 
   if (pres != GST_VP9_PARSER_OK) {
     GST_ERROR_OBJECT (self, "Failed to parsing frame header");
@@ -348,6 +349,18 @@ gst_vp9_decoder_handle_frame (GstVideoDecoder * decoder,
     goto unmap_and_error;
   }
 
+  if (self->parse_compressed_headers && !frame_hdr.show_existing_frame) {
+    pres =
+        gst_vp9_stateful_parser_parse_compressed_frame_header (priv->parser,
+        &frame_hdr, map.data + frame_hdr.frame_header_length_in_bytes,
+        map.size);
+
+    if (pres != GST_VP9_PARSER_OK) {
+      GST_ERROR_OBJECT (self, "Failed to parse the compressed frame header");
+      goto unmap_and_error;
+    }
+  }
+
   if (frame_hdr.show_existing_frame) {
     /* This is a non-intra, dummy frame */
     intra_only = FALSE;
index 76983f5..2a17507 100644 (file)
@@ -51,6 +51,7 @@ struct _GstVp9Decoder
 
   /*< protected >*/
   GstVideoCodecState * input_state;
+  gboolean parse_compressed_headers;
 
   /*< private >*/
   GstVp9DecoderPrivate *priv;
index 6289c3f..950d3e2 100644 (file)
@@ -149,6 +149,550 @@ ensure_debug_category (void)
 #define CHECK_ALLOWED(val, min, max) \
   CHECK_ALLOWED_WITH_DEBUG (G_STRINGIFY (val), val, min, max)
 
+typedef struct _Vp9BoolDecoder
+{
+  guint64 value;
+  guint32 range;
+  guint32 bits_left;
+  gint count_to_fill;
+  GstBitReader *bit_reader;
+  gboolean out_of_bits;
+} Vp9BoolDecoder;
+
+/* how much to shift to get range > 128 */
+const static guint8 bool_shift_table[256] = {
+  0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
+  3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const guint8 inv_map_table[255] = {
+  7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176,
+  189, 202, 215, 228, 241, 254, 1, 2, 3, 4, 5, 6, 8, 9,
+  10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24,
+  25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 39,
+  40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54,
+  55, 56, 57, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+  70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+  86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 99, 100,
+  101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115,
+  116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130,
+  131, 132, 133, 134, 135, 136, 138, 139, 140, 141, 142, 143, 144, 145,
+  146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
+  161, 162, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+  177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 190, 191,
+  192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205, 206,
+  207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221,
+  222, 223, 224, 225, 226, 227, 229, 230, 231, 232, 233, 234, 235, 236,
+  237, 238, 239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+  252, 253, 253,
+};
+
+static void
+fill_bool (Vp9BoolDecoder * bd)
+{
+  guint max_bits_to_read;
+  guint bits_to_read;
+  guint64 data;
+
+  if (G_UNLIKELY (bd->bits_left < bd->count_to_fill)) {
+    GST_ERROR
+        ("Invalid VP9 bitstream: the boolean decoder ran out of bits to read");
+    bd->out_of_bits = TRUE;
+    return;
+  }
+
+  max_bits_to_read =
+      8 * (sizeof (bd->value) - sizeof (guint8)) + bd->count_to_fill;
+  bits_to_read = MIN (max_bits_to_read, bd->bits_left);
+
+  data =
+      gst_bit_reader_get_bits_uint64_unchecked (bd->bit_reader, bits_to_read);
+
+  bd->value |= data << (max_bits_to_read - bits_to_read);
+  bd->count_to_fill -= bits_to_read;
+  bd->bits_left -= bits_to_read;
+}
+
+static gboolean
+read_bool (Vp9BoolDecoder * bd, guint8 probability)
+{
+  guint64 split;
+  guint64 big_split;
+  guint count;
+  gboolean bit;
+
+  if (bd->count_to_fill > 0)
+    fill_bool (bd);
+
+  split = 1 + (((bd->range - 1) * probability) >> 8);
+  big_split = split << 8 * (sizeof (bd->value) - sizeof (guint8));
+
+  if (bd->value < big_split) {
+    bd->range = split;
+    bit = FALSE;
+  } else {
+    bd->range -= split;
+    bd->value -= big_split;
+    bit = TRUE;
+  }
+
+  count = bool_shift_table[bd->range];
+  bd->range <<= count;
+  bd->value <<= count;
+  bd->count_to_fill += count;
+
+  return bit;
+}
+
+static guint
+read_literal (Vp9BoolDecoder * bd, guint n)
+{
+  guint ret = 0;
+  guint i;
+
+  for (i = 0; G_UNLIKELY (!bd->out_of_bits) && i < n; i++) {
+    ret = 2 * ret + read_bool (bd, 128);
+  }
+
+  return ret;
+}
+
+static GstVp9ParserResult
+init_bool (Vp9BoolDecoder * bd, GstBitReader * br, guint size_in_bytes)
+{
+  gboolean marker_bit;
+
+  if (size_in_bytes < 1)
+    GST_ERROR ("VP9 Boolean Decoder has no bits to read");
+
+  if ((gst_bit_reader_get_pos (br) % 8) != 0)
+    GST_ERROR ("VP9 Boolean Decoder was passed an unaligned buffer");
+
+  bd->value = 0;
+  bd->range = 255;
+  bd->bits_left = 8 * size_in_bytes;
+  bd->bit_reader = br;
+  bd->count_to_fill = 8;
+  bd->out_of_bits = FALSE;
+
+  marker_bit = read_literal (bd, 1);
+  if (marker_bit != 0) {
+    GST_ERROR ("Marker bit should be zero was %d", marker_bit);
+    return GST_VP9_PARSER_BROKEN_DATA;
+  }
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+exit_bool (Vp9BoolDecoder * bd)
+{
+  guint8 padding;
+  guint8 bits = bd->bits_left;
+  guint8 n;
+
+  while (bits) {
+    n = MIN (bits, 8);
+    padding = gst_bit_reader_get_bits_uint32_unchecked (bd->bit_reader, n);
+    if (padding != 0 || (n < 8 && (padding & 0xe0) == 0xc0)) {
+      GST_ERROR
+          ("Invalid padding at end of frame. Total padding bits is %d and the wrong byte is: %x",
+          bd->bits_left, padding);
+      return GST_VP9_PARSER_BROKEN_DATA;
+    }
+    bits -= n;
+  }
+
+  return GST_VP9_PARSER_OK;
+}
+
+static guint
+decode_term_subexp (Vp9BoolDecoder * bd)
+{
+  guint8 bit;
+  guint v;
+  /* only coded if update_prob is set */
+  gboolean prob_is_coded_in_bitstream;
+  guint delta;
+
+  prob_is_coded_in_bitstream = read_bool (bd, 252);
+  if (!prob_is_coded_in_bitstream)
+    return 0;
+
+  bit = read_literal (bd, 1);
+  if (bit == 0) {
+    delta = read_literal (bd, 4);
+    goto end;
+  }
+
+  bit = read_literal (bd, 1);
+  if (bit == 0) {
+    delta = read_literal (bd, 4) + 16;
+    goto end;
+  }
+
+  bit = read_literal (bd, 1);
+  if (bit == 0) {
+    delta = read_literal (bd, 5) + 32;
+    goto end;
+  }
+
+  v = read_literal (bd, 7);
+  if (v < 65) {
+    delta = v + 64;
+    goto end;
+  }
+
+  bit = read_literal (bd, 1);
+  delta = (v << 1) - 1 + bit;
+end:
+  return inv_map_table[delta];
+}
+
+static guint8
+read_mv_prob (Vp9BoolDecoder * bd)
+{
+  gboolean update_mv_prob;
+  guint8 mv_prob;
+  guint8 prob = 0;
+
+  update_mv_prob = read_bool (bd, 252);
+  if (update_mv_prob) {
+    mv_prob = read_literal (bd, 7);
+    prob = (mv_prob << 1) | 1;
+  }
+
+  return prob;
+}
+
+static GstVp9ParserResult
+parse_mv_probs (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  guint i, j, k;
+
+  for (j = 0; j < GST_VP9_MV_JOINTS - 1; j++)
+    hdr->delta_probabilities.mv.joint[j] = read_mv_prob (bd);
+
+  for (i = 0; i < 2; i++) {
+    hdr->delta_probabilities.mv.sign[i] = read_mv_prob (bd);
+
+    for (j = 0; j < GST_VP9_MV_CLASSES - 1; j++)
+      hdr->delta_probabilities.mv.klass[i][j] = read_mv_prob (bd);
+
+    hdr->delta_probabilities.mv.class0_bit[i] = read_mv_prob (bd);
+
+    for (j = 0; j < GST_VP9_MV_OFFSET_BITS; j++)
+      hdr->delta_probabilities.mv.bits[i][j] = read_mv_prob (bd);
+  }
+
+  for (i = 0; i < 2; i++) {
+    for (j = 0; j < GST_VP9_CLASS0_SIZE; j++)
+      for (k = 0; k < GST_VP9_MV_FR_SIZE - 1; k++)
+        hdr->delta_probabilities.mv.class0_fr[i][j][k] = read_mv_prob (bd);
+
+    for (k = 0; k < GST_VP9_MV_FR_SIZE - 1; k++)
+      hdr->delta_probabilities.mv.fr[i][k] = read_mv_prob (bd);
+  }
+
+  if (hdr->allow_high_precision_mv) {
+    for (i = 0; i < 2; i++) {
+      hdr->delta_probabilities.mv.class0_hp[i] = read_mv_prob (bd);
+      hdr->delta_probabilities.mv.hp[i] = read_mv_prob (bd);
+    }
+
+  }
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_partition_probs (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  guint i, j;
+
+  for (i = 0; i < GST_VP9_PARTITION_CONTEXTS; i++)
+    for (j = 0; j < GST_VP9_PARTITION_TYPES - 1; j++)
+      hdr->delta_probabilities.partition[i][j] = decode_term_subexp (bd);
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_y_mode_probs (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  guint i, j;
+
+  for (i = 0; i < GST_VP9_BLOCK_SIZE_GROUPS; i++)
+    for (j = 0; j < GST_VP9_INTRA_MODES - 1; j++)
+      hdr->delta_probabilities.y_mode[i][j] = decode_term_subexp (bd);
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_frame_reference_mode_probs (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  guint i;
+
+  if (hdr->reference_mode == GST_VP9_REFERENCE_MODE_SELECT)
+    for (i = 0; i < GST_VP9_COMP_MODE_CONTEXTS; i++)
+      hdr->delta_probabilities.comp_mode[i] = decode_term_subexp (bd);
+
+  if (hdr->reference_mode != GST_VP9_REFERENCE_MODE_COMPOUND_REFERENCE)
+    for (i = 0; i < GST_VP9_REF_CONTEXTS; i++) {
+      hdr->delta_probabilities.single_ref[i][0] = decode_term_subexp (bd);
+      hdr->delta_probabilities.single_ref[i][1] = decode_term_subexp (bd);
+    }
+
+  if (hdr->reference_mode != GST_VP9_REFERENCE_MODE_SINGLE_REFERENCE)
+    for (i = 0; i < GST_VP9_REF_CONTEXTS; i++)
+      hdr->delta_probabilities.comp_ref[i] = decode_term_subexp (bd);
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_frame_reference (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  gboolean compound_ref_allowed = FALSE;
+  guint8 non_single_reference;
+  guint8 reference_select;
+  guint i;
+
+  for (i = GST_VP9_REF_FRAME_LAST; i < GST_VP9_REFS_PER_FRAME; i++)
+    if (hdr->ref_frame_sign_bias[i + 1] !=
+        hdr->ref_frame_sign_bias[GST_VP9_REF_FRAME_LAST])
+      compound_ref_allowed = TRUE;
+
+  if (compound_ref_allowed) {
+    non_single_reference = read_literal (bd, 1);
+    if (!non_single_reference)
+      hdr->reference_mode = GST_VP9_REFERENCE_MODE_SINGLE_REFERENCE;
+    else {
+      reference_select = read_literal (bd, 1);
+      if (!reference_select)
+        hdr->reference_mode = GST_VP9_REFERENCE_MODE_COMPOUND_REFERENCE;
+      else
+        hdr->reference_mode = GST_VP9_REFERENCE_MODE_SELECT;
+    }
+  } else
+    hdr->reference_mode = GST_VP9_REFERENCE_MODE_SINGLE_REFERENCE;
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_is_inter_probs (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  guint i;
+
+  for (i = 0; i < GST_VP9_IS_INTER_CONTEXTS; i++)
+    hdr->delta_probabilities.is_inter[i] = decode_term_subexp (bd);
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_interp_filter_probs (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  guint i, j;
+
+  for (i = 0; i < GST_VP9_INTERP_FILTER_CONTEXTS; i++)
+    for (j = 0; j < GST_VP9_SWITCHABLE_FILTERS - 1; j++)
+      hdr->delta_probabilities.interp_filter[i][j] = decode_term_subexp (bd);
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_inter_mode_probs (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  guint i, j;
+
+  for (i = 0; i < GST_VP9_INTER_MODE_CONTEXTS; i++)
+    for (j = 0; j < GST_VP9_INTER_MODES - 1; j++)
+      hdr->delta_probabilities.inter_mode[i][j] = decode_term_subexp (bd);
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_skip_probs (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  guint i;
+
+  for (i = 0; i < GST_VP9_SKIP_CONTEXTS; i++)
+    hdr->delta_probabilities.skip[i] = decode_term_subexp (bd);
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_coef_probs (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  GstVp9TxSize tx_size, max_tx_size;
+  guint8 i, j, k, l, m;
+  guint8 update_probs;
+
+  static const guint8 tx_mode_to_biggest_tx_size[GST_VP9_TX_MODES] = {
+    GST_VP9_TX_4x4,
+    GST_VP9_TX_8x8,
+    GST_VP9_TX_16x16,
+    GST_VP9_TX_32x32,
+    GST_VP9_TX_32x32,
+  };
+
+  max_tx_size = tx_mode_to_biggest_tx_size[hdr->tx_mode];
+  for (tx_size = GST_VP9_TX_4x4; tx_size <= max_tx_size; tx_size++) {
+    update_probs = read_literal (bd, 1);
+    if (update_probs) {
+      for (i = 0; i < 2; i++)
+        for (j = 0; j < 2; j++)
+          for (k = 0; k < 6; k++)
+            for (l = 0; l < ((k == 0) ? 3 : 6); l++)
+              for (m = 0; m < 3; m++)
+                hdr->delta_probabilities.coef[tx_size][i][j][k][l][m] =
+                    decode_term_subexp (bd);
+    }
+  }
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_tx_mode_probs (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  guint i, j;
+
+  for (i = 0; i < GST_VP9_TX_SIZE_CONTEXTS; i++)
+    for (j = 0; j < GST_VP9_TX_SIZES - 3; j++)
+      hdr->delta_probabilities.tx_probs_8x8[i][j] = decode_term_subexp (bd);
+
+  for (i = 0; i < GST_VP9_TX_SIZE_CONTEXTS; i++)
+    for (j = 0; j < GST_VP9_TX_SIZES - 2; j++)
+      hdr->delta_probabilities.tx_probs_16x16[i][j] = decode_term_subexp (bd);
+
+  for (i = 0; i < GST_VP9_TX_SIZE_CONTEXTS; i++)
+    for (j = 0; j < GST_VP9_TX_SIZES - 1; j++)
+      hdr->delta_probabilities.tx_probs_32x32[i][j] = decode_term_subexp (bd);
+
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_tx_mode (GstVp9FrameHeader * hdr, Vp9BoolDecoder * bd)
+{
+  guint8 tx_mode;
+  guint8 tx_mode_select;
+
+  if (hdr->lossless_flag) {
+    hdr->tx_mode = GST_VP9_TX_MODE_ONLY_4x4;
+    return GST_VP9_PARSER_OK;
+  }
+
+  tx_mode = read_literal (bd, 2);
+  if (tx_mode == GST_VP9_TX_MODE_ALLOW_32x32) {
+    tx_mode_select = read_literal (bd, 1);
+    tx_mode += tx_mode_select;
+  }
+
+  hdr->tx_mode = tx_mode;
+  return GST_VP9_PARSER_OK;
+}
+
+static GstVp9ParserResult
+parse_compressed_header (GstVp9StatefulParser * self, GstVp9FrameHeader * hdr,
+    GstBitReader * br)
+{
+  GstVp9ParserResult rst;
+  gboolean frame_is_intra_only;
+  Vp9BoolDecoder bd;
+
+  /* consume trailing bits */
+  while (gst_bit_reader_get_pos (br) & 0x7)
+    gst_bit_reader_get_bits_uint8_unchecked (br, 1);
+
+  rst = init_bool (&bd, br, hdr->header_size_in_bytes);
+  if (rst != GST_VP9_PARSER_OK) {
+    GST_ERROR ("Failed to init the boolean decoder.");
+    return rst;
+  }
+
+  rst = parse_tx_mode (hdr, &bd);
+  if (rst != GST_VP9_PARSER_OK)
+    return rst;
+
+  if (hdr->tx_mode == GST_VP9_TX_MODE_SELECT) {
+    rst = parse_tx_mode_probs (hdr, &bd);
+    if (rst != GST_VP9_PARSER_OK)
+      return rst;
+  }
+
+  rst = parse_coef_probs (hdr, &bd);
+  if (rst != GST_VP9_PARSER_OK)
+    return rst;
+
+  rst = parse_skip_probs (hdr, &bd);
+  if (rst != GST_VP9_PARSER_OK)
+    return rst;
+
+  frame_is_intra_only = (hdr->frame_type == GST_VP9_KEY_FRAME
+      || hdr->intra_only);
+
+  if (!frame_is_intra_only) {
+    rst = parse_inter_mode_probs (hdr, &bd);
+    if (rst != GST_VP9_PARSER_OK)
+      return rst;
+
+    if (hdr->interpolation_filter == GST_VP9_INTERPOLATION_FILTER_SWITCHABLE) {
+      rst = parse_interp_filter_probs (hdr, &bd);
+      if (rst != GST_VP9_PARSER_OK)
+        return rst;
+    }
+
+    rst = parse_is_inter_probs (hdr, &bd);
+    if (rst != GST_VP9_PARSER_OK)
+      return rst;
+
+    rst = parse_frame_reference (hdr, &bd);
+    if (rst != GST_VP9_PARSER_OK)
+      return rst;
+
+    rst = parse_frame_reference_mode_probs (hdr, &bd);
+    if (rst != GST_VP9_PARSER_OK)
+      return rst;
+
+    rst = parse_y_mode_probs (hdr, &bd);
+    if (rst != GST_VP9_PARSER_OK)
+      return rst;
+
+    rst = parse_partition_probs (hdr, &bd);
+    if (rst != GST_VP9_PARSER_OK)
+      return rst;
+
+    rst = parse_mv_probs (hdr, &bd);
+    if (rst != GST_VP9_PARSER_OK)
+      return rst;
+  }
+
+  rst = exit_bool (&bd);
+  if (rst != GST_VP9_PARSER_OK) {
+    GST_ERROR ("The boolean decoder did not exit cleanly.");
+    return rst;
+  }
+
+  return GST_VP9_PARSER_OK;
+}
+
 static const gint16 dc_qlookup[256] = {
   4, 8, 8, 9, 10, 11, 12, 12,
   13, 14, 15, 16, 17, 18, 19, 19,
@@ -753,7 +1297,6 @@ parse_segmentation_params (GstBitReader * br, GstVp9SegmentationParams * params)
       VP9_READ_BIT (params->feature_enabled[i][GST_VP9_SEG_SEG_LVL_SKIP]);
     }
   }
-
   return GST_VP9_PARSER_OK;
 }
 
@@ -878,7 +1421,42 @@ gst_vp9_stateful_parser_free (GstVp9StatefulParser * parser)
 }
 
 /**
- * gst_vp9_stateful_parser_parse_frame_header:
+ * gst_vp9_stateful_parser_parse_compressed_frame_header:
+ * @parser: The #GstVp9StatefulParser
+ * @header: The #GstVp9FrameHeader to fill
+ * @data: The data to parse
+ * @size: The size of the @data to parse
+ *
+ * Parses the compressed information in the VP9 bitstream contained in @data,
+ * and fills in @header with the parsed values.
+ * The @size argument represent the whole frame size.
+ *
+ * Returns: a #GstVp9ParserResult
+ *
+ * Since: 1.20
+ */
+
+GstVp9ParserResult
+gst_vp9_stateful_parser_parse_compressed_frame_header (GstVp9StatefulParser *
+    parser, GstVp9FrameHeader * header, const guint8 * data, gsize size)
+{
+  GstVp9ParserResult rst = GST_VP9_PARSER_OK;
+  GstBitReader bit_reader;
+  GstBitReader *br = &bit_reader;
+
+  gst_bit_reader_init (br, data, size);
+
+  rst = parse_compressed_header (parser, header, br);
+  if (rst != GST_VP9_PARSER_OK) {
+    GST_ERROR ("Failed to parse the compressed header");
+    return GST_VP9_PARSER_ERROR;
+  }
+
+  return rst;
+}
+
+/**
+ * gst_vp9_stateful_parser_parse_uncompressed_frame_header:
  * @parser: The #GstVp9StatefulParser
  * @header: The #GstVp9FrameHeader to fill
  * @data: The data to parse
@@ -892,8 +1470,8 @@ gst_vp9_stateful_parser_free (GstVp9StatefulParser * parser)
  * Since: 1.20
  */
 GstVp9ParserResult
-gst_vp9_stateful_parser_parse_frame_header (GstVp9StatefulParser * parser,
-    GstVp9FrameHeader * header, const guint8 * data, gsize size)
+gst_vp9_stateful_parser_parse_uncompressed_frame_header (GstVp9StatefulParser *
+    parser, GstVp9FrameHeader * header, const guint8 * data, gsize size)
 {
   GstBitReader bit_reader;
   GstBitReader *br = &bit_reader;
@@ -1089,6 +1667,7 @@ gst_vp9_stateful_parser_parse_frame_header (GstVp9StatefulParser * parser,
 
   header->frame_header_length_in_bytes = (gst_bit_reader_get_pos (br) + 7) / 8;
 
+
   return GST_VP9_PARSER_OK;
 }
 
index 0ba5071..7f887f6 100644 (file)
@@ -29,6 +29,8 @@ typedef struct _GstVp9StatefulParser        GstVp9StatefulParser;
 typedef struct _GstVp9LoopFilterParams      GstVp9LoopFilterParams;
 typedef struct _GstVp9QuantizationParams    GstVp9QuantizationParams;
 typedef struct _GstVp9SegmentationParams    GstVp9SegmentationParams;
+typedef struct _GstVp9MvDeltaProbs          GstVp9MvDeltaProbs;
+typedef struct _GstVp9DeltaProbabilities    GstVp9DeltaProbabilities;
 typedef struct _GstVp9FrameHeader           GstVp9FrameHeader;
 
 /**
@@ -75,6 +77,263 @@ typedef struct _GstVp9FrameHeader           GstVp9FrameHeader;
  * Since: 1.20
  */
 #define GST_VP9_SEG_LVL_MAX 4
+/**
+ * GST_VP9_TX_SIZE_CONTEXTS:
+ *
+ * Number of contexts for transform size
+ *
+ * Since: 1.20
+ */
+#define GST_VP9_TX_SIZE_CONTEXTS 2
+
+/**
+ * GST_VP9_TX_SIZES:
+ *
+ * Number of values for tx_size
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_TX_SIZES 4
+
+/**
+ * GST_VP9_SKIP_CONTEXTS:
+ *
+ * Number of contexts for decoding skip
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_SKIP_CONTEXTS 3
+
+/**
+ * GST_VP9_INTER_MODE_CONTEXTS:
+ *
+ * Number of contexts for inter_mode
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_INTER_MODE_CONTEXTS 7
+
+/**
+ * GST_VP9_INTER_MODES:
+ *
+ * Number of values for inter_mode
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_INTER_MODES 4
+
+/**
+ * GST_VP9_INTERP_FILTER_CONTEXTS:
+ *
+ * Number of contexts for interp_filter
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_INTERP_FILTER_CONTEXTS 4
+
+/**
+ * GST_VP9_SWITCHABLE_FILTERS:
+ *
+ * Number of contexts for interp_filter
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_SWITCHABLE_FILTERS 3
+
+
+/**
+ * GST_VP9_IS_INTER_CONTEXTS:
+ *
+ * Number of contexts for interp_filter
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_IS_INTER_CONTEXTS 4
+
+/**
+ * GST_VP9_COMP_MODE_CONTEXTS:
+ *
+ * Number of contexts for comp_mode
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_COMP_MODE_CONTEXTS 5
+
+/**
+ * GST_VP9_REF_CONTEXTS:
+ *
+ * Number of contexts for single_ref and comp_ref
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_REF_CONTEXTS 5
+
+/**
+ * GST_VP9_BLOCK_SIZE_GROUPS:
+ *
+ * Number of contexts when decoding intra_mode
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_BLOCK_SIZE_GROUPS 4
+
+/**
+ * GST_VP9_INTRA_MODES:
+ *
+ * Number of values for intra_mode
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_INTRA_MODES 10
+
+/**
+ * GST_VP9_PARTITION_CONTEXTS:
+ *
+ * Number of contexts when decoding partition
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_PARTITION_CONTEXTS 16
+
+/**
+ * GST_VP9_PARTITION_TYPES:
+ *
+ * Number of values for partition
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_PARTITION_TYPES 4
+
+/**
+ * GST_VP9_MV_JOINTS:
+ *
+ * Number of values for partition
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_MV_JOINTS 4
+
+/**
+ * GST_VP9_MV_CLASSES:
+ *
+ * Number of values for mv_class
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_MV_CLASSES 11
+
+/**
+ * GST_VP9_MV_OFFSET_BITS:
+ *
+ * Maximum number of bits for decoding motion vectors
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_MV_OFFSET_BITS 10
+
+/**
+ * GST_VP9_CLASS0_SIZE:
+ *
+ * Number of values for mv_classO_bit
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_CLASS0_SIZE 2
+
+/**
+ * GST_VP9_MV_FR_SIZE:
+ *
+ * Number of values that can be decoded for mv_fr
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_MV_FR_SIZE 4
+
+/**
+ * GST_VP9_TX_MODES:
+ *
+ * Number of values for tx_mode
+ *
+ * Since: 1.20
+ *
+ */
+#define GST_VP9_TX_MODES 5
+
+/**
+ * GstVp9TxMode:
+ * @GST_VP9_TX_MODE_ONLY_4x4: Only 4x4
+ * @GST_VP9_TX_MODE_ALLOW_8x8: Allow 8x8
+ * @GST_VP9_TX_MODE_ALLOW_16x16: Allow 16x16
+ * @GST_VP9_TX_MODE_ALLOW_32x32: Allow 32x32
+ * @GST_VP9_TX_MODE_SELECT: The choice is specified explicitly for each block
+ *
+ * TxMode: Specifies how the transform size is determined
+ *
+ * Since: 1.20
+ */
+typedef enum
+{
+  GST_VP9_TX_MODE_ONLY_4x4 = 0,
+  GST_VP9_TX_MODE_ALLOW_8x8 = 1,
+  GST_VP9_TX_MODE_ALLOW_16x16 = 2,
+  GST_VP9_TX_MODE_ALLOW_32x32 = 3,
+  GST_VP9_TX_MODE_SELECT = 4,
+
+} GstVp9TxMode;
+
+/**
+ * GstVp9ReferenceMode:
+ * @GST_VP9_REFERENCE_MODE_SINGLE_REFERENCE: Indicates that all the inter blocks use only a single reference frame
+ * @GST_VP9_REFERENCE_MODE_COMPOUND_REFERENCE: Requires all the inter blocks to use compound mode
+ * @GST_VP9_REFERENCE_MODE_SELECT: Allows each individual inter block to select between single and compound prediction modes
+ *
+ * Reference modes: Specify the type of inter prediction to be used
+ *
+ * Since: 1.20
+ */
+typedef enum
+{
+  GST_VP9_REFERENCE_MODE_SINGLE_REFERENCE = 0,
+  GST_VP9_REFERENCE_MODE_COMPOUND_REFERENCE = 1,
+  GST_VP9_REFERENCE_MODE_SELECT = 2,
+} GstVp9ReferenceMode;
+
+/**
+ * GstVp9TxSize:
+ * @GST_VP9_TX_4x4: 4x4
+ * @GST_VP9_TX_8x8: 8x8
+ * @GST_VP9_TX_16x16: 16x16
+ * @GST_VP9_TX_32x32: 32x32
+ *
+ * TxSize: Specifies the transform size
+ *
+ * Since: 1.20
+ */
+typedef enum
+{
+  GST_VP9_TX_4x4 = 0,
+  GST_VP9_TX_8x8 = 1,
+  GST_VP9_TX_16x16 = 2,
+  GST_VP9_TX_32x32 = 3,
+} GstVp9TxSize;
 
 /**
  * GstVp9LoopFilterParams:
@@ -180,6 +439,59 @@ struct _GstVp9SegmentationParams
 };
 
 /**
+ * GstVp9MvDeltaProbs:
+ *
+ * Stores motion vectors probabilities updates. This is from the spec
+ * and can be used as a binary.
+ *
+ * Since: 1.20
+ */
+struct _GstVp9MvDeltaProbs
+{
+  /*< private >*/
+  guint8 joint[GST_VP9_MV_JOINTS - 1];
+  guint8 sign[2];
+  guint8 klass[2][GST_VP9_MV_CLASSES - 1];
+  guint8 class0_bit[2];
+  guint8 bits[2][GST_VP9_MV_OFFSET_BITS];
+  guint8 class0_fr[2][GST_VP9_CLASS0_SIZE][GST_VP9_MV_FR_SIZE - 1];
+  guint8 fr[2][GST_VP9_MV_FR_SIZE - 1];
+  guint8 class0_hp[2];
+  guint8 hp[2];
+};
+
+
+/**
+ * GstVp9DeltaProbabilities:
+ *
+ * Stores probabilities updates. This is from the spec
+ * and can be used as a binary.
+ *
+ * Since: 1.20
+ */
+struct _GstVp9DeltaProbabilities
+{
+  /*< private >*/
+  guint8 tx_probs_8x8[GST_VP9_TX_SIZE_CONTEXTS][GST_VP9_TX_SIZES - 3];
+  guint8 tx_probs_16x16[GST_VP9_TX_SIZE_CONTEXTS][GST_VP9_TX_SIZES - 2];
+  guint8 tx_probs_32x32[GST_VP9_TX_SIZE_CONTEXTS][GST_VP9_TX_SIZES - 1];
+  guint8 coef[4][2][2][6][6][3];
+  guint8 skip[GST_VP9_SKIP_CONTEXTS];
+  guint8 inter_mode[GST_VP9_INTER_MODE_CONTEXTS][GST_VP9_INTER_MODES - 1];
+    guint8
+      interp_filter[GST_VP9_INTERP_FILTER_CONTEXTS][GST_VP9_SWITCHABLE_FILTERS
+      - 1];
+  guint8 is_inter[GST_VP9_IS_INTER_CONTEXTS];
+  guint8 comp_mode[GST_VP9_COMP_MODE_CONTEXTS];
+  guint8 single_ref[GST_VP9_REF_CONTEXTS][2];
+  guint8 comp_ref[GST_VP9_REF_CONTEXTS];
+  guint8 y_mode[GST_VP9_BLOCK_SIZE_GROUPS][GST_VP9_INTRA_MODES - 1];
+  guint8 partition[GST_VP9_PARTITION_CONTEXTS][GST_VP9_PARTITION_TYPES - 1];
+  GstVp9MvDeltaProbs mv;
+};
+
+
+/**
  * GstVp9FrameHeader:
  * @profile: encoded profile
  * @bit_depth: encoded bit depth
@@ -225,11 +537,38 @@ struct _GstVp9SegmentationParams
  * @segmentation_params: a #GstVp9SegmentationParams
  * @tile_cols_log2: specifies the base 2 logarithm of the width of each tile
  * @tile_rows_log2: specifies the base 2 logarithm of the height of each tile
+ * @tx_mode: specifies how the transform size is determined
+ * @reference_mode: is a derived syntax element that specifies the type of
+ *   inter prediction to be used
+ * @delta_probabilities: modification to the probabilities encoded in the
+ *   bitstream
  * @lossless_flag: lossless mode decode
  * @frame_header_length_in_bytes: length of uncompressed header
  *
  * Since: 1.20
  */
+/**
+ * GstVp9FrameHeader.tx_mode:
+ *
+ * Specifies how the transform size is determined.
+ *
+ * Since: 1.20
+ */
+/**
+ * GstVp9FrameHeader.reference_mode:
+ * 
+ * Is a derived syntax element that specifies the type of
+ * inter prediction to be used.
+ *
+ * Since: 1.20
+ */
+/**
+ * GstVp9FrameHeader.delta_probabilities:
+ * 
+ * Modification to the probabilities encoded in the bitstream.
+ *
+ * Since: 1.20
+ */
 struct _GstVp9FrameHeader
 {
   guint8 profile;
@@ -269,6 +608,11 @@ struct _GstVp9FrameHeader
 
   guint16 header_size_in_bytes;
 
+  /* compressed header */
+  GstVp9TxMode tx_mode;
+  GstVp9ReferenceMode reference_mode;
+  GstVp9DeltaProbabilities delta_probabilities;
+
   /* calculated values */
   guint8 lossless_flag;
   guint32 frame_header_length_in_bytes;
@@ -312,10 +656,16 @@ GST_CODECS_API
 void                    gst_vp9_stateful_parser_free               (GstVp9StatefulParser * parser);
 
 GST_CODECS_API
-GstVp9ParserResult      gst_vp9_stateful_parser_parse_frame_header (GstVp9StatefulParser * parser,
-                                                                    GstVp9FrameHeader * header,
-                                                                    const guint8 * data,
-                                                                    gsize size);
+GstVp9ParserResult      gst_vp9_stateful_parser_parse_compressed_frame_header (GstVp9StatefulParser * parser,
+                                                                               GstVp9FrameHeader * header,
+                                                                               const guint8 * data,
+                                                                               gsize size);
+
+GST_CODECS_API
+GstVp9ParserResult      gst_vp9_stateful_parser_parse_uncompressed_frame_header (GstVp9StatefulParser * parser,
+                                                                                 GstVp9FrameHeader * header,
+                                                                                 const guint8 * data,
+                                                                                 gsize size);
 
 /* Util methods */
 GST_CODECS_API