Esempio n. 1
0
gboolean
mpeg4_util_parse_VOL (GstBuffer * buf, Mpeg4VisualObject * vo,
    Mpeg4VideoObjectLayer * vol)
{
  GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buf);

  guint8 video_object_layer_start_code;
  guint8 aspect_ratio_info;
  guint8 control_parameters;
  guint8 not_8_bit;

  /* set default values */
  vol->verid = vo->verid;
  vol->priority = vo->priority;

  vol->low_delay = FALSE;
  vol->chroma_format = 1;
  vol->vbv_parameters = FALSE;
  vol->quant_precision = 5;
  vol->bits_per_pixel = 8;
  vol->quarter_sample = FALSE;

  /* start code prefix */
  SKIP (&reader, 24);

  READ_UINT8 (&reader, video_object_layer_start_code, 8);
  if (!(video_object_layer_start_code >= MPEG4_PACKET_VOL_MIN &&
          video_object_layer_start_code <= MPEG4_PACKET_VOL_MAX))
    goto wrong_start_code;

  READ_UINT8 (&reader, vol->random_accesible_vol, 1);
  READ_UINT8 (&reader, vol->video_object_type_indication, 8);

  READ_UINT8 (&reader, vol->is_object_layer_identifier, 1);
  if (vol->is_object_layer_identifier) {
    READ_UINT8 (&reader, vol->verid, 4);
    READ_UINT8 (&reader, vol->priority, 3);
  }

  READ_UINT8 (&reader, aspect_ratio_info, 4);
  if (aspect_ratio_info != 0xff)
    mpeg4_util_par_from_info (aspect_ratio_info, &vol->par_n, &vol->par_d);

  else {
    READ_UINT8 (&reader, vol->par_n, 8);
    CHECK_ALLOWED (vol->par_n, 1, 255);
    READ_UINT8 (&reader, vol->par_d, 8);
    CHECK_ALLOWED (vol->par_d, 1, 255);
  }

  READ_UINT8 (&reader, control_parameters, 1);
  if (control_parameters) {
    READ_UINT8 (&reader, vol->chroma_format, 2);
    READ_UINT8 (&reader, vol->low_delay, 1);

    READ_UINT8 (&reader, vol->vbv_parameters, 1);
    if (vol->vbv_parameters) {
      guint16 first_half, latter_half;
      guint8 latter_part;

      READ_UINT16 (&reader, first_half, 15);
      SKIP (&reader, 1);
      READ_UINT16 (&reader, latter_half, 15);
      SKIP (&reader, 1);
      vol->bit_rate = (first_half << 15) | latter_half;

      READ_UINT16 (&reader, first_half, 15);
      SKIP (&reader, 1);
      READ_UINT8 (&reader, latter_part, 3);
      SKIP (&reader, 1);
      vol->vbv_buffer_size = (first_half << 15) | latter_part;
    }
  }

  READ_UINT8 (&reader, vol->shape, 2);
  if (vol->shape != 0x0)
    goto invalid_shape;

  /* marker_bit */
  SKIP (&reader, 1);
  READ_UINT16 (&reader, vol->vop_time_increment_resolution, 16);
  CHECK_ALLOWED (vol->vop_time_increment_resolution, 1, G_MAXUINT16);
  vol->vop_time_increment_bits =
      g_bit_storage (vol->vop_time_increment_resolution);
  /* marker_bit */
  SKIP (&reader, 1);

  READ_UINT8 (&reader, vol->fixed_vop_rate, 1);
  if (vol->fixed_vop_rate)
    READ_UINT16 (&reader, vol->fixed_vop_time_increment,
        vol->vop_time_increment_bits);

  /* marker bit */
  SKIP (&reader, 1);
  READ_UINT16 (&reader, vol->width, 13);
  /* marker bit */
  SKIP (&reader, 1);
  READ_UINT16 (&reader, vol->height, 13);
  /* marker bit */
  SKIP (&reader, 1);

  READ_UINT8 (&reader, vol->interlaced, 1);
  READ_UINT8 (&reader, vol->obmc_disable, 1);

  if (vol->verid == 0x1) {
    READ_UINT8 (&reader, vol->sprite_enable, 1);
  } else
    READ_UINT8 (&reader, vol->sprite_enable, 2);

  if (vol->sprite_enable != 0x0)
    goto invalid_sprite_enable;

  READ_UINT8 (&reader, not_8_bit, 1);
  if (not_8_bit) {
    READ_UINT8 (&reader, vol->quant_precision, 4);
    CHECK_ALLOWED (vol->quant_precision, 3, 9);

    READ_UINT8 (&reader, vol->bits_per_pixel, 4);
    CHECK_ALLOWED (vol->bits_per_pixel, 4, 12);
  }


  READ_UINT8 (&reader, vol->quant_type, 1);
  if (vol->quant_type) {
    if (!mpeg4_util_parse_quant (&reader, vol->intra_quant_mat,
            default_intra_quant_mat))
      goto error;

    if (!mpeg4_util_parse_quant (&reader, vol->non_intra_quant_mat,
            default_non_intra_quant_mat))
      goto error;
  } else {
    memset (&vol->intra_quant_mat, 0, 64);
    memset (&vol->non_intra_quant_mat, 0, 64);
  }

  if (vol->verid != 0x1)
    READ_UINT8 (&reader, vol->quarter_sample, 1);

  READ_UINT8 (&reader, vol->complexity_estimation_disable, 1);
  if (!vol->complexity_estimation_disable)
    goto complexity_estimation_error;

  READ_UINT8 (&reader, vol->resync_marker_disable, 1);

  return TRUE;

error:
  GST_WARNING ("error parsing \"Video Object Layer\"");
  return FALSE;

wrong_start_code:
  GST_WARNING ("got buffer with wrong start code");
  goto error;

invalid_shape:
  GST_WARNING ("we only support rectangular shape");
  goto error;

invalid_sprite_enable:
  GST_WARNING ("we only support sprite_enable == 0");
  goto error;

complexity_estimation_error:
  GST_WARNING ("don't support complexity estimation");
  goto error;
}
/**
 * gst_mpeg4_parse_video_object_layer:
 * @vol: The #GstMpeg4VideoObjectLayer structure to fill
 * @vo: The #GstMpeg4VisualObject currently being parsed or %NULL
 * @data: The data to parse
 * @size: The size of the @data to parse
 *
 * Parses @data containing the video object layer packet, and fills
 * the @vol structure.
 *
 * Returns: a #GstMpeg4ParseResult
 */
GstMpeg4ParseResult
gst_mpeg4_parse_video_object_layer (GstMpeg4VideoObjectLayer * vol,
    GstMpeg4VisualObject * vo, const guint8 * data, gsize size)
{
  guint8 video_object_layer_start_code;

  /* Used for enums types */
  guint8 tmp;
  GstBitReader br = GST_BIT_READER_INIT (data, size);

  g_return_val_if_fail (vol != NULL, GST_MPEG4_PARSER_ERROR);

  GST_DEBUG ("Parsing video object layer");

  READ_UINT8 (&br, video_object_layer_start_code, 8);
  if (!(video_object_layer_start_code >= GST_MPEG4_VIDEO_LAYER_FIRST &&
          video_object_layer_start_code <= GST_MPEG4_VIDEO_LAYER_LAST))
    goto wrong_start_code;

  /* set default values */
  if (vo) {
    vol->verid = vo->verid;
    vol->priority = vo->priority;
  } else {
    vol->verid = 1;
    vol->priority = 0;
  }

  vol->low_delay = FALSE;
  vol->chroma_format = 1;
  vol->vbv_parameters = FALSE;
  vol->quant_precision = 5;
  vol->bits_per_pixel = 8;
  vol->quarter_sample = FALSE;
  vol->newpred_enable = FALSE;
  vol->interlaced = 0;
  vol->width = 0;
  vol->height = 0;

  READ_UINT8 (&br, vol->random_accessible_vol, 1);
  READ_UINT8 (&br, vol->video_object_type_indication, 8);

  READ_UINT8 (&br, vol->is_object_layer_identifier, 1);
  if (vol->is_object_layer_identifier) {
    READ_UINT8 (&br, vol->verid, 4);
    READ_UINT8 (&br, vol->priority, 3);
  }

  READ_UINT8 (&br, tmp, 4);
  vol->aspect_ratio_info = tmp;
  if (vol->aspect_ratio_info != GST_MPEG4_EXTENDED_PAR) {
    mpeg4_util_par_from_info (vol->aspect_ratio_info, &vol->par_width,
        &vol->par_height);

  } else {
    gint v;

    READ_UINT8 (&br, vol->par_width, 8);
    v = vol->par_width;
    CHECK_ALLOWED (v, 1, 255);

    READ_UINT8 (&br, vol->par_height, 8);
    v = vol->par_height;
    CHECK_ALLOWED (v, 1, 255);
  }
  GST_DEBUG ("Pixel aspect ratio %d/%d", vol->par_width, vol->par_width);

  READ_UINT8 (&br, vol->control_parameters, 1);
  if (vol->control_parameters) {
    guint8 chroma_format;

    READ_UINT8 (&br, chroma_format, 2);
    vol->chroma_format = chroma_format;
    READ_UINT8 (&br, vol->low_delay, 1);

    READ_UINT8 (&br, vol->vbv_parameters, 1);
    if (vol->vbv_parameters) {
      CHECK_REMAINING (&br, 79);

      vol->first_half_bitrate =
          gst_bit_reader_get_bits_uint16_unchecked (&br, 15);
      MARKER_UNCHECKED (&br);

      vol->latter_half_bitrate =
          gst_bit_reader_get_bits_uint16_unchecked (&br, 15);
      MARKER_UNCHECKED (&br);

      vol->bit_rate =
          (vol->first_half_bitrate << 15) | vol->latter_half_bitrate;

      vol->first_half_vbv_buffer_size =
          gst_bit_reader_get_bits_uint16_unchecked (&br, 15);
      MARKER_UNCHECKED (&br);

      vol->latter_half_vbv_buffer_size =
          gst_bit_reader_get_bits_uint8_unchecked (&br, 3);

      vol->vbv_buffer_size = (vol->first_half_vbv_buffer_size << 15) |
          vol->latter_half_vbv_buffer_size;

      vol->first_half_vbv_occupancy =
          gst_bit_reader_get_bits_uint16_unchecked (&br, 11);
      MARKER_UNCHECKED (&br);

      vol->latter_half_vbv_occupancy =
          gst_bit_reader_get_bits_uint16_unchecked (&br, 15);
      MARKER_UNCHECKED (&br);
    }
  }

  READ_UINT8 (&br, tmp, 2);
  vol->shape = tmp;

  if (vol->shape == GST_MPEG4_GRAYSCALE) {
    /* TODO support grayscale shapes, for now we just pass */

    /* Something the standard starts to define... */
    GST_WARNING ("Grayscale shaped not supported");
    goto failed;
  }

  if (vol->shape == GST_MPEG4_GRAYSCALE && vol->verid != 0x01)
    READ_UINT8 (&br, vol->shape_extension, 4);

  CHECK_REMAINING (&br, 19);

  MARKER_UNCHECKED (&br);
  vol->vop_time_increment_resolution =
      gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
  if (vol->vop_time_increment_resolution < 1) {
    GST_WARNING ("value not in allowed range. value: %d, range %d-%d",
        vol->vop_time_increment_resolution, 1, G_MAXUINT16);
    goto failed;
  }
  vol->vop_time_increment_bits =
      g_bit_storage (vol->vop_time_increment_resolution);

  MARKER_UNCHECKED (&br);
  vol->fixed_vop_rate = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
  if (vol->fixed_vop_rate)
    READ_UINT16 (&br, vol->fixed_vop_time_increment,
        vol->vop_time_increment_bits);

  if (vol->shape != GST_MPEG4_BINARY_ONLY) {
    if (vol->shape == GST_MPEG4_RECTANGULAR) {
      CHECK_REMAINING (&br, 29);

      MARKER_UNCHECKED (&br);
      vol->width = gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
      MARKER_UNCHECKED (&br);
      vol->height = gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
      MARKER_UNCHECKED (&br);
    }

    READ_UINT8 (&br, vol->interlaced, 1);
    READ_UINT8 (&br, vol->obmc_disable, 1);

    if (vol->verid == 0x1)
      READ_UINT8 (&br, tmp, 1);
    else
      READ_UINT8 (&br, tmp, 2);
    vol->sprite_enable = tmp;

    if (vol->sprite_enable == GST_MPEG4_SPRITE_STATIC ||
        vol->sprite_enable == GST_MPEG4_SPRITE_GMG) {

      if (vol->sprite_enable == GST_MPEG4_SPRITE_GMG)
        CHECK_REMAINING (&br, 9);
      else {
        CHECK_REMAINING (&br, 65);

        vol->sprite_width = gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
        MARKER_UNCHECKED (&br);

        vol->sprite_height = gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
        MARKER_UNCHECKED (&br);

        vol->sprite_left_coordinate =
            gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
        MARKER_UNCHECKED (&br);

        vol->sprite_top_coordinate =
            gst_bit_reader_get_bits_uint16_unchecked (&br, 13);
        MARKER_UNCHECKED (&br);
      }
      vol->no_of_sprite_warping_points =
          gst_bit_reader_get_bits_uint8_unchecked (&br, 6);
      vol->sprite_warping_accuracy =
          gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
      vol->sprite_brightness_change =
          gst_bit_reader_get_bits_uint8_unchecked (&br, 1);

      if (vol->sprite_enable != GST_MPEG4_SPRITE_GMG)
        vol->low_latency_sprite_enable =
            gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
    }

    if (vol->verid != 0x1 && vol->shape != GST_MPEG4_RECTANGULAR)
      READ_UINT8 (&br, vol->sadct_disable, 1);

    READ_UINT8 (&br, vol->not_8_bit, 1);
    if (vol->not_8_bit) {
      READ_UINT8 (&br, vol->quant_precision, 4);
      CHECK_ALLOWED (vol->quant_precision, 3, 9);

      READ_UINT8 (&br, vol->bits_per_pixel, 4);
      CHECK_ALLOWED (vol->bits_per_pixel, 4, 12);
    }

    if (vol->shape == GST_MPEG4_GRAYSCALE) {
      /* We don't actually support it */
      READ_UINT8 (&br, vol->no_gray_quant_update, 1);
      READ_UINT8 (&br, vol->composition_method, 1);
      READ_UINT8 (&br, vol->linear_composition, 1);
    }

    READ_UINT8 (&br, vol->quant_type, 1);
    if (vol->quant_type) {
      if (!parse_quant (&br, vol->intra_quant_mat, default_intra_quant_mat,
              &vol->load_intra_quant_mat))
        goto failed;

      if (!parse_quant (&br, vol->non_intra_quant_mat,
              default_non_intra_quant_mat, &vol->load_non_intra_quant_mat))
        goto failed;

      if (vol->shape == GST_MPEG4_GRAYSCALE) {
        /* Something the standard starts to define... */
        GST_WARNING ("Grayscale shaped not supported");
        goto failed;
      }

    } else {
      memset (&vol->intra_quant_mat, 0, 64);
      memset (&vol->non_intra_quant_mat, 0, 64);
    }

    if (vol->verid != 0x1)
      READ_UINT8 (&br, vol->quarter_sample, 1);

    READ_UINT8 (&br, vol->complexity_estimation_disable, 1);
    if (!vol->complexity_estimation_disable) {
      guint8 estimation_method;
      guint8 estimation_disable;

      /* skip unneeded properties */
      READ_UINT8 (&br, estimation_method, 2);
      if (estimation_method < 2) {
        READ_UINT8 (&br, estimation_disable, 1);
        if (!estimation_disable)
          SKIP (&br, 6);
        READ_UINT8 (&br, estimation_disable, 1);
        if (!estimation_disable)
          SKIP (&br, 4);
        CHECK_MARKER (&br);
        READ_UINT8 (&br, estimation_disable, 1);
        if (!estimation_disable)
          SKIP (&br, 4);
        READ_UINT8 (&br, estimation_disable, 1);
        if (!estimation_disable)
          SKIP (&br, 6);
        CHECK_MARKER (&br);

        if (estimation_method == 1) {
          READ_UINT8 (&br, estimation_disable, 1);
          if (!estimation_disable)
            SKIP (&br, 2);
        }
      }
    }

    READ_UINT8 (&br, vol->resync_marker_disable, 1);
    READ_UINT8 (&br, vol->data_partitioned, 1);

    if (vol->data_partitioned)
      READ_UINT8 (&br, vol->reversible_vlc, 1);

    if (vol->verid != 0x01) {
      READ_UINT8 (&br, vol->newpred_enable, 1);
      if (vol->newpred_enable)
        /* requested_upstream_message_type and newpred_segment_type */
        SKIP (&br, 3);

      READ_UINT8 (&br, vol->reduced_resolution_vop_enable, 1);
    }

    READ_UINT8 (&br, vol->scalability, 1);
    if (vol->scalability) {
      SKIP (&br, 26);           /* Few not needed props */
      READ_UINT8 (&br, vol->enhancement_type, 1);
    }

    /* More unused infos */
  } else if (vol->verid != 0x01) {
    GST_WARNING ("Binary only shapes not fully supported");
    goto failed;
  }
  /* ... */

  return GST_MPEG4_PARSER_OK;

failed:
  GST_WARNING ("failed parsing \"Video Object Layer\"");
  return GST_MPEG4_PARSER_ERROR;

wrong_start_code:
  GST_WARNING ("got buffer with wrong start code");
  goto failed;
}