[Libav-user] Missing audio frames in mpegts muxer output

Ryan Owen ryaowe at gmail.com
Fri Jul 8 20:32:21 CEST 2016

I'm attempting to build something that will let me manipulate audio and
video frames as I receive them over a socket connection, then send them
back out over a different socket. It is long-running, so it might modify
hours worth of audio/video.  For this reason, I want it all to happen in
memory, processing data as it arrives and writing data out as it completes.

The data coming in is MPEG2 TS with H.264 and AAC+ADTS.  I use libavformat
to demux it into encoded audio and video frames.  From there, my code
decides if it wants to modify the frames, delete them, or just pass them
through.  From there, the encoded frames get fed back into libavformat to
be muxed back into MPEG TS format.

The challenge I'm coming across is that when I close out a stream, the
resulting TS data is missing the last couple of ADTS frames.

I've verified that I am in fact sending all of the frames to the muxer.
They're just  not all making it into the output for some reason.

I set up libavformat to mux to TS and call a callback method to receive the
muxed data:

/* ic is the input context. I just want to copy the streams from it */
int setup_muxer(AVFormatContext *ic, int (*write_callback)(void *, uint8_t
*, int))
    int i;
    int buf_size = 8192;
    unsigned char *buf;
    AVFormatContext *oc = NULL;
    AVOutputFormat *fmt = av_guess_format("mpegts", NULL, NULL);

    avformat_alloc_output_context2(&oc, fmt, NULL, NULL);
    if (oc == NULL) return 1;
    buf = (unsigned char *)av_malloc(buf_size);
    if (buf == NULL) return 2;

    oc->pb = avio_alloc_context(buf, buf_size, 1, NULL, NULL,
write_callback, NULL);
    if (oc->pb == NULL) return 3;

    /*Grab all the streams from the input and add them to the output*/
    for (i = 0; i < ic->nb_streams; i++)
        AVStream *in_stream = ic->streams[i];
        AVCodec *codec = avcodec_find_encoder(in_stream->codec->codec_id);
        AVStream *out_stream = avformat_new_stream(oc, codec);

        /*Copy common fields
        Some of this may not be necessary anymore with codecpar, but
ffmpeg.c still uses it*/
        out_stream->codec->codec_id = in_stream->codec->codec_id;
        out_stream->codec->codec_type = in_stream->codec->codec_type;
        out_stream->codec->bit_rate = in_stream->codec->bit_rate;
        out_stream->codec->extradata =
av_memdup(in_stream->codec->extradata, in_stream->codec->extradata_size);
        out_stream->codec->extradata_size =
        out_stream->time_base.den = in_stream->time_base.den;
        out_stream->time_base.num = in_stream->time_base.num;

        /*copy audio and video specific fields*/
        if (in_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)
            out_stream->codec->width = in_stream->codec->width;
            out_stream->codec->height = in_stream->codec->height;
            out_stream->codec->pix_fmt = in_stream->codec->pix_fmt;
            out_stream->codec->sample_fmt = in_stream->codec->sample_fmt;
            out_stream->codec->sample_rate = in_stream->codec->sample_rate;
            out_stream->codec->channels = in_stream->codec->channels;

        if (oc->oformat->flags & AVFMT_GLOBALHEADER)
            out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
    return avformat_write_header(oc, NULL);

I then write frames out with:

av_interleaved_write_frame(oc, pkt);

And then when I close out a stream, I do:


for (i = 0; i < oc->nb_streams; i++)
    AVStream *stream = oc->streams[i];

I've also tried adding:

av_interleaved_write_frame(oc, NULL);

But I still end up one or two ADTS frames short.

Is there something else I should be flushing?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20160708/cccbe620/attachment.html>

More information about the Libav-user mailing list