ffmpeg 解码音频(aac、mp3)输出pcm文件

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;
}

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

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

相关文章

Jquery getJSON()

getJSON与aspx 准备工作 Customer类 public class Customer{public int Unid { get; set; }public string CustomerName { get; set; }public string Memo { get; set; }public string Other { get; set; }}&#xff08;一&#xff09;ashx Customer customer new Customer { …

北京中信银行总行地址_中信银行拉萨分行举行“存款保险标识”启用和存款保险条例宣传活动...

11月NOV中信银行拉萨分行举行“存款保险标识”启用和《存款保险条例》宣传活动揭牌启用仪式111月Jul根据人民银行和总行关于“存款保险标识”启用工作相关要求&#xff0c;分行行领导高度重视“存款保险标识”启用和《存款保险条例》宣传活动工作&#xff0c;按照统一工作部署、…

Java ClassLoader getPackage()方法与示例

ClassLoader类的getPackage()方法 (ClassLoader Class getPackage() method) getPackage() method is available in java.lang package. getPackage()方法在java.lang包中可用。 getPackage() method is used to return the package that has been defined in ClassLoader or t…

C---编写程序:求出1~1000之间能被7或12整除,但不能同时被二者整除的所有整数,将结果保存在数组中,要求程序数据的输入、计算和输出均使用函数实现。

编写程序&#xff1a;求出1~1000之间能被7或12整除&#xff0c;但不能同时被二者整除的所有整数&#xff0c;将结果保存在数组中&#xff0c;要求程序数据的输入、计算和输出均使用函数实现。 编程思路&#xff1a;分别编写函数input()、cal()、output()实现数据的输入、计算和…

报告称我国成最大移民输出国 将形成投资产业链(关注)

时代特有的现象&#xff0c;我们应该予以关注 “现在国内房价这么高&#xff0c;政策也看不清&#xff0c;还不如逢高卖掉之前买的几套房子&#xff0c;一两套房子的钱办个投资移民&#xff0c;趁还年轻&#xff0c;拿到绿卡后享受一下美国本国待遇的高等教育了。”广州&#x…

转整型_156.Ruby烘焙大理石豆沙吐司解锁大理石花纹整型

好看又好吃的大理石豆沙面包。红豆馅均匀分布在松软细腻的面包体里&#xff0c;手撕着吃&#xff0c;一层层的甜美与温柔&#xff5e;关于吐司面包&#xff0c;我公众号里写过白吐司(基础款牛奶吐司&#xff0c;超绵鲜奶油吐司)和全麦吐司(基础款50%全麦吐司&#xff0c;经典燕…

ffmpeg 解码视频(h264、mpeg2)输出yuv420p文件

ffmpeg 解码视频&#xff08;h264、mpeg2&#xff09;输出yuv420p文件 播放yuv可以参考&#xff1a;ffplay -pixel_format yuv420p -video_size 768x320 -framerate 25 out.yuv main.c #include <stdio.h> #include <stdlib.h> #include <string.h>#includ…

VS2010 快捷键 (空格显示 绿点, Tab 显示箭头)

VS2010 有用的快捷键 &#xff1a; Ctrl r, ctrl w, 切换空格示。 转载于:https://www.cnblogs.com/fengye87626/archive/2012/11/21/2780716.html

C---编写程序:实现一个随堂测试,能进行加减乘除运算。要求如下:(1)随机产生两个1~10的正整数,在屏幕上输出题目,如:5+3=?(2)学生输入答案,程序检查学生输入答案是否正确,若正确,

编写程序&#xff1a;实现一个随堂测试&#xff0c;能进行加减乘除运算。要求如下&#xff1a; 1&#xff09;随机产生两个1~10的正整数&#xff0c;在屏幕上输出题目&#xff0c;如&#xff1a;53&#xff1f; 2&#xff09;学生输入答案&#xff0c;程序检查学生输入答案是…

分析一下mp4格式的trak -> mdia -> minf -> stbl -> stts、stsc 这两个box信息

分析一下mp4格式的trak -> mdia -> minf -> stbl -> stts、stsc 这两个box信息 &#xff08;因为这两个box在音频trak和视频trak 下都有的&#xff0c;而且都有一个数组的值是比较绕的&#xff09; 目录&#xff1a;stts&#xff1a;记录时间戳的&#xff0c;每个s…

利用SQL注入2分钟入侵网站

说起流光、溯雪、乱刀&#xff0c;可以说是大名鼎鼎无人不知无人不晓&#xff0c;这些都是小榕哥的作品。每次一提起小榕哥来&#xff0c;我的崇拜景仰就如滔滔江水&#xff0c;连绵不绝~~~~&#xff08;又来了&#xff01;&#xff09; 让我们崇拜的小榕哥最新又发布了SQL注入…

pip安装deb_技术|如何在 Ubuntu 上安装 pip

pip 是一个命令行工具&#xff0c;允许你安装 Python 编写的软件包。 学习如何在 Ubuntu 上安装 pip 以及如何使用它来安装 Python 应用程序。有许多方法可以在 Ubuntu 上安装软件。 你可以从软件中心安装应用程序&#xff0c;也可以从下载的 DEB 文件、PPA(LCTT 译注&#xff…

assubclass_Java类class asSubclass()方法及示例

assubclass类类asSubclass()方法 (Class class asSubclass() method) asSubclass() method is available in java.lang package. asSubclass()方法在java.lang包中可用。 asSubclass() method casts this Class object to denote a subclass of the class denoted by the given…

VB6.0 怎样启用控件comdlg32.ocx

VB6.0 怎样启用控件comdlg32.ocx 怎样启用控件comdlg32.ocx 2008-10-08 09:32 提问者&#xff1a; nefu_20061617 |浏览次数&#xff1a;1502次vbs文件中有代码Set ComDlg CreateObject("MSComdlg.CommonDialog")运行时发生错误ActiveX 部件不能创建对象: MSComdlg.…

Python---爬虫案例

例1、爬取公众号文章中的图片。 1&#xff0c;首先打开要获取公众号文章的地址 2&#xff0c;按下F12&#xff0c;再按Ctrl Shift C&#xff0c;然后鼠标移动到图片位置&#xff0c;然后观察控制台中显示图片对应的代码位置 3&#xff0c;分析该位置的代码段 代码段如下&…

WinCE驱动开发问题精华集锦(二)

转自&#xff1a;http://hgh123.blog.163.com/blog/static/5980422120086183115543/ 感谢 我怎么能在PB左边的定制平台加进我的驱动呢&#xff1f; 两种办法&#xff1a; 1、在platform.bib或者project.bib的MODULES部分添加一条语句&#xff0c;例如&#xff1a; MyDriver.dll…

报错Unable to resolve target android-5

报错信息&#xff1a;Error:Unable to resolve target android-X&#xff08;X是一个数字&#xff09; 错误分析&#xff1a;这种错误一般大部分是SDK 版本不符所造成的&#xff0c;一般会在Ecplise工作空间导入项目时候出现此错误&#xff0c;一般提示&#xff1a;Error:Unabl…

matlab盒子分形维数_分形维数--matlab

一维曲线分形维数的matlab程序function DFractalDim(y,cellmax)%求输入一维信号的计盒分形维数%y是一维信号%cellmax:方格子的最大边长,可以取2的偶数次幂次(1,2,4,8...),取大于数据长度的偶数%D是y的计盒维数(一般情况下D>1),Dlim(log(N(e))/log(k/e)),if cellmaxerror(cel…

Java布尔类toString()方法及示例

Syntax: 句法&#xff1a; public String toString();public static String toString(boolean value);布尔类toString()方法 (Boolean class toString() method) toString() method is available in java.lang package. toString()方法在java.lang包中可用。 toString() metho…

pcm数据编码成为aac格式文件(可以在酷狗播放)

pcm数据编码成为aac格式文件&#xff08;可以在酷狗播放&#xff09; 关于其中的aac adts格式可以参考&#xff1a;AAC ADTS格式分析 main.c #include <stdio.h> #include <stdlib.h> #include <stdlib.h>#include <libavcodec/avcodec.h> #include …