<div dir="ltr"><span style="font-size:12.8px">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.</span><div style="font-size:12.8px"><div><br></div><div>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.</div><div><br></div><div>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. </div><div><br></div><div>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.</div><div><br></div><div>I set up libavformat to mux to TS and call a callback method to receive the muxed data:</div><div><br></div><div>/* ic is the input context. I just want to copy the streams from it */</div><div><div>int setup_muxer(AVFormatContext *ic, int (*write_callback)(void *, uint8_t *, int))</div><div>{</div><div>    int i;</div><div>    int buf_size = 8192;</div><div>    unsigned char *buf;</div><div>    AVFormatContext *oc = NULL;</div><div>    AVOutputFormat *fmt = av_guess_format("mpegts", NULL, NULL);</div><div><br></div><div>    avformat_alloc_output_context2(&oc, fmt, NULL, NULL);</div><div>    if (oc == NULL) return 1;</div><div>    buf = (unsigned char *)av_malloc(buf_size);</div><div>    if (buf == NULL) return 2;</div><div><br></div><div>    oc->pb = avio_alloc_context(buf, buf_size, 1, NULL, NULL, write_callback, NULL);</div><div>    if (oc->pb == NULL) return 3;</div><div><br></div><div>    /*Grab all the streams from the input and add them to the output*/</div><div>    for (i = 0; i < ic->nb_streams; i++)</div><div>    {</div><div>        AVStream *in_stream = ic->streams[i];</div><div>        AVCodec *codec = avcodec_find_encoder(in_stream->codec->codec_id);</div><div>        AVStream *out_stream = avformat_new_stream(oc, codec);</div><div>        avcodec_parameters_from_context(out_stream->codecpar, in_stream->codec);</div><div><br></div><div>        /*Copy common fields</div><div>        Some of this may not be necessary anymore with codecpar, but ffmpeg.c still uses it*/</div><div>        out_stream->codec->codec_id = in_stream->codec->codec_id;</div><div>        out_stream->codec->codec_type = in_stream->codec->codec_type;</div><div>        out_stream->codec->bit_rate = in_stream->codec->bit_rate;</div><div>        out_stream->codec->extradata = av_memdup(in_stream->codec->extradata, in_stream->codec->extradata_size);</div><div>        out_stream->codec->extradata_size = in_stream->codec->extradata_size;</div><div>        out_stream->time_base.den = in_stream->time_base.den;</div><div>        out_stream->time_base.num = in_stream->time_base.num;</div><div><br></div><div>        /*copy audio and video specific fields*/</div><div>        if (in_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)</div><div>        {</div><div>            out_stream->codec->width = in_stream->codec->width;</div><div>            out_stream->codec->height = in_stream->codec->height;</div><div>            out_stream->codec->pix_fmt = in_stream->codec->pix_fmt;</div><div>        }</div><div>        else</div><div>        {</div><div>            out_stream->codec->sample_fmt = in_stream->codec->sample_fmt;</div><div>            out_stream->codec->sample_rate = in_stream->codec->sample_rate;</div><div>            out_stream->codec->channels = in_stream->codec->channels;</div><div>        }</div><div><br></div><div>        if (oc->oformat->flags & AVFMT_GLOBALHEADER)</div><div>            out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;</div><div>    }</div><div>    return avformat_write_header(oc, NULL);</div><div>}</div></div><div><br></div><div><br></div><div>I then write frames out with:</div><div><br></div><div>av_interleaved_write_frame(oc, pkt);<br></div><div><br></div><div>And then when I close out a stream, I do:</div><div><br></div><div>av_write_trailer(oc);</div><div><br></div><div>for (i = 0; i < oc->nb_streams; i++)<br></div><div><div>{</div><div>    AVStream *stream = oc->streams[i];</div><div>    avcodec_close(stream->codec);</div><div>}</div></div><div><br></div><div>I've also tried adding:</div><div><br></div><div>av_interleaved_write_frame(oc, NULL);<br></div><div><br></div><div>But I still end up one or two ADTS frames short.</div><div><br></div><div>Is there something else I should be flushing?</div><div><br></div><div>Thanks!</div></div></div>