【问题标题】:av_write_frame fails when encoding a larger audio file to .mpg将较大的音频文件编码为 .mpg 时,av_write_frame 失败
【发布时间】:2012-11-11 23:33:53
【问题描述】:

我正在将实时渲染的视频数据和现有的 .wav 文件编码为 mpg 文件。

为此,我首先编写所有音频帧,然后是来自渲染引擎的视频帧。对于较小的 .wav 文件(

我正在关注the muxing example(或多或少)。

这是我编写音频帧的函数:

void write_audio_frame( Cffmpeg_dll * ptr, AVFormatContext *oc, AVStream *st, int16_t sample_val )
{
AVCodecContext *c;
AVPacket pkt = { 0 }; // data and size must be 0;
AVFrame *frame = avcodec_alloc_frame();
int got_packet;

av_init_packet(&pkt);
c = st->codec;

get_audio_frame(ptr, ptr->samples, ptr->audio_input_frame_size, c->channels);
frame->nb_samples =  ptr->audio_input_frame_size;
int result = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt,
                        (uint8_t *) ptr->samples,
                         ptr->audio_input_frame_size *
                        av_get_bytes_per_sample(c->sample_fmt) *
                        c->channels, 0);
if (result != 0)
{
    av_log(c, AV_LOG_ERROR, "Error filling audio frame. Code: %i\n", result);
    exit(1);
}

result = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
if (result != 0)
{
    av_log(c, AV_LOG_ERROR, "Error encoding audio. Code: %i\n", result);
    exit(1);
}


if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)
    pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
pkt.flags |= AV_PKT_FLAG_KEY;

pkt.stream_index= st->index;
av_log(c, AV_LOG_ERROR, "Got? %i Pts: %i Dts: %i Flags: %i Side Elems: %i Size: %i\n", 
        got_packet, pkt.pts, pkt.dts, pkt.flags, pkt.side_data_elems, pkt.size);

/* write the compressed frame in the media file */
result = av_write_frame(oc, &pkt);
if (result != 0) 
{
    av_log(c, AV_LOG_ERROR, "Error while writing audio frame. Result: %i\n", result);
    exit(1);
}
}

所以 “写入音频帧时出错。结果:-1” 是我在某些帧之后总是得到的。

这是我的 get_audio_frame 函数:

void get_audio_frame( Cffmpeg_dll* ptr, int16_t* samples, int frame_size, int nb_channels, int16_t sample_val ) 
{
    fread( samples, sizeof( int16_t ), frame_size * nb_channels, ptr->fp_sound_input );
};

最后,这是我编写所有音频帧的循环(不用担心 .wav 标头,我在该循环之前跳过了它):

while (!feof(ptr->fp_sound_input))
    {
        write_audio_frame( ptr, ptr->oc, ptr->audio_st, -1 );
    }

如您所见,我正在输出数据包中的几乎所有内容并检查是否存在任何可能的错误。除了 av_write_frame 在我编码较长的音频文件一段时间后失败之外,一切似乎都很好。我正在跟踪的所有数据包值对于所有帧都是 100% 相同的(显然,除了数据指针)。此外,如上所述,对于较短的 fp_sound_input 文件,相同的过程可以完美地工作。 avcodec_encode_audio2() 和 avcodec_fill_audio_frame() 也永远不会失败。

我用于编码的编解码器是 CODEC_ID_MPEG2VIDEO(视频)和 CODEC_ID_MP2(音频)。 .wav 文件保存在 PCM 16 LE 中(都使用完全相同的编码)。

这里有什么问题?

【问题讨论】:

    标签: audio ffmpeg video-encoding libavcodec avcodec


    【解决方案1】:

    尝试使用av_interleaved_write_frame 而不是av_write_frame

    【讨论】:

    • 等我回去工作再试试。但为什么?所有的音频帧都在一个块中。
    • 当您使用av_write_frame 时,数据包必须根据容器规范正确交错。因此,通常最好使用av_interleaved_write_frame。在这种情况下,交织过程是自动的。
    • 就是这样,谢谢!我只是想知道为什么它适用于较小的音频文件。猜猜这属于 ffmpeg 的恼人魔法;)
    • 对于较小的音频文件,可能不会超过音频和视频时间戳的差异限制
    猜你喜欢
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 2017-08-19
    相关资源
    最近更新 更多