我想使用ffmpeg库进行音频转码。现在我有文件,但我只能听到噪音。 我的计划的步骤是: 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, 0, 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,decoded_frame,&complete_decode);
if(complete_decode){
// printf("complete decode frame");
fwrite(packet_encoder.data, 1, packet_encoder.size, outfile);
av_free_packet(&packet_encoder);
}
}
}
fclose(outfile);
return (EXIT_SUCCESS);
}
答案 0 :(得分:1)
您无法设置变量sample_fmts
的任意值:
aCodec_decoder->sample_fmts=AV_SAMPLE_FMT_S16P; // It's wrong
将始终使用编解码器设置的参数执行解码。
您必须创建SwrContext
并执行到目标的格式转换(SwrContext
转换样本格式,采样率和频道布局)
答案 1 :(得分:1)
使用以下代码进行样本格式转换。 你可以在ffmpeg / doc / examples / resampling_audio.c
中得到例子 SwrContext *swr = swr_alloc();
av_opt_set_int(node_handle->swr, "in_channel_layout", decoded_frame->channel_layout, 0);
av_opt_set_int(node_handle->swr, "out_channel_layout", encoder_ctx->channel_layout, 0);
av_opt_set_int(node_handle->swr, "in_sample_rate", decoded_frame->sample_rate, 0);
av_opt_set_int(node_handle->swr, "out_sample_rate", encoder_ctx->sample_rate, 0);
av_opt_set_sample_fmt(swr, "in_sample_fmt", decoded_frame->format, 0);
av_opt_set_sample_fmt(swr, "out_sample_fmt", encoder_ctx->sample_fmt, 0);
swr_init(swr);
uint8_t* swr_out_data;
int linesize;
av_samples_alloc(&swr_out_data,
linesize,
encoder_ctx->nb_channels,
decoded_frame->nb_samples,
encoder_ctx->sample_fmt,
0
);
swr_convert(swr,&swr_out_data, decoded_frame->nb_samples, decoded_frame->data, decoded_frame->nb_samples);
答案 2 :(得分:0)
修改为此,工作正常
aCodec_decoder->sample_fmts=audioCodec->sample_fmt;