当前位置: 首页 > news >正文

音视频入门基础:AAC专题(5)——FFmpeg源码中,判断某文件是否为AAC裸流文件的实现

=================================================================

音视频入门基础:AAC专题系列文章:

音视频入门基础:AAC专题(1)——AAC官方文档下载

音视频入门基础:AAC专题(2)——使用FFmpeg命令生成AAC裸流文件

音视频入门基础:AAC专题(3)——AAC的ADTS格式简介

音视频入门基础:AAC专题(4)——ADTS格式的AAC裸流实例分析

音视频入门基础:AAC专题(5)——FFmpeg源码中,判断某文件是否为AAC裸流文件的实现

音视频入门基础:AAC专题(6)——FFmpeg源码中解码ADTS格式的AAC的Header的实现

音视频入门基础:AAC专题(7)——FFmpeg源码中计算AAC裸流每个packet的size值的实现

音视频入门基础:AAC专题(8)——FFmpeg源码中计算AAC裸流AVStream的time_base的实现

音视频入门基础:AAC专题(9)——FFmpeg源码中计算AAC裸流每个packet的duration和duration_time的实现

音视频入门基础:AAC专题(10)——FFmpeg源码中计算AAC裸流每个packet的pts、dts、pts_time、dts_time的实现

=================================================================

一、引言

通过FFmpeg命令:

./ffmpeg -i XXX.aac

可以判断出某个文件是否为AAC裸流文件:

所以FFmpeg是怎样判断出某个文件是否为AAC裸流文件呢?它内部其实是通过adts_aac_probe函数来判断的。从《FFmpeg源码:av_probe_input_format3函数和AVInputFormat结构体分析(FFmpeg源码5.0.3版本)》和《7.0.1版本的FFmpeg源码中av_probe_input_format3函数和AVInputFormat结构体的改变》中我们可以知道:

FFmpeg源码中实现容器格式检测的函数是av_probe_input_format3函数,其内部通过循环while ((fmt1 = av_demuxer_iterate(&i))) 拿到所有容器格式对应的AVInputFormat结构,然后通过score = fmt1->read_probe(&lpd)语句执行不同容器格式对应的解析函数,根据是否能被解析,以及匹配程度,来判断出这是哪种容器格式。而AAC裸流文件对应的解析函数就是adts_aac_probe函数。

二、adts_aac_probe函数的定义

adts_aac_probe函数定义在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的源文件libavformat/aacdec.c中:

static int adts_aac_probe(const AVProbeData *p)
{int max_frames = 0, first_frames = 0;int fsize, frames;const uint8_t *buf0 = p->buf;const uint8_t *buf2;const uint8_t *buf;const uint8_t *end = buf0 + p->buf_size - 7;buf = buf0;for (; buf < end; buf = buf2 + 1) {buf2 = buf;for (frames = 0; buf2 < end; frames++) {uint32_t header = AV_RB16(buf2);if ((header & 0xFFF6) != 0xFFF0) {if (buf != buf0) {// Found something that isn't an ADTS header, starting// from a position other than the start of the buffer.// Discard the count we've accumulated so far since it// probably was a false positive.frames = 0;}break;}fsize = (AV_RB32(buf2 + 3) >> 13) & 0x1FFF;if (fsize < 7)break;fsize = FFMIN(fsize, end - buf2);buf2 += fsize;}max_frames = FFMAX(max_frames, frames);if (buf == buf0)first_frames = frames;}if (first_frames >= 3)return AVPROBE_SCORE_EXTENSION + 1;else if (max_frames > 100)return AVPROBE_SCORE_EXTENSION;else if (max_frames >= 3)return AVPROBE_SCORE_EXTENSION / 2;else if (first_frames >= 1)return 1;elsereturn 0;
}

其作用就是检测某个文件是否为AAC裸流文件。由于通过FFmpeg命令(通过《音视频入门基础:AAC专题(2)——使用FFmpeg命令生成AAC裸流文件》)生成的AAC裸流文件都是ADTS格式的,所以adts_aac_probe函数只能用于检测某个文件是否为ADTS格式的AAC裸流,不能用于检测是否为AAC的ADIF格式。

形参pd:输入型参数,为AVProbeData类型的指针。

AVProbeData结构体声明在libavformat/avformat.h中:

/*** This structure contains the data a format has to probe a file.*/
typedef struct AVProbeData {const char *filename;unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */int buf_size;       /**< Size of buf except extra allocated bytes */const char *mime_type; /**< mime_type, when known. */
} AVProbeData;

p->filename为:需要被推测格式的文件的路径。

p->buf:指向“存放从路径为p->filename的文件(AAC裸流文件)中读取出来的二进制数据”的缓冲区。

p->buf_size:缓冲区p->buf的大小,单位为字节。注:FFmpeg判断某个文件的格式时不会读取完整个文件,只会读取它前面的一部分,比如最开始的2048个字节。只要根据前面的这些字节就足够判断出它的格式了,所以p->buf_size的值一般就是2048。

p->mime_type:一般为NULL,可忽略。

返回值:返回一个类型为整形的分值。返回0表示该文件完全不符合AAC的ADTS格式。返回一个大于0的值表示该文件比较符合AAC的ADTS格式,但还需要在av_probe_input_format3函数中执行其它容器格式对应的解析函数来进行对比,最终通过最高分来确定到底是哪种容器格式。

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

adts_aac_probe函数内部,首先定义局部变量fsize来记录某个ADTS音频帧的长度;定义局部变量frames记录该AAC裸流文件前2048个字节(因为p->buf_size的值一般就是2048)中的有效音频帧的个数:

int fsize, frames;

让指针buf2指向“AAC裸流文件二进制数据”的开头,也就是第一个ADTS音频帧的adts_fixed_header:

    for (; buf < end; buf = buf2 + 1) {buf2 = buf;

按照大端模式读取第一个ADTS音频帧的前2个字节,赋值给变量header。关于AV_RB16宏定义的用法可以参考:《FFmpeg源码:AV_RB32、AV_RB16、AV_RB8宏定义分析》:

uint32_t header = AV_RB16(buf2);

由《音视频入门基础:AAC专题(3)——AAC的ADTS格式简介》可以知道,ADTS音频帧的adts_fixed_header中的syncword属性占12位,每个位都必须被设置为1;layer属性占2位,必须被设置为0。所以通过下面代码块判断syncword和layer属性的值是否正确。如果表达式:header & 0xFFF6) != 0xFFF0为真,表示这两个属性的值不正确,即表示ADTS Header格式不正确,让变量frames的值归0,表示有效音频帧的个数归0:

            if ((header & 0xFFF6) != 0xFFF0) {if (buf != buf0) {// Found something that isn't an ADTS header, starting// from a position other than the start of the buffer.// Discard the count we've accumulated so far since it// probably was a false positive.frames = 0;}break;}

获取adts_variable_header中的aac_frame_length属性,即该ADTS音频帧的总长度(包含ADTS Header、错误校验和AAC原始数据块,单位为字节)。赋值给变量fsize:

fsize = (AV_RB32(buf2 + 3) >> 13) & 0x1FFF;

由《音视频入门基础:AAC专题(3)——AAC的ADTS格式简介》可以知道,ADTS Header至少占7个字节(当存在CRC校验时,ADTS Header占9字节;不存在CRC校验时,ADTS Header占7字节),所以如果从上面得到的该ADTS音频帧的总长度小于7,表示ADTS Header格式不正确,通过break关键字跳出循环:

            if (fsize < 7)break;

让指针buf2指向下一个ADTS音频帧的adts_fixed_header:

buf2 += fsize;

如果该音频帧的ADTS Header格式正确,让frames的值(有效音频帧的个数)加1。执行for循环,继续判断下一个ADTS音频帧的Header的格式是否正确:

for (frames = 0; buf2 < end; frames++) {

buf等于buf0,意味着读取到ADTS音频帧的Header的格式都是正确的,让first_frames的值等于frames:

        max_frames = FFMAX(max_frames, frames);if (buf == buf0)first_frames = frames;

如果该AAC裸流文件前2048个字节中的有效音频帧的个数不小于3个,adts_aac_probe函数返回AVPROBE_SCORE_EXTENSION + 1(也就是返回51分),意味着该文件比较符合AAC的ADTS格式:

    if (first_frames >= 3)return AVPROBE_SCORE_EXTENSION + 1;

相关文章:

音视频入门基础:AAC专题(5)——FFmpeg源码中,判断某文件是否为AAC裸流文件的实现

音视频入门基础&#xff1a;AAC专题系列文章&#xff1a; 音视频入门基础&#xff1a;AAC专题&#xff08;1&#xff09;——AAC官方文档下载 音视频入门基础&#xff1a;AAC专题&#xff08;2&#xff09;——使用FFmpeg命令生成AAC裸流文件 音视频入门基础&#xff1a;AAC…...

几何 | 数学专项

日期内容2024.9.19创建 { d > 0 , 递增数列 d < 0 , 递减数列 d 0 &#xff0c;常数列 \begin{cases} d>0,递增数列\\ d<0,递减数列\\ d0&#xff0c;常数列 \end{cases} ⎩ ⎨ ⎧​d>0,递增数列d<0,递减数列d0&#xff0c;常数列​ 【2010.13】 【1.历年真…...

学习CubeIDE——定时器开发

在b站上学习洋桃电子关于HAL库开发&#xff0c;发现使用CubeIDE是真的简单又方便。 实验现象&#xff1a;使用定时器来产生中断&#xff0c;中断程序是LED灯翻转 在我看来&#xff0c;定时器&#xff0c;是一个从0开始增1&#xff08;常规&#xff09;&#xff0c;增加到一定…...

【Elasticsearch】-图片向量化存储

需要结合深度学习模型 1、pom依赖 注意结尾的webp-imageio 包&#xff0c;用于解决ImageIO.read读取部分图片返回为null的问题 <dependency><groupId>org.openpnp</groupId><artifactId>opencv</artifactId><version>4.7.0-0</versio…...

二叉树(一)高度与深度

高度&#xff1a;从最底层往上数&#xff08;后序遍历&#xff0c;左右根&#xff09;&#xff0c;更简单&#xff08;递归&#xff09; 深度&#xff1a;从上往下数直到有叶子&#xff08;前序遍历&#xff0c;根左右&#xff09;&#xff0c;较复杂 高度是最大深度 一、求…...

梧桐数据库(WuTongDB):MySQL 优化器简介

MySQL 优化器是数据库管理系统中的一个重要组件&#xff0c;用于生成并选择最优的查询执行计划&#xff0c;以提高 SQL 查询的执行效率。它采用了基于代价的优化方法&#xff08;Cost-Based Optimizer, CBO&#xff09;&#xff0c;通过评估不同查询执行方案的代价&#xff0c;…...

交通运输部力推高速公路监测,做好结构安全预警,保护人民安全

在快速发展的交通网络中&#xff0c;高速公路作为经济命脉与生命通道&#xff0c;其结构安全直接关系到每一位行路者的生命财产安全。为此&#xff0c;广东省交通运输厅正式发布《关于积极申报高速公路监测预警应用示范揭榜的通知》&#xff0c;旨在通过技术创新与应用示范&…...

基于PHP+MySQL组合开发的在线客服源码系统 聊天记录实时保存 带完整的安装代码包以及搭建部署教程

系统概述 随着互联网技术的飞速发展&#xff0c;企业与客户之间的沟通方式日益多样化&#xff0c;在线客服系统作为连接企业与客户的桥梁&#xff0c;其重要性不言而喻。然而&#xff0c;市场上现有的在线客服系统往往存在成本高、定制性差、维护复杂等问题。针对这些痛点&…...

NEXT.js 创建postgres数据库-关联github项目-连接数据库-在项目初始化数据库的数据

github创建项目仓库创建Vercel账号选择hobby连接github仓库install - deploy创建postgres数据库&#xff08;等待deploy完成&#xff09; Continue to DashboardStorage&#xff08;头部nav哪里&#xff09;create Postgresconnect连接完后&#xff0c;切换到.env.local&#x…...

Matlab如何配置小波工具(Wavelet Toolbox)

1、发现问题 因为实验要使用小波工具函数&#xff0c;运行时报错如下&#xff1a; 查看对应文件夹发现没有小波工具&#xff08;也可在控制台输入ver&#xff09;&#xff0c;检查是否有该工具&#xff0c;输入后回车返回如下&#xff1a; 2、下载工具包 没有这个工具就要去下…...

FTP、SFTP安装,整合Springboot教程

文章目录 前言一、FTP、SFTP是什么&#xff1f;1.FTP2.SFTP 二、安装FTP1.安装vsftp服务2.启动服务并设置开机自启动3.开放防火墙和SELinux4.创建用户和FTP目录4.修改vsftpd.conf文件5.启动FTP服务6.问题 二、安装SFTP1、 创建用户2、配置ssh和权限3、建立目录并赋予权限4、启动…...

24年蓝桥杯及攻防世界赛题-MISC-3

21 reverseMe 复制图片&#xff0c;在线ocr识别&#xff0c;https://ocr.wdku.net/&#xff0c;都不费眼睛。 22 misc_pic_again ┌──(holyeyes㉿kali2023)-[~/Misc/tool-misc/zsteg] └─$ zsteg misc_pic_again.png imagedata … text: “$$KaTeX parse error: Undefined…...

阿里云容器服务Kubernetes部署新服务

这里部署的是前端项目 1.登录控制台-选择集群 2.选择无状态-命名空间-使用镜像创建 3.填写相关信息 应用基本信息&#xff1a; 容器配置&#xff1a; 高级配置&#xff1a; 创建成功后就可以通过30006端口访问项目了...

记录生产环境,通过域名访问的图片展示不全,通过ip+端口的方式访问图片是完整的

原因&#xff1a;部署nginx的服务器硬盘满了 排查发现nginx日志文件占用了大量硬盘 解决方案&#xff1a; 删除该文件&#xff0c;重启nginx服务&#xff0c;问题解决。...

网络安全实训八(y0usef靶机渗透实例)

1 信息收集 1.1 扫描靶机IP 1.2 收集靶机的端口开放情况 1.3 探测靶机网站的目录 1.4 发现可疑网站 1.5 打开可疑网站 2 渗透 2.1 使用BP获取请求 2.2 使用工具403bypasser.py探测可疑网页 2.3 显示可以添加头信息X-Forwarded-For:localhost来访问 2.4 添加之后转发&#xff…...

QT信号槽原理是什么,如何去使用它?

QT的信号槽&#xff08;Signals and Slots&#xff09;机制是QT框架的核心特性之一&#xff0c;它提供了一种对象间通信的方式&#xff0c;使得QT的部件可以在不知道彼此详细实现的情况下相互通信。这种机制在图形用户界面编程中尤为重要&#xff0c;因为它有助于降低对象间的耦…...

mybatisplus介绍以及使用(上)

目录 一、概念 1、什么是mybatisplus 2、为什么要使用mybatisplus 二、mybatisplus的使用 1、安装 2、常用注解 3、条件构造器 一、概念 1、什么是mybatisplus MyBatis-Plus&#xff08;简称MP&#xff09;是一个基于MyBatis的增强框架&#xff0c;旨在简化开发、提高…...

maxwell 输出消息到 redis

文章目录 1、maxwell 输出消息到 redis1.1、启动一个Maxwell容器&#xff0c;它会连接到指定的MySQL数据库&#xff0c;捕获变更事件&#xff0c;并将这些事件以Redis发布/订阅的形式发送到指定的Redis服务器1.2、在已运行的 Redis 容器中执行 Redis 命令行界面&#xff08;CLI…...

infoNCE损失和互信息的关系

文章目录 InfoNCE 损失与互信息的关系推导将相似度 sim ( q , x ) \text{sim}(q, x) sim(q,x) 看作是负的能量函数infoNCE和互信息的分母不同 InfoNCE 损失与互信息的关系推导 为了理解 InfoNCE 损失与互信息的关系&#xff0c;首先我们回顾两个公式的基本形式&#xff1a; 互…...

Java学习路线指南

目录 前言1. Java基础知识1.1 面向对象编程思想1.2 Java平台与JVM1.3 Java语言的核心概念 2. Java语法与基础实践2.1 数据类型与变量2.2 控制结构2.3 方法与函数2.4 数据结构与集合框架 3. Java进阶知识3.1 异步编程与多线程3.2 JVM调优与垃圾回收机制3.3 设计模式 4. 实践与项…...

在SpringCloud中实现服务间链路追踪

在微服务架构中&#xff0c;由于系统的复杂性和多样性&#xff0c;往往会涉及到多个服务之间的调用。当一个请求经过多个服务时&#xff0c;如果出现问题&#xff0c;我们希望能够快速定位问题所在。这就需要引入链路追踪机制&#xff0c;帮助我们定位问题。 Spring Cloud为我们…...

[数据集][目标检测]红外微小目标无人机直升机飞机飞鸟检测数据集VOC+YOLO格式7559张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;7559 标注数量(xml文件个数)&#xff1a;7559 标注数量(txt文件个数)&#xff1a;7559 标注…...

TS Vue项目中使用TypeScript

模块系统与命名空间 概念 模块化开发是目前最流行的组织代码方式&#xff0c;可以有效的解决代码之间的冲突与代码之间的依赖关系&#xff0c;模块系统一般视为“外部模块”&#xff0c;而命名空间一般视为“内部模块” 模块系统 TS中的模块化开发跟ES6中的模块化开发并没有…...

打工人、设计师必备的AI抠图工具

前言 你是否厌倦了繁琐的PS操作&#xff1f;是否在寻找一种快速、简便的抠图方法&#xff1f;别担心&#xff0c;AI技术已经为你准备好了解决方案。以下是9个令人惊叹的AI抠图工具&#xff0c;让你无需PS也能轻松获得专业级别的抠图效果。 1. 千鹿设计助手&#xff1a;EmGaur…...

MyBatis中一对多关系的两种处理方法

目录 1.多表联查&#xff08;通过collection标签的ofType属性&#xff09; 1&#xff09;mapper 2&#xff09;mapper.xml 3&#xff09;测试代码 4&#xff09;测试结果 2.分布查询(通过collection标签的select属性) 1&#xff09;mapper 2&#xff09;mapper.xml 3&#xff0…...

视频美颜SDK与直播美颜工具的实现原理与优化方案

本篇文章&#xff0c;小编将为大家详细讲解视频美颜SDK的实现原理&#xff0c;并提出优化方案。 一、视频美颜SDK的实现原理 1.图像采集与处理 2.人脸识别与关键点检测 3.美颜滤镜与特效处理 4.实时性与低延迟 二、直播美颜工具的实现原理 直播美颜工具与视频美颜SDK的…...

Linux 安装JDK8和卸载

目录 一、下载JDK8的rpm包 二、安装JDK 三、设置环境变量 Linux环境下安装JDK的方式有多种&#xff0c;可以通过rpm包、yum安装或者tar.gz压缩包。本章节会教大家通过前两者方式来安装JDK&#xff0c;压缩包的形式因为下载压缩包后上传到服务器环境下&#xff0c;将压缩包解…...

javascript 浏览器打印不同页面设置方向,横向纵向打印

// 在JavaScript中添加打印样式 const printStyle document.createElement(style); printStyle.innerHTML media print { page { size: landscape; }body { margin: 10mm; } }; document.head.appendChild(printStyle);// 触发打印 function printPage() {window.print(); }/…...

Maven 的多种打jar包方式详细介绍、区别及使用教程——附使用命令

文章目录 1. **标准 JAR 打包****打包方式****配置示例****使用方式****优点****缺点** 2. **可执行 JAR&#xff08;Executable JAR&#xff09;****打包方式****配置示例****使用方式****优点****缺点** 3. **Uber JAR&#xff08;Fat JAR / Shadow JAR&#xff09;****打包方…...

计算机毕业设计 基于协同过滤算法的个性化音乐推荐系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...