[FFmpeg-devel] [PATCH 07/44] avformat/utils: Move stream_options, avformat_new_stream to options.c

Andreas Rheinhardt andreas.rheinhardt at outlook.com
Sat May 7 14:27:53 EEST 2022


This is the appropriate place given that AVStream is about to
become an AVOpt-enabled struct.
Also move av_disposition_(to|from)_string, as these are tied
to the disposition stream option.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
---
 libavformat/avidec.c   |   2 +-
 libavformat/internal.h |  12 +++-
 libavformat/options.c  | 151 ++++++++++++++++++++++++++++++++++++++
 libavformat/rmdec.c    |   2 +-
 libavformat/utils.c    | 159 ++---------------------------------------
 5 files changed, 169 insertions(+), 157 deletions(-)

diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 3c749aec14..21fc2b87ff 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -621,7 +621,7 @@ static int avi_read_header(AVFormatContext *s)
 
                 ast = s->streams[0]->priv_data;
                 st->priv_data = NULL;
-                ff_free_stream(s, st);
+                ff_remove_stream(s, st);
 
                 avi->dv_demux = avpriv_dv_init_demux(s);
                 if (!avi->dv_demux) {
diff --git a/libavformat/internal.h b/libavformat/internal.h
index a40a29c5c0..a3fdab03af 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -742,7 +742,17 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt);
 int ff_add_attached_pic(AVFormatContext *s, AVStream *st, AVIOContext *pb,
                         AVBufferRef **buf, int size);
 
-void ff_free_stream(AVFormatContext *s, AVStream *st);
+/**
+ * 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);
 
 unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id);
 
diff --git a/libavformat/options.c b/libavformat/options.c
index 2d55d3ad6e..14ae55e3fd 100644
--- a/libavformat/options.c
+++ b/libavformat/options.c
@@ -21,8 +21,12 @@
 #include "avio_internal.h"
 #include "internal.h"
 
+#include "libavcodec/avcodec.h"
+#include "libavcodec/codec_par.h"
+
 #include "libavutil/avassert.h"
 #include "libavutil/internal.h"
+#include "libavutil/intmath.h"
 #include "libavutil/opt.h"
 
 /**
@@ -188,3 +192,150 @@ const AVClass *avformat_get_class(void)
 {
     return &av_format_context_class;
 }
+
+static const AVOption stream_options[] = {
+    { "disposition", NULL, offsetof(AVStream, disposition), AV_OPT_TYPE_FLAGS, { .i64 = 0 },
+        .flags = AV_OPT_FLAG_ENCODING_PARAM, .unit = "disposition" },
+        { "default",            .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEFAULT           },    .unit = "disposition" },
+        { "dub",                .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DUB               },    .unit = "disposition" },
+        { "original",           .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ORIGINAL          },    .unit = "disposition" },
+        { "comment",            .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_COMMENT           },    .unit = "disposition" },
+        { "lyrics",             .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_LYRICS            },    .unit = "disposition" },
+        { "karaoke",            .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_KARAOKE           },    .unit = "disposition" },
+        { "forced",             .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_FORCED            },    .unit = "disposition" },
+        { "hearing_impaired",   .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED  },    .unit = "disposition" },
+        { "visual_impaired",    .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED   },    .unit = "disposition" },
+        { "clean_effects",      .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS     },    .unit = "disposition" },
+        { "attached_pic",       .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ATTACHED_PIC      },    .unit = "disposition" },
+        { "timed_thumbnails",   .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_TIMED_THUMBNAILS  },    .unit = "disposition" },
+        { "captions",           .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS          },    .unit = "disposition" },
+        { "descriptions",       .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS      },    .unit = "disposition" },
+        { "metadata",           .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA          },    .unit = "disposition" },
+        { "dependent",          .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEPENDENT         },    .unit = "disposition" },
+        { "still_image",        .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_STILL_IMAGE       },    .unit = "disposition" },
+    { NULL }
+};
+
+static const AVClass stream_class = {
+    .class_name     = "AVStream",
+    .item_name      = av_default_item_name,
+    .version        = LIBAVUTIL_VERSION_INT,
+    .option         = stream_options,
+};
+
+const AVClass *av_stream_get_class(void)
+{
+    return &stream_class;
+}
+
+AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
+{
+    FFFormatContext *const si = ffformatcontext(s);
+    FFStream *sti;
+    AVStream *st;
+    AVStream **streams;
+
+    if (s->nb_streams >= s->max_streams) {
+        av_log(s, AV_LOG_ERROR, "Number of streams exceeds max_streams parameter"
+               " (%d), see the documentation if you wish to increase it\n",
+               s->max_streams);
+        return NULL;
+    }
+    streams = av_realloc_array(s->streams, s->nb_streams + 1, sizeof(*streams));
+    if (!streams)
+        return NULL;
+    s->streams = streams;
+
+    sti = av_mallocz(sizeof(*sti));
+    if (!sti)
+        return NULL;
+    st = &sti->pub;
+
+#if FF_API_AVSTREAM_CLASS
+    st->av_class = &stream_class;
+#endif
+
+    st->codecpar = avcodec_parameters_alloc();
+    if (!st->codecpar)
+        goto fail;
+
+    sti->avctx = avcodec_alloc_context3(NULL);
+    if (!sti->avctx)
+        goto fail;
+
+    if (s->iformat) {
+        sti->info = av_mallocz(sizeof(*sti->info));
+        if (!sti->info)
+            goto fail;
+
+#if FF_API_R_FRAME_RATE
+        sti->info->last_dts      = AV_NOPTS_VALUE;
+#endif
+        sti->info->fps_first_dts = AV_NOPTS_VALUE;
+        sti->info->fps_last_dts  = AV_NOPTS_VALUE;
+
+        /* default pts setting is MPEG-like */
+        avpriv_set_pts_info(st, 33, 1, 90000);
+        /* we set the current DTS to 0 so that formats without any timestamps
+         * but durations get some timestamps, formats with some unknown
+         * timestamps have their first few packets buffered and the
+         * timestamps corrected before they are returned to the user */
+        sti->cur_dts = RELATIVE_TS_BASE;
+    } else {
+        sti->cur_dts = AV_NOPTS_VALUE;
+    }
+
+    st->index      = s->nb_streams;
+    st->start_time = AV_NOPTS_VALUE;
+    st->duration   = AV_NOPTS_VALUE;
+    sti->first_dts     = AV_NOPTS_VALUE;
+    sti->probe_packets = s->max_probe_packets;
+    sti->pts_wrap_reference = AV_NOPTS_VALUE;
+    sti->pts_wrap_behavior  = AV_PTS_WRAP_IGNORE;
+
+    sti->last_IP_pts = AV_NOPTS_VALUE;
+    sti->last_dts_for_order_check = AV_NOPTS_VALUE;
+    for (int i = 0; i < MAX_REORDER_DELAY + 1; i++)
+        sti->pts_buffer[i] = AV_NOPTS_VALUE;
+
+    st->sample_aspect_ratio = (AVRational) { 0, 1 };
+
+    sti->inject_global_side_data = si->inject_global_side_data;
+
+    sti->need_context_update = 1;
+
+    s->streams[s->nb_streams++] = st;
+    return st;
+fail:
+    ff_free_stream(&st);
+    return NULL;
+}
+
+static int option_is_disposition(const AVOption *opt)
+{
+    return opt->type == AV_OPT_TYPE_CONST &&
+           opt->unit && !strcmp(opt->unit, "disposition");
+}
+
+int av_disposition_from_string(const char *disp)
+{
+    for (const AVOption *opt = stream_options; opt->name; opt++)
+        if (option_is_disposition(opt) && !strcmp(disp, opt->name))
+            return opt->default_val.i64;
+    return AVERROR(EINVAL);
+}
+
+const char *av_disposition_to_string(int disposition)
+{
+    int val;
+
+    if (disposition <= 0)
+        return NULL;
+
+    val = 1 << ff_ctz(disposition);
+    for (const AVOption *opt = stream_options; opt->name; opt++)
+        if (option_is_disposition(opt) && opt->default_val.i64 == val)
+            return opt->name;
+
+    return NULL;
+}
diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c
index b6b72e6ead..cb0ca31f40 100644
--- a/libavformat/rmdec.c
+++ b/libavformat/rmdec.c
@@ -349,7 +349,7 @@ int ff_rm_read_mdpr_codecdata(AVFormatContext *s, AVIOContext *pb,
                                                 st->codecpar->codec_tag);
     } else if(mime && !strcmp(mime, "logical-fileinfo")){
         int stream_count, rule_count, property_count, i;
-        ff_free_stream(s, st);
+        ff_remove_stream(s, st);
         if (avio_rb16(pb) != 0) {
             av_log(s, AV_LOG_WARNING, "Unsupported version\n");
             goto skip;
diff --git a/libavformat/utils.c b/libavformat/utils.c
index fcee417c4e..f31dda9b44 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -28,7 +28,6 @@
 #include "libavutil/bprint.h"
 #include "libavutil/dict.h"
 #include "libavutil/internal.h"
-#include "libavutil/intmath.h"
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/pixfmt.h"
@@ -258,7 +257,7 @@ int ff_add_attached_pic(AVFormatContext *s, AVStream *st0, AVIOContext *pb,
     return 0;
 fail:
     if (!st0)
-        ff_free_stream(s, st);
+        ff_remove_stream(s, st);
     return ret;
 }
 
@@ -621,7 +620,7 @@ int ff_stream_side_data_copy(AVStream *dst, const AVStream *src)
     return 0;
 }
 
-static void free_stream(AVStream **pst)
+void ff_free_stream(AVStream **pst)
 {
     AVStream *st = *pst;
     FFStream *const sti = ffstream(st);
@@ -657,12 +656,12 @@ static void free_stream(AVStream **pst)
     av_freep(pst);
 }
 
-void ff_free_stream(AVFormatContext *s, AVStream *st)
+void ff_remove_stream(AVFormatContext *s, AVStream *st)
 {
     av_assert0(s->nb_streams>0);
     av_assert0(s->streams[ s->nb_streams - 1 ] == st);
 
-    free_stream(&s->streams[ --s->nb_streams ]);
+    ff_free_stream(&s->streams[ --s->nb_streams ]);
 }
 
 void avformat_free_context(AVFormatContext *s)
@@ -683,7 +682,7 @@ void avformat_free_context(AVFormatContext *s)
         av_opt_free(s->priv_data);
 
     for (unsigned i = 0; i < s->nb_streams; i++)
-        free_stream(&s->streams[i]);
+        ff_free_stream(&s->streams[i]);
     s->nb_streams = 0;
 
     for (unsigned i = 0; i < s->nb_programs; i++) {
@@ -710,125 +709,6 @@ void avformat_free_context(AVFormatContext *s)
     av_free(s);
 }
 
-static const AVOption stream_options[] = {
-    { "disposition", NULL, offsetof(AVStream, disposition), AV_OPT_TYPE_FLAGS, { .i64 = 0 },
-        .flags = AV_OPT_FLAG_ENCODING_PARAM, .unit = "disposition" },
-        { "default",            .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEFAULT           },    .unit = "disposition" },
-        { "dub",                .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DUB               },    .unit = "disposition" },
-        { "original",           .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ORIGINAL          },    .unit = "disposition" },
-        { "comment",            .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_COMMENT           },    .unit = "disposition" },
-        { "lyrics",             .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_LYRICS            },    .unit = "disposition" },
-        { "karaoke",            .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_KARAOKE           },    .unit = "disposition" },
-        { "forced",             .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_FORCED            },    .unit = "disposition" },
-        { "hearing_impaired",   .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED  },    .unit = "disposition" },
-        { "visual_impaired",    .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED   },    .unit = "disposition" },
-        { "clean_effects",      .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS     },    .unit = "disposition" },
-        { "attached_pic",       .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ATTACHED_PIC      },    .unit = "disposition" },
-        { "timed_thumbnails",   .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_TIMED_THUMBNAILS  },    .unit = "disposition" },
-        { "captions",           .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS          },    .unit = "disposition" },
-        { "descriptions",       .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS      },    .unit = "disposition" },
-        { "metadata",           .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA          },    .unit = "disposition" },
-        { "dependent",          .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEPENDENT         },    .unit = "disposition" },
-        { "still_image",        .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_STILL_IMAGE       },    .unit = "disposition" },
-    { NULL }
-};
-
-static const AVClass stream_class = {
-    .class_name     = "AVStream",
-    .item_name      = av_default_item_name,
-    .version        = LIBAVUTIL_VERSION_INT,
-    .option         = stream_options,
-};
-
-const AVClass *av_stream_get_class(void)
-{
-    return &stream_class;
-}
-
-AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
-{
-    FFFormatContext *const si = ffformatcontext(s);
-    FFStream *sti;
-    AVStream *st;
-    AVStream **streams;
-
-    if (s->nb_streams >= s->max_streams) {
-        av_log(s, AV_LOG_ERROR, "Number of streams exceeds max_streams parameter"
-               " (%d), see the documentation if you wish to increase it\n",
-               s->max_streams);
-        return NULL;
-    }
-    streams = av_realloc_array(s->streams, s->nb_streams + 1, sizeof(*streams));
-    if (!streams)
-        return NULL;
-    s->streams = streams;
-
-
-    sti = av_mallocz(sizeof(*sti));
-    if (!sti)
-        return NULL;
-    st = &sti->pub;
-
-#if FF_API_AVSTREAM_CLASS
-    st->av_class = &stream_class;
-#endif
-
-    st->codecpar = avcodec_parameters_alloc();
-    if (!st->codecpar)
-        goto fail;
-
-    sti->avctx = avcodec_alloc_context3(NULL);
-    if (!sti->avctx)
-        goto fail;
-
-    if (s->iformat) {
-        sti->info = av_mallocz(sizeof(*sti->info));
-        if (!sti->info)
-            goto fail;
-
-#if FF_API_R_FRAME_RATE
-        sti->info->last_dts      = AV_NOPTS_VALUE;
-#endif
-        sti->info->fps_first_dts = AV_NOPTS_VALUE;
-        sti->info->fps_last_dts  = AV_NOPTS_VALUE;
-
-        /* default pts setting is MPEG-like */
-        avpriv_set_pts_info(st, 33, 1, 90000);
-        /* we set the current DTS to 0 so that formats without any timestamps
-         * but durations get some timestamps, formats with some unknown
-         * timestamps have their first few packets buffered and the
-         * timestamps corrected before they are returned to the user */
-        sti->cur_dts = RELATIVE_TS_BASE;
-    } else {
-        sti->cur_dts = AV_NOPTS_VALUE;
-    }
-
-    st->index      = s->nb_streams;
-    st->start_time = AV_NOPTS_VALUE;
-    st->duration   = AV_NOPTS_VALUE;
-    sti->first_dts     = AV_NOPTS_VALUE;
-    sti->probe_packets = s->max_probe_packets;
-    sti->pts_wrap_reference = AV_NOPTS_VALUE;
-    sti->pts_wrap_behavior  = AV_PTS_WRAP_IGNORE;
-
-    sti->last_IP_pts = AV_NOPTS_VALUE;
-    sti->last_dts_for_order_check = AV_NOPTS_VALUE;
-    for (int i = 0; i < MAX_REORDER_DELAY + 1; i++)
-        sti->pts_buffer[i] = AV_NOPTS_VALUE;
-
-    st->sample_aspect_ratio = (AVRational) { 0, 1 };
-
-    sti->inject_global_side_data = si->inject_global_side_data;
-
-    sti->need_context_update = 1;
-
-    s->streams[s->nb_streams++] = st;
-    return st;
-fail:
-    free_stream(&st);
-    return NULL;
-}
-
 AVProgram *av_new_program(AVFormatContext *ac, int id)
 {
     AVProgram *program = NULL;
@@ -1953,35 +1833,6 @@ void ff_format_set_url(AVFormatContext *s, char *url)
     s->url = url;
 }
 
-static int option_is_disposition(const AVOption *opt)
-{
-    return opt->type == AV_OPT_TYPE_CONST &&
-           opt->unit && !strcmp(opt->unit, "disposition");
-}
-
-int av_disposition_from_string(const char *disp)
-{
-    for (const AVOption *opt = stream_options; opt->name; opt++)
-        if (option_is_disposition(opt) && !strcmp(disp, opt->name))
-            return opt->default_val.i64;
-    return AVERROR(EINVAL);
-}
-
-const char *av_disposition_to_string(int disposition)
-{
-    int val;
-
-    if (disposition <= 0)
-        return NULL;
-
-    val = 1 << ff_ctz(disposition);
-    for (const AVOption *opt = stream_options; opt->name; opt++)
-        if (option_is_disposition(opt) && opt->default_val.i64 == val)
-            return opt->name;
-
-    return NULL;
-}
-
 int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size)
 {
     int ret;
-- 
2.32.0



More information about the ffmpeg-devel mailing list