Пример #1
0
static GstFlowReturn
gst_h264_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
{
  GstH264Parse *h264parse;
  GstBuffer *buffer;
  guint av;

  h264parse = GST_H264_PARSE (parse);
  buffer = frame->buffer;

  gst_h264_parse_update_src_caps (h264parse);

  gst_h264_params_get_timestamp (h264parse->params,
      &GST_BUFFER_TIMESTAMP (buffer), &GST_BUFFER_DURATION (buffer),
      h264parse->frame_start);

  if (h264parse->keyframe)
    GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
  else
    GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);

  /* replace with transformed AVC output if applicable */
  av = gst_adapter_available (h264parse->frame_out);
  if (av) {
    GstBuffer *buf;

    buf = gst_adapter_take_buffer (h264parse->frame_out, av);
    gst_buffer_copy_metadata (buf, buffer, GST_BUFFER_COPY_ALL);
    gst_buffer_replace (&frame->buffer, buf);
  }

  return GST_FLOW_OK;
}
Пример #2
0
static gboolean
gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
{
  GstH264Parse *h264parse;
  GstStructure *str;
  const GValue *value;
  GstBuffer *buffer = NULL;
  guint size;

  h264parse = GST_H264_PARSE (parse);

  /* reset */
  h264parse->push_codec = FALSE;

  str = gst_caps_get_structure (caps, 0);

  /* accept upstream info if provided */
  gst_structure_get_int (str, "width", &h264parse->width);
  gst_structure_get_int (str, "height", &h264parse->height);
  gst_structure_get_fraction (str, "framerate", &h264parse->fps_num,
      &h264parse->fps_den);

  /* packetized video has a codec_data */
  if ((value = gst_structure_get_value (str, "codec_data"))) {
    guint8 *data;
    guint num_sps, num_pps, profile, len;
    gint i;

    GST_DEBUG_OBJECT (h264parse, "have packetized h264");
    /* make note for optional split processing */
    h264parse->packetized = TRUE;

    buffer = gst_value_get_buffer (value);
    if (!buffer)
      goto wrong_type;
    data = GST_BUFFER_DATA (buffer);
    size = GST_BUFFER_SIZE (buffer);

    /* parse the avcC data */
    if (size < 7)
      goto avcc_too_small;
    /* parse the version, this must be 1 */
    if (data[0] != 1)
      goto wrong_version;

    /* AVCProfileIndication */
    /* profile_compat */
    /* AVCLevelIndication */
    profile = (data[1] << 16) | (data[2] << 8) | data[3];
    GST_DEBUG_OBJECT (h264parse, "profile %06x", profile);

    /* 6 bits reserved | 2 bits lengthSizeMinusOne */
    /* this is the number of bytes in front of the NAL units to mark their
     * length */
    h264parse->nal_length_size = (data[4] & 0x03) + 1;
    GST_DEBUG_OBJECT (h264parse, "nal length %u", h264parse->nal_length_size);

    num_sps = data[5] & 0x1f;
    data += 6;
    size -= 6;
    for (i = 0; i < num_sps; i++) {
      len = GST_READ_UINT16_BE (data);
      if (size < len + 2 || len < 2)
        goto avcc_too_small;
      /* digest for later reference */
      gst_h264_parse_process_nal (h264parse, data, 0, 2, len);
      data += len + 2;
      size -= len + 2;
    }
    num_pps = data[0];
    data++;
    size++;
    for (i = 0; i < num_pps; i++) {
      len = GST_READ_UINT16_BE (data);
      if (size < len + 2 || len < 2)
        goto avcc_too_small;
      /* digest for later reference */
      gst_h264_parse_process_nal (h264parse, data, 0, 2, len);
      data += len + 2;
      size -= len + 2;
    }
  } else {
    GST_DEBUG_OBJECT (h264parse, "have bytestream h264");
    /* nothing to pre-process */
    h264parse->packetized = FALSE;
    /* we have 4 sync bytes */
    h264parse->nal_length_size = 4;
  }

  if (h264parse->packetized) {
    if (h264parse->split_packetized) {
      GST_DEBUG_OBJECT (h264parse,
          "converting AVC to nal bytestream prior to parsing");
      /* negotiate behaviour with upstream */
      gst_h264_parse_negotiate (h264parse);
      if (h264parse->format == GST_H264_PARSE_FORMAT_BYTE) {
        /* arrange to insert codec-data in-stream if needed */
        h264parse->push_codec = h264parse->packetized;
      }
    } else {
      GST_DEBUG_OBJECT (h264parse, "passing on packetized AVC");
      /* no choice to negotiate */
      h264parse->format = GST_H264_PARSE_FORMAT_AVC;
      h264parse->align = GST_H264_PARSE_ALIGN_AU;
      /* fallback codec-data */
      h264parse->codec_data = gst_buffer_ref (buffer);
      /* pass through unharmed, though _chain will parse a bit */
      gst_base_parse_set_format (parse,
          GST_BASE_PARSE_FORMAT_PASSTHROUGH, TRUE);
      /* we did parse codec-data and might supplement src caps */
      gst_h264_parse_update_src_caps (h264parse);
    }
  }

  /* src caps are only arranged for later on */
  return TRUE;

  /* ERRORS */
avcc_too_small:
  {
    GST_DEBUG_OBJECT (h264parse, "avcC size %u < 7", size);
    goto refuse_caps;
  }
wrong_version:
  {
    GST_DEBUG_OBJECT (h264parse, "wrong avcC version");
    goto refuse_caps;
  }
wrong_type:
  {
    GST_DEBUG_OBJECT (h264parse, "wrong codec-data type");
    goto refuse_caps;
  }
refuse_caps:
  {
    GST_WARNING_OBJECT (h264parse, "refused caps %" GST_PTR_FORMAT, caps);
    return FALSE;
  }
}
Пример #3
0
static gboolean
gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
{
  GstH264Parse *h264parse;
  GstStructure *str;
  const GValue *value;
  GstBuffer *codec_data = NULL;
  guint size, format, align;

  h264parse = GST_H264_PARSE (parse);

  /* reset */
  h264parse->push_codec = FALSE;

  str = gst_caps_get_structure (caps, 0);

  /* accept upstream info if provided */
  gst_structure_get_int (str, "width", &h264parse->width);
  gst_structure_get_int (str, "height", &h264parse->height);
  gst_structure_get_fraction (str, "framerate", &h264parse->fps_num,
      &h264parse->fps_den);

  /* get upstream format and align from caps */
  gst_h264_parse_format_from_caps (caps, &format, &align);

  /* packetized video has a codec_data */
  if (format != GST_H264_PARSE_FORMAT_BYTE &&
      (value = gst_structure_get_value (str, "codec_data"))) {
    guint8 *data;
    guint num_sps, num_pps, profile, len;
    gint i;

    GST_DEBUG_OBJECT (h264parse, "have packetized h264");
    /* make note for optional split processing */
    h264parse->packetized = TRUE;

    codec_data = gst_value_get_buffer (value);
    if (!codec_data)
      goto wrong_type;
    data = GST_BUFFER_DATA (codec_data);
    size = GST_BUFFER_SIZE (codec_data);

    /* parse the avcC data */
    if (size < 7)
      goto avcc_too_small;
    /* parse the version, this must be 1 */
    if (data[0] != 1)
      goto wrong_version;

    /* AVCProfileIndication */
    /* profile_compat */
    /* AVCLevelIndication */
    profile = (data[1] << 16) | (data[2] << 8) | data[3];
    GST_DEBUG_OBJECT (h264parse, "profile %06x", profile);

    /* 6 bits reserved | 2 bits lengthSizeMinusOne */
    /* this is the number of bytes in front of the NAL units to mark their
     * length */
    h264parse->nal_length_size = (data[4] & 0x03) + 1;
    GST_DEBUG_OBJECT (h264parse, "nal length %u", h264parse->nal_length_size);

    num_sps = data[5] & 0x1f;
    data += 6;
    size -= 6;
    for (i = 0; i < num_sps; i++) {
      len = GST_READ_UINT16_BE (data);
      if (size < len + 2 || len < 2)
        goto avcc_too_small;
      /* digest for later reference */
      gst_h264_parse_process_nal (h264parse, data, 0, 2, len);
      data += len + 2;
      size -= len + 2;
    }
    num_pps = data[0];
    data++;
    size++;
    for (i = 0; i < num_pps; i++) {
      len = GST_READ_UINT16_BE (data);
      if (size < len + 2 || len < 2)
        goto avcc_too_small;
      /* digest for later reference */
      gst_h264_parse_process_nal (h264parse, data, 0, 2, len);
      data += len + 2;
      size -= len + 2;
    }

    h264parse->codec_data = gst_buffer_ref (codec_data);

    /* if upstream sets codec_data without setting stream-format and alignment, we
     * assume stream-format=avc,alignment=au */
    if (format == GST_H264_PARSE_FORMAT_NONE) {
      format = GST_H264_PARSE_FORMAT_AVC;
      align = GST_H264_PARSE_ALIGN_AU;
    }
  } else {
    GST_DEBUG_OBJECT (h264parse, "have bytestream h264");
    /* nothing to pre-process */
    h264parse->packetized = FALSE;
    /* we have 4 sync bytes */
    h264parse->nal_length_size = 4;

    if (format == GST_H264_PARSE_FORMAT_NONE) {
      format = GST_H264_PARSE_FORMAT_BYTE;
      align = GST_H264_PARSE_ALIGN_AU;
    }
  }

  /* negotiate with downstream, sets ->format and ->align */
  gst_h264_parse_negotiate (h264parse);

  if (format == h264parse->format && align == h264parse->align) {
    gst_base_parse_set_passthrough (parse, TRUE);

    /* we did parse codec-data and might supplement src caps */
    gst_h264_parse_update_src_caps (h264parse, caps);
  } else if (format == GST_H264_PARSE_FORMAT_AVC) {
    /* if input != output, and input is avc, must split before anything else */
    /* arrange to insert codec-data in-stream if needed.
     * src caps are only arranged for later on */
    h264parse->push_codec = TRUE;
    h264parse->split_packetized = TRUE;
    h264parse->packetized = TRUE;
  }

  return TRUE;

  /* ERRORS */
avcc_too_small:
  {
    GST_DEBUG_OBJECT (h264parse, "avcC size %u < 7", size);
    goto refuse_caps;
  }
wrong_version:
  {
    GST_DEBUG_OBJECT (h264parse, "wrong avcC version");
    goto refuse_caps;
  }
wrong_type:
  {
    GST_DEBUG_OBJECT (h264parse, "wrong codec-data type");
    goto refuse_caps;
  }
unknown_input_format:
  {
    GST_DEBUG_OBJECT (h264parse, "unknown stream-format and no codec_data");
    goto refuse_caps;
  }
refuse_caps:
  {
    GST_WARNING_OBJECT (h264parse, "refused caps %" GST_PTR_FORMAT, caps);
    return FALSE;
  }
}