FFmpeg简单使用:解封装h264 ---- 提取SPS PPS

news2025/2/28 14:58:51

前言

我们从flv和mp4等文件解封装读取的AVPacket并没有SPS、PPS数据,而是保存在 AVFormatContext -> streams -> codecpar -> extradata里面,下面我们打开一个flv文件看一下

 

分析一下这块数据,起始位置:0980 大小:39 结束位置:09a6

前4个字节:

  0x01: version

  0x42: avc profile (首个SPS的第1个字节)

  0xc0: avc compatibility (首个SPS的第2个字节)

     0x28: avc level (首个SPS的第3个字节,可以发现后面0x0989位置的3个字,和这3个是一样的)

第5个字节:

  0xff:

    6_bit: 默认111111

      2_bit: 数据长度-1:avcc格式是extradata | [length] [nalu]  | [length][nalu],这里length所占的字节数就是3(11)+ 1 = 4 

第6个字节:

  0xe1: [111 00001]

    3_bit: 默认 111

    5_bit: 接下来的sps或pps的个数::这里为1

第7 8个字节:

  0x00 0x18: 表示接下来sps或者pps的长度为24

第9个字节:

  0x67: [0110 0111] nalu_type为7,表示SPS,就是说从0988到099f这24个数据为sps

第33个字节:9 (sps_pos) + 24(sps_size)

  0x01: 接下来的sps或pps的个数::这里为1

第34 35字节:

  0x00 0x04: 表示接下来sps或者pps的长度为4

第36个字节:

  0x68: [0110 1000] nalu_type为8,表示PPS

编码

 

int VideoSend::ParseExtradata(VideoState* is)
{
    uint8_t* start_data = is->video_st->codecpar->extradata;
    uint8_t* extradata = is->video_st->codecpar->extradata;
    int extradata_size = is->video_st->codecpar->extradata_size;
    std::cout << "extradata_size:" << extradata_size << std::endl;
    for (int i = 0; i < extradata_size; ++i) {
        printf(" %02x", *(extradata+i));
    }
    std::cout << std::endl;
    // 1. 跳过前4个字节
    extradata = extradata +4;
    
    // 2. byte_5:获取nalu length所占字节数
    d->nalu_length_bytes = (*extradata++ & 0x03) + 1;
    std::cout << "nalu_length_bytes:" << (int)d->nalu_length_bytes << std::endl;

    int sps_seen = 0, pps_seen = 0;
    while ((extradata - start_data) < extradata_size) {
        // 3. byte_6:获取下面sps/pps个数
        uint8_t item_nb = *extradata++ & 0x1f;
        std::cout << "item_nb:" << (int)item_nb << std::endl;
        if (!item_nb) {
            continue;
        }

        int ret;
        while(item_nb--){
            // 4. byte_7 byte_8: 表示sps或者pps长度
            uint16_t uint_size = (extradata[0] << 8) | extradata[1];
            std::cout << "uint_size: " << uint_size << std::endl;

            // 5. 数据异常
            if ((extradata - start_data + uint_size + 2) > extradata_size) {
                 std::cout << "extradata exception " << uint_size << std::endl;
                 goto failed;
            }

            // 6. byte_9: 检查包类型
            uint8_t nalu_type =  extradata[2];
            nalu_type = nalu_type & 0x1f;
            std::cout << "nalu_type: " << (int)nalu_type << std::endl;

            // 7. sps
            if (nalu_type == 7 && !sps_seen) {
                std::cout << "--sps--" << std::endl;
                // a.分配内存
                if (ret = av_reallocp(&d->sps_pkt.buf, uint_size) < 0) {
                    goto failed;
                }
                // b.数据拷贝
                memcpy(d->sps_pkt.buf, extradata + 2, uint_size);
                sps_seen = 1;
                d->sps_pkt.size = uint_size;
            }

            // 8. pps
            if (nalu_type == 8 && !pps_seen) {
                std::cout << "--pps--" << std::endl;
                 // a.分配内存
                if (ret = av_reallocp(&d->pps_pkt.buf, uint_size) < 0) {
                    goto failed;
                }
                // b.数据拷贝
                memcpy(d->pps_pkt.buf, extradata + 2, uint_size);
                pps_seen = 1;
                d->pps_pkt.size = uint_size;
            }
            extradata = extradata + 2 + uint_size;
        }  
    }

    if (pps_seen && sps_seen) {
        std::cout << "sps:";
        for (int i = 0; i < d->sps_pkt.size; ++i) {
            printf(" %02x", d->sps_pkt.buf[i]);
        }
        std::cout << std::endl;

        std::cout << "pps:";
        for (int i = 0; i < d->pps_pkt.size; ++i) {
            printf(" %02x", d->pps_pkt.buf[i]);
        }
        std::cout << std::endl;
        return 0;
    }
  
failed:
    std::cout << "VideoSend::ParseExtradata failed." << std::endl;
    if (d->pps_pkt.buf) {
        av_free(d->pps_pkt.buf);
        d->pps_pkt.buf = NULL;
    }

    if (d->sps_pkt.buf) {
        av_free(d->sps_pkt.buf);
        d->sps_pkt.buf = NULL;
    }
    return -1;
}

输出: 

 extradata_size:40
 01 42 c0 1e ff e1 00 18 67 42 c0 1e db 02 c0 c7 96 a1 00 00 03 00 01 00 00 03 00 32 8f 16 2e e0 01 00 05 68 ca 83 cb 20
nalu_length_bytes:4
item_nb:1
uint_size: 24
nalu_type: 7
--sps--
item_nb:1
uint_size: 5
nalu_type: 8
--pps--
sps: 67 42 c0 1e db 02 c0 c7 96 a1 00 00 03 00 01 00 00 03 00 32 8f 16 2e e0
pps: 68 ca 83 cb 20

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/117488.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【软件测试】测试点总结,收取短信验证码的测试(详全),你的即用宝典......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 现在的APP&#xff…

技术评审管理方案

技术评审&#xff08;Technical Review, TR&#xff09;的目的是尽早地发现工作成果中的缺陷&#xff0c;并帮助开发人员及时消除缺陷&#xff0c;从而有效地提高产品的质量。 技术评审过程域是SPP模型的重要组成部分。本规范阐述了技术评审过程域的三个主要规程&#xff1a; …

基于Java(SSM+SpringBoot+Thymeleaf)+MySQL 开发的论坛社区网站【100010072】

基于 SSM Spring Boot Thymeleaf 开发的论坛社区网站 项目概述 本项目是依据 2019 年牛客项目&#xff0c;基于 SSM Spring Boot Thymeleaf 开发的论坛社区网站&#xff0c;网站实现了如下功能&#xff1a; 使用 Spring Email Interceptor Spring Security 等实现网站…

unity组件介绍

所有物体都是一个空物体&#xff0c;加上一些组件才形成了所需要的GameObject。 这是一个空物体&#xff0c;在Scene场景中没有任何外在表现&#xff0c;因为它只有Transform这个组件&#xff0c;表示它仅仅只有位置&#xff0c;旋转和缩放。 Mesh组件 Mesh Filter mesh filt…

【聆思CSK6 视觉AI开发套件试用】(有彩蛋)AI头肩手势检测

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;Tony_c217AK 牛逼的AI套件 如何3分钟体验AI功能&#xff08;windows系统 &#xff09; 插入上图左边的USB(上图中靠近左边的USB接口),给设备上…

锁,CAS,Synchronized 原理

作者&#xff1a;~小明学编程 文章专栏&#xff1a;JavaEE 格言&#xff1a;热爱编程的&#xff0c;终将被编程所厚爱。 目录 常见的锁 悲观锁与乐观锁 悲观锁 乐观锁 读写锁 重量级锁 vs 轻量级锁 挂起等待锁和自旋锁 公平锁和非公平锁 可重入锁与不可重入锁 CAS …

JavaDS4-链表

目录 1.定义 2.结构 2.1.类似火车 2.2.分类 2.2.1.按方向分 2.2.2.按是否带头节点分 2.2.3.按是否循环分 3.重点掌握 3.1.无头单向非循环链表 3.1.1.在链表的头部添加节点 3.1.2.在链表的任意位置index处添加节点 3.1.3.在链表的尾部添加节点 3.1.4.查询链表的任意…

如何使用单总线?

如何使用单总线&#xff1f;一、什么叫单总线&#xff1f;二、单总线协议&#xff1f;三、怎么使用单总线来做开发&#xff1f;IBUTTON 钥匙读取复制设备项目一、什么叫单总线&#xff1f; 1.如下图&#xff0c;使用单总线的传感器DS18B20 2.使用单总线的储物柜钥匙 3.定义&…

元素偏移量 offset、元素可视区 client和元素滚动 scroll

1、元素偏移量 offset 系列 1.1、offset 概述 offset 翻译过来就是偏移量&#xff0c; 我们使用 offset系列相关属性可以动态的得到该元素的位置&#xff08;偏移&#xff09;、大小等。 获得元素距离带有定位父元素的位置获得元素自身的大小&#xff08;宽度高度&#xff09…

【java】static关键字

static可以修饰的内容如下&#xff1a; ● 变量 ● 方法 ● 代码块 ● 内部类 那就有一个问题&#xff0c;为什么static不能修饰外部类&#xff1f; 我们首先看一下static的作用是什么&#xff1f; 先看看其他人怎么解释的&#xff1a; A static method can be accessed with…

RK3588平台开发系列讲解(进程篇)进程的简介

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、进程的四要素二、进程的三种状态三、task_struct数据结构四、进程优先级五、进程系统调用沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍进程的相关知识。 一、进程的四要素 1、有一段程序供其…

Axure 原型适应到不同平台的方法

“老师&#xff0c;公司要求我做一个不同机型的原型&#xff0c;不想重新做&#xff0c;可以适配吗&#xff1f;” “老师&#xff0c;手机有那么多类型&#xff0c;我难道要做那么多的原型吗&#xff1f;” “老师&#xff0c;axure中怎么进行原型的适配呢&#xff1f;应该怎…

云服务器搭建网站(初学)

第一步&#xff1a;来到/var/www/目录下 第二步&#xff1a;在www目录下创建web1文件夹 第三步&#xff1a;来到root目录 第四步&#xff1a;在root目录上传所需要的压缩包 第五步&#xff1a;解压刚刚上传的压缩包到指定的目录&#xff08;我们刚刚所创建的web1目录&#xff…

HTML5 文件操作

文章目录HTML5 文件操作file元素选择单个文件选择多个文件美化file元素File对象获取文件信息转化单位FileReader对象读取txt文本在线预览图片拖拽文件并读取拖拽图片并预览Blob对象创建并下载txt文件将Canvas下载为一张图片HTML5 文件操作 file元素 语法 <input type&quo…

SpringIOC流程以及Mybatis架构

1、Spring IOC 流程图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/626a8582f4b14ac3983567a85bce1d4d.png IOC 依赖注入整体流程 1、环境初始化 2、Bean工厂初始化 3、读取项目配置 4、定义解析Bean-->BeanDefintion 5、将BeanDefinition存储工厂类的Map 6、通过…

Golang 将视频按照时间维度剪切 | Golang工具

目录 前言 环境依赖 代码 总结 前言 本文提供将视频按照时间维度进行剪切的工具方法&#xff0c;一如既往的实用主义。 主要也是学习一下golang使用ffmpeg工具的方式。 环境依赖 ffmpeg环境安装&#xff0c;可以参考我的另一篇文章&#xff1a;windows ffmpeg安装部署_阿…

2022 IoTDB Summit:IoTDB PMC 乔嘉林《端边云协同:Apache IoTDB 全新单机分布式架构》...

12 月 3 日、4日&#xff0c;2022 Apache IoTDB 物联网生态大会在线上圆满落幕。大会上发布 Apache IoTDB 的分布式 1.0 版本&#xff0c;并分享 Apache IoTDB 实现的数据管理技术与物联网场景实践案例&#xff0c;深入探讨了 Apache IoTDB 与物联网企业如何共建活跃生态&#…

具有循环条件gan的实值(医疗)时间序列生成-2017

REAL-VALUED (MEDICAL) TIME SERIES GENERATION WITH RECURRENT CONDITIONAL GANS ABSTRACT 生成对抗网络(GANs)作为一种训练模型以产生逼真数据的框架已经取得了显著的成功。在这项工作中&#xff0c;我们提出了循环GAN (RGAN)和循环条件GAN (RCGAN)来生成真实的实值多维时间…

canal实战问题汇总分析

canal在实战过程经常会遇到这样或者那样的问题&#xff0c;今天我们专门用一篇文章来列举分析一下&#xff0c;比如、JDK版meta.dat 中保存的位点信息和数据库的位点信息不一致本不匹配、bin-log信息消费失败等问题&#xff0c;下面我们开始一一分析&#xff1a; 1、数据库数据…

数据可视化软件有哪些?

随着大数据概念的普及与业务数据的爆炸式增长&#xff0c;越来越多的企业已经不满足于Excel的常规操作。 因为相较于以往PPT/Word/Excel数据汇报的形式而言&#xff0c;数据可视化平台包含了丰富的图表、组件信息&#xff0c;仅用一张屏幕就能够囊括诸多讯息&#xff0c;画面色…