音视频入门基础:H.264专题(5)——FFmpeg源码中 解析NALU Header的函数分析

news2024/10/6 16:20:30

一、引言

FFmpeg源码中 通过h264_parse_nal_header函数将H.264码流的NALU Header解析出来。下面对h264_parse_nal_header函数进行分析。


 

二、h264_parse_nal_header函数定义

h264_parse_nal_header函数定义在FFmpeg源码(下面演示的FFmpeg源码版本是5.0.3)的源文件libavcodec/h2645_parse.c 中:

static int h264_parse_nal_header(H2645NAL *nal, void *logctx)
{
    GetBitContext *gb = &nal->gb;

    if (get_bits1(gb) != 0)
        return AVERROR_INVALIDDATA;

    nal->ref_idc = get_bits(gb, 2);
    nal->type    = get_bits(gb, 5);

    av_log(logctx, AV_LOG_DEBUG,
           "nal_unit_type: %d(%s), nal_ref_idc: %d\n",
           nal->type, h264_nal_unit_name(nal->type), nal->ref_idc);

    return 0;
}

该函数作用是:将NALU Header解析出来,由形参nal返回。

形参nal:

nal->gb:输入型参数。(&(nal->gb))->buffer指向存放NALU Header + RBSP 的缓冲区。

nal->ref_idc:输出型参数。执行h264_parse_nal_header函数后,nal->ref_idc的值为NALU Header中的nal_ref_idc。

nal->type:输出型参数。执行h264_parse_nal_header函数后,nal->type的值为NALU Header中的nal_unit_type。

形参logctx:输入型参数。用来输出日志,可以忽略。

返回值:解析NALU Header成功返回0。失败返回AVERROR_INVALIDDATA。

三、h264_parse_nal_header函数的内部实现原理

h264_parse_nal_header函数中,首先通过语句get_bits1(gb);拿到NALU Header中forbidden_zero_bit。关于get_bits1用法可以参考:《FFmpeg中位操作相关的源码:GetBitContext结构体,init_get_bits函数、get_bits1函数和get_bits函数分析》。

由于forbidden_zero_bit 的值应为0,如果它的值为1,则意味着比特流语法出错了,也就是FFmpeg头文件libavutil/error.h里面定义的“Invalid data found when processing input”:

#define AVERROR_INVALIDDATA        FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input

所以如果forbidden_zero_bit的值不为0,返回AVERROR_INVALIDDATA。

所以有下面语句:

if (get_bits1(gb) != 0)
        return AVERROR_INVALIDDATA;

然后通过下面语句,读取NALU Header中的nal_ref_idc和nal_unit_type,分别保存到nal->ref_idc和nal->type中。

nal->ref_idc = get_bits(gb, 2);
nal->type    = get_bits(gb, 5);

最后通过

av_log(logctx, AV_LOG_DEBUG,
           "nal_unit_type: %d(%s), nal_ref_idc: %d\n",
           nal->type, h264_nal_unit_name(nal->type), nal->ref_idc);

日志输出NALU Header的信息。

h264_nal_unit_name函数是用来得到nal_unit_type的名称。其定义如下:

static const char *const h264_nal_type_name[32] = {
    "Unspecified 0", //H264_NAL_UNSPECIFIED
    "Coded slice of a non-IDR picture", // H264_NAL_SLICE
    "Coded slice data partition A", // H264_NAL_DPA
    "Coded slice data partition B", // H264_NAL_DPB
    "Coded slice data partition C", // H264_NAL_DPC
    "IDR", // H264_NAL_IDR_SLICE
    "SEI", // H264_NAL_SEI
    "SPS", // H264_NAL_SPS
    "PPS", // H264_NAL_PPS
    "AUD", // H264_NAL_AUD
    "End of sequence", // H264_NAL_END_SEQUENCE
    "End of stream", // H264_NAL_END_STREAM
    "Filler data", // H264_NAL_FILLER_DATA
    "SPS extension", // H264_NAL_SPS_EXT
    "Prefix", // H264_NAL_PREFIX
    "Subset SPS", // H264_NAL_SUB_SPS
    "Depth parameter set", // H264_NAL_DPS
    "Reserved 17", // H264_NAL_RESERVED17
    "Reserved 18", // H264_NAL_RESERVED18
    "Auxiliary coded picture without partitioning", // H264_NAL_AUXILIARY_SLICE
    "Slice extension", // H264_NAL_EXTEN_SLICE
    "Slice extension for a depth view or a 3D-AVC texture view", // H264_NAL_DEPTH_EXTEN_SLICE
    "Reserved 22", // H264_NAL_RESERVED22
    "Reserved 23", // H264_NAL_RESERVED23
    "Unspecified 24", // H264_NAL_UNSPECIFIED24
    "Unspecified 25", // H264_NAL_UNSPECIFIED25
    "Unspecified 26", // H264_NAL_UNSPECIFIED26
    "Unspecified 27", // H264_NAL_UNSPECIFIED27
    "Unspecified 28", // H264_NAL_UNSPECIFIED28
    "Unspecified 29", // H264_NAL_UNSPECIFIED29
    "Unspecified 30", // H264_NAL_UNSPECIFIED30
    "Unspecified 31", // H264_NAL_UNSPECIFIED31
};

static const char *h264_nal_unit_name(int nal_type)
{
    av_assert0(nal_type >= 0 && nal_type < 32);
    return h264_nal_type_name[nal_type];
}

可以看到h264_nal_unit_name函数内部通过nal_unit_type拿到数组h264_nal_type_name中对应的字符串(名称)。

h264_nal_type_name数组跟H.264官方文档《T-REC-H.264-202108-I!!PDF-E.pdf》第65页描述的nal_unit_type对应:

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

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

相关文章

阅读笔记——《Large Language Model guided Protocol Fuzzing》

【参考文献】Meng R, Mirchev M, Bhme M, et al. Large language model guided protocol fuzzing[C]//Proceedings of the 31st Annual Network and Distributed System Security Symposium (NDSS). 2024.&#xff08;CCF A类会议&#xff09;【注】本文仅为作者个人学习笔记&a…

Geoserver源码解读四 REST服务

文章目录 文章目录 一、概要 二、前置知识点-FreeMarker 三、前置知识点-AbstractHttpMessageConverter 3.1 描述 3.2 应用 四、前置知识点-AbstractDecorator 4.1描述 4.2 应用 五、工作空间查询解读 5.1 模板解读 5.2 请求转换器解读 一、概要 关于geoserver的r…

2024最新算法:北极海鹦优化(Arctic puffin optimization,APO)算法求解23个函数,MATLAB代码

一、算法介绍 北极海鹦优化&#xff08;Arctic puffin optimization&#xff0c;APO&#xff09;算法是2024年提出一种智能优化算法。该算法模拟海鹦在空中飞行和水下觅食两个阶段的行为&#xff0c;旨在实现勘探与开发之间更好的平衡。该算法包括几个关键操作&#xff0c;包括…

Nginx开发【Nginx虚拟主机和域名解析】

03 【Nginx虚拟主机和域名解析】 虚拟主机使用特殊的软硬件技术&#xff0c;把一台运行在因特网上的服务器主机分成一台台“虚拟”的主机&#xff0c;每一台虚拟主机都具有独立的域名&#xff0c;具有完整的Internet服务器&#xff08;WWW、FTP、Email等&#xff09;功能&…

FFmpeg+javacpp+javacv使用

FFmpegjavacppjavacv使用 Bytedeco官网案例1、导入opencv、ffmpeg依赖包2、FFmpeg 数据结构2.1 AVFormatContext 格式化I/O上下文2.1.1 metadata2.1.2 Duration、start、bitrate等其他信息2.1.3 dump信息 Bytedeco GitHub&#xff1a;javacpp Bytedeco官网案例 FFmpeg – [示例…

C语言·动态内存管理

1. 为什么要有动态内存管理&#xff1f; 例1&#xff1a; //固定的向内存申请4个字节 int a 10;//申请连续的一块空间 int arr[10]; 这些数据一旦声明定义之后就会在内存中有一块空间&#xff0c;这些空间都是固定的&#xff0c;为了让内存使用更加灵活&#xff0c;这时我们…

【回溯算法题记录】组合总和题汇总

组合总和 39. 组合总和题目描述初始思路后续分析 40. 组合总和 II题目描述思路&#xff08;参考代码随想录&#xff09; 39. 组合总和 题目&#x1f517; 题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数…

开源网安参与编制的《代码大模型安全风险防范能力要求及评估方法》正式发布

​代码大模型在代码生成、代码翻译、代码补全、错误定位与修复、自动化测试等方面为研发人员带来了极大便利的同时&#xff0c;也带来了对安全风险防范能力的挑战。基于此&#xff0c;中国信通院依托中国人工智能产业发展联盟&#xff08;AIIA&#xff09;&#xff0c;联合开源…

教你使用 Go 语言访问智谱 AI 大模型!

AI 大模型太火爆了&#xff01;我在工作中经常使用它们&#xff0c;感觉已经离不开了&#xff01; 最近测试了智谱 AI 大模型&#xff0c;实测下来感觉还挺不错的。 官方提供了体验包&#xff0c;注册并实名认证之后有 300 万 token&#xff0c;非常壕&#xff01; 今天的股…

uni-push(2.0)常见问题,Android平台

将常用的网址一定要收藏在标签栏中&#xff0c;方便后期找&#xff0c;不然后期会很生气。 草料二维码&#xff0c;这个在线工具可以将打包生成的apk文件生成二维码&#xff0c;供测试人员测试。生成的apk只有五次下载机会&#xff0c;可点击链接后的一键上传&#xff0c;这样…

站在巨人的肩膀上 C语言理解和简单练习(包含指针前的简单内容)

1.格式化的输入/输出 1.1printf函数 printf函数你需要了解的就是转换说明&#xff0c;转换说明的作用是将内存中的二进制转换成你所需要的格式入%d就是将内存中存储的变量的二进制转化为十进制并打印出来&#xff0c;同时我们可以在%X的转换说明对精度和最小字段宽度的指定&a…

如何在SpringBoot中自定义starter

如何在SpringBoot中自定义starter Spring Boot 提供了一种简便的方法来创建自定义的 starter&#xff0c;从而帮助开发者封装常用的配置和依赖。本文将介绍如何在 Spring Boot 中自定义一个 starter。 1. 创建 Maven 项目 首先&#xff0c;创建一个新的 Maven 项目&#xff…

SpringBoot开启事务日志

一般框架开启日志的方式&#xff1a; 开启某个包下的日志就写该包路径&#xff0c;开启某个类下的日志就写该类路径。

全国首场以AI数字内容风控为主题的大会,开放参会报名中

网易易盾将于2024年7月6日举办一场AI数字内容风控大会&#xff0c;邀请AI产业链的基础层、模型层和应用层的企业代表&#xff0c;科研机构、律所、院校的专家老师&#xff0c;探讨大模型时代下的自由与责任等话题。参会报名链接&#xff1a;https://sourl.cn/vqUU7X&#xff0c…

【计算机毕业设计】基于Springboot的月度员工绩效考核管理系统【源码+lw+部署文档】

包含论文源码的压缩包较大&#xff0c;请私信或者加我的绿色小软件获取 免责声明&#xff1a;资料部分来源于合法的互联网渠道收集和整理&#xff0c;部分自己学习积累成果&#xff0c;供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者…

HTTP/2 头部压缩 Header Compress(HPACK)详解

文章目录 1. HPACK 的工作原理1.1 静态表1.2 动态表 2. 压缩过程2.1 编码过程2.2 解码过程 3. HPACK 的优势 在HTTP1.0中&#xff0c;我们使用文本的形式传输header&#xff0c;在header中携带cookie的话&#xff0c;每次都需要重复传输几百到几千的字节&#xff0c;这着实是一…

推荐系统-FM模型

参考&#xff1a;推荐系统&#xff08;三&#xff09;Factorization Machines&#xff08;FM&#xff09;_svmmf-CSDN博客 一句话概括下FM&#xff1a;隐式向量特征交叉----类似embedding的思想 LR 如果利用LR做特征的二阶交叉&#xff0c;有&#xff1a; 但这个公式存在显著…

从0开始C++(七):继承

相关文章&#xff1a; 从0开始C&#xff08;一&#xff09;&#xff1a;从C到C 从0开始C&#xff08;二&#xff09;&#xff1a;类、对象、封装 从0开始C&#xff08;三&#xff09;&#xff1a;构造函数与析构函数详解 从0开始C&#xff08;四&#xff09;&#xff1a;作…

香港服务器托管对外贸行业必要性和优势

在当今全球化的经济环境下&#xff0c;外贸企业面临着前所未有的机遇与挑战。其中&#xff0c;服务器托管的选择对于外贸企业的运营效率和市场拓展具有举足轻重的作用。香港服务器&#xff0c;凭借其独特的地理位置、优质的网络环境和卓越的服务性能&#xff0c;一直是外贸企业…

2024年必备的15个免费 SVG 设计资源

在动态设计领域&#xff0c;SVG&#xff08;可缩放矢量图形&#xff09;已成为设计师打造响应迅速、清晰且适应性强的视觉效果的必备工具。 这些设计非常适合幻灯片 PowerPoint 演示文稿、应用程序设计、网站设计、原型设计、社交媒体帖子等。 在这篇文章中&#xff0c;我们将…