ffmpeg 解码音频(aac、mp3)输出pcm文件
播放pcm可以参考: ffplay -ar 48000 -ac 2 -f f32le out.pcm

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <libavutil/frame.h>
#include <libavutil/mem.h>
#include <libavcodec/avcodec.h>#define AUDIO_INBUF_SIZE    10240
#define AUDIO_REFILL_THRESH 4096static void decode(AVCodecContext* dec_ctx, AVPacket* pkt, AVFrame* frame, FILE *outfile)
{int i, ch;int ret, sample_size;int send_ret = 1;do{//传入要解码的packetret = avcodec_send_packet(dec_ctx, pkt);//AVERROR(EAGAIN) 传入失败,表示先要receive frame再重新send packetif(ret == AVERROR(EAGAIN)){send_ret = 0;fprintf(stderr, "avcodec_send_packet = AVERROR(EAGAIN)\n");}else if(ret < 0){char err[128] = {0};av_strerror(ret, err, 128);fprintf(stderr, "avcodec_send_packet = ret < 0 : %s\n", err);return;}while (ret >= 0){//调用avcodec_receive_frame会在内部首先调用av_frame_unref来释放frame本来的数据//就是这次调用会将上次调用返回的frame数据释放ret = avcodec_receive_frame(dec_ctx, frame);if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)return;else if(ret < 0){fprintf(stderr, "avcodec_receive_frame = ret < 0\n");exit(1);}//获取采样点占用的字节sample_size = av_get_bytes_per_sample(dec_ctx->sample_fmt);if(sample_size < 0){fprintf(stderr, "av_get_bytes_per_sample = sample_size < 0\n");exit(1);}//在第一帧的时候输出一下音频信息static int print_info = 1;if(print_info){print_info = 0;printf("ar-samplerate: %uHz\n", frame->sample_rate);printf("ac-channel: %u\n", frame->channels);printf("f-format: %u\n", frame->format);}//平面方式://LLLLRRRRLLLLRRRRLLLLRRRR      (LLLLRRRR这样为一个音频帧)//交错方式://LRLRLRLRLRLRLRLRLR           (LR这样为一个音频样本)//按交错方式写入(nb_samples这一帧多少样本)for(i = 0; i < frame->nb_samples; i++){   //dec_ctx->channels 多少个通道的数据for(int channle = 0; channle < dec_ctx->channels; channle++){//frame->data[0] = L 通道//frame->data[1] = R 通道fwrite(frame->data[channle] + sample_size * i, 1, sample_size, outfile);}}}}while(!send_ret);}#define AAC 0
int main()
{const char* outfilename = "out.pcm";#if AACconst char* filename = "test.aac";
#elseconst char* filename = "test.mp3";
#endifconst AVCodec *codec;AVCodecContext *codec_ctx= NULL;AVCodecParserContext *parser = NULL;int len = 0;int ret = 0;FILE *infile = NULL;FILE *outfile = NULL;uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];uint8_t *data = NULL;size_t   data_size = 0;AVPacket *pkt = NULL;AVFrame *de_frame = NULL;//申请AVPacket本身的内存pkt = av_packet_alloc();//要使用的解码器IDenum AVCodecID audio_codec_id = AV_CODEC_ID_AAC;if(strstr(filename, "aac") != NULL){audio_codec_id = AV_CODEC_ID_AAC;}else if(strstr(filename, ".mp3") != NULL){audio_codec_id = AV_CODEC_ID_MP3;}else{printf("audio_codec_id = AV_CODEC_ID_NONE\n");return 0;}//查找相应的解码器codec = avcodec_find_decoder(audio_codec_id);if(!codec){printf("Codec not find!\n");return 0;}//根据解码器ID获取裸流的解析器parser = av_parser_init(codec->id);if(!parser){printf("Parser not find!\n");return 0;}//分配codec使用的上下文codec_ctx = avcodec_alloc_context3(codec);if(!codec_ctx){printf("avcodec_alloc_context3 failed!\n");return 0;}//将解码器和解码使用的上下文关联if(avcodec_open2(codec_ctx, codec, NULL) < 0){printf("avcodec_open2 failed!\n");return 0;}//打开输入文件infile = fopen(filename, "rb");if(!infile){printf("infile fopen failed!\n");return 0;}//输出文件outfile = fopen(outfilename, "wb");if(!outfile){printf("outfilie fopen failed!\n");return 0;}int file_end = 0;//读取文件开始解码data = inbuf;data_size = fread(inbuf, 1, AUDIO_INBUF_SIZE, infile);de_frame = av_frame_alloc();while (data_size > 0){//获取传入到avcodec_send_packet一个packet的数据量//(一帧的量可能也会多帧的量,这里测试是一帧的量)ret = av_parser_parse2(parser, codec_ctx, &pkt->data, &pkt->size,data, data_size,AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);if(ret < 0){printf("av_parser_parser2 Error!\n");return 0;}//使用了多少数据做一个偏移data += ret;data_size -= ret;if(pkt->size)decode(codec_ctx, pkt, de_frame, outfile);//如果当前缓冲区中数据少于AUDIO_REFILL_THRESH就再读//避免多次读文件if((data_size < AUDIO_REFILL_THRESH) && !file_end ){//剩余数据移动缓冲区前memmove(inbuf, data, data_size);data = inbuf;//跨过已有数据存储len = fread(data + data_size, 1, AUDIO_INBUF_SIZE - data_size, infile);if(len > 0)data_size += len;else if(len == 0){file_end = 1;printf("file end!\n");}}}//冲刷解码器pkt->data = NULL;pkt->size = 0;decode(codec_ctx, pkt, de_frame, outfile);fclose(infile);fclose(outfile);avcodec_free_context(&codec_ctx);av_parser_close(parser);av_frame_free(&de_frame);av_packet_free(&pkt);printf("audio decoder end!\n");return 0;
}

ffmpeg 解码音频(aac、mp3)输出pcm文件相关推荐

  1. FFmpeg开发笔记(七):ffmpeg解码音频保存为PCM并使用软件播放

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108799279 各位读者,知识无穷而人力有穷 ...

  2. 使用ffmpeg解码音频sdl(push)播放

    自定义播放器系列 第一章 视频渲染 第二章 音频(push)播放(本章) 第三章 音频(pull)播放 第四章 实现时钟同步 第五章 实现通用时钟同步 第六章 实现播放器 文章目录 自定义播放器系列 ...

  3. 老调重弹之ffmpeg解码音频

    老调重弹之ffmpeg解码音频 接着之前的视频解码,在之前的基础上加上音频解码,还是使用SDL. 首先找到音频流 与找视频流时一样,在avformat_find_stream_info之后,遍历一下A ...

  4. FFmpeg解码音频代码

    工程请访问DecodeTest.用c++写的,使用FFmpeg-4.1.0.比较完善的是OfficalDecodeAudio.cpp,它是我研究了一下ffplay.c的源码得来的.该代码按照统一的44 ...

  5. ffmpeg 将音频转为mp3问题解决

    安装完成ffmpeg后,就可以使用ffmpeg进行音频文件格式转换.比如 ./ffmpeg -i /media/1.mp3 /media/1.wav, 通过该命令行可以将/media文件夹下1.mp3 ...

  6. AU软件导出mp3为pcm文件

    1.打开AU软件,选择文件导入选项卡,将所需要的音频文件导入到项目. 2.可以在左上角看到音频文件的采样率,声道数和位宽. 3.点击文件导出选项卡. 4.文件导出设置如图上,点击确定即可导出pcm文件 ...

  7. ffmpeg h264和aac封装为mp4文件

    1.I帧/P帧/B帧 I帧:帧内编码图像帧,也叫关键帧,包含一幅完整的图像信息,不含运动矢量,在解码时不需要参考其它帧图像.在闭合式GOP(画面组)中,每个GOP的开始是IDR帧,且当前GOP的数据不 ...

  8. ffmpeg 实现音频aac编码

    1.编译ffmepg ./configure --disable-yasm --enable-nonfree --enable-libfaac --prefix=/home/ffmpeg/1_ffmp ...

  9. python3 利用ffmpeg把音频转换为16khz的wav文件

    最近语音识别需要转换为16khz 16位的wav文件,这里分享一下我的代码: 这里默认电脑已经安装好ffmpeg,没安装好的话,mac用hombrew安装一下就行了,然后: import osdef ...

最新文章

  1. android用java_原来android不是只能用java写软件
  2. 1月23日服务器例行维护更新公告,1月24日服务器例行维护公告(已完成)
  3. Python模块学习——optparse
  4. 线段树 区间更新模板
  5. 正则匹配查询_如何用MySQL中的正则表达式过滤掉配送单
  6. Windows Phone 7(accelerometer)重力感应编程
  7. python的print怎么输出utf-8的编码_原创反转精度算法:小数的终极编码
  8. OpenWrt 编译分割
  9. Visual studio 2019 报错没有“dirent.h”文件
  10. SSM框架整合环境搭建
  11. 电子计算机机房防雷装置,网络机房防雷方案
  12. 点击vue页面链接打开本地exe文件
  13. 华为全球发布UMTS终端商用新品
  14. 操作系统实验七(银行家算法)
  15. 6. Excel 图表制作
  16. 有关R星游戏(尤其是荒野大镖客玩家)二次验证码/两步验证/谷歌验证绑定相关问题
  17. 用canvas制作的躲避球小游戏html5源码
  18. [C语言] 一维数组
  19. 排列组合“捆绑法”、“插空法”、“插板法
  20. pytorch Module中的forward使用for循环与不使用for循环的区别

热门文章

  1. 用CSS伪类制作一个不断旋转的八卦图?
  2. PAT_B_1012 数字分类 (有待改进)
  3. 用asp.net编写冒泡排序法
  4. Eclipse安装TestNG插件
  5. 简单谈谈js中的MVC
  6. 动态给H5页面绑定数据,基本万能无错误!
  7. MyBatis 入门到精通(二) SQL语句映射XML文件
  8. dynamic与var
  9. ajax 复制到“剪贴板”
  10. 想起温习一下JS中的this apply call arguments