Using av_interleaved_write_frame in FFmpeg
This article explains how to write individual media packets to an
output container using the FFmpeg
av_interleaved_write_frame function. You will learn how to
initialize the output context, rescale presentation and decoding
timestamps (PTS/DTS) to match container time bases, pass encoded packets
to the interleaving queue, and finalize the stream output correctly.
1. Initialize the Output Context and Write the Header
Before writing any packets, you must allocate an output format
context (AVFormatContext), create the necessary video or
audio streams (AVStream), and write the container header
using avformat_write_header.
AVFormatContext *out_ctx = NULL;
avformat_alloc_output_context2(&out_ctx, NULL, NULL, "output.mp4");
// Add an AVStream and configure its codec parameters here...
// Open output file if needed
if (!(out_ctx->oformat->flags & AVFMT_NOFILE)) {
avio_open(&out_ctx->pb, "output.mp4", AVIO_FLAG_WRITE);
}
// Write the stream header
if (avformat_write_header(out_ctx, NULL) < 0) {
// Handle error
}2. Prepare the AVPacket and Rescale Timestamps
Each encoded packet (AVPacket) produced by your encoder
uses the encoder's time base (AVCodecContext::time_base).
Container formats typically require timestamps expressed in the stream's
time base (AVStream::time_base).
Before writing, set the stream index and rescale the packet's
pts, dts, and duration values
using av_packet_rescale_ts:
// Assign the packet to the corresponding stream index
pkt->stream_index = stream->index;
// Rescale timestamps from codec timebase to stream timebase
av_packet_rescale_ts(pkt, codec_ctx->time_base, stream->time_base);3. Write the
Packet with av_interleaved_write_frame
The av_interleaved_write_frame function buffers packets
internally to ensure that audio and video packets are written in
ascending order of their Decoding Timestamp (DTS). This prevents
playback stuttering and ensures container specification compliance.
int ret = av_interleaved_write_frame(out_ctx, pkt);
if (ret < 0) {
// Handle write error
}Note that av_interleaved_write_frame takes ownership of
the packet data if the call succeeds, automatically unreferencing the
packet buffers. If you need to reuse the AVPacket
structure, allocate a fresh reference or allocate it via
av_packet_alloc().
4. Flush the Interleaver and Finalize the Output
Once all frames are encoded and written, any remaining packets
buffered inside the interleaver must be flushed to disk. Pass
NULL to av_interleaved_write_frame to flush
the internal buffer, write the container trailer with
av_write_trailer, and clean up resources:
// Flush any buffered interleaved packets
av_interleaved_write_frame(out_ctx, NULL);
// Write the file trailer
av_write_trailer(out_ctx);
// Clean up
if (!(out_ctx->oformat->flags & AVFMT_NOFILE)) {
avio_closep(&out_ctx->pb);
}
avformat_free_context(out_ctx);