diff mbox series

[FFmpeg-devel,01/18] lavf: move AVStream.info to AVStreamInternal

Message ID 20201009130430.602-1-anton@khirnov.net
State Accepted
Commit 8741f1fe2663f0d5adeaa21c98d6b03cac9dbaa9
Headers show
Series [FFmpeg-devel,01/18] lavf: move AVStream.info to AVStreamInternal
Related show

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Anton Khirnov Oct. 9, 2020, 1:04 p.m. UTC
This struct is for internal use of avformat_find_stream_info(), so it
should not be exposed in public headers. Keep a stub pointer in its
place to avoid changing AVStream layout, since e.g. ffmpeg.c accesses
some fields located after it (even though they are marked as private).
---
 libavformat/avformat.h |  36 +------
 libavformat/internal.h |  33 ++++++
 libavformat/utils.c    | 228 ++++++++++++++++++++---------------------
 3 files changed, 151 insertions(+), 146 deletions(-)
diff mbox series

Patch

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index c8c0b6c08d..8eff5b8eaa 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1023,38 +1023,10 @@  typedef struct AVStream {
      *****************************************************************
      */
 
-#define MAX_STD_TIMEBASES (30*12+30+3+6)
-    /**
-     * Stream information used internally by avformat_find_stream_info()
-     */
-    struct {
-        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;
-
-    } *info;
+#if LIBAVFORMAT_VERSION_MAJOR < 59
+    // kept for ABI compatibility only, do not access in any way
+    void *unused;
+#endif
 
     int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */
 
diff --git a/libavformat/internal.h b/libavformat/internal.h
index f4174628e0..30b4df9181 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -191,6 +191,39 @@  struct AVStreamInternal {
     int is_intra_only;
 
     FFFrac *priv_pts;
+
+#define MAX_STD_TIMEBASES (30*12+30+3+6)
+    /**
+     * Stream information used internally by avformat_find_stream_info()
+     */
+    struct {
+        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;
+
+    } *info;
 };
 
 #ifdef __GNUC__
diff --git a/libavformat/utils.c b/libavformat/utils.c
index a2e701ea1a..a13f31dccf 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -992,7 +992,7 @@  int ff_is_intra_only(enum AVCodecID id)
 static int has_decode_delay_been_guessed(AVStream *st)
 {
     if (st->codecpar->codec_id != AV_CODEC_ID_H264) return 1;
-    if (!st->info) // if we have left find_stream_info then nb_decoded_frames won't increase anymore for stream copy
+    if (!st->internal->info) // if we have left find_stream_info then nb_decoded_frames won't increase anymore for stream copy
         return 1;
 #if CONFIG_H264_DECODER
     if (st->internal->avctx->has_b_frames &&
@@ -1539,7 +1539,7 @@  static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
             if (avcodec_is_open(st->internal->avctx)) {
                 av_log(s, AV_LOG_DEBUG, "Demuxer context update while decoder is open, closing and trying to re-open\n");
                 avcodec_close(st->internal->avctx);
-                st->info->found_decoder = 0;
+                st->internal->info->found_decoder = 0;
             }
 
             /* close parser, because it depends on the codec */
@@ -2812,10 +2812,10 @@  static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
                 else
                     duration -= st->first_dts;
                 if (duration > 0) {
-                    if (st->duration == AV_NOPTS_VALUE || st->info->last_duration<= 0 ||
-                        (st->duration < duration && FFABS(duration - st->info->last_duration) < 60LL*st->time_base.den / st->time_base.num))
+                    if (st->duration == AV_NOPTS_VALUE || st->internal->info->last_duration<= 0 ||
+                        (st->duration < duration && FFABS(duration - st->internal->info->last_duration) < 60LL*st->time_base.den / st->time_base.num))
                         st->duration = duration;
-                    st->info->last_duration = duration;
+                    st->internal->info->last_duration = duration;
                 }
             }
             av_packet_unref(pkt);
@@ -2952,20 +2952,20 @@  static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
     case AVMEDIA_TYPE_AUDIO:
         if (!avctx->frame_size && determinable_frame_size(avctx))
             FAIL("unspecified frame size");
-        if (st->info->found_decoder >= 0 &&
+        if (st->internal->info->found_decoder >= 0 &&
             avctx->sample_fmt == AV_SAMPLE_FMT_NONE)
             FAIL("unspecified sample format");
         if (!avctx->sample_rate)
             FAIL("unspecified sample rate");
         if (!avctx->channels)
             FAIL("unspecified number of channels");
-        if (st->info->found_decoder >= 0 && !st->nb_decoded_frames && avctx->codec_id == AV_CODEC_ID_DTS)
+        if (st->internal->info->found_decoder >= 0 && !st->nb_decoded_frames && avctx->codec_id == AV_CODEC_ID_DTS)
             FAIL("no decodable DTS frames");
         break;
     case AVMEDIA_TYPE_VIDEO:
         if (!avctx->width)
             FAIL("unspecified size");
-        if (st->info->found_decoder >= 0 && avctx->pix_fmt == AV_PIX_FMT_NONE)
+        if (st->internal->info->found_decoder >= 0 && avctx->pix_fmt == AV_PIX_FMT_NONE)
             FAIL("unspecified pixel format");
         if (st->codecpar->codec_id == AV_CODEC_ID_RV30 || st->codecpar->codec_id == AV_CODEC_ID_RV40)
             if (!st->sample_aspect_ratio.num && !st->codecpar->sample_aspect_ratio.num && !st->codec_info_nb_frames)
@@ -2999,14 +2999,14 @@  static int try_decode_frame(AVFormatContext *s, AVStream *st,
         return AVERROR(ENOMEM);
 
     if (!avcodec_is_open(avctx) &&
-        st->info->found_decoder <= 0 &&
-        (st->codecpar->codec_id != -st->info->found_decoder || !st->codecpar->codec_id)) {
+        st->internal->info->found_decoder <= 0 &&
+        (st->codecpar->codec_id != -st->internal->info->found_decoder || !st->codecpar->codec_id)) {
         AVDictionary *thread_opt = NULL;
 
         codec = find_probe_decoder(s, st, st->codecpar->codec_id);
 
         if (!codec) {
-            st->info->found_decoder = -st->codecpar->codec_id;
+            st->internal->info->found_decoder = -st->codecpar->codec_id;
             ret                     = -1;
             goto fail;
         }
@@ -3020,14 +3020,14 @@  static int try_decode_frame(AVFormatContext *s, AVStream *st,
         if (!options)
             av_dict_free(&thread_opt);
         if (ret < 0) {
-            st->info->found_decoder = -avctx->codec_id;
+            st->internal->info->found_decoder = -avctx->codec_id;
             goto fail;
         }
-        st->info->found_decoder = 1;
-    } else if (!st->info->found_decoder)
-        st->info->found_decoder = 1;
+        st->internal->info->found_decoder = 1;
+    } else if (!st->internal->info->found_decoder)
+        st->internal->info->found_decoder = 1;
 
-    if (st->info->found_decoder < 0) {
+    if (st->internal->info->found_decoder < 0) {
         ret = -1;
         goto fail;
     }
@@ -3293,59 +3293,59 @@  int ff_get_extradata(AVFormatContext *s, AVCodecParameters *par, AVIOContext *pb
 int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t ts)
 {
     int i, j;
-    int64_t last = st->info->last_dts;
+    int64_t last = st->internal->info->last_dts;
 
     if (   ts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && ts > last
        && ts - (uint64_t)last < INT64_MAX) {
         double dts = (is_relative(ts) ?  ts - RELATIVE_TS_BASE : ts) * av_q2d(st->time_base);
         int64_t duration = ts - last;
 
-        if (!st->info->duration_error)
-            st->info->duration_error = av_mallocz(sizeof(st->info->duration_error[0])*2);
-        if (!st->info->duration_error)
+        if (!st->internal->info->duration_error)
+            st->internal->info->duration_error = av_mallocz(sizeof(st->internal->info->duration_error[0])*2);
+        if (!st->internal->info->duration_error)
             return AVERROR(ENOMEM);
 
 //         if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
 //             av_log(NULL, AV_LOG_ERROR, "%f\n", dts);
         for (i = 0; i<MAX_STD_TIMEBASES; i++) {
-            if (st->info->duration_error[0][1][i] < 1e10) {
+            if (st->internal->info->duration_error[0][1][i] < 1e10) {
                 int framerate = get_std_framerate(i);
                 double sdts = dts*framerate/(1001*12);
                 for (j= 0; j<2; j++) {
                     int64_t ticks = llrint(sdts+j*0.5);
                     double error= sdts - ticks + j*0.5;
-                    st->info->duration_error[j][0][i] += error;
-                    st->info->duration_error[j][1][i] += error*error;
+                    st->internal->info->duration_error[j][0][i] += error;
+                    st->internal->info->duration_error[j][1][i] += error*error;
                 }
             }
         }
-        if (st->info->rfps_duration_sum <= INT64_MAX - duration) {
-            st->info->duration_count++;
-            st->info->rfps_duration_sum += duration;
+        if (st->internal->info->rfps_duration_sum <= INT64_MAX - duration) {
+            st->internal->info->duration_count++;
+            st->internal->info->rfps_duration_sum += duration;
         }
 
-        if (st->info->duration_count % 10 == 0) {
-            int n = st->info->duration_count;
+        if (st->internal->info->duration_count % 10 == 0) {
+            int n = st->internal->info->duration_count;
             for (i = 0; i<MAX_STD_TIMEBASES; i++) {
-                if (st->info->duration_error[0][1][i] < 1e10) {
-                    double a0     = st->info->duration_error[0][0][i] / n;
-                    double error0 = st->info->duration_error[0][1][i] / n - a0*a0;
-                    double a1     = st->info->duration_error[1][0][i] / n;
-                    double error1 = st->info->duration_error[1][1][i] / n - a1*a1;
+                if (st->internal->info->duration_error[0][1][i] < 1e10) {
+                    double a0     = st->internal->info->duration_error[0][0][i] / n;
+                    double error0 = st->internal->info->duration_error[0][1][i] / n - a0*a0;
+                    double a1     = st->internal->info->duration_error[1][0][i] / n;
+                    double error1 = st->internal->info->duration_error[1][1][i] / n - a1*a1;
                     if (error0 > 0.04 && error1 > 0.04) {
-                        st->info->duration_error[0][1][i] = 2e10;
-                        st->info->duration_error[1][1][i] = 2e10;
+                        st->internal->info->duration_error[0][1][i] = 2e10;
+                        st->internal->info->duration_error[1][1][i] = 2e10;
                     }
                 }
             }
         }
 
         // ignore the first 4 values, they might have some random jitter
-        if (st->info->duration_count > 3 && is_relative(ts) == is_relative(last))
-            st->info->duration_gcd = av_gcd(st->info->duration_gcd, duration);
+        if (st->internal->info->duration_count > 3 && is_relative(ts) == is_relative(last))
+            st->internal->info->duration_gcd = av_gcd(st->internal->info->duration_gcd, duration);
     }
     if (ts != AV_NOPTS_VALUE)
-        st->info->last_dts = ts;
+        st->internal->info->last_dts = ts;
 
     return 0;
 }
@@ -3362,9 +3362,9 @@  void ff_rfps_calculate(AVFormatContext *ic)
         // the check for tb_unreliable() is not completely correct, since this is not about handling
         // an unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
         // ipmovie.c produces.
-        if (tb_unreliable(st->internal->avctx) && st->info->duration_count > 15 && st->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num)
-            av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->info->duration_gcd, INT_MAX);
-        if (st->info->duration_count>1 && !st->r_frame_rate.num
+        if (tb_unreliable(st->internal->avctx) && st->internal->info->duration_count > 15 && st->internal->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num)
+            av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->internal->info->duration_gcd, INT_MAX);
+        if (st->internal->info->duration_count>1 && !st->r_frame_rate.num
             && tb_unreliable(st->internal->avctx)) {
             int num = 0;
             double best_error= 0.01;
@@ -3373,19 +3373,19 @@  void ff_rfps_calculate(AVFormatContext *ic)
             for (j= 0; j<MAX_STD_TIMEBASES; j++) {
                 int k;
 
-                if (st->info->codec_info_duration &&
-                    st->info->codec_info_duration*av_q2d(st->time_base) < (1001*11.5)/get_std_framerate(j))
+                if (st->internal->info->codec_info_duration &&
+                    st->internal->info->codec_info_duration*av_q2d(st->time_base) < (1001*11.5)/get_std_framerate(j))
                     continue;
-                if (!st->info->codec_info_duration && get_std_framerate(j) < 1001*12)
+                if (!st->internal->info->codec_info_duration && get_std_framerate(j) < 1001*12)
                     continue;
 
-                if (av_q2d(st->time_base) * st->info->rfps_duration_sum / st->info->duration_count < (1001*12.0 * 0.8)/get_std_framerate(j))
+                if (av_q2d(st->time_base) * st->internal->info->rfps_duration_sum / st->internal->info->duration_count < (1001*12.0 * 0.8)/get_std_framerate(j))
                     continue;
 
                 for (k= 0; k<2; k++) {
-                    int n = st->info->duration_count;
-                    double a= st->info->duration_error[k][0][j] / n;
-                    double error= st->info->duration_error[k][1][j]/n - a*a;
+                    int n = st->internal->info->duration_count;
+                    double a= st->internal->info->duration_error[k][0][j] / n;
+                    double error= st->internal->info->duration_error[k][1][j]/n - a*a;
 
                     if (error < best_error && best_error> 0.000000001) {
                         best_error= error;
@@ -3400,19 +3400,19 @@  void ff_rfps_calculate(AVFormatContext *ic)
                 av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX);
         }
         if (   !st->avg_frame_rate.num
-            && st->r_frame_rate.num && st->info->rfps_duration_sum
-            && st->info->codec_info_duration <= 0
-            && st->info->duration_count > 2
-            && fabs(1.0 / (av_q2d(st->r_frame_rate) * av_q2d(st->time_base)) - st->info->rfps_duration_sum / (double)st->info->duration_count) <= 1.0
+            && st->r_frame_rate.num && st->internal->info->rfps_duration_sum
+            && st->internal->info->codec_info_duration <= 0
+            && st->internal->info->duration_count > 2
+            && fabs(1.0 / (av_q2d(st->r_frame_rate) * av_q2d(st->time_base)) - st->internal->info->rfps_duration_sum / (double)st->internal->info->duration_count) <= 1.0
             ) {
             av_log(ic, AV_LOG_DEBUG, "Setting avg frame rate based on r frame rate\n");
             st->avg_frame_rate = st->r_frame_rate;
         }
 
-        av_freep(&st->info->duration_error);
-        st->info->last_dts = AV_NOPTS_VALUE;
-        st->info->duration_count = 0;
-        st->info->rfps_duration_sum = 0;
+        av_freep(&st->internal->info->duration_error);
+        st->internal->info->last_dts = AV_NOPTS_VALUE;
+        st->internal->info->duration_count = 0;
+        st->internal->info->rfps_duration_sum = 0;
     }
 }
 
@@ -3660,10 +3660,10 @@  FF_ENABLE_DEPRECATION_WARNINGS
 
     for (i = 0; i < ic->nb_streams; i++) {
 #if FF_API_R_FRAME_RATE
-        ic->streams[i]->info->last_dts = AV_NOPTS_VALUE;
+        ic->streams[i]->internal->info->last_dts = AV_NOPTS_VALUE;
 #endif
-        ic->streams[i]->info->fps_first_dts = AV_NOPTS_VALUE;
-        ic->streams[i]->info->fps_last_dts  = AV_NOPTS_VALUE;
+        ic->streams[i]->internal->info->fps_first_dts = AV_NOPTS_VALUE;
+        ic->streams[i]->internal->info->fps_last_dts  = AV_NOPTS_VALUE;
     }
 
     read_size = 0;
@@ -3697,8 +3697,8 @@  FF_ENABLE_DEPRECATION_WARNINGS
                 fps_analyze_framecount = 0;
             /* variable fps and no guess at the real fps */
             count = (ic->iformat->flags & AVFMT_NOTIMESTAMPS) ?
-                       st->info->codec_info_duration_fields/2 :
-                       st->info->duration_count;
+                       st->internal->info->codec_info_duration_fields/2 :
+                       st->internal->info->duration_count;
             if (!(st->r_frame_rate.num && st->avg_frame_rate.num) &&
                 st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
                 if (count < fps_analyze_framecount)
@@ -3706,7 +3706,7 @@  FF_ENABLE_DEPRECATION_WARNINGS
             }
             // Look at the first 3 frames if there is evidence of frame delay
             // but the decoder delay is not set.
-            if (st->info->frame_delay_evidence && count < 2 && st->internal->avctx->has_b_frames == 0)
+            if (st->internal->info->frame_delay_evidence && count < 2 && st->internal->avctx->has_b_frames == 0)
                 break;
             if (!st->internal->avctx->extradata &&
                 (!st->internal->extract_extradata.inited ||
@@ -3741,7 +3741,7 @@  FF_ENABLE_DEPRECATION_WARNINGS
                    "Probe buffer size limit of %"PRId64" bytes reached\n", probesize);
             for (i = 0; i < ic->nb_streams; i++)
                 if (!ic->streams[i]->r_frame_rate.num &&
-                    ic->streams[i]->info->duration_count <= 1 &&
+                    ic->streams[i]->internal->info->duration_count <= 1 &&
                     ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
                     strcmp(ic->iformat->name, "image2"))
                     av_log(ic, AV_LOG_WARNING,
@@ -3788,57 +3788,57 @@  FF_ENABLE_DEPRECATION_WARNINGS
 
         if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) {
             /* check for non-increasing dts */
-            if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
-                st->info->fps_last_dts >= pkt->dts) {
+            if (st->internal->info->fps_last_dts != AV_NOPTS_VALUE &&
+                st->internal->info->fps_last_dts >= pkt->dts) {
                 av_log(ic, AV_LOG_DEBUG,
                        "Non-increasing DTS in stream %d: packet %d with DTS "
                        "%"PRId64", packet %d with DTS %"PRId64"\n",
-                       st->index, st->info->fps_last_dts_idx,
-                       st->info->fps_last_dts, st->codec_info_nb_frames,
+                       st->index, st->internal->info->fps_last_dts_idx,
+                       st->internal->info->fps_last_dts, st->codec_info_nb_frames,
                        pkt->dts);
-                st->info->fps_first_dts =
-                st->info->fps_last_dts  = AV_NOPTS_VALUE;
+                st->internal->info->fps_first_dts =
+                st->internal->info->fps_last_dts  = AV_NOPTS_VALUE;
             }
             /* Check for a discontinuity in dts. If the difference in dts
              * is more than 1000 times the average packet duration in the
              * sequence, we treat it as a discontinuity. */
-            if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
-                st->info->fps_last_dts_idx > st->info->fps_first_dts_idx &&
-                (pkt->dts - (uint64_t)st->info->fps_last_dts) / 1000 >
-                (st->info->fps_last_dts     - (uint64_t)st->info->fps_first_dts) /
-                (st->info->fps_last_dts_idx - st->info->fps_first_dts_idx)) {
+            if (st->internal->info->fps_last_dts != AV_NOPTS_VALUE &&
+                st->internal->info->fps_last_dts_idx > st->internal->info->fps_first_dts_idx &&
+                (pkt->dts - (uint64_t)st->internal->info->fps_last_dts) / 1000 >
+                (st->internal->info->fps_last_dts     - (uint64_t)st->internal->info->fps_first_dts) /
+                (st->internal->info->fps_last_dts_idx - st->internal->info->fps_first_dts_idx)) {
                 av_log(ic, AV_LOG_WARNING,
                        "DTS discontinuity in stream %d: packet %d with DTS "
                        "%"PRId64", packet %d with DTS %"PRId64"\n",
-                       st->index, st->info->fps_last_dts_idx,
-                       st->info->fps_last_dts, st->codec_info_nb_frames,
+                       st->index, st->internal->info->fps_last_dts_idx,
+                       st->internal->info->fps_last_dts, st->codec_info_nb_frames,
                        pkt->dts);
-                st->info->fps_first_dts =
-                st->info->fps_last_dts  = AV_NOPTS_VALUE;
+                st->internal->info->fps_first_dts =
+                st->internal->info->fps_last_dts  = AV_NOPTS_VALUE;
             }
 
             /* update stored dts values */
-            if (st->info->fps_first_dts == AV_NOPTS_VALUE) {
-                st->info->fps_first_dts     = pkt->dts;
-                st->info->fps_first_dts_idx = st->codec_info_nb_frames;
+            if (st->internal->info->fps_first_dts == AV_NOPTS_VALUE) {
+                st->internal->info->fps_first_dts     = pkt->dts;
+                st->internal->info->fps_first_dts_idx = st->codec_info_nb_frames;
             }
-            st->info->fps_last_dts     = pkt->dts;
-            st->info->fps_last_dts_idx = st->codec_info_nb_frames;
+            st->internal->info->fps_last_dts     = pkt->dts;
+            st->internal->info->fps_last_dts_idx = st->codec_info_nb_frames;
         }
         if (st->codec_info_nb_frames>1) {
             int64_t t = 0;
             int64_t limit;
 
             if (st->time_base.den > 0)
-                t = av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q);
+                t = av_rescale_q(st->internal->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q);
             if (st->avg_frame_rate.num > 0)
                 t = FFMAX(t, av_rescale_q(st->codec_info_nb_frames, av_inv_q(st->avg_frame_rate), AV_TIME_BASE_Q));
 
             if (   t == 0
                 && st->codec_info_nb_frames>30
-                && st->info->fps_first_dts != AV_NOPTS_VALUE
-                && st->info->fps_last_dts  != AV_NOPTS_VALUE)
-                t = FFMAX(t, av_rescale_q(st->info->fps_last_dts - st->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q));
+                && st->internal->info->fps_first_dts != AV_NOPTS_VALUE
+                && st->internal->info->fps_last_dts  != AV_NOPTS_VALUE)
+                t = FFMAX(t, av_rescale_q(st->internal->info->fps_last_dts - st->internal->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q));
 
             if (analyzed_all_streams)                                limit = max_analyze_duration;
             else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) limit = max_subtitle_analyze_duration;
@@ -3854,10 +3854,10 @@  FF_ENABLE_DEPRECATION_WARNINGS
             }
             if (pkt->duration) {
                 if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE && pkt->pts != AV_NOPTS_VALUE && st->start_time != AV_NOPTS_VALUE && pkt->pts >= st->start_time) {
-                    st->info->codec_info_duration = FFMIN(pkt->pts - st->start_time, st->info->codec_info_duration + pkt->duration);
+                    st->internal->info->codec_info_duration = FFMIN(pkt->pts - st->start_time, st->internal->info->codec_info_duration + pkt->duration);
                 } else
-                    st->info->codec_info_duration += pkt->duration;
-                st->info->codec_info_duration_fields += st->parser && st->need_parsing && avctx->ticks_per_frame ==2 ? st->parser->repeat_pict + 1 : 2;
+                    st->internal->info->codec_info_duration += pkt->duration;
+                st->internal->info->codec_info_duration_fields += st->parser && st->need_parsing && avctx->ticks_per_frame ==2 ? st->parser->repeat_pict + 1 : 2;
             }
         }
         if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
@@ -3865,7 +3865,7 @@  FF_ENABLE_DEPRECATION_WARNINGS
             ff_rfps_add_frame(ic, st, pkt->dts);
 #endif
             if (pkt->dts != pkt->pts && pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE)
-                st->info->frame_delay_evidence = 1;
+                st->internal->info->frame_delay_evidence = 1;
         }
         if (!st->internal->avctx->extradata) {
             ret = extract_extradata(st, pkt);
@@ -3928,7 +3928,7 @@  FF_ENABLE_DEPRECATION_WARNINGS
             st = ic->streams[i];
 
             /* flush the decoders */
-            if (st->info->found_decoder == 1) {
+            if (st->internal->info->found_decoder == 1) {
                 do {
                     err = try_decode_frame(ic, st, &empty_pkt,
                                             (options && i < orig_nb_streams)
@@ -3956,20 +3956,20 @@  FF_ENABLE_DEPRECATION_WARNINGS
             }
 
             /* estimate average framerate if not set by demuxer */
-            if (st->info->codec_info_duration_fields &&
+            if (st->internal->info->codec_info_duration_fields &&
                 !st->avg_frame_rate.num &&
-                st->info->codec_info_duration) {
+                st->internal->info->codec_info_duration) {
                 int best_fps      = 0;
                 double best_error = 0.01;
                 AVRational codec_frame_rate = avctx->framerate;
 
-                if (st->info->codec_info_duration        >= INT64_MAX / st->time_base.num / 2||
-                    st->info->codec_info_duration_fields >= INT64_MAX / st->time_base.den ||
-                    st->info->codec_info_duration        < 0)
+                if (st->internal->info->codec_info_duration        >= INT64_MAX / st->time_base.num / 2||
+                    st->internal->info->codec_info_duration_fields >= INT64_MAX / st->time_base.den ||
+                    st->internal->info->codec_info_duration        < 0)
                     continue;
                 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
-                          st->info->codec_info_duration_fields * (int64_t) st->time_base.den,
-                          st->info->codec_info_duration * 2 * (int64_t) st->time_base.num, 60000);
+                          st->internal->info->codec_info_duration_fields * (int64_t) st->time_base.den,
+                          st->internal->info->codec_info_duration * 2 * (int64_t) st->time_base.num, 60000);
 
                 /* Round guessed framerate to a "standard" framerate if it's
                  * within 1% of the original estimate. */
@@ -4138,10 +4138,10 @@  FF_ENABLE_DEPRECATION_WARNINGS
 find_stream_info_err:
     for (i = 0; i < ic->nb_streams; i++) {
         st = ic->streams[i];
-        if (st->info)
-            av_freep(&st->info->duration_error);
+        if (st->internal->info)
+            av_freep(&st->internal->info->duration_error);
         avcodec_close(ic->streams[i]->internal->avctx);
-        av_freep(&ic->streams[i]->info);
+        av_freep(&ic->streams[i]->internal->info);
         av_bsf_free(&ic->streams[i]->internal->extract_extradata.bsf);
         av_packet_free(&ic->streams[i]->internal->extract_extradata.pkt);
     }
@@ -4343,6 +4343,10 @@  static void free_stream(AVStream **pst)
         av_freep(&st->internal->priv_pts);
         av_bsf_free(&st->internal->extract_extradata.bsf);
         av_packet_free(&st->internal->extract_extradata.pkt);
+
+        if (st->internal->info)
+            av_freep(&st->internal->info->duration_error);
+        av_freep(&st->internal->info);
     }
     av_freep(&st->internal);
 
@@ -4356,9 +4360,6 @@  FF_DISABLE_DEPRECATION_WARNINGS
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
     av_freep(&st->priv_data);
-    if (st->info)
-        av_freep(&st->info->duration_error);
-    av_freep(&st->info);
 #if FF_API_LAVF_FFSERVER
 FF_DISABLE_DEPRECATION_WARNINGS
     av_freep(&st->recommended_encoder_configuration);
@@ -4466,17 +4467,11 @@  AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
     st = av_mallocz(sizeof(AVStream));
     if (!st)
         return NULL;
-    if (!(st->info = av_mallocz(sizeof(*st->info)))) {
-        av_free(st);
-        return NULL;
-    }
-    st->info->last_dts = AV_NOPTS_VALUE;
 
 #if FF_API_LAVF_AVCTX
 FF_DISABLE_DEPRECATION_WARNINGS
     st->codec = avcodec_alloc_context3(c);
     if (!st->codec) {
-        av_free(st->info);
         av_free(st);
         return NULL;
     }
@@ -4487,6 +4482,11 @@  FF_ENABLE_DEPRECATION_WARNINGS
     if (!st->internal)
         goto fail;
 
+    st->internal->info = av_mallocz(sizeof(*st->internal->info));
+    if (!st->internal->info)
+        goto fail;
+    st->internal->info->last_dts = AV_NOPTS_VALUE;
+
     st->codecpar = avcodec_parameters_alloc();
     if (!st->codecpar)
         goto fail;
@@ -4530,10 +4530,10 @@  FF_ENABLE_DEPRECATION_WARNINGS
     st->sample_aspect_ratio = (AVRational) { 0, 1 };
 
 #if FF_API_R_FRAME_RATE
-    st->info->last_dts      = AV_NOPTS_VALUE;
+    st->internal->info->last_dts      = AV_NOPTS_VALUE;
 #endif
-    st->info->fps_first_dts = AV_NOPTS_VALUE;
-    st->info->fps_last_dts  = AV_NOPTS_VALUE;
+    st->internal->info->fps_first_dts = AV_NOPTS_VALUE;
+    st->internal->info->fps_last_dts  = AV_NOPTS_VALUE;
 
     st->inject_global_side_data = s->internal->inject_global_side_data;