FFmpeg音视频开发知识点(二)
系列文章目录
FFmpeg音视频开发知识点(一)
文章目录
- 系列文章目录
- 前言
- 一、AAC音频编码
- 1. ffmpeg编译第三方的libfdk_aac
- 2. S16重采样FLTP
- 二、AAC音频解码
- 总结
前言
该篇讲解一下,音频编解码中的难点,以及开发过程中遇到问题,有不对的地方,欢迎大佬指正
一、AAC音频编码
在开发音频编解码AAC,我使用QAudioInput进行采样,但是采样格式只有S16(有符号16位)最接近AAC的采样,我看了下安卓采样的样本长度也是16(PS:需要和安卓终端通话),于是查找并打开编码器
AVCodec* pCodec = avcodec_find_encoder(AV_CODEC_ID_AAC);if (pCodec == nullptr){//...省略return;}AVCodecContext* pCodecCtx = avcodec_alloc_context3(pCodec);if(pCodecCtx == NULL){//...省略return;}pCodecCtx->codec_id = pCodec->id;pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;//...省略int iRet = avcodec_open2(pCodecCtx, pCodec, NULL);if (iRet < 0){//...省略return;}
但是会报错(忘了是查找还是打开编码器报错了🤣),后面一查,ffmpeg本身自带的aac并不支持AV_SAMPLE_FMT_S16的,有两种方式可以编码S16音频采样
1. ffmpeg编译第三方的libfdk_aac
编译libfdk_aac可以参考我这篇文章:Linux部分开源库编译,附上我的ffmepg编译的configure配置命令,具体如下:
sudo ./configure \
--prefix=/home/lzy/Project/new_project/libH323Stack_src_1.2.0/bin4 \
--extra-cflags="-I/home/lzy/Project/bin/include -Wall -fPIC" \ #第三方库的头文件路径
--extra-ldflags="-L/home/lzy/Project/bin/lib -ldl" \ #第三方库的所在路径
--disable-static \
--enable-shared \
--disable-debug \
--disable-doc \
--disable-ffplay \
--disable-ffprobe \
--disable-symver \
--enable-small \
--enable-gpl \
--enable-nonfree \
--enable-libfdk-aac \
--enable-libx264 \
--enable-libx265 \
--enable-openssl \
--enable-hardcoded-tables \
--enable-avresample \
--enable-decoder=h264 \
--enable-decoder=hevc \
--enable-decoder=mjpeg \
--enable-decoder=aac \
--enable-encoder=libx264 \
--enable-encoder=libx265 \
--enable-encoder=libfdk_aac \
--enable-encoder=mjpeg \
--enable-encoder=pcm_s16le \
--enable-decoder=pcm_s16le \
--enable-protocol=file \
--enable-protocol=rtp \
--enable-protocol=tcp \
--enable-protocol=udp \
--enable-demuxer=mp3 \
--enable-demuxer=wav \
--enable-demuxer=mpegts \
--enable-demuxer=mov \
--enable-demuxer=flv \
--enable-bsf=h264_mp4toannexb \
--enable-bsf=hevc_mp4toannexb \
--enable-bsf=aac_adtstoasc
编译之后,就可以打开AV_SAMPLE_FMT_S16采样格式的编码器了,具体如下:
AVCodec* pCodec = avcodec_find_encoder_by_name("libfdk_aac");if (pCodec == nullptr){//...省略return;}//...省略
最后,附上一个比较关键的部分,就是将S16的音频采样数据,赋值给AVFrame,之前参数不对也折腾了很久
// 创建输入帧AVFrame* pS16AudioFrame = av_frame_alloc();if (pS16AudioFrame == nullptr){//...省略return;}// frame缓冲区中的样本帧数量(由ctx->frame_size决定)pS16AudioFrame->nb_samples = pCodecCtx->frame_size;// 音频采样格式pS16AudioFrame->format = pCodecCtx->sample_fmt;// 声道布局pS16AudioFrame->channel_layout = pCodecCtx->channel_layout;pS16AudioFrame->channels = pCodecCtx->channels;// 采样率pS16AudioFrame->sample_rate = pCodecCtx->sample_rate;// 利用nb_samples、format、channel_layout创建frame的数据缓冲区int iRet = av_frame_get_buffer(pS16AudioFrame, 0);if (iRet < 0){//...省略return;}//...省略// 将读取到的PCM数据填充到frame去,但要注意格式的匹配, 是planar还是packed都要区分清楚iRet = av_samples_fill_arrays(pS16AudioFrame->data, pS16AudioFrame->linesize,stFrame.pFrame, pS16AudioFrame->channels,pCodecCtx->frame_size, pCodecCtx->sample_fmt, 0);if (iRet < 0){//...省略return;}
2. S16重采样FLTP
// 创建音频转换上下文SwrContext* pSwrCtx = swr_alloc_set_opts(NULL, pCodecCtx->channel_layout, AV_SAMPLE_FMT_FLTP, pCodecCtx->sample_rate,pCodecCtx->channel_layout, AV_SAMPLE_FMT_S16, pCodecCtx->sample_rate, 0, NULL);if (pSwrCtx == nullptr){printf("无法分配音频转换上下文\n");return;}// 初始化音频转换上下文if (swr_init(pSwrCtx) < 0){printf("音频转换上下文初始化失败\n");return;}// 进行音频转换AVFrame* pFltpAudioFrame = av_frame_alloc();if (pCodec == nullptr){//...省略return;}pFltpAudioFrame->format = pCodecCtx->sample_fmt;pFltpAudioFrame->channel_layout = AV_CH_LAYOUT_STEREO;pFltpAudioFrame->sample_rate = pCodecCtx->sample_rate;pFltpAudioFrame->nb_samples = 1024; //一帧音频一通道的采样数量int iRet = av_frame_get_buffer(pFltpAudioFrame, 0); //给pcm分配存储空间if (iRet < 0){//...省略return;}//...省略PCM复制给AVFrame// 执行音频转换iRet = swr_convert_frame(pSwrCtx, pFltpAudioFrame, pS16AudioFrame);if(iRet < 0){//...省略return;}
二、AAC音频解码
音频编码完成后,发送给安卓端,能够正常播放音频;现在开始解码安卓发过来的AAC音频,原本以为很快就能解决,结果发现调用avcodec_receive_frame函数一直返回-11,也就是说没有能获取到解码后的完整的一帧数据,我打印了一下返回值,发现一次都没成功;由于我发送S16的编码数据给安卓能够正常播放,且安卓采样也是S16(但是走的硬编解码);让我一度认为,安卓发过来的音频编码数据的采样格式是S16,直到我一次偶然的尝试,将
AVCodec* pCodec = avcodec_find_decoder_by_name("libfdk_aac");
// ...省略
AVCodecContext* pCodecCtx = avcodec_alloc_context3(pCodec);
// ...省略
pCodecCtx->request_sample_fmt = AV_SAMPLE_FMT_S16;
改为
AVCodec* pCodec = avcodec_find_decoder(AV_CODEC_ID_AAC);
// ...省略
AVCodecContext* pCodecCtx = avcodec_alloc_context3(pCodec);
// ...省略
pCodecCtx->request_sample_fmt = AV_SAMPLE_FMT_FLTP;
结果发现解码成功了,…,附上FLTP重采样S16代码,其实和S16重采样FLTP差不多
// 创建音频转换上下文SwrContext* pSwrCtx = swr_alloc_set_opts(NULL, pCodecCtx->channel_layout, AV_SAMPLE_FMT_S16, pCodecCtx->sample_rate,pCodecCtx->channel_layout, AV_SAMPLE_FMT_FLTP, pCodecCtx->sample_rate, 0, NULL);if (pSwrCtx == nullptr){printf("无法分配音频转换上下文\n");return;}// 初始化音频转换上下文if (swr_init(pSwrCtx) < 0){printf("音频转换上下文初始化失败\n");return;}// 进行音频转换AVFrame* pS16AudioFrame = av_frame_alloc();if (NULL == pS16AudioFrame ){printf("av_frame_alloc failed!\n");return ;}pS16AudioFrame->format = AV_SAMPLE_FMT_S16;pS16AudioFrame->channel_layout = AV_CH_LAYOUT_STEREO;pS16AudioFrame->sample_rate = pCodecCtx->sample_rate;pS16AudioFrame->nb_samples = 1024; //一帧音频一通道的采样数量iRet = av_frame_get_buffer(pS16AudioFrame, 0); //给pcm分配存储空间if(iRet < 0){//...省略return;}// 分配一帧空间,存放解码后的一帧数据AVFrame* pAudioFrame = av_frame_alloc();//...省略// 执行音频转换iRet = swr_convert_frame(pSwrCtx, pS16AudioFrame, pAudioFrame);//...省略
总结
音频编解码相对来说比较简单,就AAC稍微复杂一点,如果编解码失败,大概分两种情况:
1)编解码上下文参数不对
2)传给编解码器的数据不对
另外,每个函数的返回值也要判断一下,这样出现异常,也能迅速定位所在位置
相关文章:
FFmpeg音视频开发知识点(二)
系列文章目录 FFmpeg音视频开发知识点(一) 文章目录 系列文章目录前言一、AAC音频编码1. ffmpeg编译第三方的libfdk_aac2. S16重采样FLTP 二、AAC音频解码总结 前言 该篇讲解一下,音频编解码中的难点,以及开发过程中遇到问题&am…...
【Java可执行命令】(十)JAR文件签名工具 jarsigner:通过数字签名及验证保证代码信任与安全,深入解析 Java的 jarsigner命令~
Java可执行命令之jarsigner 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法3.1.1 可选参数:jarsigner -keystore < url>3.1.2 可选参数:jarsigner -storepass <口令>3.1.3 可选参数:jarsigner -keypass <口令>3.1.4 可选参…...
c#调用c++ dll,Release版本内存访问错误
最近遇到个比较经典的案例,在c#中调用yara进行文件检测,yara是c编写的一个非常强大库,github有个大佬用c#对其进行了封装,使其能在跨平台下,只需编译yara的so或dll就能直接跑。但总是在Release版本下时不时就崩溃&…...
内网安全:Cobalt Strike 与 MSF 联动( 会话 相互转移 )
内网安全:Cobalt Strike 与 MSF 联动( 会话 相互转移 ) 在渗透中,有时候 Cobalt Strike 会话可能会受限制,所以我们需要把 Cobalt Strike 会话转移到 MSF 上进行后面的渗透。也有的时候会话在 MSF 上,但是…...
性能测试讲解超详细Jmeter
目录 什么是性能 性能测试的目的 功能测试和性能测试 基准测试 负载测试 稳定性测试 压力测试 并发测试 总结 性能测试指标 响应时间 并发数 吞吐量 点击数 错误率 资源使用率 总结 性能测试流程 性能测试需求分析 性能测试计划和方案 编辑性能测试用例编辑 性…...
微服务 – Spring Cloud – Nacos 配置中心
微服务 – Spring Cloud – Nacos 配置中心 文章目录 微服务 – Spring Cloud – Nacos 配置中心打开nacos面板新建配置引入依赖配置文件启动类业务类打开nacos面板新建配置 Data ID: nacos-config-client-dev.yaml Group: DEV-CLOUD2023 config:info: config info lalalal …...
超细,设计一个“完美“的测试用例,用户登录模块实例...
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 好的测试用例一定…...
【C#】文件拖拽,获取文件路径
系列文章 【C#】编号生成器(定义单号规则、固定字符、流水号、业务单号) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/129129787 【C#】日期范围生成器(开始日期、结束日期) 本文链接:h…...
SAP PI/PO初步了解 2023.07.03
SAP PI/PO 是SAP 提供的一种集成中间件解决方案,用于在组织内部或不同组织之间实现系统的无缝通信和数据交换。它使企业能够以统一高效的方式集成各种应用和系统,无论这些系统的技术平台或数据格式如何。 以下是关于SAP PI/PO的简要概述: 1…...
Java中生产者消费者模型
在Java中,生产者消费者模型是一种常见的多线程编程模型,用于解决生产者和消费者之间的数据交互问题。 简介 生产者(Producer)负责生成数据,并将数据放入共享的缓冲区(队列)中。消费者…...
测试Hyperledger Fabric环境
首先进入fabric-samples目录中的first-networked 子目录 cd fabric-samples/first-network 在first-network目录下有一个自动化脚本byfn.sh,可以使用-help参数查看相应的可 用命令,在命令提示符中输入如下命令: ./byfn.sh --help命令执行成功后&#…...
ClickHouse查询sql长度超超过最大限制
ClickHouse查询sql长度超超过最大限制 Max query size exceeded ClickHouse exception, message: Code: 62. DB::Exception: Syntax error: failed at position 262102 (‘fwm00ud6a3ynu0kaxr.ya0eyemkbzdvrxkhwgchccll’) (line 10406, col 17): fwm00ud6a3ynu0kaxr.ya0eyemk…...
【Axure教程】拖动调整行高列宽的表格
表格是在系统软件中非常常用的工具。表格通常由行和列组成,用于以结构化的方式显示和组织数据。它们在各种场景中都有广泛的应用,包括数据分析、数据录入、报表生成、项目管理和数据可视化等领域。 今天作者就教大家如何在Axure里制作一个能通过鼠标拖动…...
中间件-netty(1)
netty 前言篇 文章目录 一、IO基础篇1.概念1.1 阻塞(Block)和非阻塞(Non-Block)1.2 同步(Synchronization)和异步(Asynchronous)1.3 BIO 与 NIO 对比1.3.1 面向流与面向缓冲1.3.2 阻塞与非阻塞1.3.3 选择器的问世 2.NIO 和 BIO 如何影响应用程序的设计2.1 API调用2.2 数据处理2…...
【方法】想把PDF文档转换成PPT,如何操作?
很多小伙伴在工作中,会使用PDF或者PPT来展示内容。那如果需要把PDF转换成PPT,要如何操作呢? 我们知道,PPT转换成PDF很容易操作,只需通过PPT的【导出】选项,就可以直接转换成PDF;还可以通过“另…...
Linux--设置目录或文件的默认权限:umask权限掩码
目录起始权限是从777,普通文件起始权限从666 为何我们创建一个目录或文件,默认权限是你所看到的样子? 因为凡是在umask中出现的权限,都不应该在最终权限中出现! 最终权限起始权限&(~umask)…...
C++实现websocket单server单client全双工通信(基于boost!!!)
自身环境:ubuntu18.04gcc7.5.0boost1.7,3 环境配置 gcc或者g一般都有,这里主要介绍一下boost的配置方法 执行如下代码: wget https://boostorg.jfrog.io/artifactory/main/release/1.73.0/source/boost_1_73_0.tar.bz2 --no-check-cert…...
好用的网址5
搜番神器:https://trace.moe/ Online converter:Online converter - convert video, images, audio and documents for free 格式转换 GIF Explode:https://gif-explode.com/ SongDonkey:SongDonkey - AI Online Audio Split…...
做项目去实习到底做的什么?
300万字!全网最全大数据学习面试社区等你来! 今天是手机编辑的文章,说说做项目/实习这回事。 我之前发过一些视频,讲校招四要素的,其中一个很重要的部分就是实习。 对社招同学来说,就简单了,面试…...
VSC++: 验证身份证
缘由https://ask.csdn.net/questions/1082358 void 验证身份证() {//缘由https://ask.csdn.net/questions/1082358int 权重[] { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 }, 个 0, j 0, a 0, he 0;char M[] "10X98765432", 身份号[100][20]{};//…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
