Ffmpeg对sps/pps的解析和格式转换

H264流的 SPS(序列参数集Sequence Parameter Set)和PPS(图像参数集Picture Parameter Set)记录了视频的基本编码信息,在进行视频处理的时候,难免会对其进行处理,下面介绍几个相关的API对其进行解析和格式转换。

首先来看两种格式:

Annex-B 和 AVCC/HVCC

H.264码流分Annex-B和AVCC两种格式。 H.265码流是Annex-B和HVCC格式。 (以下内容针对H.264,但大体也适用于H.265/HEVC)

别名

  • AVCC格式 也叫AVC1格式,MPEG-4格式,字节对齐,因此也叫Byte-Stream Format。用于mp4/flv/mkv, VideoToolbox。
  • Annex-B格式 也叫MPEG-2 transport stream format格式(ts格式), ElementaryStream格式

结构上的区别:

区别有两点:一个是参数集(SPS, PPS)组织格式;一个是分隔。 - Annex-B:使用start code分隔NAL(start code为三字节或四字节,0x000001或0x00000001,一般是四字节);SPS和PPS按流的方式写在头部。 - AVCC:使用NALU长度(固定字节,通常为4字节)分隔NAL;在头部包含extradata(或sequence header)的结构体。(extradata包含分隔的字节数、SPS和PPS)

举两个例子:

avcc格式:

01 64 00 1f ff e1 00 19 67 64 00 1f ac d9 40 50 05 ba 10 00 00 03 00 10 00 00 03 03 c8 f1 83 19 60 01 00 05 68 ea ec b2 2c

annex-b格式

00 00 00 01 67 64 00 28 ac b3 00 a0 0b 74 20 00 00 03 00 20 00 00 fa 01 e3 06 4d 00 00 00 01 68 e9 73 2c 8b

其中0x67表示SPS,0x68表示PPS

Annex-B格式转AVCC

int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)

在flvenc.c里面可以看到有以下调用:

            avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
            avio_w8(pb, 0); // AVC sequence header
            avio_wb24(pb, 0); // composition time
            ff_isom_write_avcc(pb, par->extradata, par->extradata_size);

将extradata以avcc的格式写入avc sequence header里面

AVCC格式转Annex-B

int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size)

解析Annex-B格式

    AVCodec *const codec = avcodec_find_decoder(AV_CODEC_ID_H264);
    if (codec != NULL) 
    {               
        AVCodecContext* ctx = avcodec_alloc_context3(codec);
        ctx->debug = ~0;
        ctx->extradata = (uint8_t *)av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
        ctx->extradata_size = size;
        memcpy(ctx->extradata, data,size); 
        memset(&ctx->extradata[ctx->extradata_size], 0, FF_INPUT_BUFFER_PADDING_SIZE); 

        if (avcodec_open2(ctx, codec, NULL) < 0) 
        {
            fprintf(stderr, "Failed to open codec\n");
        }
        else
        {   
            char buf[1024];
            avcodec_string(buf, sizeof(buf), ctx, 0);
            fprintf(stderr, "[%s\n", buf);

        }
        avcodec_close(ctx);
        av_free(ctx);
    }
     

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

Thomas的技术专栏

1 篇文章1 人订阅

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java学习网

常见的 Java 错误及避免方法之第五集(每集10个错误后续持续发布)

当输入期间意外终止文件或流时,将抛出“EOFException”。 以下是抛出EOFException异常的一个示例,来自JavaBeat应用程序:

17230
来自专栏java一日一条

50个常见的 Java 错误及避免方法(第三部分)

当我们尝试调用带有错误参数的Java代码时,通常会产生此Java错误消息(@ghacksnews):

16130
来自专栏逸鹏说道

我这么玩Web Api(二)

数据验证,全局数据验证与单元测试 目录 一、模型状态 - ModelState 二、数据注解 - Data Annotations 三、自定义数据注解 四、全局...

54760
来自专栏java、Spring、技术分享

Netty NioEventLoop源码解读

  NioEventLoop中维护了一个线程,线程启动时会调用NioEventLoop的run方法,执行I/O任务和非I/O任务:I/O任务:即selectio...

27130
来自专栏飞扬的花生

在ASP.MVC中使用Ajax

      Asp.net MVC 抛弃了Asp.net WebForm那种高度封装的控件,让我们跟底层的HTML有了更多的亲近。可以更自由、更灵活的去控制HT...

23190
来自专栏菩提树下的杨过

silverlight动态读取txt文件/解析json数据/调用wcf示例

终于开始正式学习silverlight,虽然有点晚,但总算开始了,今天看了一下sdk,主要是想看下silverlight中如何动态调用数据,对于数据库的访问,s...

251100
来自专栏Android 开发学习

JsBridge 源码分析

19830
来自专栏技术博客

MVC Html.RenderPartial和Html.partial

①Html.Partial是HtmlHelper的扩展方法,而Html.RenderPartial是HtmlHelper自带方法,两者功能相近。但

19140
来自专栏大内老A

WCF的Binding模型之四:信道工厂(Channel Factory)

由于信道管理器在客户端和服务端所起的不同作用,分为信道监听器和信道工厂。和服务端的信道监听其相比,处于客户端的信道工厂显得简单。从名称就可以看得出来,信道工厂的...

19280
来自专栏刘望舒

LeakCanary看这一篇文章就够了

LeakCanary是Square公司基于MAT开源的一个内存泄漏检测工具,在发生内存泄漏的时候LeakCanary会自动显示泄漏信息。

3.3K50

扫码关注云+社区

领取腾讯云代金券