Demuxers

Libav provides dozens of demuxers for various container formats. They can be found in libavformat/, by general convention they normally end in dec.c.

New demuxers must be registered in libavformat/allformats.c; see 'registration' for details.

There is also more API documentation on demuxers available on the Libav website.

Structure description

There are two main structures involved in demuxers. All demuxers have a AVInputFormat structure, which specifies the name of the demuxer, what functions to use for identifying and reading the container to demux, etc. Most also specify a demuxer-specific context structure, which is used for holding any additional state or information that it is useful to have available.

Here are concrete examples from takdek.c.

First, there is the AVInputFormat structure, which is similar for all demuxers, it should be placed at the end of the file:

AVInputFormat ff_tak_demuxer = {
    .name           = "tak",
    .long_name      = NULL_IF_CONFIG_SMALL("raw TAK"),
    .priv_data_size = sizeof(TAKDemuxContext),
    .read_probe     = tak_probe,
    .read_header    = tak_read_header,
    .read_packet    = raw_read_packet,
    .flags          = AVFMT_GENERIC_INDEX,
    .extensions     = "tak",
    .raw_codec_id   = AV_CODEC_ID_TAK,
};

Many of the AVInputFormat fields are optional, but it is good to specify name, long_name, priv_data_size, read_probe, read_header, and read_packet. priv_data_size should be set to the size of the demuxer-specific context structure, used to store the internal demuxer state when needed, described below.

Here is an example of a demuxer-specific structure:

typedef struct TAKDemuxContext {
    int     mlast_frame;
    int64_t data_end;
} TAKDemuxContext;

The demuxer-specific structures can be arbitrarily complex. The Silicon Graphics Movie demuxer, mvdec.c, is fairly typical:

typedef struct MvContext {
    int nb_video_tracks;
    int nb_audio_tracks;

    int eof_count;        ///< number of streams that have finished
    int stream_index;     ///< current stream index
    int frame[2];         ///< frame nb for current stream

    int acompression;     ///< compression level for audio stream
    int aformat;          ///< audio format
} MvContext;

An older example is the AVI demuxer, from 2001, in avdec.c.

typedef struct {
    int64_t riff_end;
    int64_t movi_end;
    int64_t fsize;
    int64_t movi_list;
    int64_t last_pkt_pos;
    int index_loaded;
    int is_odml;
    int non_interleaved;
    int stream_index;
    DVDemuxContext *dv_demux;
    int odml_depth;
} AVIContext;

Please avoid anonymous structs with typedef; much of the older code uses them (such as avdec.c), but this is strongly discouraged. That is, use "typedef struct SomeName {...} SomeName;", not "typedef struct {} SomeName;".

The details of the demuxer-specific structure are entirely dependent on the needs of the demuxer, though information about positions, endings, and interleaving are often useful.

Registration

Demuxers need to be registered to be used. Registrations are in libavformat/allformats.c, and look like this:

REGISTER_DEMUXER (XA,               xa);

They consist of a pair of all-uppercase and all-lowercase versions of the same string, which is interpolated into configure options and AVInputFormat struct names. The above example would have an AVInputFormat struct "ff_xa_demuxer", while the ff_tak_demuxer of the previous section was registered with:

REGISTER_DEMUXER (TAK,              tak);

Makefile

Makefile changes go in libavformat/Makefile, and consist of specifying OBJS-$(CONFIG_SOMETHING_MUXER) and the file(s) necessary for it. See 'Registration' for the value of 'SOMETHING' - it is interpolated from the uppercase string.

The simplest examples are one source file:

OBJS-$(CONFIG_ANM_DEMUXER)               += anm.o

Please preserve alphabetical ordering, and see the Makefile for formatting details when there are multiple files required.

Configure dependencies

TODO.

Callbacks

A Libav demuxer implementation is effectively a set of functions that are called by external code. Crucially, it will provide functions for probing (figuring out if some data can be demuxed by that specific demuxer implementation, or not), reading headers, and reading packets.

Other functions are optional. It should also provide a read_close function if any deallocation of private data needs to be done at the end of demuxing. It should provide a read_timestamp function if it needs to read timestamps. Several demuxers also provide a read_seek.

read_probe

A probe function is given probe data; this is read to determine if the demuxer can handle the data or not. A skeleton version looks like this:

static int rm_probe(AVProbeData *p)
{
    return 0;
}

If the demuxer is for a container which has a well-defined header, the probe consists of checking for this. Optionally, if there is a bit more header information that would increase certainty (such as version numbers), it is good to also check that.

It should return 0 if the data cannot be handled, and AVPROBE_SCORE_MAX if it seems very likely that the demuxer can handle the data. A real example:

#define RA_HEADER MKTAG('.', 'r', 'a', '\xfd')

static int ra_probe(AVProbeData *p)
{
    /* RealAudio header; for RMF, use rm_probe. */
    uint8_t version;
    if (MKTAG(p->buf[0], p->buf[1], p->buf[2], p->buf[3]) != RA_HEADER)
       return 0;
    version = p->buf[5];
    if ((version < 3) || (version > 4))
        return 0;
    return AVPROBE_SCORE_MAX;
}

read_header

Read the header information of a given container. Return 0 on success, AVERROR(ENOMEM) on allocation failure, and AVERROR_INVALIDDATA on finding invalid data in the header.

Most read_header functions use the avio_ functions heavily. You can skip and seek with avio_skip and avio_seek. Data is read with avio_r8 to read a byte, avio_rl16/avio_rb16 to read 2 bytes as big-endian or little-endian, and so on - there are also avio_rl24, avio_rb24, avio_rl32, avio_rb32, and for arbitrary buffers, avio_read. See libavformat/avio.h for documentation, libavformat/aviobuf.c for the concrete implementation, and any decoder for examples of how to use the functions.

If the header was read succesfully, the stream position should reflect this - if there are some header bytes at the end that are going to be ignored, skip/seek past them.

Usual C caveats apply: do not leak memory if you run into an error condition, and do not blindly trust length information, especially if you are going to allocate memory or use it as an index into a buffer.

static int rm_read_header(AVFormatContext *s)
{
    avio_skip(s->pb, NUMBER_OF_HEADER_BYTES);
    return 0;
}

read_packet

Read a packet; the packet will be fed to a decoder.

The simplest case looks something like this:

/* The relevant VSELP format has 159-bit frames, stored in 20 bytes */
#define RA144_PKT_SIZE 20
static int ra_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    return av_get_packet(s->pb, pkt, RA144_PKT_SIZE);
}

Most read_packet functions are much more complex. Complications include interlacing, partial packets/subpackets, queued packets, etc.

Return values are documented as being zero on success, and < 0 on error.

read_close

This function is optional: there is no need to create it if it has nothing to do. Its purpose is to clean up when it is time to close the stream. It should free any internally-allocated data - for instance, anything that has been allocated for the private demuxer-specific structure.

The relevant part of libavformat/avformat.h says:

    /**
     * Close the stream. The AVFormatContext and AVStreams are not
     * freed by this function
     */
    int (*read_close)(struct AVFormatContext *);

read_seek

See libavformat/avformat.h for details.

read_timestamp

Return the next timestamp; see libavformat/avformat.h for details.

Template

Minimal boilerplate. The code below is a variation on rmdec.c, but is fairly general once 'rm' is substituted with the abbreviation of another demuxer.

/*
 * [Name of Demuxer] Demuxer.
 * Copyright (c) [current year] [your name]
 *
 * This file is part of Libav.
 *
 * Libav is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Libav is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Libav; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "avformat.h"
#include "rm.h"

typedef struct RMDemuxContext {
} RMDemuxContext;

static int rm_probe(AVProbeData *p)
{
    return 0;
}

static int rm_read_header(AVFormatContext *s)
{
    return 0;
}

static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    return 0;
}

static int rm_read_close(AVFormatContext *s)
{
    return 0;
}

static int64_t rm_read_dts(AVFormatContext *s, int stream_index,
                               int64_t *ppos, int64_t pos_limit)
{
    return 0;
}

static int rm_read_seek(AVFormatContext *s, int stream_idx, int64_t ts, int flags)
{
    return 0;
}


AVInputFormat ff_rm_demuxer = {
    .name           = "rm",
    .long_name      = NULL_IF_CONFIG_SMALL("RealMedia"),
    .priv_data_size = sizeof(RMDemuxContext),
    .read_probe     = rm_probe,
    .read_header    = rm_read_header,
    .read_packet    = rm_read_packet,
    .read_close     = rm_read_close,
    .read_timestamp = rm_read_dts,
    .read_seek      = rm_read_seek,
};

Technically, this isn't minimal - read_close, read_timestamp, and read_seek can be eliminated, along with their corresponding functions.

Model code

Demuxer implementations from 2012 onward tend to have cleaner code. Many of the older demuxers are quite sloppy about details like return values. A relatively trivial demuxer is in takdec.c; a larger one is rtpdec.c.

See also

CodecHowTo



CategoryHowTo CategoryWIP