gstreamer中h264对齐方式au和nal

在gstreamer中,h264的格式有:

static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("video/x-h264, parsed = (boolean) true, "
        "stream-format=(string) { avc, avc3, byte-stream }, "
        "alignment=(string) { au, nal }"));

H264有两种对齐方式:
1、AVC (length-prefixed)
2、Annex B (0x000001 start code prefix)

还有同学问SVC和MVC,这里拓展一下:

/**
 * GstH264NalUnitExtensionType:
 * @GST_H264_NAL_EXTENSION_NONE: No NAL unit header extension is available
 * @GST_H264_NAL_EXTENSION_SVC: NAL unit header extension for SVC (Annex G)
 * @GST_H264_NAL_EXTENSION_MVC: NAL unit header extension for MVC (Annex H)
 *
 * Indicates the type of H.264 NAL unit extension.
 *
 * Since: 1.6
 */
typedef enum
{
  GST_H264_NAL_EXTENSION_NONE = 0,
  GST_H264_NAL_EXTENSION_SVC,
  GST_H264_NAL_EXTENSION_MVC,
} GstH264NalUnitExtensionType;

那么,看下面:

 "stream-format=(string) { avc, avc3, byte-stream }, "
 "alignment=(string) { au, nal }"));

这两个要从gsth264parser.c中看:

gst_h264_parse_get_string (GstH264Parse * parse, gboolean format, gint code)
{
  if (format) {
    switch (code) {
      case GST_H264_PARSE_FORMAT_AVC:
        return "avc";
      case GST_H264_PARSE_FORMAT_BYTE:
        return "byte-stream";
      case GST_H264_PARSE_FORMAT_AVC3:
        return "avc3";
      default:
        return "none";
    }
  } else {
    switch (code) {
      case GST_H264_PARSE_ALIGN_NAL:
        return "nal";
      case GST_H264_PARSE_ALIGN_AU:
        return "au";
      default:
        return "none";
    }
  }
}


static void
gst_h264_parse_format_from_caps (GstCaps * caps, guint * format, guint * align)
{
  if (format)
    *format = GST_H264_PARSE_FORMAT_NONE;

  if (align)
    *align = GST_H264_PARSE_ALIGN_NONE;

  g_return_if_fail (gst_caps_is_fixed (caps));

  GST_DEBUG ("parsing caps: %" GST_PTR_FORMAT, caps);

  if (caps && gst_caps_get_size (caps) > 0) {
    GstStructure *s = gst_caps_get_structure (caps, 0);
    const gchar *str = NULL;

    if (format) {
      if ((str = gst_structure_get_string (s, "stream-format"))) {
        if (strcmp (str, "avc") == 0)
          *format = GST_H264_PARSE_FORMAT_AVC;
        else if (strcmp (str, "byte-stream") == 0)
          *format = GST_H264_PARSE_FORMAT_BYTE;
        else if (strcmp (str, "avc3") == 0)
          *format = GST_H264_PARSE_FORMAT_AVC3;
      }
    }

    if (align) {
      if ((str = gst_structure_get_string (s, "alignment"))) {
        if (strcmp (str, "au") == 0)
          *align = GST_H264_PARSE_ALIGN_AU;
        else if (strcmp (str, "nal") == 0)
          *align = GST_H264_PARSE_ALIGN_NAL;
      }
    }
  }
}
  /* fix up caps witho
  ut stream-format for max. backwards compatibility */
  if (format == GST_H264_PARSE_FORMAT_NONE) {
    /* codec_data implies avc */
    if (codec_data_value != NULL) {
      GST_ERROR ("video/x-h264 caps with codec_data but no stream-format=avc");
      //这里对齐格式是AVC,也就是指定了nal的长度
      format = GST_H264_PARSE_FORMAT_AVC;
    } else {
      /* otherwise assume bytestream input */
      GST_ERROR ("video/x-h264 caps without codec_data or stream-format");
      //那么这里应该就是start code
      format = GST_H264_PARSE_FORMAT_BYTE;
    }
  }

  /* avc caps sanity checks */
  if (format == GST_H264_PARSE_FORMAT_AVC) {
    /* AVC requires codec_data, AVC3 might have one and/or SPS/PPS inline */
    if (codec_data_value == NULL)
      goto avc_caps_codec_data_missing;

    /* AVC implies alignment=au, everything else is not allowed */
    //如果是AVC那么对齐格式就必须是AU
    if (align == GST_H264_PARSE_ALIGN_NONE)
      align = GST_H264_PARSE_ALIGN_AU;
    else if (align != GST_H264_PARSE_ALIGN_AU)
      goto avc_caps_wrong_alignment;
  }

  /* bytestream caps sanity checks */
  if (format == GST_H264_PARSE_FORMAT_BYTE) {
    /* should have SPS/PSS in-band (and/or oob in streamheader field) */
    if (codec_data_value != NULL)
      goto bytestream_caps_with_codec_data;
  }

/* packetized video has codec_data (required for AVC, optional for AVC3) */
  if (codec_data_value != NULL) {
    GstMapInfo map;
    guint8 *data;
    guint num_sps, num_pps;
#ifndef GST_DISABLE_GST_DEBUG
    guint profile;
#endif
    gint i;

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

    /* codec_data field should hold a buffer */
    if (!GST_VALUE_HOLDS_BUFFER (codec_data_value))
      goto avc_caps_codec_data_wrong_type;

    codec_data = gst_value_get_buffer (codec_data_value);
    if (!codec_data)
      goto avc_caps_codec_data_missing;
    gst_buffer_map (codec_data, &map, GST_MAP_READ);
    data = map.data;
    size = map.size;

    /* parse the avcC data */
    if (size < 7) {             /* when numSPS==0 and numPPS==0, length is 7 bytes */
      gst_buffer_unmap (codec_data, &map);
      goto avcc_too_small;
    }
    /* parse the version, this must be 1 */
    if (data[0] != 1) {
      gst_buffer_unmap (codec_data, &map);
      goto wrong_version;
    }
#ifndef GST_DISABLE_GST_DEBUG
    /* AVCProfileIndication */
    /* profile_compat */
    /* AVCLevelIndication */
    profile = (data[1] << 16) | (data[2] << 8) | data[3];
    GST_DEBUG_OBJECT (h264parse, "profile %06x", profile);
#endif

    /* 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 size %u",
        h264parse->nal_length_size);

    num_sps = data[5] & 0x1f;
    off = 6;
    for (i = 0; i < num_sps; i++) {
    
      parseres = gst_h264_parser_identify_nalu_avc (h264parse->nalparser,
          data, off, size, 2, &nalu);
      if (parseres != GST_H264_PARSER_OK) {
        gst_buffer_unmap (codec_data, &map);
        goto avcc_too_small;
      }

      gst_h264_parse_process_nal (h264parse, &nalu);
      off = nalu.offset + nalu.size;
    }

    if (off >= size) {
      gst_buffer_unmap (codec_data, &map);
      goto avcc_too_small;
    }
    num_pps = data[off];
    off++;

    for (i = 0; i < num_pps; i++) {
      parseres = gst_h264_parser_identify_nalu_avc (h264parse->nalparser,
          data, off, size, 2, &nalu);
      if (parseres != GST_H264_PARSER_OK) {
        gst_buffer_unmap (codec_data, &map);
        goto avcc_too_small;
      }

      gst_h264_parse_process_nal (h264parse, &nalu);
      off = nalu.offset + nalu.size;
    }

    gst_buffer_unmap (codec_data, &map);

    gst_buffer_replace (&h264parse->codec_data_in, codec_data);

    /* don't confuse codec_data with inband sps/pps */
    h264parse->have_sps_in_frame = FALSE;
    h264parse->have_pps_in_frame = FALSE;
  } else if (format == GST_H264_PARSE_FORMAT_BYTE) {
  //这里明显看到GST_H264_PARSE_FORMAT_BYTE就是start code
    GST_DEBUG_OBJECT (h264parse, "have bytestream h264");
    /* nothing to pre-process */
    h264parse->packetized = FALSE;
    /* we have 4 sync bytes */
    h264parse->nal_length_size = 4;
  } else {
    /* probably AVC3 without codec_data field, anything to do here? */
  }

一定要看这个:入口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值