[FFmpeg-devel] [PATCH] [RFC]avformat: introduce AVStreamGroup

Anton Khirnov anton at khirnov.net
Mon Oct 2 12:37:33 EEST 2023


Quoting James Almer (2023-09-06 16:38:32)
> Signed-off-by: James Almer <jamrial at gmail.com>
> ---
> This is an initial proof of concept for AVStream groups, something that's
> needed for quite a few existing and upcoming formats that lavf has no way to
> currently export. Said formats define a single video or audio stream composed
> by merging several individualy multiplexed streams within a media file.
> This is the case of HEIF, a format defining a tiled image where each tile is a
> separate image (either hevc, av1, etc) all of which need to be decoded
> individualy and then stitched together for presentation using container level
> information; IAMF, a new audio format where several individual streams (mono or
> stereo) need to be decoded individually and then combined to form audio streams
> with different channel layouts; and MPEG-TS programs, currently exported as
> AVProgram, which this new general purpose API would replace.
> There may be others too, like something ISOBMFF specific and not HEIF related,
> I'm told.
> 
> A new struct, AVStreamGroup, would cover all these cases by grouping the
> relevant streams and propagating format specific metadata for the purpose of
> combining them into what's expected for presentation (Something a filter for
> example would have to take care of).
> 
> Missing from this first version is something like a type field, which could be
> an enum listing the different currently known formats the user would then use
> to interpret the attached metadata, defined perhaps in codecpar.extradata
> 
> I'd like to hear opinions and suggestions to improve and properly handle this.
> 
>  libavformat/avformat.c |  26 ++++++++
>  libavformat/avformat.h | 143 ++++++++++++++++++++++++++++++++++++++++-
>  libavformat/dump.c     |  65 +++++++++++++++++--
>  libavformat/internal.h |  28 ++++++++
>  libavformat/options.c  |  77 ++++++++++++++++++++++
>  5 files changed, 332 insertions(+), 7 deletions(-)
> 

> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 1916aa2dc5..d18eafb933 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -1007,6 +1007,59 @@ typedef struct AVStream {
>      int pts_wrap_bits;
>  } AVStream;
>  
> +typedef struct AVStreamGroup {
> +    /**
> +     * A class for @ref avoptions. Set on stream creation.
                                             ^^^^^^
                                             group

> +     */
> +    const AVClass *av_class;
> +
> +    /**
> +     * Group index in AVFormatContext.
> +     */
> +    int index;

unsigned?

> +
> +    /**
> +     * Format-specific group ID.
> +     * decoding: set by libavformat
> +     * encoding: set by the user, replaced by libavformat if left unset
> +     */
> +    int id;

might want to make this 64bit

> +
> +    /**
> +     * Codec parameters associated with this stream group. Allocated and freed
> +     * by libavformat in avformat_new_stream_group() and avformat_free_context()
> +     * respectively.
> +     *
> +     * - demuxing: filled by libavformat on stream group creation or in
> +     *             avformat_find_stream_info()
> +     * - muxing: filled by the caller before avformat_write_header()
> +     */
> +    AVCodecParameters *codecpar;
> +
> +    void *priv_data;

Do we really need this?

> +
> +    /**
> +     * Number of elements in AVStreamGroup.stream_index.
> +     *
> +     * Set by av_stream_group_add_stream() and av_stream_group_new_stream(), must not
> +     * be modified by any other code.
> +     */
> +    int nb_stream_indexes;
> +
> +    /**
> +     * A list of indexes of streams in the group. New entries are created with
> +     * av_stream_group_add_stream() and av_stream_group_new_stream().
> +     *
> +     * - demuxing: entries are created by libavformat in avformat_open_input().
> +     *             If AVFMTCTX_NOHEADER is set in ctx_flags, then new entries may also
> +     *             appear in av_read_frame().
> +     * - muxing: entries are created by the user before avformat_write_header().
> +     *
> +     * Freed by libavformat in avformat_free_context().
> +     */
> +    int *stream_index;

unsigned for both?

> @@ -1844,6 +1940,51 @@ const AVClass *av_stream_get_class(void);
>   */
>  AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);
>  
> +/**
> + * Add a new stream to a stream group.
> + *
> + * When demuxing, it may be called by the demuxer in read_header(). If the
> + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also
> + * be called in read_packet().
> + *
> + * When muxing, may be called by the user before avformat_write_header() after
> + * having allocated a new group with avformat_new_stream_group().
> + *
> + * User is required to call avformat_free_context() to clean up the allocation
> + * by av_stream_group_new_stream().
> + *
> + * This is functionally the same as avformat_new_stream() while also adding the
> + * newly allocated stream to the group belonging to the media file.
> + *
> + * @param stg stream group belonging to a media file.
> + *
> + * @return newly created stream or NULL on error.
> + * @see av_stream_group_add_stream, avformat_new_stream_group.
> + */
> +AVStream *av_stream_group_new_stream(AVStreamGroup *stg);

Is there a big enough advantage to having this as a separate function?

> +
> +/**
> + * Add an already allocated stream to a stream group.
> + *
> + * When demuxing, it may be called by the demuxer in read_header(). If the
> + * flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also
> + * be called in read_packet().
> + *
> + * When muxing, may be called by the user before avformat_write_header() after
> + * having allocated a new group with avformat_new_stream_group() and stream with
> + * avformat_new_stream().
> + *
> + * User is required to call avformat_free_context() to clean up the allocation
> + * by av_stream_group_add_stream().
> + *
> + * @param stg stream group belonging to a media file.
> + * @param st  stream in the media file to add to the group.
> + *
> + * @return 0 on success, or a negative AVERROR otherwise.
> + * @see avformat_new_stream, av_stream_group_new_stream, avformat_new_stream_group.
> + */
> +int av_stream_group_add_stream(AVStreamGroup *stg, const AVStream *st);

It'd be nice to have the streamgroup-related functions consistenly
namespaced.

E.g.
* avformat_stream_group_add()
* avformat_stream_group_add_stream()
* ff_stream_group_free()
etc.

alternatively for the first two:
* avformat_stream_group_create()
* avformat_stream_group_extend()

-- 
Anton Khirnov


More information about the ffmpeg-devel mailing list