hevc_mp4toannexb_bsf.c/h264_mp4toannexb_bsf.c

本文主要分析mp4封装的h265/h264,copy转hls,红色为自己添加的注释。

动态添加此filter
    for (i = 0; i < nb_output_streams; i++) {
        ost = output_streams[i];
        if(ost->st->codec->codec_type  == AVMEDIA_TYPE_VIDEO && ost->st->codec->codec_id == AV_CODEC_ID_H264)
        {
           AVBitStreamFilterContext * avFilter = av_bitstream_filter_init("h264_mp4toannexb");
           ost->bitstream_filters = avFilter;
        }else if(ost->st->codec->codec_type  == AVMEDIA_TYPE_VIDEO && ost->st->codec->codec_id == AV_CODEC_ID_HEVC)
        {
           AVBitStreamFilterContext * avFilter = av_bitstream_filter_init("hevc_mp4toannexb");
           ost->bitstream_filters = avFilter;
        }

}

hevc->hls

如果不加 -bsf:v hevc_mp4toannex,就会报如下错误:

原因如下:

check_hevc_startcode会发现没有00000001字段。



相关代码有:hevc_mp4toannexb_bsf.c

前缀(vps,sps,pps)例子如下:


typedef structHEVCBSFContext {

    uint8_t length_size;

    int     extradata_parsed;

}HEVCBSFContext;


static inthevc_extradata_to_annexb(AVBSFContext *ctx)

{

    GetByteContext gb;

    int length_size, num_arrays, i, j;

    int ret = 0;

    uint8_t *new_extradata = NULL;

    size_t  new_extradata_size = 0;

    bytestream2_init(&gb,ctx->par_in->extradata, ctx->par_in->extradata_size);

    bytestream2_skip(&gb, 21); 

    //跳过21个字节

    length_size =(bytestream2_get_byte(&gb) & 3) + 1;

    //22个字节(0x03)后两位加上1

    num_arrays = bytestream2_get_byte(&gb);

    //23个字节(0x03

    for (i = 0; i < num_arrays; i++) {

        int type =bytestream2_get_byte(&gb) & 0x3f;

        //对应0x200x210x22

        int cnt = bytestream2_get_be16(&gb);

        //对应0x00 0x01 0x00 0x01 0x00 0x01,

        if (!(type == NAL_VPS || type ==NAL_SPS || type == NAL_PPS ||

              type == NAL_SEI_PREFIX || type ==NAL_SEI_SUFFIX || type == 0)) {

            av_log(ctx, AV_LOG_ERROR,"Invalid NAL unit type in extradata: %d\n",

                   type);

            ret = AVERROR_INVALIDDATA;

            goto fail;

        }

        for (j = 0; j < cnt; j++) {

            int nalu_len =bytestream2_get_be16(&gb);

            //对应0x00 0x170x40~0x59),0x00 0x270x42~0x40),0x00 0x070x44~0x20

            if (4 +AV_INPUT_BUFFER_PADDING_SIZE + nalu_len > SIZE_MAX - new_extradata_size) {

                ret = AVERROR_INVALIDDATA;

                goto fail;

            }

            ret =av_reallocp(&new_extradata, new_extradata_size + nalu_len + 4 +AV_INPUT_BUFFER_PADDING_SIZE);

            if (ret < 0)

                goto fail;

            AV_WB32(new_extradata +new_extradata_size, 1);

            // addthe startcode,也就是00 00 00 01

            bytestream2_get_buffer(&gb,new_extradata + new_extradata_size + 4, nalu_len);

            new_extradata_size += 4 + nalu_len;

            memset(new_extradata + new_extradata_size,0, AV_INPUT_BUFFER_PADDING_SIZE);

        }

    }

   av_freep(&ctx->par_out->extradata);

    ctx->par_out->extradata      = new_extradata;

    ctx->par_out->extradata_size =new_extradata_size;

    //得到新的字符串,长度。

    if (!new_extradata_size)

        av_log(ctx, AV_LOG_WARNING, "Noparameter sets in the extradata\n");

    return length_size;

fail:

    av_freep(&new_extradata);

    return ret;

}

 

static inthevc_mp4toannexb_init(AVBSFContext *ctx)

{

  ...

}

 

//对于每一帧,都会进入hevc_mp4toannexb_filter函数,如下:


static inthevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)

{

    HEVCBSFContext *s = ctx->priv_data;

    AVPacket *in;

    GetByteContext gb;

    int got_irap = 0;

    int i, ret = 0;

    ret = ff_bsf_get_packet(ctx, &in);

    if (ret < 0)

        return ret;

    if (!s->extradata_parsed) {

        av_packet_move_ref(out, in);

        av_packet_free(&in);

        return 0;

    }

    bytestream2_init(&gb, in->data,in->size);

    while (bytestream2_get_bytes_left(&gb)){

        uint32_t nalu_size = 0;

        int     nalu_type;

        int is_irap, add_extradata, extra_size,prev_size;

        for (i = 0; i < s->length_size;i++)

            nalu_size = (nalu_size << 8)| bytestream2_get_byte(&gb);

        //4位表示数据大小。

        nalu_type =(bytestream2_peek_byte(&gb) >> 1) & 0x3f;

        //对应0x26

        /* prepend extradata to IRAP frames */

        is_irap       = nalu_type >= 16 &&nalu_type <= 23;

        //帧类型在1623之间,都会被强插入vps等前缀。

        add_extradata = is_irap &&!got_irap;

        extra_size    = add_extradata *ctx->par_out->extradata_size;

        got_irap     |= is_irap;

        if (SIZE_MAX - nalu_size < 4 ||

            SIZE_MAX - 4 - nalu_size <extra_size) {

            ret = AVERROR_INVALIDDATA;

            goto fail;

        }

        prev_size = out->size;

        ret = av_grow_packet(out, 4 + nalu_size+ extra_size);

        if (ret < 0)

            goto fail;

        if (add_extradata)

            memcpy(out->data + prev_size,ctx->par_out->extradata, extra_size);

        //插入vps等前缀。

        AV_WB32(out->data + prev_size +extra_size, 1);

        // add thestartcode,也就是00 00 00 01

        bytestream2_get_buffer(&gb,out->data + prev_size + 4 + extra_size, nalu_size);

        //拷贝帧数据。

    }

    ret = av_packet_copy_props(out, in);

    if (ret < 0)

        goto fail;

fail:

    if (ret < 0)

        av_packet_unref(out);

    av_packet_free(&in);

    return ret;

}

...

h264->hls

解析mp4的块,得到sps,pps总数据,在h264_mp4toannexb_filter中去除头,得到sps,pps(只做一次),然后在每个关键帧前插sps,pps数据。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山西茄子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值