FFmpeg音频解码流程详解及简单demo参考

article/2025/10/23 5:18:42

        本文主要讲解FFmpeg的音频解码具体流程,API使用。最后再以一个非常简单的demo演示将一个mp3格式的音频文件解码为原始数据pcm文件。 本文主要基于FFmpeg音频解码新接口。

一、FFmpeg音频解码API调用流程图      

   API接口简单大体讲解如下:

av_register_all():注册FFmpeg所有编解码器。avformat_open_input():打开音频地址并获取里面的内容(解封装)avformat_find_stream_info():获取内容avcodec_find_decoder():寻找解码器avcodec_alloc_context3():申请解码器相关上下文avcodec_open2():打开解码器av_read_frame():从原始有格式文件中一帧一帧读取出来avcodec_send_packet():解码核心接口新接口,发送一帧音频给解码器。即是AVPacket(存储AAC等音频格式码流数据)。avcodec_receive_frame():解码核心接口新接口,接收解码器解码后的一帧视频,AVFrame(PCM原始数据)。

二、音频解码过程API调用流程

1、注册各大组件

        这一步是ffmpeg的任何程序的第一步都是需要先注册ffmpeg相关的各大组件的:

    //注册各大组件av_register_all();LOGE("注册成功")

2、打开音频文件并获取相关上下文

        在解码之前我们得获取里面的内容,这一步就是打开地址并且获取里面的内容。其中avFormatContext是内容的一个上下文。

        并使用avformat_open_input打开播放源,inputPath为输入的地址,也就是音频文件,然后使用avformat_find_stream_info从获取的内容中寻找相关流。

//打开音频地址并获取里面的内容(解封装)
error = avformat_open_input(&avFormatContext, inputPath, NULL, NULL);
if (error < 0){LOGE("打开音频文件失败\n");return false;
}
if (avformat_find_stream_info(avFormatContext, NULL) < 0){LOGE("获取内容失败")return false;
}

3、寻找音频流

        我们在上面已经获取了内容,我们再从中找出相对应的音频流。

//获取音频的编码信息
AVCodecParameters *origin_par = NULL;
int mAudioStreamIdx = -1;
mAudioStreamIdx = av_find_best_stream(avFormatContext, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
if (mAudioStreamIdx < 0) {av_log(NULL, AV_LOG_ERROR, "Can't find audio stream in input file\n");return false;
}
LOGE("成功找到音频流")

4、获取并打开解码器

        如果要进行解码,那么得有解码器并打开解码器。在这一步中我加了个过滤器的相关配置,这个东西不是非必要的,所以我加了个宏ABSFILTER_ENABLE可以选择是否打开。

    // 寻找解码器 {startAVCodec *mAcodec = NULL;AVCodecContext *mAvContext = NULL;mAcodec = avcodec_find_decoder(origin_par->codec_id);mAvContext = avcodec_alloc_context3(mAcodec);if (!mAcodec || !mAvContext){return false;}#if ABSFILTER_ENABLE//过滤器相关配置,这个与音频码流格式相关const AVBitStreamFilter * absFilter = NULL;AVBSFContext *absCtx = NULL;AVCodecParameters *codecpar = NULL;absFilter = av_bsf_get_by_name("mp3decomp");//过滤器分配内存av_bsf_alloc(absFilter, &absCtx);//添加解码器属性codecpar = avFormatContext->streams[mAudioStreamIdx]->codecpar;avcodec_parameters_copy(absCtx->par_in, codecpar);absCtx->time_base_in = avFormatContext->streams[mAudioStreamIdx]->time_base;//初始化过滤器上下文av_bsf_init(absCtx);
#endif// 打开解码器if (avcodec_open2(mAvContext, mAcodec, NULL) != 0){LOGE("打开失败")return false;}LOGE("解码器打开成功")// 寻找解码器 end}

5、申请AVPacket和AVFrame以及相关设置

        申请AVPacket和AVFrame,其中AVPacket的作用是:保存解码之前的数据和一些附加信息等;AVFrame的作用是:存放解码过后的数据。

    //申请AVPacketAVPacket *packet = (AVPacket *) av_malloc(sizeof(AVPacket));av_init_packet(packet);//申请AVFrameAVFrame *frame = av_frame_alloc();//分配一个AVFrame结构体,AVFrame结构体一般用于存储原始数据,指向解码后的原始帧

6、开始解码

        接下来就可以开始解码,如下是解码的核心段代码,这里同样有上面所说的过滤器的,这个可以先不关心:

{// 发送待解码包int result = avcodec_send_packet(mAvContext, packet);av_packet_unref(packet);if (result < 0){av_log(NULL, AV_LOG_ERROR, "Error submitting a packet for decoding\n");continue;}// 接收解码数据while (result >= 0){result = avcodec_receive_frame(mAvContext, frame);if (result == AVERROR_EOF)break;else if (result == AVERROR(EAGAIN)){result = 0;break;}else if (result < 0){av_log(NULL, AV_LOG_ERROR, "Error decoding frame\n");av_frame_unref(frame);break;}av_frame_unref(frame);}
}

7、解码并保存为PCM文件

        PCM是音频解码后的原始数据,我们将解码后的数据保存为PCM文件,用于分析。在上一步中解码后的地方加上保存为PCM文件的操作。

        另外这里有用了上面所说的过滤器的东西,我们暂时先不关心。

        完整过程如下:

while(1)
{int ret = av_read_frame(avFormatContext, packet);if (ret != 0){av_strerror(ret,buf,sizeof(buf));LOGE("--%s--\n",buf);av_packet_unref(packet);break;}if (ret >= 0 && packet->stream_index != mAudioStreamIdx){av_packet_unref(packet);continue;}#if ABSFILTER_ENABLEif (av_bsf_send_packet(absCtx, packet) < 0){LOGE("av_bsf_send_packet faile \n");av_packet_unref(packet);continue;}if (av_bsf_receive_packet(absCtx, packet) < 0) {LOGE("av_bsf_receive_packet faile \n");av_packet_unref(packet);continue;}
#endif{// 发送待解码包int result = avcodec_send_packet(mAvContext, packet);av_packet_unref(packet);if (result < 0){av_log(NULL, AV_LOG_ERROR, "Error submitting a packet for decoding\n");continue;}// 接收解码数据while (result >= 0){result = avcodec_receive_frame(mAvContext, frame);if (result == AVERROR_EOF)break;else if (result == AVERROR(EAGAIN)){result = 0;break;}else if (result < 0){av_log(NULL, AV_LOG_ERROR, "Error decoding frame\n");av_frame_unref(frame);break;}// 写文件保存音频数据data_size = av_get_bytes_per_sample(mAvContext->sample_fmt);if (data_size < 0) {/* This should not occur, checking just for paranoia */LOGE("Failed to calculate data size\n");return false;}for (i = 0; i < frame->nb_samples; i++)for (ch = 0; ch < mAvContext->channels; ch++)fwrite(frame->data[ch] + data_size*i, 1, data_size, fp_PCM);av_frame_unref(frame);}}}

8、收尾释放

        最后释放相关资源

    fclose(fp_PCM);av_frame_free(&frame);avcodec_close(mAvContext);avformat_free_context(avFormatContext);
#if ABSFILTER_ENABLEav_bsf_free(&absCtx);absCtx = NULL;
#endif

        至此,mp3格式的文件就被解码出原始数据并保存为PCM文件。

三、demo运行

         demo中指定了视频源文件是/sdcard/input.mp3,编码后的pcm文件是/sdcard/audioDecodeOut.pcm,如下代码,若要改文件,可以在此处修改:

@Override
public void run() {String PATH = Environment.getExternalStorageDirectory().getPath();//视频解码String input = PATH + File.separator + "input.mp3";String output = PATH + File.separator + "audioDecodeOut.pcm";decode_audio(input,output);Toast.makeText(MainActivity.this, "音频解码完成,请自行从手机中拉取pcm文件", Toast.LENGTH_SHORT).show();
}

        运行后截图如下:

        点击"START AUDIO DECODE"按钮,开始对音频文件进行解码,界面不会有什么提示,等解码完成后会弹出提示词 "音频解码完成,请自行从手机中拉取pcm文件"

        我们从运行log中也能看到一些信息,如下:

        当有--- audio decode finished ---打印出来说明已经解码完成。

        然后我们adb shell进去手机看看解码前后的文件:

         可以看到解码后的pcm原始数据文件比解码前是大很多的。

四、分析PCM文件

        接下来我们分析下解码后的PCM文件是否正确。

        首先我们需要先知道一下解码前的mp3文件的一些信息,比如声道数,采样率等等。这些我们可以通过FFmpeg的ffprobe来获取,这里我在我的Ubuntu电脑上通过ffmpeg命令行获取一下:

        红圈圈中的就是几个比较重要的信息,看到是采样率是44100,双声道,fltp格式。

        接下来使用PCM分析工具,我使用的是Audacity:

         打开工具,并点击导入原始数据:

        然后选择pcm文件,弹出格式选择的弹窗,采样率就是刚才的44100,声道是双声道也就是2声道,字节序一般是小尾端,编码是fltp,也就是选32-bit float。

         点击导入后,显示如下,可以看到音频数据的波形图,然后点击右上方的播放按钮播放pcm文件,若音乐听起来正常,与之前的mp3文件一致,则说明解码后的pcm数据正常。

         完整例子已经放到github上,如下:

https://github.com/weekend-y/FFmpeg_Android_Demo/tree/master/demo6_audioDecode


http://chatgpt.dhexx.cn/article/p6B1Xbdp.shtml

相关文章

ffmpeg 音频解码一

1. ffmpeg 视频解码一 2. ffmpeg 视频解码二 3. ffmpeg 音频解码一 4. ffmpeg 音频解码二 5. ffmpeg 音视频解码 6. ffmpeg 视频编码一 7. ffmpeg 视频编码一&#xff08;精简版&#xff09; 8. ffmpeg 视频编码二&#xff08;基于 libswscale 转换视频&#xff09; 9. ffmpeg …

MP3音频解码详细过程(二)

最近做了无人机的音频解码&#xff0c;二周内从无任何音频基础到输出PCM数据码流到无人机上可以实现播报功能&#xff0c;其中遇到了许多莫名的坑&#xff0c;谨以此篇记录心得。也算交个作业。 架构设计思路&#xff1a;由usart 实时传输mp3音频码流&#xff0c;STM32F446 将…

低延迟音频中的音频解码优化策略

文章目录 前言音频播放举个例子&#xff1a;PortAudio回调函数解码与播放 优化策略1. 一次性读取音频到内存中2. MMAP3. 音频转码&#xff0c;再接 MMAP4. 解码缓冲 总结参考资料 前言 延迟是指信号在系统中传输所需的时间。下面是常见类型的音频应用相关延迟时间&#xff1a;…

音频编解码基础

1. PCM PCM 脉冲编码调制是Pulse Code Modulation的缩写。脉冲编码调制是数字通信的编码方式之一。主要过程是将话音、图像等模拟信号每隔一定时间进行取样&#xff0c;使其离散化&#xff0c;同时将抽样值按分层单位四舍五入取整量化&#xff0c;同时将抽样值按一组二进制码来…

音视频解码流程详解

1、解码整体流程 &#xff08;1&#xff09; 音频解码整体流程 &#xff08;2&#xff09;视频解码整体流程 2、FFmpeg音视频解码详细流程 3、关键数据结构 AVCodecParser&#xff1a;⽤于解析输⼊的数据流并把它分成⼀帧⼀帧的压缩编码数据。⽐较形象 的说法就是把⻓⻓的⼀…

FFmpeg 音频解码(秒懂)

1.简介 解码音频数据&#xff0c;如下图所示&#xff0c;把MP3或者AAC数据解码成原始的数据pcm。 2.流程 2.1在使用FFmpeg API之前&#xff0c;需要先注册API&#xff0c;然后才能使用API。当然&#xff0c;新版本的库不需要再调用下面的方法。 av_register_all() 2.2 构建输…

语音编解码技术演进和应用选型

本文来自现网易云音乐音视频实验室负责人刘华平在LiveVideoStackCon 2017大会上的分享&#xff0c;并由LiveVideoStack整理而成。分享中刘华平以时间为主线&#xff0c;讲述了语音编解码技术的演进路线及实际应用中的技术选型。 文 / 刘华平 整理 / LiveVideoStack 大家好&…

回访。

wyx 过来&#xff0c;还 sxt &#xff0c;拿走了几张碟。为此&#xff0c;特意收拾了房间。还是被说没地方坐。 由于事先约了 zhmm 吃饭&#xff0c;没调开时间&#xff0c;所以&#xff0c;五点多&#xff0c;大家就一起吃了。大青花&#xff0c;东北风味儿。餐厅在二楼&…

客户信息管理软件系统

拟实现一个基于文本界面的《客户信息管理软件》 进一步掌握编程技巧和调试技巧&#xff0c;熟悉面向对象编程 主要涉及以下知识点&#xff1a; ▶类结构的使用&#xff1a; ▶对象的创建与使用 ▶类的封装性 ▶声明和使用数组 ▶数组的插入、删除和替换 ▶关键字的使用&#xf…

企业如何通过CRM系统有效触达客户,获取潜在商机

“守株待兔”式坐等客户上门的时代了已经过去了&#xff0c;尤其是在存量时代&#xff0c;企业想要提高销售&#xff0c;扩大客源&#xff0c;就要不断的通过各种渠道来去拓展自己的客户和销路&#xff0c;而互联网时代&#xff0c;获客的渠道也丰富多样&#xff0c;企业选择好…

呼叫中心系统接入CRM客户管理系统

呼叫中心是企业与客户建立联系的桥梁&#xff0c;企业想要发展必须要有统一的客户管理系统&#xff0c;呼叫中心与客户管理系统对接到一起能够更高效管理客户&#xff0c;档案数据更准确。 在以前企业都是通过纸质的客户档案管理客户的&#xff0c;寻找某个客户时特别不方便&am…

CRM管理系统、教育后台、赠品管理、优惠管理、预约管理、试听课、教师、学生、客户、学员、商品管理、科目、优惠券、完课回访、客户管理系统、收费、退费、回访、账号权限、订单流水、Axure原型、rp原型

CRM管理系统、教育后台、赠品管理、优惠管理、预约管理、试听课、教师、学生、客户、学员、商品管理、科目、优惠券、完课回访、客户管理系统、收费、退费、回访、账号权限、订单流水、Axure原型、rp原型 Axure原型演示及下载地址&#xff1a;https://www.pmdaniu.com/storage…

在线云客服管理系统、会话管理、访客管理、客户管理、工单管理、会话记录、考勤统计、数据报表、工单设置、全局设置、转人工服务、自动回复、客户标签、客服监控、客服系统、前端会话、客服管理、在线客服、人工客服

在线云客服管理系统、会话管理、访客管理、客户管理、工单管理、会话记录、考勤统计、数据报表、工单设置、全局设置、转人工服务、自动回复、客户标签、客服监控、客服系统、前端会话、客服管理、在线客服 、人工客服 Axure原型演示及下载地址&#xff1a;Untitled Documenth…

CRM管理系统、教育后台、赠品管理、优惠管理、预约管理、试听课、教师、学生、客户、学员、商品管理、科目、优惠券、完课回访、客户管理系统、收费、退费、回访、账号权限、订单流水、审批、转账、rp原型

CRM管理系统、教育后台、赠品管理、优惠管理、预约管理、试听课、教师、学生、客户、学员、商品管理、科目、优惠券、完课回访、客户管理系统、收费、退费、回访、账号权限、订单流水、Axure原型、rp原型 Axure原型演示及下载地址&#xff1a;Untitled Documenthttps://f2b1hj…

客户管理系统

项目github地址&#xff1a;https://github.com/gh995836/crm 项目技术&#xff1a;SpringMVCSpringMybatisAjaxBootstrap 项目描述&#xff1a;该客户管理系统&#xff0c;前端采用Bootstrap框架 Ajax发送请求&#xff0c;后台采用JavaWeb的SpringMVCSpringMybatis框架进行…

“顾客总是对的”,客户满意从在线客服系统开始

"顾客总是对的"——马歇尔菲尔德 哈里戈登赛尔费里奇 毋庸置疑&#xff0c;赢得客户的青睐是维系自身经济长青的基础。想要客户满意&#xff0c;得到最佳的客户评价&#xff0c;企业就需要为客户提供超出他们期望的服务。 有人将客户服务分为三重境界:第一重境界&am…

一文读懂:客户管理系统平台是什么?有什么作用?

“客户管理系统平台是什么&#xff1f;” “客户管理系统平台有什么作用&#xff1f;在哪里可以应用&#xff1f;怎么用&#xff1f;” 经常可以听到企业内部关于客户管理系统平台的这些问题&#xff0c;本文将会为您一一解答&#xff1a; 一、客户管理系统平台是什么 顾名…

什么是客户自助服务门户及其搭建方法

随着信息技术的快速发展&#xff0c;越来越多的企业开始转向以客户为中心的服务模式&#xff0c;而客户自助服务门户&#xff08;Customer Self-Service Portal&#xff09;则成为了重要的服务方式。它可以让客户在不需要人工干预的情况下&#xff0c;自行解决问题&#xff0c;…

客户管理系统如何提升体验

数字化时代&#xff0c;客户与企业交互的触点爆炸式增长&#xff0c;客户体验正从单一触点走向端到端旅程。众多的产品、海量的数据&#xff0c;导致客户对体验的要求越来越多......CRM客户管理系统是企业提升客户体验的有效工具&#xff0c;它不仅可以帮助您进一步了解客户&am…

在线云客服管理系统、会话管理、访客管理、客户管理、工单管理、会话记录、考勤统计、数据报表、工单设置、全局设置、人工服务、自动回复、客户标签、客服监控、客服系统、前端会话、客服管理、在线客服 、人工客服

在线云客服管理系统、会话管理、访客管理、客户管理、工单管理、会话记录、考勤统计、数据报表、工单设置、全局设置、转人工服务、自动回复、客户标签、客服监控、客服系统、前端会话、客服管理、在线客服 、人工客服 Axure原型演示及下载地址&#xff1a;https://www.pmdani…