diff mbox series

[FFmpeg-devel] avformat: move internal stream related functions and structs to a separate header

Message ID 20240116005031.30423-1-jamrial@gmail.com
State New
Headers show
Series [FFmpeg-devel] avformat: move internal stream related functions and structs to a separate header | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

James Almer Jan. 16, 2024, 12:50 a.m. UTC
Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavformat/Makefile          |   1 +
 libavformat/avformat.c        | 171 ----------------
 libavformat/demux.h           |  29 ---
 libavformat/internal.h        | 319 +---------------------------
 libavformat/stream.c          | 196 ++++++++++++++++++
 libavformat/stream_internal.h | 376 ++++++++++++++++++++++++++++++++++
 6 files changed, 574 insertions(+), 518 deletions(-)
 create mode 100644 libavformat/stream.c
 create mode 100644 libavformat/stream_internal.h

Comments

Andreas Rheinhardt Jan. 24, 2024, 3:14 p.m. UTC | #1
James Almer:
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  libavformat/Makefile          |   1 +
>  libavformat/avformat.c        | 171 ----------------
>  libavformat/demux.h           |  29 ---
>  libavformat/internal.h        | 319 +---------------------------
>  libavformat/stream.c          | 196 ++++++++++++++++++
>  libavformat/stream_internal.h | 376 ++++++++++++++++++++++++++++++++++
>  6 files changed, 574 insertions(+), 518 deletions(-)
>  create mode 100644 libavformat/stream.c
>  create mode 100644 libavformat/stream_internal.h
> 
> diff --git a/libavformat/internal.h b/libavformat/internal.h
> index f93832b3c4..f97ebc818f 100644
> --- a/libavformat/internal.h
> +++ b/libavformat/internal.h
> @@ -26,6 +26,7 @@
>  #include "libavcodec/packet_internal.h"
>  
>  #include "avformat.h"
> +#include "stream_internal.h"

You seem to have included the new header in order to avoid checking
which of the internal.h inclusions should be replaced by
stream_internal.h. This basically defeats the point of adding a new
header (honestly, I don't really get the point of splitting this off
anyway: avformat.c is not that big).

>  
>  #define MAX_URL_SIZE 4096
>  

...

> diff --git a/libavformat/stream_internal.h b/libavformat/stream_internal.h
> new file mode 100644
> index 0000000000..9759f30e3f
> --- /dev/null
> +++ b/libavformat/stream_internal.h
> @@ -0,0 +1,376 @@
> +/*
> + * Stream related functions and structs
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg 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.
> + *
> + * FFmpeg 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 FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef AVFORMAT_STREAM_INTERNAL_H
> +#define AVFORMAT_STREAM_INTERNAL_H
> +
> +#include <stdint.h>
> +
> +#include "libavcodec/bsf.h"
> +#include "libavcodec/packet_internal.h"
> +#include "libavcodec/parser.h"

Including bsf.h and parser.h is unnecessary (the structs here don't need
the complete types and almost no file including this needs them either).

> +#include "avformat.h"
> +
> +/**
> + * Fractional numbers for exact pts handling
> + *
> + * The exact value of the fractional number is: 'val + num / den'.
> + * num is assumed to be 0 <= num < den.
> + */
> +typedef struct FFFrac {
> +    int64_t val, num, den;
> +} FFFrac;
> +
> +#define MAX_STD_TIMEBASES (30*12+30+3+6)
> +typedef struct FFStreamInfo {
> +    int64_t last_dts;
> +    int64_t duration_gcd;
> +    int duration_count;
> +    int64_t rfps_duration_sum;
> +    double (*duration_error)[2][MAX_STD_TIMEBASES];
> +    int64_t codec_info_duration;
> +    int64_t codec_info_duration_fields;
> +    int frame_delay_evidence;
> +
> +    /**
> +     * 0  -> decoder has not been searched for yet.
> +     * >0 -> decoder found
> +     * <0 -> decoder with codec_id == -found_decoder has not been found
> +     */
> +    int found_decoder;
> +
> +    int64_t last_duration;
> +
> +    /**
> +     * Those are used for average framerate estimation.
> +     */
> +    int64_t fps_first_dts;
> +    int     fps_first_dts_idx;
> +    int64_t fps_last_dts;
> +    int     fps_last_dts_idx;
> +} FFStreamInfo;

Moving FFStreamInfo to this header makes it accessible to muxers,
although this is supposed to be a demuxer-only struct.
(Didn't you send this patch once before?)

- Andreas
James Almer Jan. 24, 2024, 6:45 p.m. UTC | #2
On 1/24/2024 12:14 PM, Andreas Rheinhardt wrote:
> James Almer:
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>>   libavformat/Makefile          |   1 +
>>   libavformat/avformat.c        | 171 ----------------
>>   libavformat/demux.h           |  29 ---
>>   libavformat/internal.h        | 319 +---------------------------
>>   libavformat/stream.c          | 196 ++++++++++++++++++
>>   libavformat/stream_internal.h | 376 ++++++++++++++++++++++++++++++++++
>>   6 files changed, 574 insertions(+), 518 deletions(-)
>>   create mode 100644 libavformat/stream.c
>>   create mode 100644 libavformat/stream_internal.h
>>
>> diff --git a/libavformat/internal.h b/libavformat/internal.h
>> index f93832b3c4..f97ebc818f 100644
>> --- a/libavformat/internal.h
>> +++ b/libavformat/internal.h
>> @@ -26,6 +26,7 @@
>>   #include "libavcodec/packet_internal.h"
>>   
>>   #include "avformat.h"
>> +#include "stream_internal.h"
> 
> You seem to have included the new header in order to avoid checking
> which of the internal.h inclusions should be replaced by
> stream_internal.h. This basically defeats the point of adding a new
> header (honestly, I don't really get the point of splitting this off
> anyway: avformat.c is not that big).

Anton suggested to split the stream related functions into their own 
file. But agree there's not a lot to gain.

> 
>>   
>>   #define MAX_URL_SIZE 4096
>>   
> 
> ...
> 
>> diff --git a/libavformat/stream_internal.h b/libavformat/stream_internal.h
>> new file mode 100644
>> index 0000000000..9759f30e3f
>> --- /dev/null
>> +++ b/libavformat/stream_internal.h
>> @@ -0,0 +1,376 @@
>> +/*
>> + * Stream related functions and structs
>> + *
>> + * This file is part of FFmpeg.
>> + *
>> + * FFmpeg 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.
>> + *
>> + * FFmpeg 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 FFmpeg; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>> + */
>> +
>> +#ifndef AVFORMAT_STREAM_INTERNAL_H
>> +#define AVFORMAT_STREAM_INTERNAL_H
>> +
>> +#include <stdint.h>
>> +
>> +#include "libavcodec/bsf.h"
>> +#include "libavcodec/packet_internal.h"
>> +#include "libavcodec/parser.h"
> 
> Including bsf.h and parser.h is unnecessary (the structs here don't need
> the complete types and almost no file including this needs them either).
> 
>> +#include "avformat.h"
>> +
>> +/**
>> + * Fractional numbers for exact pts handling
>> + *
>> + * The exact value of the fractional number is: 'val + num / den'.
>> + * num is assumed to be 0 <= num < den.
>> + */
>> +typedef struct FFFrac {
>> +    int64_t val, num, den;
>> +} FFFrac;
>> +
>> +#define MAX_STD_TIMEBASES (30*12+30+3+6)
>> +typedef struct FFStreamInfo {
>> +    int64_t last_dts;
>> +    int64_t duration_gcd;
>> +    int duration_count;
>> +    int64_t rfps_duration_sum;
>> +    double (*duration_error)[2][MAX_STD_TIMEBASES];
>> +    int64_t codec_info_duration;
>> +    int64_t codec_info_duration_fields;
>> +    int frame_delay_evidence;
>> +
>> +    /**
>> +     * 0  -> decoder has not been searched for yet.
>> +     * >0 -> decoder found
>> +     * <0 -> decoder with codec_id == -found_decoder has not been found
>> +     */
>> +    int found_decoder;
>> +
>> +    int64_t last_duration;
>> +
>> +    /**
>> +     * Those are used for average framerate estimation.
>> +     */
>> +    int64_t fps_first_dts;
>> +    int     fps_first_dts_idx;
>> +    int64_t fps_last_dts;
>> +    int     fps_last_dts_idx;
>> +} FFStreamInfo;
> 
> Moving FFStreamInfo to this header makes it accessible to muxers,
> although this is supposed to be a demuxer-only struct.
> (Didn't you send this patch once before?)

Ah, guess i did. I did get a sense of deja vu when i wrote this.
I couldn't find anything like this in my local repo, so i might have 
lost the commit after sending the patch and ended up writing it again.
diff mbox series

Patch

diff --git a/libavformat/Makefile b/libavformat/Makefile
index dcc99eeac4..6dd9b10e6b 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -27,6 +27,7 @@  OBJS = allformats.o         \
        riff.o               \
        sdp.o                \
        seek.o               \
+       stream.o             \
        url.o                \
        utils.o              \
        version.o            \
diff --git a/libavformat/avformat.c b/libavformat/avformat.c
index 882927f7b1..596d1dfb92 100644
--- a/libavformat/avformat.c
+++ b/libavformat/avformat.c
@@ -24,7 +24,6 @@ 
 #include "libavutil/avstring.h"
 #include "libavutil/channel_layout.h"
 #include "libavutil/frame.h"
-#include "libavutil/iamf.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
@@ -32,89 +31,13 @@ 
 #include "libavutil/samplefmt.h"
 #include "libavcodec/avcodec.h"
 #include "libavcodec/codec.h"
-#include "libavcodec/bsf.h"
 #include "libavcodec/codec_desc.h"
-#include "libavcodec/packet_internal.h"
 #include "avformat.h"
 #include "avio.h"
 #include "demux.h"
 #include "mux.h"
 #include "internal.h"
 
-void ff_free_stream(AVStream **pst)
-{
-    AVStream *st = *pst;
-    FFStream *const sti = ffstream(st);
-
-    if (!st)
-        return;
-
-#if FF_API_AVSTREAM_SIDE_DATA
-FF_DISABLE_DEPRECATION_WARNINGS
-    for (int i = 0; i < st->nb_side_data; i++)
-        av_freep(&st->side_data[i].data);
-    av_freep(&st->side_data);
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
-
-    if (st->attached_pic.data)
-        av_packet_unref(&st->attached_pic);
-
-    av_parser_close(sti->parser);
-    avcodec_free_context(&sti->avctx);
-    av_bsf_free(&sti->bsfc);
-    av_freep(&sti->priv_pts);
-    av_freep(&sti->index_entries);
-    av_freep(&sti->probe_data.buf);
-
-    av_bsf_free(&sti->extract_extradata.bsf);
-
-    if (sti->info) {
-        av_freep(&sti->info->duration_error);
-        av_freep(&sti->info);
-    }
-
-    av_dict_free(&st->metadata);
-    avcodec_parameters_free(&st->codecpar);
-    av_freep(&st->priv_data);
-
-    av_freep(pst);
-}
-
-void ff_free_stream_group(AVStreamGroup **pstg)
-{
-    AVStreamGroup *stg = *pstg;
-
-    if (!stg)
-        return;
-
-    av_freep(&stg->streams);
-    av_dict_free(&stg->metadata);
-    av_freep(&stg->priv_data);
-    switch (stg->type) {
-    case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT: {
-        av_iamf_audio_element_free(&stg->params.iamf_audio_element);
-        break;
-    }
-    case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION: {
-        av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
-        break;
-    }
-    default:
-        break;
-    }
-
-    av_freep(pstg);
-}
-
-void ff_remove_stream(AVFormatContext *s, AVStream *st)
-{
-    av_assert0(s->nb_streams>0);
-    av_assert0(s->streams[ s->nb_streams - 1 ] == st);
-
-    ff_free_stream(&s->streams[ --s->nb_streams ]);
-}
-
 /* XXX: suppress the packet queue */
 void ff_flush_packet_queue(AVFormatContext *s)
 {
@@ -247,68 +170,6 @@  uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type,
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
-/**
- * Copy all stream parameters from source to destination stream, with the
- * exception of the index field, which is usually set by avformat_new_stream().
- *
- * @param dst pointer to destination AVStream
- * @param src pointer to source AVStream
- * @return >=0 on success, AVERROR code on error
- */
-static int stream_params_copy(AVStream *dst, const AVStream *src)
-{
-    int ret;
-
-    dst->id                  = src->id;
-    dst->time_base           = src->time_base;
-    dst->start_time          = src->start_time;
-    dst->duration            = src->duration;
-    dst->nb_frames           = src->nb_frames;
-    dst->disposition         = src->disposition;
-    dst->discard             = src->discard;
-    dst->sample_aspect_ratio = src->sample_aspect_ratio;
-    dst->avg_frame_rate      = src->avg_frame_rate;
-    dst->event_flags         = src->event_flags;
-    dst->r_frame_rate        = src->r_frame_rate;
-    dst->pts_wrap_bits       = src->pts_wrap_bits;
-
-    av_dict_free(&dst->metadata);
-    ret = av_dict_copy(&dst->metadata, src->metadata, 0);
-    if (ret < 0)
-        return ret;
-
-    ret = avcodec_parameters_copy(dst->codecpar, src->codecpar);
-    if (ret < 0)
-        return ret;
-
-    av_packet_unref(&dst->attached_pic);
-    if (src->attached_pic.data) {
-        ret = av_packet_ref(&dst->attached_pic, &src->attached_pic);
-        if (ret < 0)
-            return ret;
-    }
-
-    return 0;
-}
-
-AVStream *ff_stream_clone(AVFormatContext *dst_ctx, const AVStream *src)
-{
-    AVStream *st;
-    int ret;
-
-    st = avformat_new_stream(dst_ctx, NULL);
-    if (!st)
-        return NULL;
-
-    ret = stream_params_copy(st, src);
-    if (ret < 0) {
-        ff_remove_stream(dst_ctx, st);
-        return NULL;
-    }
-
-    return st;
-}
-
 AVProgram *av_new_program(AVFormatContext *ac, int id)
 {
     AVProgram *program = NULL;
@@ -825,38 +686,6 @@  FF_ENABLE_DEPRECATION_WARNINGS
     return 0;
 }
 
-AVRational av_stream_get_codec_timebase(const AVStream *st)
-{
-    // See avformat_transfer_internal_stream_timing_info() TODO.
-    return cffstream(st)->avctx->time_base;
-}
-
-void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits,
-                         unsigned int pts_num, unsigned int pts_den)
-{
-    FFStream *const sti = ffstream(st);
-    AVRational new_tb;
-    if (av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)) {
-        if (new_tb.num != pts_num)
-            av_log(NULL, AV_LOG_DEBUG,
-                   "st:%d removing common factor %d from timebase\n",
-                   st->index, pts_num / new_tb.num);
-    } else
-        av_log(NULL, AV_LOG_WARNING,
-               "st:%d has too large timebase, reducing\n", st->index);
-
-    if (new_tb.num <= 0 || new_tb.den <= 0) {
-        av_log(NULL, AV_LOG_ERROR,
-               "Ignoring attempt to set invalid timebase %d/%d for st:%d\n",
-               new_tb.num, new_tb.den,
-               st->index);
-        return;
-    }
-    st->time_base     = new_tb;
-    sti->avctx->pkt_timebase = new_tb;
-    st->pts_wrap_bits = pts_wrap_bits;
-}
-
 const AVCodec *ff_find_decoder(AVFormatContext *s, const AVStream *st,
                                enum AVCodecID codec_id)
 {
diff --git a/libavformat/demux.h b/libavformat/demux.h
index d65eb16ff8..ac822e0d58 100644
--- a/libavformat/demux.h
+++ b/libavformat/demux.h
@@ -26,35 +26,6 @@ 
 #include "libavcodec/packet.h"
 #include "avformat.h"
 
-#define MAX_STD_TIMEBASES (30*12+30+3+6)
-typedef struct FFStreamInfo {
-    int64_t last_dts;
-    int64_t duration_gcd;
-    int duration_count;
-    int64_t rfps_duration_sum;
-    double (*duration_error)[2][MAX_STD_TIMEBASES];
-    int64_t codec_info_duration;
-    int64_t codec_info_duration_fields;
-    int frame_delay_evidence;
-
-    /**
-     * 0  -> decoder has not been searched for yet.
-     * >0 -> decoder found
-     * <0 -> decoder with codec_id == -found_decoder has not been found
-     */
-    int found_decoder;
-
-    int64_t last_duration;
-
-    /**
-     * Those are used for average framerate estimation.
-     */
-    int64_t fps_first_dts;
-    int     fps_first_dts_idx;
-    int64_t fps_last_dts;
-    int     fps_last_dts_idx;
-} FFStreamInfo;
-
 /**
  * Returned by demuxers to indicate that data was consumed but discarded
  * (ignored streams or junk data). The framework will re-call the demuxer.
diff --git a/libavformat/internal.h b/libavformat/internal.h
index f93832b3c4..f97ebc818f 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -26,6 +26,7 @@ 
 #include "libavcodec/packet_internal.h"
 
 #include "avformat.h"
+#include "stream_internal.h"
 
 #define MAX_URL_SIZE 4096
 
@@ -55,18 +56,6 @@  typedef struct CodecMime{
     enum AVCodecID id;
 } CodecMime;
 
-/*************************************************/
-/* fractional numbers for exact pts handling */
-
-/**
- * The exact value of the fractional number is: 'val + num / den'.
- * num is assumed to be 0 <= num < den.
- */
-typedef struct FFFrac {
-    int64_t val, num, den;
-} FFFrac;
-
-
 typedef struct FFFormatContext {
     /**
      * The public context.
@@ -196,258 +185,6 @@  static av_always_inline FFFormatContext *ffformatcontext(AVFormatContext *s)
     return (FFFormatContext*)s;
 }
 
-typedef struct FFStream {
-    /**
-     * The public context.
-     */
-    AVStream pub;
-
-    AVFormatContext *fmtctx;
-    /**
-     * Set to 1 if the codec allows reordering, so pts can be different
-     * from dts.
-     */
-    int reorder;
-
-    /**
-     * bitstream filter to run on stream
-     * - encoding: Set by muxer using ff_stream_add_bitstream_filter
-     * - decoding: unused
-     */
-    struct AVBSFContext *bsfc;
-
-    /**
-     * Whether or not check_bitstream should still be run on each packet
-     */
-    int bitstream_checked;
-
-    /**
-     * The codec context used by avformat_find_stream_info, the parser, etc.
-     */
-    struct AVCodecContext *avctx;
-    /**
-     * 1 if avctx has been initialized with the values from the codec parameters
-     */
-    int avctx_inited;
-
-    /* the context for extracting extradata in find_stream_info()
-     * inited=1/bsf=NULL signals that extracting is not possible (codec not
-     * supported) */
-    struct {
-        struct AVBSFContext *bsf;
-        int inited;
-    } extract_extradata;
-
-    /**
-     * Whether the internal avctx needs to be updated from codecpar (after a late change to codecpar)
-     */
-    int need_context_update;
-
-    int is_intra_only;
-
-    FFFrac *priv_pts;
-
-    /**
-     * Stream information used internally by avformat_find_stream_info()
-     */
-    struct FFStreamInfo *info;
-
-    AVIndexEntry *index_entries; /**< Only used if the format does not
-                                    support seeking natively. */
-    int nb_index_entries;
-    unsigned int index_entries_allocated_size;
-
-    int64_t interleaver_chunk_size;
-    int64_t interleaver_chunk_duration;
-
-    /**
-     * stream probing state
-     * -1   -> probing finished
-     *  0   -> no probing requested
-     * rest -> perform probing with request_probe being the minimum score to accept.
-     */
-    int request_probe;
-    /**
-     * Indicates that everything up to the next keyframe
-     * should be discarded.
-     */
-    int skip_to_keyframe;
-
-    /**
-     * Number of samples to skip at the start of the frame decoded from the next packet.
-     */
-    int skip_samples;
-
-    /**
-     * If not 0, the number of samples that should be skipped from the start of
-     * the stream (the samples are removed from packets with pts==0, which also
-     * assumes negative timestamps do not happen).
-     * Intended for use with formats such as mp3 with ad-hoc gapless audio
-     * support.
-     */
-    int64_t start_skip_samples;
-
-    /**
-     * If not 0, the first audio sample that should be discarded from the stream.
-     * This is broken by design (needs global sample count), but can't be
-     * avoided for broken by design formats such as mp3 with ad-hoc gapless
-     * audio support.
-     */
-    int64_t first_discard_sample;
-
-    /**
-     * The sample after last sample that is intended to be discarded after
-     * first_discard_sample. Works on frame boundaries only. Used to prevent
-     * early EOF if the gapless info is broken (considered concatenated mp3s).
-     */
-    int64_t last_discard_sample;
-
-    /**
-     * Number of internally decoded frames, used internally in libavformat, do not access
-     * its lifetime differs from info which is why it is not in that structure.
-     */
-    int nb_decoded_frames;
-
-    /**
-     * Timestamp offset added to timestamps before muxing
-     */
-    int64_t mux_ts_offset;
-
-    /**
-     * This is the lowest ts allowed in this track; it may be set by the muxer
-     * during init or write_header and influences the automatic timestamp
-     * shifting code.
-     */
-    int64_t lowest_ts_allowed;
-
-    /**
-     * Internal data to check for wrapping of the time stamp
-     */
-    int64_t pts_wrap_reference;
-
-    /**
-     * Options for behavior, when a wrap is detected.
-     *
-     * Defined by AV_PTS_WRAP_ values.
-     *
-     * If correction is enabled, there are two possibilities:
-     * If the first time stamp is near the wrap point, the wrap offset
-     * will be subtracted, which will create negative time stamps.
-     * Otherwise the offset will be added.
-     */
-    int pts_wrap_behavior;
-
-    /**
-     * Internal data to prevent doing update_initial_durations() twice
-     */
-    int update_initial_durations_done;
-
-#define MAX_REORDER_DELAY 16
-
-    /**
-     * Internal data to generate dts from pts
-     */
-    int64_t pts_reorder_error[MAX_REORDER_DELAY+1];
-    uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];
-
-    int64_t pts_buffer[MAX_REORDER_DELAY+1];
-
-    /**
-     * Internal data to analyze DTS and detect faulty mpeg streams
-     */
-    int64_t last_dts_for_order_check;
-    uint8_t dts_ordered;
-    uint8_t dts_misordered;
-
-#if FF_API_AVSTREAM_SIDE_DATA
-    /**
-     * Internal data to inject global side data
-     */
-    int inject_global_side_data;
-#endif
-
-    /**
-     * display aspect ratio (0 if unknown)
-     * - encoding: unused
-     * - decoding: Set by libavformat to calculate sample_aspect_ratio internally
-     */
-    AVRational display_aspect_ratio;
-
-    AVProbeData probe_data;
-
-    /**
-     * last packet in packet_buffer for this stream when muxing.
-     */
-    PacketListEntry *last_in_packet_buffer;
-
-    int64_t last_IP_pts;
-    int last_IP_duration;
-
-    /**
-     * Number of packets to buffer for codec probing
-     */
-    int probe_packets;
-
-    /* av_read_frame() support */
-    enum AVStreamParseType need_parsing;
-    struct AVCodecParserContext *parser;
-
-    /**
-     * Number of frames that have been demuxed during avformat_find_stream_info()
-     */
-    int codec_info_nb_frames;
-
-    /**
-     * Stream Identifier
-     * This is the MPEG-TS stream identifier +1
-     * 0 means unknown
-     */
-    int stream_identifier;
-
-    // Timestamp generation support:
-    /**
-     * Timestamp corresponding to the last dts sync point.
-     *
-     * Initialized when AVCodecParserContext.dts_sync_point >= 0 and
-     * a DTS is received from the underlying container. Otherwise set to
-     * AV_NOPTS_VALUE by default.
-     */
-    int64_t first_dts;
-    int64_t cur_dts;
-
-    const struct AVCodecDescriptor *codec_desc;
-} FFStream;
-
-static av_always_inline FFStream *ffstream(AVStream *st)
-{
-    return (FFStream*)st;
-}
-
-static av_always_inline const FFStream *cffstream(const AVStream *st)
-{
-    return (const FFStream*)st;
-}
-
-typedef struct FFStreamGroup {
-    /**
-     * The public context.
-     */
-    AVStreamGroup pub;
-
-    AVFormatContext *fmtctx;
-} FFStreamGroup;
-
-
-static av_always_inline FFStreamGroup *ffstreamgroup(AVStreamGroup *stg)
-{
-    return (FFStreamGroup*)stg;
-}
-
-static av_always_inline const FFStreamGroup *cffstreamgroup(const AVStreamGroup *stg)
-{
-    return (const FFStreamGroup*)stg;
-}
-
 #ifdef __GNUC__
 #define dynarray_add(tab, nb_ptr, elem)\
 do {\
@@ -596,46 +333,12 @@  enum AVCodecID ff_guess_image2_codec(const char *filename);
 const struct AVCodec *ff_find_decoder(AVFormatContext *s, const AVStream *st,
                                       enum AVCodecID codec_id);
 
-/**
- * Set the time base and wrapping info for a given stream. This will be used
- * to interpret the stream's timestamps. If the new time base is invalid
- * (numerator or denominator are non-positive), it leaves the stream
- * unchanged.
- *
- * @param st stream
- * @param pts_wrap_bits number of bits effectively used by the pts
- *        (used for wrap control)
- * @param pts_num time base numerator
- * @param pts_den time base denominator
- */
-void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits,
-                         unsigned int pts_num, unsigned int pts_den);
-
 /**
  * Set the timebase for each stream from the corresponding codec timebase and
  * print it.
  */
 int ff_framehash_write_header(AVFormatContext *s);
 
-/**
- * Frees a stream without modifying the corresponding AVFormatContext.
- * Must only be called if the latter doesn't matter or if the stream
- * is not yet attached to an AVFormatContext.
- */
-void ff_free_stream(AVStream **st);
-/**
- * Remove a stream from its AVFormatContext and free it.
- * The stream must be the last stream of the AVFormatContext.
- */
-void ff_remove_stream(AVFormatContext *s, AVStream *st);
-
-/**
- * Frees a stream group without modifying the corresponding AVFormatContext.
- * Must only be called if the latter doesn't matter or if the stream
- * is not yet attached to an AVFormatContext.
- */
-void ff_free_stream_group(AVStreamGroup **pstg);
-
 unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id);
 
 enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag);
@@ -657,26 +360,6 @@  int ff_is_intra_only(enum AVCodecID id);
  */
 enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags);
 
-/**
- * Copy side data from source to destination stream
- *
- * @param dst pointer to destination AVStream
- * @param src pointer to source AVStream
- * @return >=0 on success, AVERROR code on error
- */
-int ff_stream_side_data_copy(AVStream *dst, const AVStream *src);
-
-/**
- * Create a new stream and copy to it all parameters from a source stream, with
- * the exception of the index field, which is set when the new stream is
- * created.
- *
- * @param dst_ctx pointer to the context in which the new stream is created
- * @param src pointer to source AVStream
- * @return pointer to the new stream or NULL on error
- */
-AVStream *ff_stream_clone(AVFormatContext *dst_ctx, const AVStream *src);
-
 /**
  * Wrap ffurl_move() and log if error happens.
  *
diff --git a/libavformat/stream.c b/libavformat/stream.c
new file mode 100644
index 0000000000..ceaee393ba
--- /dev/null
+++ b/libavformat/stream.c
@@ -0,0 +1,196 @@ 
+/*
+ * Stream related functions and structs
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/iamf.h"
+
+#include "avformat.h"
+#include "stream_internal.h"
+
+void ff_free_stream(AVStream **pst)
+{
+    AVStream *st = *pst;
+    FFStream *const sti = ffstream(st);
+
+    if (!st)
+        return;
+
+#if FF_API_AVSTREAM_SIDE_DATA
+FF_DISABLE_DEPRECATION_WARNINGS
+    for (int i = 0; i < st->nb_side_data; i++)
+        av_freep(&st->side_data[i].data);
+    av_freep(&st->side_data);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+    if (st->attached_pic.data)
+        av_packet_unref(&st->attached_pic);
+
+    av_parser_close(sti->parser);
+    avcodec_free_context(&sti->avctx);
+    av_bsf_free(&sti->bsfc);
+    av_freep(&sti->priv_pts);
+    av_freep(&sti->index_entries);
+    av_freep(&sti->probe_data.buf);
+
+    av_bsf_free(&sti->extract_extradata.bsf);
+
+    if (sti->info) {
+        av_freep(&sti->info->duration_error);
+        av_freep(&sti->info);
+    }
+
+    av_dict_free(&st->metadata);
+    avcodec_parameters_free(&st->codecpar);
+    av_freep(&st->priv_data);
+
+    av_freep(pst);
+}
+
+void ff_free_stream_group(AVStreamGroup **pstg)
+{
+    AVStreamGroup *stg = *pstg;
+
+    if (!stg)
+        return;
+
+    av_freep(&stg->streams);
+    av_dict_free(&stg->metadata);
+    av_freep(&stg->priv_data);
+    switch (stg->type) {
+    case AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT: {
+        av_iamf_audio_element_free(&stg->params.iamf_audio_element);
+        break;
+    }
+    case AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION: {
+        av_iamf_mix_presentation_free(&stg->params.iamf_mix_presentation);
+        break;
+    }
+    default:
+        break;
+    }
+
+    av_freep(pstg);
+}
+
+void ff_remove_stream(AVFormatContext *s, AVStream *st)
+{
+    av_assert0(s->nb_streams>0);
+    av_assert0(s->streams[ s->nb_streams - 1 ] == st);
+
+    ff_free_stream(&s->streams[ --s->nb_streams ]);
+}
+
+
+/**
+ * Copy all stream parameters from source to destination stream, with the
+ * exception of the index field, which is usually set by avformat_new_stream().
+ *
+ * @param dst pointer to destination AVStream
+ * @param src pointer to source AVStream
+ * @return >=0 on success, AVERROR code on error
+ */
+static int stream_params_copy(AVStream *dst, const AVStream *src)
+{
+    int ret;
+
+    dst->id                  = src->id;
+    dst->time_base           = src->time_base;
+    dst->start_time          = src->start_time;
+    dst->duration            = src->duration;
+    dst->nb_frames           = src->nb_frames;
+    dst->disposition         = src->disposition;
+    dst->discard             = src->discard;
+    dst->sample_aspect_ratio = src->sample_aspect_ratio;
+    dst->avg_frame_rate      = src->avg_frame_rate;
+    dst->event_flags         = src->event_flags;
+    dst->r_frame_rate        = src->r_frame_rate;
+    dst->pts_wrap_bits       = src->pts_wrap_bits;
+
+    av_dict_free(&dst->metadata);
+    ret = av_dict_copy(&dst->metadata, src->metadata, 0);
+    if (ret < 0)
+        return ret;
+
+    ret = avcodec_parameters_copy(dst->codecpar, src->codecpar);
+    if (ret < 0)
+        return ret;
+
+    av_packet_unref(&dst->attached_pic);
+    if (src->attached_pic.data) {
+        ret = av_packet_ref(&dst->attached_pic, &src->attached_pic);
+        if (ret < 0)
+            return ret;
+    }
+
+    return 0;
+}
+
+AVStream *ff_stream_clone(AVFormatContext *dst_ctx, const AVStream *src)
+{
+    AVStream *st;
+    int ret;
+
+    st = avformat_new_stream(dst_ctx, NULL);
+    if (!st)
+        return NULL;
+
+    ret = stream_params_copy(st, src);
+    if (ret < 0) {
+        ff_remove_stream(dst_ctx, st);
+        return NULL;
+    }
+
+    return st;
+}
+
+AVRational av_stream_get_codec_timebase(const AVStream *st)
+{
+    // See avformat_transfer_internal_stream_timing_info() TODO.
+    return cffstream(st)->avctx->time_base;
+}
+
+void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits,
+                         unsigned int pts_num, unsigned int pts_den)
+{
+    FFStream *const sti = ffstream(st);
+    AVRational new_tb;
+    if (av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)) {
+        if (new_tb.num != pts_num)
+            av_log(NULL, AV_LOG_DEBUG,
+                   "st:%d removing common factor %d from timebase\n",
+                   st->index, pts_num / new_tb.num);
+    } else
+        av_log(NULL, AV_LOG_WARNING,
+               "st:%d has too large timebase, reducing\n", st->index);
+
+    if (new_tb.num <= 0 || new_tb.den <= 0) {
+        av_log(NULL, AV_LOG_ERROR,
+               "Ignoring attempt to set invalid timebase %d/%d for st:%d\n",
+               new_tb.num, new_tb.den,
+               st->index);
+        return;
+    }
+    st->time_base     = new_tb;
+    sti->avctx->pkt_timebase = new_tb;
+    st->pts_wrap_bits = pts_wrap_bits;
+}
diff --git a/libavformat/stream_internal.h b/libavformat/stream_internal.h
new file mode 100644
index 0000000000..9759f30e3f
--- /dev/null
+++ b/libavformat/stream_internal.h
@@ -0,0 +1,376 @@ 
+/*
+ * Stream related functions and structs
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFORMAT_STREAM_INTERNAL_H
+#define AVFORMAT_STREAM_INTERNAL_H
+
+#include <stdint.h>
+
+#include "libavcodec/bsf.h"
+#include "libavcodec/packet_internal.h"
+#include "libavcodec/parser.h"
+#include "avformat.h"
+
+/**
+ * Fractional numbers for exact pts handling
+ *
+ * The exact value of the fractional number is: 'val + num / den'.
+ * num is assumed to be 0 <= num < den.
+ */
+typedef struct FFFrac {
+    int64_t val, num, den;
+} FFFrac;
+
+#define MAX_STD_TIMEBASES (30*12+30+3+6)
+typedef struct FFStreamInfo {
+    int64_t last_dts;
+    int64_t duration_gcd;
+    int duration_count;
+    int64_t rfps_duration_sum;
+    double (*duration_error)[2][MAX_STD_TIMEBASES];
+    int64_t codec_info_duration;
+    int64_t codec_info_duration_fields;
+    int frame_delay_evidence;
+
+    /**
+     * 0  -> decoder has not been searched for yet.
+     * >0 -> decoder found
+     * <0 -> decoder with codec_id == -found_decoder has not been found
+     */
+    int found_decoder;
+
+    int64_t last_duration;
+
+    /**
+     * Those are used for average framerate estimation.
+     */
+    int64_t fps_first_dts;
+    int     fps_first_dts_idx;
+    int64_t fps_last_dts;
+    int     fps_last_dts_idx;
+} FFStreamInfo;
+
+typedef struct FFStream {
+    /**
+     * The public context.
+     */
+    AVStream pub;
+
+    AVFormatContext *fmtctx;
+    /**
+     * Set to 1 if the codec allows reordering, so pts can be different
+     * from dts.
+     */
+    int reorder;
+
+    /**
+     * bitstream filter to run on stream
+     * - encoding: Set by muxer using ff_stream_add_bitstream_filter
+     * - decoding: unused
+     */
+    struct AVBSFContext *bsfc;
+
+    /**
+     * Whether or not check_bitstream should still be run on each packet
+     */
+    int bitstream_checked;
+
+    /**
+     * The codec context used by avformat_find_stream_info, the parser, etc.
+     */
+    struct AVCodecContext *avctx;
+    /**
+     * 1 if avctx has been initialized with the values from the codec parameters
+     */
+    int avctx_inited;
+
+    /* the context for extracting extradata in find_stream_info()
+     * inited=1/bsf=NULL signals that extracting is not possible (codec not
+     * supported) */
+    struct {
+        struct AVBSFContext *bsf;
+        int inited;
+    } extract_extradata;
+
+    /**
+     * Whether the internal avctx needs to be updated from codecpar (after a late change to codecpar)
+     */
+    int need_context_update;
+
+    int is_intra_only;
+
+    FFFrac *priv_pts;
+
+    /**
+     * Stream information used internally by avformat_find_stream_info()
+     */
+    struct FFStreamInfo *info;
+
+    AVIndexEntry *index_entries; /**< Only used if the format does not
+                                    support seeking natively. */
+    int nb_index_entries;
+    unsigned int index_entries_allocated_size;
+
+    int64_t interleaver_chunk_size;
+    int64_t interleaver_chunk_duration;
+
+    /**
+     * stream probing state
+     * -1   -> probing finished
+     *  0   -> no probing requested
+     * rest -> perform probing with request_probe being the minimum score to accept.
+     */
+    int request_probe;
+    /**
+     * Indicates that everything up to the next keyframe
+     * should be discarded.
+     */
+    int skip_to_keyframe;
+
+    /**
+     * Number of samples to skip at the start of the frame decoded from the next packet.
+     */
+    int skip_samples;
+
+    /**
+     * If not 0, the number of samples that should be skipped from the start of
+     * the stream (the samples are removed from packets with pts==0, which also
+     * assumes negative timestamps do not happen).
+     * Intended for use with formats such as mp3 with ad-hoc gapless audio
+     * support.
+     */
+    int64_t start_skip_samples;
+
+    /**
+     * If not 0, the first audio sample that should be discarded from the stream.
+     * This is broken by design (needs global sample count), but can't be
+     * avoided for broken by design formats such as mp3 with ad-hoc gapless
+     * audio support.
+     */
+    int64_t first_discard_sample;
+
+    /**
+     * The sample after last sample that is intended to be discarded after
+     * first_discard_sample. Works on frame boundaries only. Used to prevent
+     * early EOF if the gapless info is broken (considered concatenated mp3s).
+     */
+    int64_t last_discard_sample;
+
+    /**
+     * Number of internally decoded frames, used internally in libavformat, do not access
+     * its lifetime differs from info which is why it is not in that structure.
+     */
+    int nb_decoded_frames;
+
+    /**
+     * Timestamp offset added to timestamps before muxing
+     */
+    int64_t mux_ts_offset;
+
+    /**
+     * This is the lowest ts allowed in this track; it may be set by the muxer
+     * during init or write_header and influences the automatic timestamp
+     * shifting code.
+     */
+    int64_t lowest_ts_allowed;
+
+    /**
+     * Internal data to check for wrapping of the time stamp
+     */
+    int64_t pts_wrap_reference;
+
+    /**
+     * Options for behavior, when a wrap is detected.
+     *
+     * Defined by AV_PTS_WRAP_ values.
+     *
+     * If correction is enabled, there are two possibilities:
+     * If the first time stamp is near the wrap point, the wrap offset
+     * will be subtracted, which will create negative time stamps.
+     * Otherwise the offset will be added.
+     */
+    int pts_wrap_behavior;
+
+    /**
+     * Internal data to prevent doing update_initial_durations() twice
+     */
+    int update_initial_durations_done;
+
+#define MAX_REORDER_DELAY 16
+
+    /**
+     * Internal data to generate dts from pts
+     */
+    int64_t pts_reorder_error[MAX_REORDER_DELAY+1];
+    uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];
+
+    int64_t pts_buffer[MAX_REORDER_DELAY+1];
+
+    /**
+     * Internal data to analyze DTS and detect faulty mpeg streams
+     */
+    int64_t last_dts_for_order_check;
+    uint8_t dts_ordered;
+    uint8_t dts_misordered;
+
+#if FF_API_AVSTREAM_SIDE_DATA
+    /**
+     * Internal data to inject global side data
+     */
+    int inject_global_side_data;
+#endif
+
+    /**
+     * display aspect ratio (0 if unknown)
+     * - encoding: unused
+     * - decoding: Set by libavformat to calculate sample_aspect_ratio internally
+     */
+    AVRational display_aspect_ratio;
+
+    AVProbeData probe_data;
+
+    /**
+     * last packet in packet_buffer for this stream when muxing.
+     */
+    PacketListEntry *last_in_packet_buffer;
+
+    int64_t last_IP_pts;
+    int last_IP_duration;
+
+    /**
+     * Number of packets to buffer for codec probing
+     */
+    int probe_packets;
+
+    /* av_read_frame() support */
+    enum AVStreamParseType need_parsing;
+    struct AVCodecParserContext *parser;
+
+    /**
+     * Number of frames that have been demuxed during avformat_find_stream_info()
+     */
+    int codec_info_nb_frames;
+
+    /**
+     * Stream Identifier
+     * This is the MPEG-TS stream identifier +1
+     * 0 means unknown
+     */
+    int stream_identifier;
+
+    // Timestamp generation support:
+    /**
+     * Timestamp corresponding to the last dts sync point.
+     *
+     * Initialized when AVCodecParserContext.dts_sync_point >= 0 and
+     * a DTS is received from the underlying container. Otherwise set to
+     * AV_NOPTS_VALUE by default.
+     */
+    int64_t first_dts;
+    int64_t cur_dts;
+
+    const struct AVCodecDescriptor *codec_desc;
+} FFStream;
+
+static av_always_inline FFStream *ffstream(AVStream *st)
+{
+    return (FFStream*)st;
+}
+
+static av_always_inline const FFStream *cffstream(const AVStream *st)
+{
+    return (const FFStream*)st;
+}
+
+typedef struct FFStreamGroup {
+    /**
+     * The public context.
+     */
+    AVStreamGroup pub;
+
+    AVFormatContext *fmtctx;
+} FFStreamGroup;
+
+
+static av_always_inline FFStreamGroup *ffstreamgroup(AVStreamGroup *stg)
+{
+    return (FFStreamGroup*)stg;
+}
+
+static av_always_inline const FFStreamGroup *cffstreamgroup(const AVStreamGroup *stg)
+{
+    return (const FFStreamGroup*)stg;
+}
+
+/**
+ * Set the time base and wrapping info for a given stream. This will be used
+ * to interpret the stream's timestamps. If the new time base is invalid
+ * (numerator or denominator are non-positive), it leaves the stream
+ * unchanged.
+ *
+ * @param st stream
+ * @param pts_wrap_bits number of bits effectively used by the pts
+ *        (used for wrap control)
+ * @param pts_num time base numerator
+ * @param pts_den time base denominator
+ */
+void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits,
+                         unsigned int pts_num, unsigned int pts_den);
+
+/**
+ * Frees a stream without modifying the corresponding AVFormatContext.
+ * Must only be called if the latter doesn't matter or if the stream
+ * is not yet attached to an AVFormatContext.
+ */
+void ff_free_stream(AVStream **st);
+/**
+ * Remove a stream from its AVFormatContext and free it.
+ * The stream must be the last stream of the AVFormatContext.
+ */
+void ff_remove_stream(AVFormatContext *s, AVStream *st);
+
+/**
+ * Frees a stream group without modifying the corresponding AVFormatContext.
+ * Must only be called if the latter doesn't matter or if the stream
+ * is not yet attached to an AVFormatContext.
+ */
+void ff_free_stream_group(AVStreamGroup **pstg);
+
+/**
+ * Copy side data from source to destination stream
+ *
+ * @param dst pointer to destination AVStream
+ * @param src pointer to source AVStream
+ * @return >=0 on success, AVERROR code on error
+ */
+int ff_stream_side_data_copy(AVStream *dst, const AVStream *src);
+
+/**
+ * Create a new stream and copy to it all parameters from a source stream, with
+ * the exception of the index field, which is set when the new stream is
+ * created.
+ *
+ * @param dst_ctx pointer to the context in which the new stream is created
+ * @param src pointer to source AVStream
+ * @return pointer to the new stream or NULL on error
+ */
+AVStream *ff_stream_clone(AVFormatContext *dst_ctx, const AVStream *src);
+
+#endif /* AVFORMAT_STREAM_INTERNAL_H */