我想用ffmpeg库做一个音频转码.现在我有文件,但我只能听到噪音.
我的计划的步骤是:
1)打开输入文件并使用avcodec_decode_audio4以原始格式解码
2)编码并保存原始格式.
我不知道我错在哪里.这是我的代码.
我的计划的步骤是:
1)打开输入文件并使用avcodec_decode_audio4以原始格式解码
2)编码并保存原始格式.
我不知道我错在哪里.这是我的代码.
/* * File: newmain.c * Author: antonello * * Created on 23 gennaio 2013,11.24 */ #include <stdio.h> #include <stdlib.h> #include <libavutil/samplefmt.h> #include <libavutil/timestamp.h> #include <libavformat/avformat.h> #include <libavcodec/old_codec_ids.h> static AVCodecContext *get_encoder(int sampleRate,int channels,int audioBitrate) { AVCodecContext *audioCodec; AVCodec *codec; //Set up audio encoder codec = avcodec_find_encoder(CODEC_ID_AAC); if (codec == NULL) { printf("avcodec_find_encoder: ERROR\n"); return NULL; } audioCodec = avcodec_alloc_context(); audioCodec->bit_rate = audioBitrate; audioCodec->sample_fmt = AV_SAMPLE_FMT_S16P; audioCodec->sample_rate = sampleRate; audioCodec->channels = channels; audioCodec->profile = FF_PROFILE_AAC_MAIN; audioCodec->channel_layout=AV_CH_LAYOUT_MONO; //audioCodec->time_base = (AVRational){1,sampleRate}; audioCodec->time_base.num = 1; audioCodec->time_base.den = sampleRate; audioCodec->codec_type = AVMEDIA_TYPE_AUdio; if (avcodec_open(audioCodec,codec) < 0) { printf("avcodec_open: ERROR\n"); return NULL; } return audioCodec; } int main(int argc,char** argv) { AVFormatContext *aFormatCtx_decoder = NULL; AVFormatContext *aFormatCtx_encoder = NULL; int i,audioStream; AVPacket packet_decoder; AVPacket packet_encoder; int got_frame=0; int complete_decode=0; int len; AVFrame *decoded_frame = NULL; AVCodecContext *aCodec_decoderCtx = NULL; AVCodec *aCodec_decoder = NULL; FILE *outfile; //reding input file avcodec_register_all(); //register all codecs av_register_all(); //open file if(avformat_open_input(&aFormatCtx_decoder,"sample.aac",NULL,NULL)!=0){ fprintf(stderr,"Could not open source file \n"); return -1; // Couldn't open file } // Retrieve stream information if(avformat_find_stream_info(aFormatCtx_decoder,NULL)<0){ fprintf(stderr,"Couldn't find stream information \n"); return -1; // Couldn't find stream information } // Dump information about file onto standard error //av_dump_format(aFormatCtx_decode,argv[1],0); // Find the first audio stream audioStream=-1; for(i=0; i<aFormatCtx_decoder->nb_streams; i++) { if(aFormatCtx_decoder->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUdio && audioStream < 0) { audioStream=i; } } if(audioStream==-1){ fprintf(stderr,"File haven't sudio stream \n"); return -1; } //get audio codec contex aCodec_decoderCtx=aFormatCtx_decoder->streams[audioStream]->codec; //get audio codec aCodec_decoder = avcodec_find_decoder(aCodec_decoderCtx->codec_id); aCodec_decoder->sample_fmts=AV_SAMPLE_FMT_S16P; if(!aCodec_decoder) { fprintf(stderr,"Unsupported codec!\n"); return -1;//Unsupported codec! } //open codec // Open codec if(avcodec_open2(aCodec_decoderCtx,aCodec_decoder,NULL)<0) return -1; // Could not open codec // allocate audio frame decoded_frame = avcodec_alloc_frame(); if (!decoded_frame) { fprintf(stderr,"Could not allocate audio frame\n"); return -1;//Could not allocate audio frame } aCodec_decoderCtx->bit_rate=12000; aFormatCtx_encoder=get_encoder(8000,1,12000); av_init_packet(&packet_encoder); printf("param %d %d %d",aCodec_decoderCtx->sample_fmt,aCodec_decoderCtx->channels,aCodec_decoderCtx->bit_rate); outfile = fopen("out.aac","wb"); if (!outfile) { printf(stderr,"Could not open outfile \n"); return -1;//Could not open outfile } while(av_read_frame(aFormatCtx_decoder,&packet_decoder)>=0) { // decode frame len = avcodec_decode_audio4(aCodec_decoderCtx,decoded_frame,&got_frame,&packet_decoder); if (len < 0) { fprintf(stderr,"Error while decoding\n"); return -1; } if (got_frame){ avcodec_encode_audio2(aFormatCtx_encoder,&packet_encoder,&complete_decode); if(complete_decode){ // printf("complete decode frame"); fwrite(packet_encoder.data,packet_encoder.size,outfile); av_free_packet(&packet_encoder); } } } fclose(outfile); return (EXIT_SUCCESS); }
解决方法
您不能设置变量sample_fmts的任意值:
aCodec_decoder-> sample_fmts = AV_SAMPLE_FMT_S16P; // 这是不对的
将始终使用编解码器设置的参数执行解码.您必须创建SwrContext并执行到目标的格式转换(SwrContext转换样本格式,采样率和通道布局)