FFmpeg源码:get_bit_length函数分析

一、get_bit_length函数的作用

get_bit_length函数的定义放在FFmpeg源码(本文演示用的FFmpeg源码版本为5.0.3,该ffmpeg在CentOS 7.5上通过10.2.1版本的gcc编译)的源文件libavcodec/h2645_parse.c中:

static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros)
{
//...
}

该函数在H.264/H.265解码时被调用。当FFmpeg对H.264/H.265解码执行完ff_h2645_extract_rbsp函数后,指针nal->data会指向一个缓冲区(该缓冲区存放“NALU Header + RBSP”,详情可以参考FFmpeg源码:ff_h2645_extract_rbsp函数分析)。然后调用get_bit_length函数,可以得到nal->data指向的缓冲区的去掉补齐后的位数(bit),也就是NALU Header + SODB的位数。关于RBSP、SODB的概念可以参考《音视频入门基础:H.264专题(3)——EBSP, RBSP和SODB》

形参nal:输入型参数:

nal->data:指向一个缓冲区,该缓冲区存放“NALU Header + RBSP”。

nal->size:nal->data指向的缓冲区的大小,单位为字节。

形参skip_trailing_zeros:计算返回值的位数(bit)时是否忽略nal->data指向的缓冲区最后ASCII码值为0的字符。值为0表示不忽略,1表示忽略。一般skip_trailing_zeros的值为1。

返回值:NALU Header + SODB的位数(bit)。注意这个返回值的单位是bit不是byte。8 bit 等于 1 byte,也就是1个字节等于8位。

二、get_bit_length函数的内部实现

get_bit_length函数的完整定义如下:

static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros)
{int size = nal->size;int v;while (skip_trailing_zeros && size > 0 && nal->data[size - 1] == 0)size--;if (!size)return 0;v = nal->data[size - 1];if (size > INT_MAX / 8)return AVERROR(ERANGE);size *= 8;/* remove the stop bit and following trailing zeros,* or nothing for damaged bitstreams */if (v)size -= ff_ctz(v) + 1;return size;
}

get_bit_length函数中首先会通过语句int size = nal->size;拿到 nal->data指向的缓冲区的大小(单位为字节)。然后通过:

while (skip_trailing_zeros && size > 0 && nal->data[size - 1] == 0)size--;

去掉nal->data指向的缓冲区中最后ASCII码值为0的字符(因为最后ASCII码值为0的字符可能是下一个NALU的起始码的一部分。H.264 RBSP的最后必定是值为1的stop bit + 补齐用的rbsp_alignment_zero_bit,故最后ASCII码值为0的字符不可能是RBSP的结尾,所以得去掉)。

执行完上述语句后,size的值为NALU Header + RBSP 的实际长度(单位为字节)。

然后通过v = nal->data[size - 1] 得到RBSP最后一个字节的数据。由于8 bit 等于1 byte,通过size *= 8;得到NALU Header + RBSP的总位数,单位为bit。

通过ff_ctz(v),得到RBSP stop bit后面rbsp_alignment_zero_bit的位数。关于ff_ctz函数,可以参考:《FFmpeg源码:ff_ctz / ff_ctz_c函数分析》。

所以 ff_ctz(v) + 1 等于RBSP stop bit 加上 rbsp_alignment_zero_bit的位数。

语句size -= ff_ctz(v) + 1 等价于 size = size -( ff_ctz(v) + 1)。执行完后size的值即为NALU Header + SODB的位数(bit) 。

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

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

相关文章

尴尬时刻:如何在忘记名字时巧妙应对

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

llama系列模型学习

一、目录 llama1 模型与transformer decoder的区别llama2 模型架构llama2 相比llama1 不同之处llama3 相比llama2 不同之处llama、llama2、llama3 分词器词表大小以及优缺点采用的损失函数是什么?为什么Layer Norm 改为RMS Norm?如何消除模型幻觉? 二…

Vscode配置Verilog开发环境(二)

两年前我写过一篇vscode配置fpga开发环境的博客,近期发现查看的人数还是比较多的,经过两年的使用,优化了代码模板以及删减了一些插件等等,因此有了本文。 目前我的vscode只有下图中的九个插件,相比前文已经减少了一些了…

地级市绿色创新及碳排放与环境规划数据(2000-2021年)

数据简介:分享各个城市对于碳排放的降低做出了哪些共享。该数据是地级市2000-2021年间由绿色创新、碳排放与环境规制数据构成的能源与环境研究数据大合集,并对其进行可视化处理,供大家研究使用。当今我国大力推进生态文明建设、美丽中国建设等…

cephadm部署ceph分布式存储集群笔记

1、修改主机名、网卡名 修改主机名: sudo hostnamectl set-hostname 新主机名修改网卡名(选做): sudo ip link set eth0 name newname2、关闭防火墙和selinux (选做) 3、关闭交换分区 (选做&am…

【日常开发之Windows共享文件】Java实现Windows共享文件上传下载

文章目录 Windows 配置代码部分Maven代码 Windows 配置 首先开启服务,打开控制面板点击程序 点击启用或关闭Windows功能 SMB1.0选中红框内的 我这边是专门创建了一个用户 创建一个文件夹然后点击属性界面,点击共享 下拉框选择你选择的用户点击添加…

python爬虫必须要高匿IP吗 ?

各个平台搜索关键词就可以找到不同品牌的代理IP了。 找倒是不难,难的是能从中挑选出靠谱且合适的代理品牌。 在选择代理IP这块,不建议使用免费和超低价的代理,因为这一类的代理往往非常不稳定,很多都被网站拉黑过,特…

PS添加物体阴影

一、选择背景,确保物体和北京分割出图层 二、右键单击物体图层,点击混合选项,点击投影 三、调整参数,可以看效果决定(距离是高度,扩展是浓度,大小是模糊程度),保存即可

实用软件下载:CrossOver 2024最新安装包及详细安装教程

​根据软件大数据显示上传或者手动输入软件都非常简单,一般来说CrossOver会自动连接到一个Win文件共享服务器(Samba或CIFS)上,使用者能够直接在这个服务器中选择并上传软件执行文件。实际上我们可以这样讲调整CrossOver设置&#…

汽车数据应用构想(五)

如果说路面信息(POI)可以通过采集车、人工等方式来获取,用户习惯可以通过手机生态应用来获取,那么车的信息应该算是车辆独有的垂直领域价值了,它是实实在在只有车厂才拥有的数据财富,任何互联网大厂都抢不走…

如何使用mapXplore将SQLMap数据转储到关系型数据库中

关于mapXplore mapXplore是一款功能强大的SQLMap数据转储与管理工具,该工具基于模块化的理念开发,可以帮助广大研究人员将SQLMap数据提取出来,并转储到类似PostgreSQL或SQLite等关系型数据库中。 功能介绍 当前版本的mapXplore支持下列功能…

图像识别技术的来龙区别,图像识别的底层原理及应用场景大总结-人工智能基础知识必读

图像识别技术是人工智能领域中的一个重要分支,它涉及到从图像中自动提取信息和模式的过程。随着深度学习的发展,图像识别技术已经取得了显著的进展,并在多个领域中找到了应用。 图像识别的底层原理 图像识别的基本过程包括图像获取、预处理…

transformers 生成式模型函数generate的参数说明

# generate函数说明 """ 类用于保存生成任务的配置。调用generate支持以下对于text-decoder、text-to-text、speech-to-text和vision-to-text模型的生成方法: 如果num_beams1且do_sampleFalse,则使用贪婪搜索,调用~generati…

一条Redis命令是如何执行的?

一条Redis命令是如何执行的? 源码结构核心数据结构redisServerredisClientredisDbredisObjectaeEventLoop 核心流程redis启动流程main() 主循环aeEventProcess执行过程命令执行的流程过程1(redis启动)过程2(客户端与服务端建立链接…

LLM function call

简介 在大模型领域,尤其是在自然语言处理(NLP)和人工智能(AI)应用中,function call 是一种非常重要的技术手段。它主要用于让模型在生成或处理文本的过程中调用外部功能或执行特定任务,有以下应…

【Android】Android Studio 使用Kotlin写代码时代码提示残缺问题解决

问题描述 Android Studio升级之后,从Android Studio 4.2升级到Android Studio Arctic Fox版本,因为项目比较老,使用的Gradle 版本是3.1.3,这个版本的Android Studio最低支持Gradle 3.1版本,应该算是比较合适的版本。 …

不翻墙安装yolov8环境下的RT-DETR并实现PCB表面缺陷检测

目录 一、新建conda环境二、安装yolov8环境1.克隆安装包2.安装依赖包3.测试模型 任务2:基于RT-DETR实现PKU-PCB表面缺陷检测数据准备 数据增强测试 总结 一、新建conda环境 创建并激活conda环境: 在conda创建一个名为yolov8的新环境,并在其中…

C++网络编程实践:使用C++11基于epoll技术实现一个超大并发TCP服务器

理解epoll epoll 是一种 I/O 复用技术,它允许一个线程有效地管理多个文件描述符(在本例中为套接字),而无需为每个连接创建单独的线程。这是通过事件驱动的方式来实现的,epoll 能够通知你哪些套接字已经准备好进行读写…

国际网络专线的开通流程

1. 选择服务商:首先,您需要选择一个可靠的服务商来提供国际网络专线服务。确保服务商具有良好的声誉和专业知识,以便为您提供高质量的网络连接和支持。 2. 评估需求:在与服务商沟通之前,您需要明确自己的网络需求。这…

dp经典问题:LCS问题

dp:LCS问题 最长公共子序列(Longest Common Subsequence, LCS)问题 是寻找两个字符串中最长的子序列,使得这个子序列在两个字符串中出现的相对顺序保持一致,但不要求连续。 力扣原题链接 1.定义 给定两个字符串 S1…