Question

I am encoding live rendered video data and an existing .wav file into an mpg-file.

To do that I first write all audio frames, and then the video frames as they come in from the render engine. For smaller .wav files (< 25 seconds), everything works perfectly fine. But as soon as I use a longer .wav file, av_write_frame (when writing the audio frame) just returns -1 after having written some 100 frames. It is never the same frame at which it fails, also it is never the last frame. All test files can be played perfectly with any player I tested.

I am following the muxing example (more or less).

Here is my function that writes an audio frame:

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);
}
}

So "Error while writing audio frame. Result: -1" is what I always get after some frames.

And here is my get_audio_frame function:

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 );
};

And finally, this is the loop in which I write all audio frames (don't worry about the .wav header, I skipped it before that loop):

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

As you can see, I'm outputting almost everything in the packet and check for any possible error. Other than av_write_frame failing after some time when I am encoding a longer audio file, everything seems perfectly fine. All the packet values I am tracking are 100% the same for all frames (except the data pointer, obviously). Also, as stated, the same procedure works flawlessly for shorter fp_sound_input files. avcodec_encode_audio2() and avcodec_fill_audio_frame() also never fail.

The codecs I use for encoding are CODEC_ID_MPEG2VIDEO (video) and CODEC_ID_MP2 (audio). The .wav files are saved in PCM 16 LE (all use the exact same encoding).

What could be wrong here?

Was it helpful?

Solution

Try to use av_interleaved_write_frame instead of av_write_frame

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top