FFMPEG - 无法使用av_write_frame()生成aac音频文件 [英] FFMPEG - can not generate aac audio file by using av_write_frame()

查看:351
本文介绍了FFMPEG - 无法使用av_write_frame()生成aac音频文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有视频文件(mp4)。我想从该文件分离音频流(AAC格式)并保存在PC中。
使用下面的代码,我使用av_write_frame()来写入数据包。然后,生成的文件无法播放。
但是,如果我使用fwrite()将数据包写入文件(像这样 FFMPEG-音频文件的持续时间不准确)。然后,生成的文件可以播放。



那么如何以正确的方式使用av_write_frame(),以便生成可以播放?

  int save_detached_audio(AVFormatContext ** input_format_context,
AVStream ** input_audio_stream,
AVCodecContext ** input_codec_context,
const char * filename){
int ret;
AVCodec * codec = avcodec_find_decoder((* input_codec_context) - > codec_id);
if(!codec){
av_log(NULL,AV_LOG_FATAL,找不到分离的audio.\\\
的编解码器);
return -1;
}

AVFormatContext * output_format_context = NULL;
AVStream * output_stream = NULL;
ret = avformat_alloc_output_context2(& output_format_context,NULL,NULL,filename);
if(!output_format_context){
av_log(NULL,AV_LOG_FATAL,无法分配输出格式context.\\\
);
return -1;
}


//打开输出文件写入。
ret = avio_open2(& output_format_context-> pb,filename,AVIO_FLAG_WRITE,NULL,NULL);
if(ret< 0){
av_log(NULL,AV_LOG_FATAL,无法打开输出文件以写入它。
return -1;
}

AVOutputFormat * fmt = NULL;
fmt = av_guess_format(NULL,filename,NULL);
if(!fmt){
av_log(NULL,AV_LOG_FATAL,找不到分离的audio.\\\
的文件格式);
return -1;
}

output_format_context-> oformat = fmt;

//在输出文件容器中创建一个新的音频流。
output_stream = avformat_new_stream(output_format_context,codec);
if(!output_stream){
av_log(NULL,AV_LOG_FATAL,无法在输出文件container.\\\
中创建新的流);
return -1;
}

output_stream-> codec-> bit_rate =(* input_codec_context) - > bit_rate;
output_stream-> codec-> sample_rate =(* input_codec_context) - > sample_rate;
output_stream-> codec-> channels =(* input_codec_context) - > channel;


ret = avformat_write_header(output_format_context,NULL);
if(ret< 0){
av_log(NULL,AV_LOG_FATAL,无法写入header.\\\
);
return -1;
}

AVPacket reading_packet;
av_init_packet(& read_packet);
while(av_read_frame(* input_format_context,& reading_packet)== 0){
if(reading_packet.stream_index ==(* input_audio_stream) - > index){
reading_packet.stream_index = 0 ;
ret = av_write_frame(output_format_context,& reading_packet);
}
av_free_packet(& reading_packet);
}
ret = av_write_trailer(output_format_context);
if(ret< 0){
av_log(NULL,AV_LOG_FATAL,无法写预告片到output.\\\
);
return -1;
}


解决方案

问题解决。
因为aac音频流被写入文件。因此,我们需要为output_codec_context分配extradata和extradata_size的值。这两个值可以从input_codec_context


中获取

I have video file (mp4). I want to detach audio stream (AAC format) from that file and save in PC. With below code, I use av_write_frame() to write packet. Then, generated file can not play. But, If I use fwrite() to write packet to file (like this FFMPEG- Duration of audio file is inaccurate). Then, generated file can play.

So, How to use av_write_frame() in the right way so that generated can play?

    int save_detached_audio(AVFormatContext **input_format_context,
                                AVStream **input_audio_stream,
                                AVCodecContext **input_codec_context,
                                const char *filename) {
int ret;
AVCodec *codec = avcodec_find_decoder((*input_codec_context)->codec_id);
if (!codec) {
    av_log(NULL, AV_LOG_FATAL, "Failed to find codec of detached audio.\n");
    return -1;
}

AVFormatContext* output_format_context = NULL;
AVStream* output_stream = NULL;
ret = avformat_alloc_output_context2(&output_format_context, NULL, NULL, filename);
if (!output_format_context) {
    av_log(NULL, AV_LOG_FATAL, "Could not allocate output format context.\n");
    return -1;
}


// open output file to write to it.
ret = avio_open2(&output_format_context->pb, filename, AVIO_FLAG_WRITE, NULL, NULL);
if (ret < 0) {
    av_log(NULL, AV_LOG_FATAL, "Could not open output file to write to it.\n");
    return -1;
}

AVOutputFormat* fmt = NULL;
fmt = av_guess_format(NULL, filename, NULL);
if (!fmt) {
    av_log(NULL, AV_LOG_FATAL, "Could not find file format of detached audio.\n");
    return -1;
}

output_format_context->oformat = fmt;

// Create a new audio stream in the output file container. 
output_stream = avformat_new_stream(output_format_context, codec);
if (!output_stream) {
    av_log(NULL, AV_LOG_FATAL, "Could not create a new stream in the output file container.\n");
    return -1;
}

output_stream->codec->bit_rate = (*input_codec_context)->bit_rate;
output_stream->codec->sample_rate = (*input_codec_context)->sample_rate;
output_stream->codec->channels = (*input_codec_context)->channels;


 ret = avformat_write_header(output_format_context, NULL);
 if (ret < 0) {
     av_log(NULL, AV_LOG_FATAL, "Could not write header to output.\n");
     return -1;
 }

AVPacket reading_packet;
av_init_packet(&reading_packet);
while (av_read_frame(*input_format_context, &reading_packet) == 0) {
    if (reading_packet.stream_index == (*input_audio_stream)->index) {
        reading_packet.stream_index = 0;
        ret = av_write_frame(output_format_context, &reading_packet);
    }
    av_free_packet(&reading_packet);   
}
 ret = av_write_trailer(output_format_context);
 if (ret < 0) {
     av_log(NULL, AV_LOG_FATAL, "Could not write trailer to output.\n");
     return -1;
 }

解决方案

Problem solved. Because aac audio stream is written to file. So, we need to assign value of extradata and extradata_size for output_codec_context. These two values can be taken from input_codec_context

这篇关于FFMPEG - 无法使用av_write_frame()生成aac音频文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆