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

一、引言

通过FFmpeg命令:

./ffmpeg -i XXX.wav

可以判断出某个文件是否为WAV格式的音频文件:

所以FFmpeg是怎样判断出某个文件是否为WAV格式的音频文件呢?它内部其实是通过wav_probe函数来判断的。从文章《FFmpeg源码:av_probe_input_format3函数分析》中我们可以知道:

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

二、wav_probe函数的定义

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

static int wav_probe(const AVProbeData *p)
{/* check file header */if (p->buf_size <= 32)return 0;if (!memcmp(p->buf + 8, "WAVE", 4)) {if (!memcmp(p->buf, "RIFF", 4) || !memcmp(p->buf, "RIFX", 4))/* Since the ACT demuxer has a standard WAV header at the top of* its own, the returned score is decreased to avoid a probe* conflict between ACT and WAV. */return AVPROBE_SCORE_MAX - 1;else if ((!memcmp(p->buf,      "RF64", 4) ||!memcmp(p->buf,      "BW64", 4)) &&!memcmp(p->buf + 12, "ds64", 4))return AVPROBE_SCORE_MAX;}return 0;
}

其作用就是检测某个文件是否为WAV格式的音频文件。

形参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的文件中读取出来的二进制数据”的缓冲区。

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

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

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

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

wav_probe函数中,首先有如下判断逻辑:如果能读取到的文件中的二进制数据量小于32个字节,远远小于WAV Header中必须包含的数据量,wav_probe函数返回0,表示该文件完全不符合WAV格式:

/* check file header */if (p->buf_size <= 32)return 0;

由《音视频入门基础:WAV专题(2)——WAV格式简介》可以知道,WAV文件的第0到3字节为“区块编号”,内容必须为“RIFF”或“RIFX”;第8到11字节为“档案格式”,内容必须固定为“WAVE”。所以通过下面代码来判断该文件是否符合上述条件,如果符合返回AVPROBE_SCORE_MAX - 1(也就是返回99分),意味着该文件比较符合WAV格式。 从文章《FFmpeg源码:av_probe_input_format3函数分析》中我们可以知道容器格式探测函数的分值最高为100分,100分才是完全符合这种格式。所以为什么下面代码中不是返回100分只是返回99分呢?因为ACT音频格式可能会包含一个标准的WAV文件头,所以FFmpeg将分值减小来避免探测ACT和WAV格式时产生的冲突:

f (!memcmp(p->buf + 8, "WAVE", 4)) {if (!memcmp(p->buf, "RIFF", 4) || !memcmp(p->buf, "RIFX", 4))/* Since the ACT demuxer has a standard WAV header at the top of* its own, the returned score is decreased to avoid a probe* conflict between ACT and WAV. */return AVPROBE_SCORE_MAX - 1;

如果不符合上述的判断,通过下面代码判断该文件是否为WAVE 64位扩展格式Wave64,如果符合,返回AVPROBE_SCORE_MAX(也就是返回100分),意味着该文件完全符合WAV格式。FFmpeg内部把WAV和Wave64当成一种文件格式来处理:

else if ((!memcmp(p->buf,      "RF64", 4) ||!memcmp(p->buf,      "BW64", 4)) &&!memcmp(p->buf + 12, "ds64", 4))return AVPROBE_SCORE_MAX;

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

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

相关文章

Spring Boot集成OpenPDF和Freemarker实现PDF导出功能并附水印

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

关于@JsonSerialize序列化与@JsonDeserialize反序列化注解的使用(密码加密与解密举例)

注&#xff1a;另一种方式参考 关于TableField中TypeHandler属性&#xff0c;自定义的类型处理器的使用&#xff08;密码加密与解密举例&#xff09;http://t.csdnimg.cn/NZy4G 1.简介 1.1 序列化与反序列化 学习注解之前&#xff0c;我们可以先了解一下什么是序列化与反序列…

关于Redis持久化和集群模式(主从,哨兵,去中心化)使用和介绍

持久化: 持久化介绍 把内存中的数据存储到磁盘的过程。同时也可以把磁盘中的数据加载到内存中 持久化实现 redis实现持久化的方式提供了两种: RDB快照模式&#xff0c;数据备份和恢复速度快。 缺点: 数据完整性差。数据可能丢失多。 AOF日志追加: 数据完整性高。 缺点: 数据备…

遵义网站建设安全性保证

随着互联网的发展和普及&#xff0c;网站的建设成为了一个重要的工作&#xff0c;也是企业宣传的重要渠道。然而&#xff0c;随之而来的安全问题也是不容忽视的。为了保证遵义网站建设的安全性&#xff0c;我们需要采取一系列的措施。 首先&#xff0c;要选择合适的服务器和主机…

【Unity2D 2022:Data】读取csv格式文件的数据

一、创建csv文件 1. 打开Excel&#xff0c;创建xlsx格式文件 2. 编辑卡牌数据&#xff1a;这里共写了两类卡牌&#xff0c;第一类是灵物卡&#xff0c;具有编号、卡名、生命、攻击四个属性&#xff1b;第二类是法术卡&#xff0c;具有编号、卡名、效果三个属性。每类卡的第一…

算法题目整合5

文章目录 118. 小 y 删数字119. 小红的字符串切割120. 小红的数字匹配115. 组装手机116. 小欧的卡牌111. 构造二阶行列式112. 挑战boss 118. 小 y 删数字 题目描述 给定一个长度为 n 的数组&#xff0c;数组元素为 a1, a2, . . , an&#xff0c;每次能删除任意 a 的任意一位&…

(39)智能电池

文章目录 前言 1 通过任务规划器进行设置 2 补充信息 3 限制条件 4 参数说明 前言 虽然还不是很普遍&#xff0c;但智能电池更容易从飞行器上安装和拆卸&#xff0c;并且能够提供更多关于电池状态的信息&#xff0c;包括容量、单个电池电压、温度等。 ArduPilot 支持几种…

在Vue程序中,如何检测用户的登录状态并跳转到对应页面

在一个Vue应用程序中&#xff0c;你可以通过以下步骤来检测用户的登录状态并跳转到对应的页面。假设你使用的是Vue Router来管理路由&#xff0c;并且用户的登录状态保存在Vuex或localStorage中。 步骤一&#xff1a;在Vuex中管理用户的登录状态 首先&#xff0c;确保你在Vue…

开发环境搭建——Node.js

在启动前端项目的时候我们通常会用到Node.js&#xff0c;下面是对Node.js的下载安装以及配置的讲解 一、Node.js的安装 1.1、通过Node.js官网下载&#xff1a;Node.js — Run JavaScript Everywhere 下载后双击.msi安装文件后一直点击下一步即可 1.2、配置node 1.2.1、查看…

HTML meta

<meta>标签用于提供html文档的元信息&#xff08;metadata&#xff09;。这些信息不会显示在页面上&#xff0c;但会被浏览器或搜索引擎用来识别页面的编码方式、关键字、描述、作者信息、刷新时间等。 基本语法 <meta name"属性名" content"属性值&q…

锅总介绍技术标准基金会及组织

技术标准基金会及组织有哪些&#xff1f;中国主导的有哪些&#xff1f;它们之间有何关联&#xff1f;希望本文能帮您解答&#xff01; 一、主要的基金会和组织 以下是一些主要的基金会和组织&#xff0c;它们致力于开源软件和技术标准的发展&#xff1a; Linux Foundation 简…

js 替换json中的转义字符 \

例如有以下字符串 "\"{\\\"account\\\":\\\"66\\\",\\\"name\\\":\\\"66\\\"}\"" 想得到如下字符串 {"account":"66","name":"66"} 执行替换字符串 "\"{…

verilog数据自动扩展位宽问题

Verilog的比较运算中&#xff0c;需要以左右两边运算结果的最大值为参考进行扩展位宽 module test;reg [1 : 0] b ; reg [1 : 0] a ; reg [1 : 0] c ; wire a0;assign a0 (a b) > c; initial begin b d3; a d3; c d3; #2000; $finish; end endmodule如代码中所示&…

组队学习——决策树(以泰坦尼克号公共数据集为例)

本次我们挑战的数据集为泰坦尼克号公共数据集&#xff0c;为了降低难度&#xff0c;我们在原有数据集的基础上进行了优化&#xff0c;具体数据集介绍如下&#xff1a; 在这里也介绍一下数据的含义吧 数据介绍&#xff1a; Survived&#xff1a;是否存活&#xff08;label&#…

paraFoam 运行 报错 usr/lib/x86_64-linux-gnu/libQt5Core.so 已解决

在日常项目开发中。使用ubuntu 视图开发的时候。报错 缺少 libQt5Core 核心组件&#xff01; whereis libQt5Core.so.5sudo strip --remove-section.note.ABI-tag /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 完美解决&#xff0c;并且能正常打开&#xff0c;前提是&#xff0c…

简化mybatis @Select IN条件的编写

最近从JPA切换到Mybatis&#xff0c;使用无XML配置&#xff0c;Select注解直接写到interface上&#xff0c;发现IN条件的编写相当麻烦。 一般得写成这样&#xff1a; Select({"<script>","SELECT *", "FROM blog","WHERE id IN&quo…

redis面试(一)String底层剖析

前言 今天开始更新一些redis相关的知识点&#xff0c;初步计划是redis的数据类型&#xff0c;以及redis分布式锁 本章节主要是redis的String类型 字符串SDS 一般情况下我们认为的redis 字符串就是String&#xff0c;但是我这边要说的是底层String类型。 redis底层是C语言&a…

【python】python生活管理费系统(源码+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

Scala学习笔记20: Future 和Promise

目录 第二十章 Future 和Promise1- 简介1. Future: 对未来结果的承诺2. Promise: 兑现 Future 的谎言3. Future 和 Promise 的关系: 相辅相成4. 总结 2- 执行上下文1. ExecutionContext 的作用:2. 常见的 ExecutionContext :3. 指定 ExecutionContext :4. 示例:5. 总结:6. 注意…

加载chatglm3模型时出现ValueError: too many values to unpack (expected 2)的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…