通过ffmpeg将aac格式转换成wav格式

通过ffmpeg将aac格式转换成wav格式

2023年7月25日发(作者:)

通过ffmpeg将aac格式转换成wav格式这是⼀个很简单的⼩程序,但也让我这个初学者折腾了好⼏天,⾛算是⼊门了,总结下学习的过程,希望能够初学者能有所帮助。看源代码,⾸先得让让它跑起来。看了ffmpeg提供源码api-example.c,很好的⼊门程序,虽然对视频编解码⼗分顺利,但是源码提供的⾳频解码是有问题的,mp2⽂件不能正常的解码,这是很让⼈沮丧,特别是对⼀个初学者来说。在对源程序进⾏单步调试的过程中,问题定位在了这个语句上:avcodec_decode_audio3(in_ast_cctx, (int16_t *)outbuf, &out_size, &packet);再看前⾯看看,有这样两⾏语句。/* decode until eof */ = inbuf; = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);这两⾏代码的意思很明确,就是将待解码数据数据放⼊这个缓冲区中,通过avcodec_decode_audio3对其进⾏解码。这些看起来都很合理,但问题出在哪⾥呢?且看video_decode_example函数中这段话:/* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) and this is the only method to use them because you cannot know the compressed data size before analysing it. BUT some other codecs (msmpeg4, mpeg4) are inherently frame based, so you must call them with all the data for one frame exactly. You must also initialize 'width' and 'height' before initializing them. */ /* NOTE2: some codecs allow the raw parameters (frame size, sample rate) to be changed at any frame. We handle this, so you should also take care of it */ /* here, we use a stream based decoder (mpeg1video), so we feed decoder and see if it could decode a frame */这句话看起来与我们的⾳频解码没有任何关系,但”codecs are stream based“和“frame based”,却给我们很好的提⽰,很显然,ffmpeg提供的AAC decoder是基于帧解码的,我们在给缓冲区的填充的数据应该是⼀个完整的⾳频帧,不多也不少,⽽不是简单的⼀次从⽂件中fread AUDIO_INBUF_SIZE⼤⼩的数据。问题已经很明朗了,通过在填充之前,需要进⾏⼀个预处理,即通过AAC帧中的同步字(帧头的12bit--0xFFF)来找出完整的⼀帧。那就写预处理程序吧,转念⼀想,ffmpeg这么多⾏代码,不提供AAC帧解析的API也没有天理了,继续google,找到了下⾯⼀篇⽂章:⽂章的标题是:利⽤libavcodec和libavformat对⾳频转码。附上了很详细的代码解析,我写的源程序⼤部分基于该⽂章。下⾯就是test.c⽂件中的源码#include #include "libavformat/avformat.h"#include "libavcodec/avcodec.h"#include "audio.h"#include "neaacdec.h"int main(int argc, char **argv){ AVFormatContext *in_fctx; AVCodecContext *in_ast_cctx; AVCodec *in_ast_codec; AVPacket packet; audio_file *aufile; char *outbuf = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); int out_size; int samples; //char *filename = "C:UsersajaxheDesktopAudioCodecffmpegMyProjectoutput_"; char *filename; char *wavfile = "debug_"; //char *wavfile; int ret = 0; int ast_idx = -1; int i, first_time = 1; if (argc == 3){ filename = argv[1]; wavfile = argv[2]; } else{ printf("usage: output_ "); return -1; } av_register_all(); in_fctx = av_alloc_format_context(); ret = av_open_input_file(&in_fctx, filename, NULL, 0, NULL); if ( ret != 0 ){ printf("open input audio file[%s] fail", filename); return -1; } ret = av_find_stream_info(in_fctx); if ( ret < 0 ){ printf("find stream in audio file[%s] fail", filename); return -1; } //dump_format(in_fctx, 0, filename, 0); //这⾥我们假设,如果⼀个⽂件包含多个⾳频流, //只对第⼀个⾳频流做转码,⽽对于视频流则忽略 for (i=0; i<(int)in_fctx->nb_streams; ++i){ if (in_fctx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO){ ast_idx=i; break; } } if (ast_idx == -1){ printf("there is not any audio stream in [%s]", filename); return 0; } else{ printf("find audio stream in [%s]n", filename); } in_ast_cctx = in_fctx->streams[ast_idx]->codec; in_ast_codec = avcodec_find_decoder(in_ast_cctx->codec_id); if (!in_ast_codec){ printf("find decoder for codec_id[%d] fail, file[%s]", in_ast_cctx->codec_id, filename); return -1; } ret = avcodec_open(in_ast_cctx, in_ast_codec); if (ret >= 0){ printf("open codec[name:%s] for stream[idx:%d] of file[%s]n", in_ast_codec->name, ast_idx, filename); } av_init_packet(&packet); while (av_read_frame(in_fctx, &packet) >= 0){ out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; ret = avcodec_decode_audio3(in_ast_cctx, (int16_t *)outbuf, &out_size, &packet); if (first_time){ aufile = open_audio_file(wavfile, in_ast_cctx->sample_rate, in_ast_cctx->channels, FAAD_FMT_16BIT, OUTPUT_WAV, 0); first_time = 0; } samples = in_ast_cctx->frame_size * in_ast_cctx->channels; write_audio_file(aufile, outbuf, samples, 0); } if (!first_time) close_audio_file(aufile);

avcodec_close(in_ast_cctx); av_free(in_ast_cctx); return 0;}由于仅仅是⼀个简单的⼩程序,只写了个main函数,还请见谅。#include "audio.h"#include "neaacdec.h"这两个头⽂件是我从faad2源代码中弄过来,时间仓促,没有来得及⾃⼰整理下,需要的整个⼯程朋友就直接从下⾯这个链接下载吧

发布者:admin,转转请注明出处:http://www.yc00.com/news/1690227625a317888.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信