Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c
@ 2022-10-18 12:36 Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 02/20] fftools/ffmpeg_demux: add demuxer private data Anton Khirnov
                   ` (18 more replies)
  0 siblings, 19 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

This is similar to what was done before for output files and will allow
introducing demuxer-private state in future commits

Unlike for muxing, the code is moved to existing ffmpeg_demux.c rather
than to a new file. The reason is just file size - the demuxing code is
much smaller than muxing.
---
 fftools/ffmpeg.h       |   4 +
 fftools/ffmpeg_demux.c | 608 +++++++++++++++++++++++++++++++++++++++++
 fftools/ffmpeg_opt.c   | 606 +---------------------------------------
 3 files changed, 614 insertions(+), 604 deletions(-)

diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 91c5cfa3ab..085a775a43 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -678,6 +678,8 @@ extern int input_stream_potentially_available;
 extern int ignore_unknown_streams;
 extern int copy_unknown_streams;
 
+extern int recast_media;
+
 #if FFMPEG_OPT_PSNR
 extern int do_psnr;
 #endif
@@ -745,6 +747,8 @@ int64_t of_filesize(OutputFile *of);
 AVChapter * const *
 of_get_chapters(OutputFile *of, unsigned int *nb_chapters);
 
+int ifile_open(OptionsContext *o, const char *filename);
+
 /**
  * Get next input packet from the demuxer.
  *
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 6e89f5999a..d2b0bc9a6d 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -19,7 +19,12 @@
 #include "ffmpeg.h"
 
 #include "libavutil/avassert.h"
+#include "libavutil/avstring.h"
 #include "libavutil/error.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/opt.h"
+#include "libavutil/parseutils.h"
+#include "libavutil/pixdesc.h"
 #include "libavutil/time.h"
 #include "libavutil/timestamp.h"
 #include "libavutil/thread.h"
@@ -29,6 +34,17 @@
 
 #include "libavformat/avformat.h"
 
+static const char *const opt_name_discard[]                   = {"discard", NULL};
+static const char *const opt_name_reinit_filters[]            = {"reinit_filter", NULL};
+static const char *const opt_name_fix_sub_duration[]          = {"fix_sub_duration", NULL};
+static const char *const opt_name_canvas_sizes[]              = {"canvas_size", NULL};
+static const char *const opt_name_guess_layout_max[]          = {"guess_layout_max", NULL};
+static const char *const opt_name_ts_scale[]                  = {"itsscale", NULL};
+static const char *const opt_name_hwaccels[]                  = {"hwaccel", NULL};
+static const char *const opt_name_hwaccel_devices[]           = {"hwaccel_device", NULL};
+static const char *const opt_name_hwaccel_output_formats[]    = {"hwaccel_output_format", NULL};
+static const char *const opt_name_autorotate[]                = {"autorotate", NULL};
+
 typedef struct DemuxMsg {
     AVPacket *pkt;
     int looping;
@@ -397,3 +413,595 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt)
     *pkt = msg.pkt;
     return 0;
 }
+
+static const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *st,
+                                     enum HWAccelID hwaccel_id, enum AVHWDeviceType hwaccel_device_type)
+
+{
+    char *codec_name = NULL;
+
+    MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st);
+    if (codec_name) {
+        const AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0);
+        st->codecpar->codec_id = codec->id;
+        if (recast_media && st->codecpar->codec_type != codec->type)
+            st->codecpar->codec_type = codec->type;
+        return codec;
+    } else {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+            hwaccel_id == HWACCEL_GENERIC &&
+            hwaccel_device_type != AV_HWDEVICE_TYPE_NONE) {
+            const AVCodec *c;
+            void *i = NULL;
+
+            while ((c = av_codec_iterate(&i))) {
+                const AVCodecHWConfig *config;
+
+                if (c->id != st->codecpar->codec_id ||
+                    !av_codec_is_decoder(c))
+                    continue;
+
+                for (int j = 0; config = avcodec_get_hw_config(c, j); j++) {
+                    if (config->device_type == hwaccel_device_type) {
+                        av_log(NULL, AV_LOG_VERBOSE, "Selecting decoder '%s' because of requested hwaccel method %s\n",
+                               c->name, av_hwdevice_get_type_name(hwaccel_device_type));
+                        return c;
+                    }
+                }
+            }
+        }
+
+        return avcodec_find_decoder(st->codecpar->codec_id);
+    }
+}
+
+static int guess_input_channel_layout(InputStream *ist)
+{
+    AVCodecContext *dec = ist->dec_ctx;
+
+    if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+        char layout_name[256];
+
+        if (dec->ch_layout.nb_channels > ist->guess_layout_max)
+            return 0;
+        av_channel_layout_default(&dec->ch_layout, dec->ch_layout.nb_channels);
+        if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
+            return 0;
+        av_channel_layout_describe(&dec->ch_layout, layout_name, sizeof(layout_name));
+        av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream "
+               "#%d.%d : %s\n", ist->file_index, ist->st->index, layout_name);
+    }
+    return 1;
+}
+
+/* Add all the streams from the given input file to the global
+ * list of input streams. */
+static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
+{
+    int i, ret;
+
+    for (i = 0; i < ic->nb_streams; i++) {
+        AVStream *st = ic->streams[i];
+        AVCodecParameters *par = st->codecpar;
+        InputStream *ist;
+        char *framerate = NULL, *hwaccel_device = NULL;
+        const char *hwaccel = NULL;
+        char *hwaccel_output_format = NULL;
+        char *codec_tag = NULL;
+        char *next;
+        char *discard_str = NULL;
+        const AVClass *cc = avcodec_get_class();
+        const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL,
+                                                  0, AV_OPT_SEARCH_FAKE_OBJ);
+
+        ist = ALLOC_ARRAY_ELEM(input_streams, nb_input_streams);
+        ist->st = st;
+        ist->file_index = nb_input_files;
+        ist->discard = 1;
+        st->discard  = AVDISCARD_ALL;
+        ist->nb_samples = 0;
+        ist->first_dts = AV_NOPTS_VALUE;
+        ist->min_pts = INT64_MAX;
+        ist->max_pts = INT64_MIN;
+
+        ist->ts_scale = 1.0;
+        MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
+
+        ist->autorotate = 1;
+        MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st);
+
+        MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
+        if (codec_tag) {
+            uint32_t tag = strtol(codec_tag, &next, 0);
+            if (*next)
+                tag = AV_RL32(codec_tag);
+            st->codecpar->codec_tag = tag;
+        }
+
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+            MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st);
+            MATCH_PER_STREAM_OPT(hwaccel_output_formats, str,
+                                 hwaccel_output_format, ic, st);
+
+            if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "cuvid")) {
+                av_log(NULL, AV_LOG_WARNING,
+                    "WARNING: defaulting hwaccel_output_format to cuda for compatibility "
+                    "with old commandlines. This behaviour is DEPRECATED and will be removed "
+                    "in the future. Please explicitly set \"-hwaccel_output_format cuda\".\n");
+                ist->hwaccel_output_format = AV_PIX_FMT_CUDA;
+            } else if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "qsv")) {
+                av_log(NULL, AV_LOG_WARNING,
+                    "WARNING: defaulting hwaccel_output_format to qsv for compatibility "
+                    "with old commandlines. This behaviour is DEPRECATED and will be removed "
+                    "in the future. Please explicitly set \"-hwaccel_output_format qsv\".\n");
+                ist->hwaccel_output_format = AV_PIX_FMT_QSV;
+            } else if (hwaccel_output_format) {
+                ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format);
+                if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) {
+                    av_log(NULL, AV_LOG_FATAL, "Unrecognised hwaccel output "
+                           "format: %s", hwaccel_output_format);
+                }
+            } else {
+                ist->hwaccel_output_format = AV_PIX_FMT_NONE;
+            }
+
+            if (hwaccel) {
+                // The NVDEC hwaccels use a CUDA device, so remap the name here.
+                if (!strcmp(hwaccel, "nvdec") || !strcmp(hwaccel, "cuvid"))
+                    hwaccel = "cuda";
+
+                if (!strcmp(hwaccel, "none"))
+                    ist->hwaccel_id = HWACCEL_NONE;
+                else if (!strcmp(hwaccel, "auto"))
+                    ist->hwaccel_id = HWACCEL_AUTO;
+                else {
+                    enum AVHWDeviceType type = av_hwdevice_find_type_by_name(hwaccel);
+                    if (type != AV_HWDEVICE_TYPE_NONE) {
+                        ist->hwaccel_id = HWACCEL_GENERIC;
+                        ist->hwaccel_device_type = type;
+                    }
+
+                    if (!ist->hwaccel_id) {
+                        av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n",
+                               hwaccel);
+                        av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: ");
+                        type = AV_HWDEVICE_TYPE_NONE;
+                        while ((type = av_hwdevice_iterate_types(type)) !=
+                               AV_HWDEVICE_TYPE_NONE)
+                            av_log(NULL, AV_LOG_FATAL, "%s ",
+                                   av_hwdevice_get_type_name(type));
+                        av_log(NULL, AV_LOG_FATAL, "\n");
+                        exit_program(1);
+                    }
+                }
+            }
+
+            MATCH_PER_STREAM_OPT(hwaccel_devices, str, hwaccel_device, ic, st);
+            if (hwaccel_device) {
+                ist->hwaccel_device = av_strdup(hwaccel_device);
+                if (!ist->hwaccel_device)
+                    report_and_exit(AVERROR(ENOMEM));
+            }
+
+            ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE;
+        }
+
+        ist->dec = choose_decoder(o, ic, st, ist->hwaccel_id, ist->hwaccel_device_type);
+        ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codecpar->codec_id, ic, st, ist->dec);
+
+        ist->reinit_filters = -1;
+        MATCH_PER_STREAM_OPT(reinit_filters, i, ist->reinit_filters, ic, st);
+
+        MATCH_PER_STREAM_OPT(discard, str, discard_str, ic, st);
+        ist->user_set_discard = AVDISCARD_NONE;
+
+        if ((o->video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ||
+            (o->audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ||
+            (o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) ||
+            (o->data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA))
+                ist->user_set_discard = AVDISCARD_ALL;
+
+        if (discard_str && av_opt_eval_int(&cc, discard_opt, discard_str, &ist->user_set_discard) < 0) {
+            av_log(NULL, AV_LOG_ERROR, "Error parsing discard %s.\n",
+                    discard_str);
+            exit_program(1);
+        }
+
+        ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE;
+        ist->prev_pkt_pts = AV_NOPTS_VALUE;
+
+        ist->dec_ctx = avcodec_alloc_context3(ist->dec);
+        if (!ist->dec_ctx)
+            report_and_exit(AVERROR(ENOMEM));
+
+        ret = avcodec_parameters_to_context(ist->dec_ctx, par);
+        if (ret < 0) {
+            av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n");
+            exit_program(1);
+        }
+
+        ist->decoded_frame = av_frame_alloc();
+        if (!ist->decoded_frame)
+            report_and_exit(AVERROR(ENOMEM));
+
+        ist->pkt = av_packet_alloc();
+        if (!ist->pkt)
+            report_and_exit(AVERROR(ENOMEM));
+
+        if (o->bitexact)
+            ist->dec_ctx->flags |= AV_CODEC_FLAG_BITEXACT;
+
+        switch (par->codec_type) {
+        case AVMEDIA_TYPE_VIDEO:
+            // avformat_find_stream_info() doesn't set this for us anymore.
+            ist->dec_ctx->framerate = st->avg_frame_rate;
+
+            MATCH_PER_STREAM_OPT(frame_rates, str, framerate, ic, st);
+            if (framerate && av_parse_video_rate(&ist->framerate,
+                                                 framerate) < 0) {
+                av_log(NULL, AV_LOG_ERROR, "Error parsing framerate %s.\n",
+                       framerate);
+                exit_program(1);
+            }
+
+            ist->top_field_first = -1;
+            MATCH_PER_STREAM_OPT(top_field_first, i, ist->top_field_first, ic, st);
+
+            ist->framerate_guessed = av_guess_frame_rate(ic, st, NULL);
+
+            break;
+        case AVMEDIA_TYPE_AUDIO:
+            ist->guess_layout_max = INT_MAX;
+            MATCH_PER_STREAM_OPT(guess_layout_max, i, ist->guess_layout_max, ic, st);
+            guess_input_channel_layout(ist);
+            break;
+        case AVMEDIA_TYPE_DATA:
+        case AVMEDIA_TYPE_SUBTITLE: {
+            char *canvas_size = NULL;
+            MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st);
+            MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st);
+            if (canvas_size &&
+                av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height, canvas_size) < 0) {
+                av_log(NULL, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size);
+                exit_program(1);
+            }
+            break;
+        }
+        case AVMEDIA_TYPE_ATTACHMENT:
+        case AVMEDIA_TYPE_UNKNOWN:
+            break;
+        default:
+            abort();
+        }
+
+        ist->par = avcodec_parameters_alloc();
+        if (!ist->par)
+            report_and_exit(AVERROR(ENOMEM));
+
+        ret = avcodec_parameters_from_context(ist->par, ist->dec_ctx);
+        if (ret < 0) {
+            av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n");
+            exit_program(1);
+        }
+    }
+}
+
+static void dump_attachment(AVStream *st, const char *filename)
+{
+    int ret;
+    AVIOContext *out = NULL;
+    const AVDictionaryEntry *e;
+
+    if (!st->codecpar->extradata_size) {
+        av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n",
+               nb_input_files - 1, st->index);
+        return;
+    }
+    if (!*filename && (e = av_dict_get(st->metadata, "filename", NULL, 0)))
+        filename = e->value;
+    if (!*filename) {
+        av_log(NULL, AV_LOG_FATAL, "No filename specified and no 'filename' tag"
+               "in stream #%d:%d.\n", nb_input_files - 1, st->index);
+        exit_program(1);
+    }
+
+    assert_file_overwrite(filename);
+
+    if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &int_cb, NULL)) < 0) {
+        av_log(NULL, AV_LOG_FATAL, "Could not open file %s for writing.\n",
+               filename);
+        exit_program(1);
+    }
+
+    avio_write(out, st->codecpar->extradata, st->codecpar->extradata_size);
+    avio_flush(out);
+    avio_close(out);
+}
+
+int ifile_open(OptionsContext *o, const char *filename)
+{
+    InputFile *f;
+    AVFormatContext *ic;
+    const AVInputFormat *file_iformat = NULL;
+    int err, i, ret;
+    int64_t timestamp;
+    AVDictionary *unused_opts = NULL;
+    const AVDictionaryEntry *e = NULL;
+    char *   video_codec_name = NULL;
+    char *   audio_codec_name = NULL;
+    char *subtitle_codec_name = NULL;
+    char *    data_codec_name = NULL;
+    int scan_all_pmts_set = 0;
+
+    if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) {
+        o->stop_time = INT64_MAX;
+        av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
+    }
+
+    if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) {
+        int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time;
+        if (o->stop_time <= start_time) {
+            av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n");
+            exit_program(1);
+        } else {
+            o->recording_time = o->stop_time - start_time;
+        }
+    }
+
+    if (o->format) {
+        if (!(file_iformat = av_find_input_format(o->format))) {
+            av_log(NULL, AV_LOG_FATAL, "Unknown input format: '%s'\n", o->format);
+            exit_program(1);
+        }
+    }
+
+    if (!strcmp(filename, "-"))
+        filename = "pipe:";
+
+    stdin_interaction &= strncmp(filename, "pipe:", 5) &&
+                         strcmp(filename, "/dev/stdin");
+
+    /* get default parameters from command line */
+    ic = avformat_alloc_context();
+    if (!ic)
+        report_and_exit(AVERROR(ENOMEM));
+    if (o->nb_audio_sample_rate) {
+        av_dict_set_int(&o->g->format_opts, "sample_rate", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i, 0);
+    }
+    if (o->nb_audio_channels) {
+        const AVClass *priv_class;
+        if (file_iformat && (priv_class = file_iformat->priv_class) &&
+            av_opt_find(&priv_class, "ch_layout", NULL, 0,
+                        AV_OPT_SEARCH_FAKE_OBJ)) {
+            char buf[32];
+            snprintf(buf, sizeof(buf), "%dC", o->audio_channels[o->nb_audio_channels - 1].u.i);
+            av_dict_set(&o->g->format_opts, "ch_layout", buf, 0);
+        }
+    }
+    if (o->nb_audio_ch_layouts) {
+        const AVClass *priv_class;
+        if (file_iformat && (priv_class = file_iformat->priv_class) &&
+            av_opt_find(&priv_class, "ch_layout", NULL, 0,
+                        AV_OPT_SEARCH_FAKE_OBJ)) {
+            av_dict_set(&o->g->format_opts, "ch_layout", o->audio_ch_layouts[o->nb_audio_ch_layouts - 1].u.str, 0);
+        }
+    }
+    if (o->nb_frame_rates) {
+        const AVClass *priv_class;
+        /* set the format-level framerate option;
+         * this is important for video grabbers, e.g. x11 */
+        if (file_iformat && (priv_class = file_iformat->priv_class) &&
+            av_opt_find(&priv_class, "framerate", NULL, 0,
+                        AV_OPT_SEARCH_FAKE_OBJ)) {
+            av_dict_set(&o->g->format_opts, "framerate",
+                        o->frame_rates[o->nb_frame_rates - 1].u.str, 0);
+        }
+    }
+    if (o->nb_frame_sizes) {
+        av_dict_set(&o->g->format_opts, "video_size", o->frame_sizes[o->nb_frame_sizes - 1].u.str, 0);
+    }
+    if (o->nb_frame_pix_fmts)
+        av_dict_set(&o->g->format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0);
+
+    MATCH_PER_TYPE_OPT(codec_names, str,    video_codec_name, ic, "v");
+    MATCH_PER_TYPE_OPT(codec_names, str,    audio_codec_name, ic, "a");
+    MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, ic, "s");
+    MATCH_PER_TYPE_OPT(codec_names, str,     data_codec_name, ic, "d");
+
+    if (video_codec_name)
+        ic->video_codec    = find_codec_or_die(video_codec_name   , AVMEDIA_TYPE_VIDEO   , 0);
+    if (audio_codec_name)
+        ic->audio_codec    = find_codec_or_die(audio_codec_name   , AVMEDIA_TYPE_AUDIO   , 0);
+    if (subtitle_codec_name)
+        ic->subtitle_codec = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0);
+    if (data_codec_name)
+        ic->data_codec     = find_codec_or_die(data_codec_name    , AVMEDIA_TYPE_DATA    , 0);
+
+    ic->video_codec_id     = video_codec_name    ? ic->video_codec->id    : AV_CODEC_ID_NONE;
+    ic->audio_codec_id     = audio_codec_name    ? ic->audio_codec->id    : AV_CODEC_ID_NONE;
+    ic->subtitle_codec_id  = subtitle_codec_name ? ic->subtitle_codec->id : AV_CODEC_ID_NONE;
+    ic->data_codec_id      = data_codec_name     ? ic->data_codec->id     : AV_CODEC_ID_NONE;
+
+    ic->flags |= AVFMT_FLAG_NONBLOCK;
+    if (o->bitexact)
+        ic->flags |= AVFMT_FLAG_BITEXACT;
+    ic->interrupt_callback = int_cb;
+
+    if (!av_dict_get(o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
+        av_dict_set(&o->g->format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
+        scan_all_pmts_set = 1;
+    }
+    /* open the input file with generic avformat function */
+    err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts);
+    if (err < 0) {
+        print_error(filename, err);
+        if (err == AVERROR_PROTOCOL_NOT_FOUND)
+            av_log(NULL, AV_LOG_ERROR, "Did you mean file:%s?\n", filename);
+        exit_program(1);
+    }
+    if (scan_all_pmts_set)
+        av_dict_set(&o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
+    remove_avoptions(&o->g->format_opts, o->g->codec_opts);
+    assert_avoptions(o->g->format_opts);
+
+    /* apply forced codec ids */
+    for (i = 0; i < ic->nb_streams; i++)
+        choose_decoder(o, ic, ic->streams[i], HWACCEL_NONE, AV_HWDEVICE_TYPE_NONE);
+
+    if (o->find_stream_info) {
+        AVDictionary **opts = setup_find_stream_info_opts(ic, o->g->codec_opts);
+        int orig_nb_streams = ic->nb_streams;
+
+        /* If not enough info to get the stream parameters, we decode the
+           first frames to get it. (used in mpeg case for example) */
+        ret = avformat_find_stream_info(ic, opts);
+
+        for (i = 0; i < orig_nb_streams; i++)
+            av_dict_free(&opts[i]);
+        av_freep(&opts);
+
+        if (ret < 0) {
+            av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename);
+            if (ic->nb_streams == 0) {
+                avformat_close_input(&ic);
+                exit_program(1);
+            }
+        }
+    }
+
+    if (o->start_time != AV_NOPTS_VALUE && o->start_time_eof != AV_NOPTS_VALUE) {
+        av_log(NULL, AV_LOG_WARNING, "Cannot use -ss and -sseof both, using -ss for %s\n", filename);
+        o->start_time_eof = AV_NOPTS_VALUE;
+    }
+
+    if (o->start_time_eof != AV_NOPTS_VALUE) {
+        if (o->start_time_eof >= 0) {
+            av_log(NULL, AV_LOG_ERROR, "-sseof value must be negative; aborting\n");
+            exit_program(1);
+        }
+        if (ic->duration > 0) {
+            o->start_time = o->start_time_eof + ic->duration;
+            if (o->start_time < 0) {
+                av_log(NULL, AV_LOG_WARNING, "-sseof value seeks to before start of file %s; ignored\n", filename);
+                o->start_time = AV_NOPTS_VALUE;
+            }
+        } else
+            av_log(NULL, AV_LOG_WARNING, "Cannot use -sseof, duration of %s not known\n", filename);
+    }
+    timestamp = (o->start_time == AV_NOPTS_VALUE) ? 0 : o->start_time;
+    /* add the stream start time */
+    if (!o->seek_timestamp && ic->start_time != AV_NOPTS_VALUE)
+        timestamp += ic->start_time;
+
+    /* if seeking requested, we execute it */
+    if (o->start_time != AV_NOPTS_VALUE) {
+        int64_t seek_timestamp = timestamp;
+
+        if (!(ic->iformat->flags & AVFMT_SEEK_TO_PTS)) {
+            int dts_heuristic = 0;
+            for (i=0; i<ic->nb_streams; i++) {
+                const AVCodecParameters *par = ic->streams[i]->codecpar;
+                if (par->video_delay) {
+                    dts_heuristic = 1;
+                    break;
+                }
+            }
+            if (dts_heuristic) {
+                seek_timestamp -= 3*AV_TIME_BASE / 23;
+            }
+        }
+        ret = avformat_seek_file(ic, -1, INT64_MIN, seek_timestamp, seek_timestamp, 0);
+        if (ret < 0) {
+            av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
+                   filename, (double)timestamp / AV_TIME_BASE);
+        }
+    }
+
+    /* update the current parameters so that they match the one of the input stream */
+    add_input_streams(o, ic);
+
+    /* dump the file content */
+    av_dump_format(ic, nb_input_files, filename, 0);
+
+    f = ALLOC_ARRAY_ELEM(input_files, nb_input_files);
+
+    f->ctx        = ic;
+    f->index      = nb_input_files - 1;
+    f->ist_index  = nb_input_streams - ic->nb_streams;
+    f->start_time = o->start_time;
+    f->recording_time = o->recording_time;
+    f->input_sync_ref = o->input_sync_ref;
+    f->input_ts_offset = o->input_ts_offset;
+    f->ts_offset  = o->input_ts_offset - (copy_ts ? (start_at_zero && ic->start_time != AV_NOPTS_VALUE ? ic->start_time : 0) : timestamp);
+    f->nb_streams = ic->nb_streams;
+    f->rate_emu   = o->rate_emu;
+    f->accurate_seek = o->accurate_seek;
+    f->loop = o->loop;
+    f->duration = 0;
+    f->time_base = (AVRational){ 1, 1 };
+
+    f->readrate = o->readrate ? o->readrate : 0.0;
+    if (f->readrate < 0.0f) {
+        av_log(NULL, AV_LOG_ERROR, "Option -readrate for Input #%d is %0.3f; it must be non-negative.\n", f->index, f->readrate);
+        exit_program(1);
+    }
+    if (f->readrate && f->rate_emu) {
+        av_log(NULL, AV_LOG_WARNING, "Both -readrate and -re set for Input #%d. Using -readrate %0.3f.\n", f->index, f->readrate);
+        f->rate_emu = 0;
+    }
+
+    f->thread_queue_size = o->thread_queue_size;
+
+    /* check if all codec options have been used */
+    unused_opts = strip_specifiers(o->g->codec_opts);
+    for (i = f->ist_index; i < nb_input_streams; i++) {
+        e = NULL;
+        while ((e = av_dict_get(input_streams[i]->decoder_opts, "", e,
+                                AV_DICT_IGNORE_SUFFIX)))
+            av_dict_set(&unused_opts, e->key, NULL, 0);
+    }
+
+    e = NULL;
+    while ((e = av_dict_get(unused_opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
+        const AVClass *class = avcodec_get_class();
+        const AVOption *option = av_opt_find(&class, e->key, NULL, 0,
+                                             AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
+        const AVClass *fclass = avformat_get_class();
+        const AVOption *foption = av_opt_find(&fclass, e->key, NULL, 0,
+                                             AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
+        if (!option || foption)
+            continue;
+
+
+        if (!(option->flags & AV_OPT_FLAG_DECODING_PARAM)) {
+            av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for "
+                   "input file #%d (%s) is not a decoding option.\n", e->key,
+                   option->help ? option->help : "", f->index,
+                   filename);
+            exit_program(1);
+        }
+
+        av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for "
+               "input file #%d (%s) has not been used for any stream. The most "
+               "likely reason is either wrong type (e.g. a video option with "
+               "no video streams) or that it is a private option of some decoder "
+               "which was not actually used for any stream.\n", e->key,
+               option->help ? option->help : "", f->index, filename);
+    }
+    av_dict_free(&unused_opts);
+
+    for (i = 0; i < o->nb_dump_attachment; i++) {
+        int j;
+
+        for (j = 0; j < ic->nb_streams; j++) {
+            AVStream *st = ic->streams[j];
+
+            if (check_stream_specifier(ic, st, o->dump_attachment[i].specifier) == 1)
+                dump_attachment(st, o->dump_attachment[i].u.str);
+        }
+    }
+
+    input_stream_potentially_available = 1;
+
+    return 0;
+}
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 7fdbf08a18..38916304bc 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -54,18 +54,8 @@
 
 const char *const opt_name_codec_names[]                      = {"c", "codec", "acodec", "vcodec", "scodec", "dcodec", NULL};
 const char *const opt_name_frame_rates[]                      = {"r", NULL};
-static const char *const opt_name_ts_scale[]                  = {"itsscale", NULL};
-static const char *const opt_name_hwaccels[]                  = {"hwaccel", NULL};
-static const char *const opt_name_hwaccel_devices[]           = {"hwaccel_device", NULL};
-static const char *const opt_name_hwaccel_output_formats[]    = {"hwaccel_output_format", NULL};
-static const char *const opt_name_autorotate[]                = {"autorotate", NULL};
 const char *const opt_name_codec_tags[]                       = {"tag", "atag", "vtag", "stag", NULL};
 const char *const opt_name_top_field_first[]                  = {"top", NULL};
-static const char *const opt_name_reinit_filters[]            = {"reinit_filter", NULL};
-static const char *const opt_name_fix_sub_duration[]          = {"fix_sub_duration", NULL};
-static const char *const opt_name_canvas_sizes[]              = {"canvas_size", NULL};
-static const char *const opt_name_guess_layout_max[]          = {"guess_layout_max", NULL};
-static const char *const opt_name_discard[]                   = {"discard", NULL};
 
 HWDevice *filter_hw_device;
 
@@ -107,7 +97,7 @@ int do_psnr            = 0;
 int input_stream_potentially_available = 0;
 int ignore_unknown_streams = 0;
 int copy_unknown_streams = 0;
-static int recast_media = 0;
+int recast_media = 0;
 
 static void uninit_options(OptionsContext *o)
 {
@@ -624,278 +614,6 @@ const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int en
     return codec;
 }
 
-static const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *st,
-                                     enum HWAccelID hwaccel_id, enum AVHWDeviceType hwaccel_device_type)
-
-{
-    char *codec_name = NULL;
-
-    MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st);
-    if (codec_name) {
-        const AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0);
-        st->codecpar->codec_id = codec->id;
-        if (recast_media && st->codecpar->codec_type != codec->type)
-            st->codecpar->codec_type = codec->type;
-        return codec;
-    } else {
-        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
-            hwaccel_id == HWACCEL_GENERIC &&
-            hwaccel_device_type != AV_HWDEVICE_TYPE_NONE) {
-            const AVCodec *c;
-            void *i = NULL;
-
-            while ((c = av_codec_iterate(&i))) {
-                const AVCodecHWConfig *config;
-
-                if (c->id != st->codecpar->codec_id ||
-                    !av_codec_is_decoder(c))
-                    continue;
-
-                for (int j = 0; config = avcodec_get_hw_config(c, j); j++) {
-                    if (config->device_type == hwaccel_device_type) {
-                        av_log(NULL, AV_LOG_VERBOSE, "Selecting decoder '%s' because of requested hwaccel method %s\n",
-                               c->name, av_hwdevice_get_type_name(hwaccel_device_type));
-                        return c;
-                    }
-                }
-            }
-        }
-
-        return avcodec_find_decoder(st->codecpar->codec_id);
-    }
-}
-
-static int guess_input_channel_layout(InputStream *ist)
-{
-    AVCodecContext *dec = ist->dec_ctx;
-
-    if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
-        char layout_name[256];
-
-        if (dec->ch_layout.nb_channels > ist->guess_layout_max)
-            return 0;
-        av_channel_layout_default(&dec->ch_layout, dec->ch_layout.nb_channels);
-        if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
-            return 0;
-        av_channel_layout_describe(&dec->ch_layout, layout_name, sizeof(layout_name));
-        av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream "
-               "#%d.%d : %s\n", ist->file_index, ist->st->index, layout_name);
-    }
-    return 1;
-}
-
-/* Add all the streams from the given input file to the global
- * list of input streams. */
-static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
-{
-    int i, ret;
-
-    for (i = 0; i < ic->nb_streams; i++) {
-        AVStream *st = ic->streams[i];
-        AVCodecParameters *par = st->codecpar;
-        InputStream *ist;
-        char *framerate = NULL, *hwaccel_device = NULL;
-        const char *hwaccel = NULL;
-        char *hwaccel_output_format = NULL;
-        char *codec_tag = NULL;
-        char *next;
-        char *discard_str = NULL;
-        const AVClass *cc = avcodec_get_class();
-        const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL,
-                                                  0, AV_OPT_SEARCH_FAKE_OBJ);
-
-        ist = ALLOC_ARRAY_ELEM(input_streams, nb_input_streams);
-        ist->st = st;
-        ist->file_index = nb_input_files;
-        ist->discard = 1;
-        st->discard  = AVDISCARD_ALL;
-        ist->nb_samples = 0;
-        ist->first_dts = AV_NOPTS_VALUE;
-        ist->min_pts = INT64_MAX;
-        ist->max_pts = INT64_MIN;
-
-        ist->ts_scale = 1.0;
-        MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
-
-        ist->autorotate = 1;
-        MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st);
-
-        MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
-        if (codec_tag) {
-            uint32_t tag = strtol(codec_tag, &next, 0);
-            if (*next)
-                tag = AV_RL32(codec_tag);
-            st->codecpar->codec_tag = tag;
-        }
-
-        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
-            MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st);
-            MATCH_PER_STREAM_OPT(hwaccel_output_formats, str,
-                                 hwaccel_output_format, ic, st);
-
-            if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "cuvid")) {
-                av_log(NULL, AV_LOG_WARNING,
-                    "WARNING: defaulting hwaccel_output_format to cuda for compatibility "
-                    "with old commandlines. This behaviour is DEPRECATED and will be removed "
-                    "in the future. Please explicitly set \"-hwaccel_output_format cuda\".\n");
-                ist->hwaccel_output_format = AV_PIX_FMT_CUDA;
-            } else if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "qsv")) {
-                av_log(NULL, AV_LOG_WARNING,
-                    "WARNING: defaulting hwaccel_output_format to qsv for compatibility "
-                    "with old commandlines. This behaviour is DEPRECATED and will be removed "
-                    "in the future. Please explicitly set \"-hwaccel_output_format qsv\".\n");
-                ist->hwaccel_output_format = AV_PIX_FMT_QSV;
-            } else if (hwaccel_output_format) {
-                ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format);
-                if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) {
-                    av_log(NULL, AV_LOG_FATAL, "Unrecognised hwaccel output "
-                           "format: %s", hwaccel_output_format);
-                }
-            } else {
-                ist->hwaccel_output_format = AV_PIX_FMT_NONE;
-            }
-
-            if (hwaccel) {
-                // The NVDEC hwaccels use a CUDA device, so remap the name here.
-                if (!strcmp(hwaccel, "nvdec") || !strcmp(hwaccel, "cuvid"))
-                    hwaccel = "cuda";
-
-                if (!strcmp(hwaccel, "none"))
-                    ist->hwaccel_id = HWACCEL_NONE;
-                else if (!strcmp(hwaccel, "auto"))
-                    ist->hwaccel_id = HWACCEL_AUTO;
-                else {
-                    enum AVHWDeviceType type = av_hwdevice_find_type_by_name(hwaccel);
-                    if (type != AV_HWDEVICE_TYPE_NONE) {
-                        ist->hwaccel_id = HWACCEL_GENERIC;
-                        ist->hwaccel_device_type = type;
-                    }
-
-                    if (!ist->hwaccel_id) {
-                        av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n",
-                               hwaccel);
-                        av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: ");
-                        type = AV_HWDEVICE_TYPE_NONE;
-                        while ((type = av_hwdevice_iterate_types(type)) !=
-                               AV_HWDEVICE_TYPE_NONE)
-                            av_log(NULL, AV_LOG_FATAL, "%s ",
-                                   av_hwdevice_get_type_name(type));
-                        av_log(NULL, AV_LOG_FATAL, "\n");
-                        exit_program(1);
-                    }
-                }
-            }
-
-            MATCH_PER_STREAM_OPT(hwaccel_devices, str, hwaccel_device, ic, st);
-            if (hwaccel_device) {
-                ist->hwaccel_device = av_strdup(hwaccel_device);
-                if (!ist->hwaccel_device)
-                    report_and_exit(AVERROR(ENOMEM));
-            }
-
-            ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE;
-        }
-
-        ist->dec = choose_decoder(o, ic, st, ist->hwaccel_id, ist->hwaccel_device_type);
-        ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codecpar->codec_id, ic, st, ist->dec);
-
-        ist->reinit_filters = -1;
-        MATCH_PER_STREAM_OPT(reinit_filters, i, ist->reinit_filters, ic, st);
-
-        MATCH_PER_STREAM_OPT(discard, str, discard_str, ic, st);
-        ist->user_set_discard = AVDISCARD_NONE;
-
-        if ((o->video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ||
-            (o->audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ||
-            (o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) ||
-            (o->data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA))
-                ist->user_set_discard = AVDISCARD_ALL;
-
-        if (discard_str && av_opt_eval_int(&cc, discard_opt, discard_str, &ist->user_set_discard) < 0) {
-            av_log(NULL, AV_LOG_ERROR, "Error parsing discard %s.\n",
-                    discard_str);
-            exit_program(1);
-        }
-
-        ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE;
-        ist->prev_pkt_pts = AV_NOPTS_VALUE;
-
-        ist->dec_ctx = avcodec_alloc_context3(ist->dec);
-        if (!ist->dec_ctx)
-            report_and_exit(AVERROR(ENOMEM));
-
-        ret = avcodec_parameters_to_context(ist->dec_ctx, par);
-        if (ret < 0) {
-            av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n");
-            exit_program(1);
-        }
-
-        ist->decoded_frame = av_frame_alloc();
-        if (!ist->decoded_frame)
-            report_and_exit(AVERROR(ENOMEM));
-
-        ist->pkt = av_packet_alloc();
-        if (!ist->pkt)
-            report_and_exit(AVERROR(ENOMEM));
-
-        if (o->bitexact)
-            ist->dec_ctx->flags |= AV_CODEC_FLAG_BITEXACT;
-
-        switch (par->codec_type) {
-        case AVMEDIA_TYPE_VIDEO:
-            // avformat_find_stream_info() doesn't set this for us anymore.
-            ist->dec_ctx->framerate = st->avg_frame_rate;
-
-            MATCH_PER_STREAM_OPT(frame_rates, str, framerate, ic, st);
-            if (framerate && av_parse_video_rate(&ist->framerate,
-                                                 framerate) < 0) {
-                av_log(NULL, AV_LOG_ERROR, "Error parsing framerate %s.\n",
-                       framerate);
-                exit_program(1);
-            }
-
-            ist->top_field_first = -1;
-            MATCH_PER_STREAM_OPT(top_field_first, i, ist->top_field_first, ic, st);
-
-            ist->framerate_guessed = av_guess_frame_rate(ic, st, NULL);
-
-            break;
-        case AVMEDIA_TYPE_AUDIO:
-            ist->guess_layout_max = INT_MAX;
-            MATCH_PER_STREAM_OPT(guess_layout_max, i, ist->guess_layout_max, ic, st);
-            guess_input_channel_layout(ist);
-            break;
-        case AVMEDIA_TYPE_DATA:
-        case AVMEDIA_TYPE_SUBTITLE: {
-            char *canvas_size = NULL;
-            MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st);
-            MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st);
-            if (canvas_size &&
-                av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height, canvas_size) < 0) {
-                av_log(NULL, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size);
-                exit_program(1);
-            }
-            break;
-        }
-        case AVMEDIA_TYPE_ATTACHMENT:
-        case AVMEDIA_TYPE_UNKNOWN:
-            break;
-        default:
-            abort();
-        }
-
-        ist->par = avcodec_parameters_alloc();
-        if (!ist->par)
-            report_and_exit(AVERROR(ENOMEM));
-
-        ret = avcodec_parameters_from_context(ist->par, ist->dec_ctx);
-        if (ret < 0) {
-            av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n");
-            exit_program(1);
-        }
-    }
-}
-
 void assert_file_overwrite(const char *filename)
 {
     const char *proto_name = avio_find_protocol_name(filename);
@@ -939,326 +657,6 @@ void assert_file_overwrite(const char *filename)
     }
 }
 
-static void dump_attachment(AVStream *st, const char *filename)
-{
-    int ret;
-    AVIOContext *out = NULL;
-    const AVDictionaryEntry *e;
-
-    if (!st->codecpar->extradata_size) {
-        av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n",
-               nb_input_files - 1, st->index);
-        return;
-    }
-    if (!*filename && (e = av_dict_get(st->metadata, "filename", NULL, 0)))
-        filename = e->value;
-    if (!*filename) {
-        av_log(NULL, AV_LOG_FATAL, "No filename specified and no 'filename' tag"
-               "in stream #%d:%d.\n", nb_input_files - 1, st->index);
-        exit_program(1);
-    }
-
-    assert_file_overwrite(filename);
-
-    if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &int_cb, NULL)) < 0) {
-        av_log(NULL, AV_LOG_FATAL, "Could not open file %s for writing.\n",
-               filename);
-        exit_program(1);
-    }
-
-    avio_write(out, st->codecpar->extradata, st->codecpar->extradata_size);
-    avio_flush(out);
-    avio_close(out);
-}
-
-static int open_input_file(OptionsContext *o, const char *filename)
-{
-    InputFile *f;
-    AVFormatContext *ic;
-    const AVInputFormat *file_iformat = NULL;
-    int err, i, ret;
-    int64_t timestamp;
-    AVDictionary *unused_opts = NULL;
-    const AVDictionaryEntry *e = NULL;
-    char *   video_codec_name = NULL;
-    char *   audio_codec_name = NULL;
-    char *subtitle_codec_name = NULL;
-    char *    data_codec_name = NULL;
-    int scan_all_pmts_set = 0;
-
-    if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) {
-        o->stop_time = INT64_MAX;
-        av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
-    }
-
-    if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) {
-        int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time;
-        if (o->stop_time <= start_time) {
-            av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n");
-            exit_program(1);
-        } else {
-            o->recording_time = o->stop_time - start_time;
-        }
-    }
-
-    if (o->format) {
-        if (!(file_iformat = av_find_input_format(o->format))) {
-            av_log(NULL, AV_LOG_FATAL, "Unknown input format: '%s'\n", o->format);
-            exit_program(1);
-        }
-    }
-
-    if (!strcmp(filename, "-"))
-        filename = "pipe:";
-
-    stdin_interaction &= strncmp(filename, "pipe:", 5) &&
-                         strcmp(filename, "/dev/stdin");
-
-    /* get default parameters from command line */
-    ic = avformat_alloc_context();
-    if (!ic)
-        report_and_exit(AVERROR(ENOMEM));
-    if (o->nb_audio_sample_rate) {
-        av_dict_set_int(&o->g->format_opts, "sample_rate", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i, 0);
-    }
-    if (o->nb_audio_channels) {
-        const AVClass *priv_class;
-        if (file_iformat && (priv_class = file_iformat->priv_class) &&
-            av_opt_find(&priv_class, "ch_layout", NULL, 0,
-                        AV_OPT_SEARCH_FAKE_OBJ)) {
-            char buf[32];
-            snprintf(buf, sizeof(buf), "%dC", o->audio_channels[o->nb_audio_channels - 1].u.i);
-            av_dict_set(&o->g->format_opts, "ch_layout", buf, 0);
-        }
-    }
-    if (o->nb_audio_ch_layouts) {
-        const AVClass *priv_class;
-        if (file_iformat && (priv_class = file_iformat->priv_class) &&
-            av_opt_find(&priv_class, "ch_layout", NULL, 0,
-                        AV_OPT_SEARCH_FAKE_OBJ)) {
-            av_dict_set(&o->g->format_opts, "ch_layout", o->audio_ch_layouts[o->nb_audio_ch_layouts - 1].u.str, 0);
-        }
-    }
-    if (o->nb_frame_rates) {
-        const AVClass *priv_class;
-        /* set the format-level framerate option;
-         * this is important for video grabbers, e.g. x11 */
-        if (file_iformat && (priv_class = file_iformat->priv_class) &&
-            av_opt_find(&priv_class, "framerate", NULL, 0,
-                        AV_OPT_SEARCH_FAKE_OBJ)) {
-            av_dict_set(&o->g->format_opts, "framerate",
-                        o->frame_rates[o->nb_frame_rates - 1].u.str, 0);
-        }
-    }
-    if (o->nb_frame_sizes) {
-        av_dict_set(&o->g->format_opts, "video_size", o->frame_sizes[o->nb_frame_sizes - 1].u.str, 0);
-    }
-    if (o->nb_frame_pix_fmts)
-        av_dict_set(&o->g->format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0);
-
-    MATCH_PER_TYPE_OPT(codec_names, str,    video_codec_name, ic, "v");
-    MATCH_PER_TYPE_OPT(codec_names, str,    audio_codec_name, ic, "a");
-    MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, ic, "s");
-    MATCH_PER_TYPE_OPT(codec_names, str,     data_codec_name, ic, "d");
-
-    if (video_codec_name)
-        ic->video_codec    = find_codec_or_die(video_codec_name   , AVMEDIA_TYPE_VIDEO   , 0);
-    if (audio_codec_name)
-        ic->audio_codec    = find_codec_or_die(audio_codec_name   , AVMEDIA_TYPE_AUDIO   , 0);
-    if (subtitle_codec_name)
-        ic->subtitle_codec = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0);
-    if (data_codec_name)
-        ic->data_codec     = find_codec_or_die(data_codec_name    , AVMEDIA_TYPE_DATA    , 0);
-
-    ic->video_codec_id     = video_codec_name    ? ic->video_codec->id    : AV_CODEC_ID_NONE;
-    ic->audio_codec_id     = audio_codec_name    ? ic->audio_codec->id    : AV_CODEC_ID_NONE;
-    ic->subtitle_codec_id  = subtitle_codec_name ? ic->subtitle_codec->id : AV_CODEC_ID_NONE;
-    ic->data_codec_id      = data_codec_name     ? ic->data_codec->id     : AV_CODEC_ID_NONE;
-
-    ic->flags |= AVFMT_FLAG_NONBLOCK;
-    if (o->bitexact)
-        ic->flags |= AVFMT_FLAG_BITEXACT;
-    ic->interrupt_callback = int_cb;
-
-    if (!av_dict_get(o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
-        av_dict_set(&o->g->format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
-        scan_all_pmts_set = 1;
-    }
-    /* open the input file with generic avformat function */
-    err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts);
-    if (err < 0) {
-        print_error(filename, err);
-        if (err == AVERROR_PROTOCOL_NOT_FOUND)
-            av_log(NULL, AV_LOG_ERROR, "Did you mean file:%s?\n", filename);
-        exit_program(1);
-    }
-    if (scan_all_pmts_set)
-        av_dict_set(&o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
-    remove_avoptions(&o->g->format_opts, o->g->codec_opts);
-    assert_avoptions(o->g->format_opts);
-
-    /* apply forced codec ids */
-    for (i = 0; i < ic->nb_streams; i++)
-        choose_decoder(o, ic, ic->streams[i], HWACCEL_NONE, AV_HWDEVICE_TYPE_NONE);
-
-    if (o->find_stream_info) {
-        AVDictionary **opts = setup_find_stream_info_opts(ic, o->g->codec_opts);
-        int orig_nb_streams = ic->nb_streams;
-
-        /* If not enough info to get the stream parameters, we decode the
-           first frames to get it. (used in mpeg case for example) */
-        ret = avformat_find_stream_info(ic, opts);
-
-        for (i = 0; i < orig_nb_streams; i++)
-            av_dict_free(&opts[i]);
-        av_freep(&opts);
-
-        if (ret < 0) {
-            av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename);
-            if (ic->nb_streams == 0) {
-                avformat_close_input(&ic);
-                exit_program(1);
-            }
-        }
-    }
-
-    if (o->start_time != AV_NOPTS_VALUE && o->start_time_eof != AV_NOPTS_VALUE) {
-        av_log(NULL, AV_LOG_WARNING, "Cannot use -ss and -sseof both, using -ss for %s\n", filename);
-        o->start_time_eof = AV_NOPTS_VALUE;
-    }
-
-    if (o->start_time_eof != AV_NOPTS_VALUE) {
-        if (o->start_time_eof >= 0) {
-            av_log(NULL, AV_LOG_ERROR, "-sseof value must be negative; aborting\n");
-            exit_program(1);
-        }
-        if (ic->duration > 0) {
-            o->start_time = o->start_time_eof + ic->duration;
-            if (o->start_time < 0) {
-                av_log(NULL, AV_LOG_WARNING, "-sseof value seeks to before start of file %s; ignored\n", filename);
-                o->start_time = AV_NOPTS_VALUE;
-            }
-        } else
-            av_log(NULL, AV_LOG_WARNING, "Cannot use -sseof, duration of %s not known\n", filename);
-    }
-    timestamp = (o->start_time == AV_NOPTS_VALUE) ? 0 : o->start_time;
-    /* add the stream start time */
-    if (!o->seek_timestamp && ic->start_time != AV_NOPTS_VALUE)
-        timestamp += ic->start_time;
-
-    /* if seeking requested, we execute it */
-    if (o->start_time != AV_NOPTS_VALUE) {
-        int64_t seek_timestamp = timestamp;
-
-        if (!(ic->iformat->flags & AVFMT_SEEK_TO_PTS)) {
-            int dts_heuristic = 0;
-            for (i=0; i<ic->nb_streams; i++) {
-                const AVCodecParameters *par = ic->streams[i]->codecpar;
-                if (par->video_delay) {
-                    dts_heuristic = 1;
-                    break;
-                }
-            }
-            if (dts_heuristic) {
-                seek_timestamp -= 3*AV_TIME_BASE / 23;
-            }
-        }
-        ret = avformat_seek_file(ic, -1, INT64_MIN, seek_timestamp, seek_timestamp, 0);
-        if (ret < 0) {
-            av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
-                   filename, (double)timestamp / AV_TIME_BASE);
-        }
-    }
-
-    /* update the current parameters so that they match the one of the input stream */
-    add_input_streams(o, ic);
-
-    /* dump the file content */
-    av_dump_format(ic, nb_input_files, filename, 0);
-
-    f = ALLOC_ARRAY_ELEM(input_files, nb_input_files);
-
-    f->ctx        = ic;
-    f->index      = nb_input_files - 1;
-    f->ist_index  = nb_input_streams - ic->nb_streams;
-    f->start_time = o->start_time;
-    f->recording_time = o->recording_time;
-    f->input_sync_ref = o->input_sync_ref;
-    f->input_ts_offset = o->input_ts_offset;
-    f->ts_offset  = o->input_ts_offset - (copy_ts ? (start_at_zero && ic->start_time != AV_NOPTS_VALUE ? ic->start_time : 0) : timestamp);
-    f->nb_streams = ic->nb_streams;
-    f->rate_emu   = o->rate_emu;
-    f->accurate_seek = o->accurate_seek;
-    f->loop = o->loop;
-    f->duration = 0;
-    f->time_base = (AVRational){ 1, 1 };
-
-    f->readrate = o->readrate ? o->readrate : 0.0;
-    if (f->readrate < 0.0f) {
-        av_log(NULL, AV_LOG_ERROR, "Option -readrate for Input #%d is %0.3f; it must be non-negative.\n", f->index, f->readrate);
-        exit_program(1);
-    }
-    if (f->readrate && f->rate_emu) {
-        av_log(NULL, AV_LOG_WARNING, "Both -readrate and -re set for Input #%d. Using -readrate %0.3f.\n", f->index, f->readrate);
-        f->rate_emu = 0;
-    }
-
-    f->thread_queue_size = o->thread_queue_size;
-
-    /* check if all codec options have been used */
-    unused_opts = strip_specifiers(o->g->codec_opts);
-    for (i = f->ist_index; i < nb_input_streams; i++) {
-        e = NULL;
-        while ((e = av_dict_get(input_streams[i]->decoder_opts, "", e,
-                                AV_DICT_IGNORE_SUFFIX)))
-            av_dict_set(&unused_opts, e->key, NULL, 0);
-    }
-
-    e = NULL;
-    while ((e = av_dict_get(unused_opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
-        const AVClass *class = avcodec_get_class();
-        const AVOption *option = av_opt_find(&class, e->key, NULL, 0,
-                                             AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
-        const AVClass *fclass = avformat_get_class();
-        const AVOption *foption = av_opt_find(&fclass, e->key, NULL, 0,
-                                             AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
-        if (!option || foption)
-            continue;
-
-
-        if (!(option->flags & AV_OPT_FLAG_DECODING_PARAM)) {
-            av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for "
-                   "input file #%d (%s) is not a decoding option.\n", e->key,
-                   option->help ? option->help : "", f->index,
-                   filename);
-            exit_program(1);
-        }
-
-        av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for "
-               "input file #%d (%s) has not been used for any stream. The most "
-               "likely reason is either wrong type (e.g. a video option with "
-               "no video streams) or that it is a private option of some decoder "
-               "which was not actually used for any stream.\n", e->key,
-               option->help ? option->help : "", f->index, filename);
-    }
-    av_dict_free(&unused_opts);
-
-    for (i = 0; i < o->nb_dump_attachment; i++) {
-        int j;
-
-        for (j = 0; j < ic->nb_streams; j++) {
-            AVStream *st = ic->streams[j];
-
-            if (check_stream_specifier(ic, st, o->dump_attachment[i].specifier) == 1)
-                dump_attachment(st, o->dump_attachment[i].u.str);
-        }
-    }
-
-    input_stream_potentially_available = 1;
-
-    return 0;
-}
-
 /* read file contents into a string */
 char *read_file(const char *filename)
 {
@@ -1847,7 +1245,7 @@ int ffmpeg_parse_options(int argc, char **argv)
     term_init();
 
     /* open input files */
-    ret = open_files(&octx.groups[GROUP_INFILE], "input", open_input_file);
+    ret = open_files(&octx.groups[GROUP_INFILE], "input", ifile_open);
     if (ret < 0) {
         av_log(NULL, AV_LOG_FATAL, "Error opening input files: ");
         goto fail;
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 02/20] fftools/ffmpeg_demux: add demuxer private data
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 03/20] fftools/ffmpeg: drop init_input_threads() Anton Khirnov
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

Move InputFile.loop into it.
---
 fftools/ffmpeg.h       |  1 -
 fftools/ffmpeg_demux.c | 37 +++++++++++++++++++++++++++----------
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 085a775a43..35410ec4a1 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -434,7 +434,6 @@ typedef struct InputFile {
     int eof_reached;      /* true if eof reached */
     int eagain;           /* true if last read attempt returned EAGAIN */
     int ist_index;        /* index of first stream in input_streams */
-    int loop;             /* set number of times input stream should be looped */
     int64_t duration;     /* actual duration of the longest stream in a file
                              at the moment when looping happens */
     AVRational time_base; /* time base of the duration */
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index d2b0bc9a6d..f92500abf9 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -45,6 +45,13 @@ static const char *const opt_name_hwaccel_devices[]           = {"hwaccel_device
 static const char *const opt_name_hwaccel_output_formats[]    = {"hwaccel_output_format", NULL};
 static const char *const opt_name_autorotate[]                = {"autorotate", NULL};
 
+typedef struct Demuxer {
+    InputFile f;
+
+    /* number of times input stream should be looped */
+    int loop;
+} Demuxer;
+
 typedef struct DemuxMsg {
     AVPacket *pkt;
     int looping;
@@ -53,6 +60,11 @@ typedef struct DemuxMsg {
     int repeat_pict;
 } DemuxMsg;
 
+static Demuxer *demuxer_from_ifile(InputFile *f)
+{
+    return (Demuxer*)f;
+}
+
 static void report_new_stream(InputFile *file, const AVPacket *pkt)
 {
     AVStream *st = file->ctx->streams[pkt->stream_index];
@@ -84,8 +96,9 @@ static void ifile_duration_update(InputFile *f, InputStream *ist,
     }
 }
 
-static int seek_to_start(InputFile *ifile)
+static int seek_to_start(Demuxer *d)
 {
+    InputFile    *ifile = &d->f;
     AVFormatContext *is = ifile->ctx;
     InputStream *ist;
     int ret;
@@ -127,8 +140,8 @@ static int seek_to_start(InputFile *ifile)
         }
     }
 
-    if (ifile->loop > 0)
-        ifile->loop--;
+    if (d->loop > 0)
+        d->loop--;
 
     return ret;
 }
@@ -195,7 +208,8 @@ static void ts_fixup(InputFile *ifile, AVPacket *pkt, int *repeat_pict)
 
 static void *input_thread(void *arg)
 {
-    InputFile *f = arg;
+    Demuxer   *d = arg;
+    InputFile *f = &d->f;
     AVPacket *pkt;
     unsigned flags = f->non_blocking ? AV_THREAD_MESSAGE_NONBLOCK : 0;
     int ret = 0;
@@ -216,12 +230,12 @@ static void *input_thread(void *arg)
             continue;
         }
         if (ret < 0) {
-            if (f->loop) {
+            if (d->loop) {
                 /* signal looping to the consumer thread */
                 msg.looping = 1;
                 ret = av_thread_message_queue_send(f->in_thread_queue, &msg, 0);
                 if (ret >= 0)
-                    ret = seek_to_start(f);
+                    ret = seek_to_start(d);
                 if (ret >= 0)
                     continue;
 
@@ -320,6 +334,7 @@ static int init_input_thread(int i)
 {
     int ret;
     InputFile *f = input_files[i];
+    Demuxer   *d = demuxer_from_ifile(f);
 
     if (f->thread_queue_size <= 0)
         f->thread_queue_size = (nb_input_files > 1 ? 8 : 1);
@@ -332,7 +347,7 @@ static int init_input_thread(int i)
     if (ret < 0)
         return ret;
 
-    if (f->loop) {
+    if (d->loop) {
         int nb_audio_dec = 0;
 
         for (int i = 0; i < f->nb_streams; i++) {
@@ -350,7 +365,7 @@ static int init_input_thread(int i)
         }
     }
 
-    if ((ret = pthread_create(&f->thread, NULL, input_thread, f))) {
+    if ((ret = pthread_create(&f->thread, NULL, input_thread, d))) {
         av_log(NULL, AV_LOG_ERROR, "pthread_create failed: %s. Try to increase `ulimit -v` or decrease `ulimit -s`.\n", strerror(ret));
         ret = AVERROR(ret);
         goto fail;
@@ -720,6 +735,7 @@ static void dump_attachment(AVStream *st, const char *filename)
 
 int ifile_open(OptionsContext *o, const char *filename)
 {
+    Demuxer   *d;
     InputFile *f;
     AVFormatContext *ic;
     const AVInputFormat *file_iformat = NULL;
@@ -923,7 +939,8 @@ int ifile_open(OptionsContext *o, const char *filename)
     /* dump the file content */
     av_dump_format(ic, nb_input_files, filename, 0);
 
-    f = ALLOC_ARRAY_ELEM(input_files, nb_input_files);
+    d = allocate_array_elem(&input_files, sizeof(*d), &nb_input_files);
+    f = &d->f;
 
     f->ctx        = ic;
     f->index      = nb_input_files - 1;
@@ -936,7 +953,7 @@ int ifile_open(OptionsContext *o, const char *filename)
     f->nb_streams = ic->nb_streams;
     f->rate_emu   = o->rate_emu;
     f->accurate_seek = o->accurate_seek;
-    f->loop = o->loop;
+    d->loop = o->loop;
     f->duration = 0;
     f->time_base = (AVRational){ 1, 1 };
 
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 03/20] fftools/ffmpeg: drop init_input_threads()
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 02/20] fftools/ffmpeg_demux: add demuxer private data Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 04/20] fftools/ffmpeg: move closing the input file into a separate function Anton Khirnov
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

Start threads implicitly when ifile_get_packet() is called. Simplifies
the demuxer API.
---
 fftools/ffmpeg.c       |  3 ---
 fftools/ffmpeg.h       |  1 -
 fftools/ffmpeg_demux.c | 24 +++++++++---------------
 3 files changed, 9 insertions(+), 19 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index ceb26145a3..aac35026bd 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -3910,9 +3910,6 @@ static int transcode(void)
 
     timer_start = av_gettime_relative();
 
-    if ((ret = init_input_threads()) < 0)
-        goto fail;
-
     while (!received_sigterm) {
         int64_t cur_time= av_gettime_relative();
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 35410ec4a1..b60f415389 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -759,7 +759,6 @@ int ifile_open(OptionsContext *o, const char *filename);
  * - a negative error code on failure
  */
 int ifile_get_packet(InputFile *f, AVPacket **pkt);
-int init_input_threads(void);
 void free_input_threads(void);
 
 #define SPECIFIER_OPT_FMT_str  "%s"
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index f92500abf9..aaa91293c3 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -330,11 +330,10 @@ void free_input_threads(void)
         free_input_thread(i);
 }
 
-static int init_input_thread(int i)
+static int thread_start(Demuxer *d)
 {
     int ret;
-    InputFile *f = input_files[i];
-    Demuxer   *d = demuxer_from_ifile(f);
+    InputFile *f = &d->f;
 
     if (f->thread_queue_size <= 0)
         f->thread_queue_size = (nb_input_files > 1 ? 8 : 1);
@@ -377,24 +376,19 @@ fail:
     return ret;
 }
 
-int init_input_threads(void)
-{
-    int i, ret;
-
-    for (i = 0; i < nb_input_files; i++) {
-        ret = init_input_thread(i);
-        if (ret < 0)
-            return ret;
-    }
-    return 0;
-}
-
 int ifile_get_packet(InputFile *f, AVPacket **pkt)
 {
+    Demuxer *d = demuxer_from_ifile(f);
     InputStream *ist;
     DemuxMsg msg;
     int ret;
 
+    if (!f->in_thread_queue) {
+        ret = thread_start(d);
+        if (ret < 0)
+            return ret;
+    }
+
     if (f->readrate || f->rate_emu) {
         int i;
         int64_t file_start = copy_ts * (
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 04/20] fftools/ffmpeg: move closing the input file into a separate function
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 02/20] fftools/ffmpeg_demux: add demuxer private data Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 03/20] fftools/ffmpeg: drop init_input_threads() Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 05/20] fftools/ffmpeg: drop free_input_threads() Anton Khirnov
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

For now this is just closing the format context and freeing InputFile,
but will contain more in the future.
---
 fftools/ffmpeg.c       |  7 +++----
 fftools/ffmpeg.h       |  1 +
 fftools/ffmpeg_demux.c | 12 ++++++++++++
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index aac35026bd..d29d2e4e88 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -556,10 +556,9 @@ static void ffmpeg_cleanup(int ret)
         of_close(&output_files[i]);
 
     free_input_threads();
-    for (i = 0; i < nb_input_files; i++) {
-        avformat_close_input(&input_files[i]->ctx);
-        av_freep(&input_files[i]);
-    }
+    for (i = 0; i < nb_input_files; i++)
+        ifile_close(&input_files[i]);
+
     for (i = 0; i < nb_input_streams; i++) {
         InputStream *ist = input_streams[i];
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index b60f415389..547660d5ef 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -747,6 +747,7 @@ AVChapter * const *
 of_get_chapters(OutputFile *of, unsigned int *nb_chapters);
 
 int ifile_open(OptionsContext *o, const char *filename);
+void ifile_close(InputFile **f);
 
 /**
  * Get next input packet from the demuxer.
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index aaa91293c3..d2db0663ab 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -423,6 +423,18 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt)
     return 0;
 }
 
+void ifile_close(InputFile **pf)
+{
+    InputFile *f = *pf;
+
+    if (!f)
+        return;
+
+    avformat_close_input(&f->ctx);
+
+    av_freep(pf);
+}
+
 static const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *st,
                                      enum HWAccelID hwaccel_id, enum AVHWDeviceType hwaccel_device_type)
 
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 05/20] fftools/ffmpeg: drop free_input_threads()
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (2 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 04/20] fftools/ffmpeg: move closing the input file into a separate function Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 06/20] fftools/ffmpeg: move threading fields from InputFile to Demuxer Anton Khirnov
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

Stop demuxer threads in ifile_close() instead. Simplifies the demuxer
API.
---
 fftools/ffmpeg.c       |  4 ----
 fftools/ffmpeg.h       |  1 -
 fftools/ffmpeg_demux.c | 17 ++++++-----------
 3 files changed, 6 insertions(+), 16 deletions(-)

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index d29d2e4e88..3ad3fff5cd 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -555,7 +555,6 @@ static void ffmpeg_cleanup(int ret)
     for (i = 0; i < nb_output_files; i++)
         of_close(&output_files[i]);
 
-    free_input_threads();
     for (i = 0; i < nb_input_files; i++)
         ifile_close(&input_files[i]);
 
@@ -3932,7 +3931,6 @@ static int transcode(void)
         /* dump report by using the output first video and audio streams */
         print_report(0, timer_start, cur_time);
     }
-    free_input_threads();
 
     /* at the end of stream, we must flush the decoder buffers */
     for (i = 0; i < nb_input_streams; i++) {
@@ -3985,8 +3983,6 @@ static int transcode(void)
     ret = 0;
 
  fail:
-    free_input_threads();
-
     return ret;
 }
 
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 547660d5ef..823347f670 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -760,7 +760,6 @@ void ifile_close(InputFile **f);
  * - a negative error code on failure
  */
 int ifile_get_packet(InputFile *f, AVPacket **pkt);
-void free_input_threads(void);
 
 #define SPECIFIER_OPT_FMT_str  "%s"
 #define SPECIFIER_OPT_FMT_i    "%i"
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index d2db0663ab..5c75dd5b23 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -306,12 +306,12 @@ finish:
     return NULL;
 }
 
-static void free_input_thread(int i)
+static void thread_stop(Demuxer *d)
 {
-    InputFile *f = input_files[i];
+    InputFile *f = &d->f;
     DemuxMsg msg;
 
-    if (!f || !f->in_thread_queue)
+    if (!f->in_thread_queue)
         return;
     av_thread_message_queue_set_err_send(f->in_thread_queue, AVERROR_EOF);
     while (av_thread_message_queue_recv(f->in_thread_queue, &msg, 0) >= 0)
@@ -322,14 +322,6 @@ static void free_input_thread(int i)
     av_thread_message_queue_free(&f->audio_duration_queue);
 }
 
-void free_input_threads(void)
-{
-    int i;
-
-    for (i = 0; i < nb_input_files; i++)
-        free_input_thread(i);
-}
-
 static int thread_start(Demuxer *d)
 {
     int ret;
@@ -426,10 +418,13 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt)
 void ifile_close(InputFile **pf)
 {
     InputFile *f = *pf;
+    Demuxer   *d = demuxer_from_ifile(f);
 
     if (!f)
         return;
 
+    thread_stop(d);
+
     avformat_close_input(&f->ctx);
 
     av_freep(pf);
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 06/20] fftools/ffmpeg: move threading fields from InputFile to Demuxer
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (3 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 05/20] fftools/ffmpeg: drop free_input_threads() Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 07/20] fftools/ffmpeg: move duration/time_base " Anton Khirnov
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

They are private to the demuxer and do not need to be visible outside of
it.
---
 fftools/ffmpeg.h       |  5 -----
 fftools/ffmpeg_demux.c | 49 +++++++++++++++++++++++-------------------
 2 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 823347f670..8c3effdb05 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -455,11 +455,6 @@ typedef struct InputFile {
     float readrate;
     int accurate_seek;
 
-    AVThreadMessageQueue *in_thread_queue;
-    pthread_t thread;           /* thread reading from this file */
-    int non_blocking;           /* reading packets from the thread should not block */
-    int thread_queue_size;      /* maximum number of queued packets */
-
     /* when looping the input file, this queue is used by decoders to report
      * the last frame duration back to the demuxer thread */
     AVThreadMessageQueue *audio_duration_queue;
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 5c75dd5b23..90868de7aa 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -50,6 +50,11 @@ typedef struct Demuxer {
 
     /* number of times input stream should be looped */
     int loop;
+
+    AVThreadMessageQueue *in_thread_queue;
+    int                   thread_queue_size;
+    pthread_t             thread;
+    int                   non_blocking;
 } Demuxer;
 
 typedef struct DemuxMsg {
@@ -211,7 +216,7 @@ static void *input_thread(void *arg)
     Demuxer   *d = arg;
     InputFile *f = &d->f;
     AVPacket *pkt;
-    unsigned flags = f->non_blocking ? AV_THREAD_MESSAGE_NONBLOCK : 0;
+    unsigned flags = d->non_blocking ? AV_THREAD_MESSAGE_NONBLOCK : 0;
     int ret = 0;
 
     pkt = av_packet_alloc();
@@ -233,7 +238,7 @@ static void *input_thread(void *arg)
             if (d->loop) {
                 /* signal looping to the consumer thread */
                 msg.looping = 1;
-                ret = av_thread_message_queue_send(f->in_thread_queue, &msg, 0);
+                ret = av_thread_message_queue_send(d->in_thread_queue, &msg, 0);
                 if (ret >= 0)
                     ret = seek_to_start(d);
                 if (ret >= 0)
@@ -278,14 +283,14 @@ static void *input_thread(void *arg)
             break;
         }
         av_packet_move_ref(msg.pkt, pkt);
-        ret = av_thread_message_queue_send(f->in_thread_queue, &msg, flags);
+        ret = av_thread_message_queue_send(d->in_thread_queue, &msg, flags);
         if (flags && ret == AVERROR(EAGAIN)) {
             flags = 0;
-            ret = av_thread_message_queue_send(f->in_thread_queue, &msg, flags);
+            ret = av_thread_message_queue_send(d->in_thread_queue, &msg, flags);
             av_log(f->ctx, AV_LOG_WARNING,
                    "Thread message queue blocking; consider raising the "
                    "thread_queue_size option (current value: %d)\n",
-                   f->thread_queue_size);
+                   d->thread_queue_size);
         }
         if (ret < 0) {
             if (ret != AVERROR_EOF)
@@ -299,7 +304,7 @@ static void *input_thread(void *arg)
 
 finish:
     av_assert0(ret < 0);
-    av_thread_message_queue_set_err_recv(f->in_thread_queue, ret);
+    av_thread_message_queue_set_err_recv(d->in_thread_queue, ret);
 
     av_packet_free(&pkt);
 
@@ -311,14 +316,14 @@ static void thread_stop(Demuxer *d)
     InputFile *f = &d->f;
     DemuxMsg msg;
 
-    if (!f->in_thread_queue)
+    if (!d->in_thread_queue)
         return;
-    av_thread_message_queue_set_err_send(f->in_thread_queue, AVERROR_EOF);
-    while (av_thread_message_queue_recv(f->in_thread_queue, &msg, 0) >= 0)
+    av_thread_message_queue_set_err_send(d->in_thread_queue, AVERROR_EOF);
+    while (av_thread_message_queue_recv(d->in_thread_queue, &msg, 0) >= 0)
         av_packet_free(&msg.pkt);
 
-    pthread_join(f->thread, NULL);
-    av_thread_message_queue_free(&f->in_thread_queue);
+    pthread_join(d->thread, NULL);
+    av_thread_message_queue_free(&d->in_thread_queue);
     av_thread_message_queue_free(&f->audio_duration_queue);
 }
 
@@ -327,14 +332,14 @@ static int thread_start(Demuxer *d)
     int ret;
     InputFile *f = &d->f;
 
-    if (f->thread_queue_size <= 0)
-        f->thread_queue_size = (nb_input_files > 1 ? 8 : 1);
+    if (d->thread_queue_size <= 0)
+        d->thread_queue_size = (nb_input_files > 1 ? 8 : 1);
 
     if (f->ctx->pb ? !f->ctx->pb->seekable :
         strcmp(f->ctx->iformat->name, "lavfi"))
-        f->non_blocking = 1;
-    ret = av_thread_message_queue_alloc(&f->in_thread_queue,
-                                        f->thread_queue_size, sizeof(DemuxMsg));
+        d->non_blocking = 1;
+    ret = av_thread_message_queue_alloc(&d->in_thread_queue,
+                                        d->thread_queue_size, sizeof(DemuxMsg));
     if (ret < 0)
         return ret;
 
@@ -356,7 +361,7 @@ static int thread_start(Demuxer *d)
         }
     }
 
-    if ((ret = pthread_create(&f->thread, NULL, input_thread, d))) {
+    if ((ret = pthread_create(&d->thread, NULL, input_thread, d))) {
         av_log(NULL, AV_LOG_ERROR, "pthread_create failed: %s. Try to increase `ulimit -v` or decrease `ulimit -s`.\n", strerror(ret));
         ret = AVERROR(ret);
         goto fail;
@@ -364,7 +369,7 @@ static int thread_start(Demuxer *d)
 
     return 0;
 fail:
-    av_thread_message_queue_free(&f->in_thread_queue);
+    av_thread_message_queue_free(&d->in_thread_queue);
     return ret;
 }
 
@@ -375,7 +380,7 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt)
     DemuxMsg msg;
     int ret;
 
-    if (!f->in_thread_queue) {
+    if (!d->in_thread_queue) {
         ret = thread_start(d);
         if (ret < 0)
             return ret;
@@ -400,8 +405,8 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt)
         }
     }
 
-    ret = av_thread_message_queue_recv(f->in_thread_queue, &msg,
-                                       f->non_blocking ?
+    ret = av_thread_message_queue_recv(d->in_thread_queue, &msg,
+                                       d->non_blocking ?
                                        AV_THREAD_MESSAGE_NONBLOCK : 0);
     if (ret < 0)
         return ret;
@@ -968,7 +973,7 @@ int ifile_open(OptionsContext *o, const char *filename)
         f->rate_emu = 0;
     }
 
-    f->thread_queue_size = o->thread_queue_size;
+    d->thread_queue_size = o->thread_queue_size;
 
     /* check if all codec options have been used */
     unused_opts = strip_specifiers(o->g->codec_opts);
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 07/20] fftools/ffmpeg: move duration/time_base from InputFile to Demuxer
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (4 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 06/20] fftools/ffmpeg: move threading fields from InputFile to Demuxer Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 08/20] fftools/ffmpeg_demux: do not log to the demuxer context Anton Khirnov
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

They are private to the demuxer and do not need to be visible outside of
it.
---
 fftools/ffmpeg.h       |  3 ---
 fftools/ffmpeg_demux.c | 30 ++++++++++++++++++------------
 2 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 8c3effdb05..2f635c779d 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -434,9 +434,6 @@ typedef struct InputFile {
     int eof_reached;      /* true if eof reached */
     int eagain;           /* true if last read attempt returned EAGAIN */
     int ist_index;        /* index of first stream in input_streams */
-    int64_t duration;     /* actual duration of the longest stream in a file
-                             at the moment when looping happens */
-    AVRational time_base; /* time base of the duration */
     int64_t input_ts_offset;
     int input_sync_ref;
 
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 90868de7aa..fe1b3bd8b7 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -50,6 +50,11 @@ typedef struct Demuxer {
 
     /* number of times input stream should be looped */
     int loop;
+    /* actual duration of the longest stream in a file at the moment when
+     * looping happens */
+    int64_t duration;
+    /* time base of the duration */
+    AVRational time_base;
 
     AVThreadMessageQueue *in_thread_queue;
     int                   thread_queue_size;
@@ -84,7 +89,7 @@ static void report_new_stream(InputFile *file, const AVPacket *pkt)
     file->nb_streams_warn = pkt->stream_index + 1;
 }
 
-static void ifile_duration_update(InputFile *f, InputStream *ist,
+static void ifile_duration_update(Demuxer *d, InputStream *ist,
                                   int64_t last_duration)
 {
     /* the total duration of the stream, max_pts - min_pts is
@@ -93,11 +98,11 @@ static void ifile_duration_update(InputFile *f, InputStream *ist,
         ist->max_pts - (uint64_t)ist->min_pts < INT64_MAX - last_duration)
         last_duration += ist->max_pts - ist->min_pts;
 
-    if (!f->duration ||
-        av_compare_ts(f->duration, f->time_base,
+    if (!d->duration ||
+        av_compare_ts(d->duration, d->time_base,
                       last_duration, ist->st->time_base) < 0) {
-        f->duration = last_duration;
-        f->time_base = ist->st->time_base;
+        d->duration = last_duration;
+        d->time_base = ist->st->time_base;
     }
 }
 
@@ -126,7 +131,7 @@ static int seek_to_start(Demuxer *d)
             got_durations++;
 
             ist = input_streams[ifile->ist_index + dur.stream_idx];
-            ifile_duration_update(ifile, ist, dur.duration);
+            ifile_duration_update(d, ist, dur.duration);
         }
     } else {
         for (int i = 0; i < ifile->nb_streams; i++) {
@@ -141,7 +146,7 @@ static int seek_to_start(Demuxer *d)
                 duration = 1;
             }
 
-            ifile_duration_update(ifile, ist, duration);
+            ifile_duration_update(d, ist, duration);
         }
     }
 
@@ -151,8 +156,9 @@ static int seek_to_start(Demuxer *d)
     return ret;
 }
 
-static void ts_fixup(InputFile *ifile, AVPacket *pkt, int *repeat_pict)
+static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict)
 {
+    InputFile *ifile = &d->f;
     InputStream *ist = input_streams[ifile->ist_index + pkt->stream_index];
     const int64_t start_time = ifile->ctx->start_time;
     int64_t duration;
@@ -195,7 +201,7 @@ static void ts_fixup(InputFile *ifile, AVPacket *pkt, int *repeat_pict)
     if (pkt->dts != AV_NOPTS_VALUE)
         pkt->dts *= ist->ts_scale;
 
-    duration = av_rescale_q(ifile->duration, ifile->time_base, ist->st->time_base);
+    duration = av_rescale_q(d->duration, d->time_base, ist->st->time_base);
     if (pkt->pts != AV_NOPTS_VALUE) {
         pkt->pts += duration;
         ist->max_pts = FFMAX(pkt->pts, ist->max_pts);
@@ -274,7 +280,7 @@ static void *input_thread(void *arg)
             }
         }
 
-        ts_fixup(f, pkt, &msg.repeat_pict);
+        ts_fixup(d, pkt, &msg.repeat_pict);
 
         msg.pkt = av_packet_alloc();
         if (!msg.pkt) {
@@ -960,8 +966,8 @@ int ifile_open(OptionsContext *o, const char *filename)
     f->rate_emu   = o->rate_emu;
     f->accurate_seek = o->accurate_seek;
     d->loop = o->loop;
-    f->duration = 0;
-    f->time_base = (AVRational){ 1, 1 };
+    d->duration = 0;
+    d->time_base = (AVRational){ 1, 1 };
 
     f->readrate = o->readrate ? o->readrate : 0.0;
     if (f->readrate < 0.0f) {
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 08/20] fftools/ffmpeg_demux: do not log to the demuxer context
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (5 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 07/20] fftools/ffmpeg: move duration/time_base " Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 09/20] fftools/ffmpeg: move nb_streams_warn from InputFile to Demuxer Anton Khirnov
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

Only the demuxer itself is supposed to do that.
---
 fftools/ffmpeg_demux.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index fe1b3bd8b7..e5e7cd1a54 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -81,7 +81,7 @@ static void report_new_stream(InputFile *file, const AVPacket *pkt)
 
     if (pkt->stream_index < file->nb_streams_warn)
         return;
-    av_log(file->ctx, AV_LOG_WARNING,
+    av_log(NULL, AV_LOG_WARNING,
            "New %s stream %d:%d at pos:%"PRId64" and DTS:%ss\n",
            av_get_media_type_string(st->codecpar->codec_type),
            file->index, pkt->stream_index,
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 09/20] fftools/ffmpeg: move nb_streams_warn from InputFile to Demuxer
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (6 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 08/20] fftools/ffmpeg_demux: do not log to the demuxer context Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 10/20] fftools/ffmpeg_demux: log when the demuxer thread terminates Anton Khirnov
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

It is private to the demuxer and do not need to be visible outside of
it.
---
 fftools/ffmpeg.h       |  1 -
 fftools/ffmpeg_demux.c | 15 +++++++++------
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 2f635c779d..a124b1b045 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -447,7 +447,6 @@ typedef struct InputFile {
     int64_t recording_time;
     int nb_streams;       /* number of stream that ffmpeg is aware of; may be different
                              from ctx.nb_streams if new streams appear during av_read_frame() */
-    int nb_streams_warn;  /* number of streams that the user was warned of */
     int rate_emu;
     float readrate;
     int accurate_seek;
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index e5e7cd1a54..040213b392 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -56,6 +56,9 @@ typedef struct Demuxer {
     /* time base of the duration */
     AVRational time_base;
 
+    /* number of streams that the user was warned of */
+    int nb_streams_warn;
+
     AVThreadMessageQueue *in_thread_queue;
     int                   thread_queue_size;
     pthread_t             thread;
@@ -75,18 +78,18 @@ static Demuxer *demuxer_from_ifile(InputFile *f)
     return (Demuxer*)f;
 }
 
-static void report_new_stream(InputFile *file, const AVPacket *pkt)
+static void report_new_stream(Demuxer *d, const AVPacket *pkt)
 {
-    AVStream *st = file->ctx->streams[pkt->stream_index];
+    AVStream *st = d->f.ctx->streams[pkt->stream_index];
 
-    if (pkt->stream_index < file->nb_streams_warn)
+    if (pkt->stream_index < d->nb_streams_warn)
         return;
     av_log(NULL, AV_LOG_WARNING,
            "New %s stream %d:%d at pos:%"PRId64" and DTS:%ss\n",
            av_get_media_type_string(st->codecpar->codec_type),
-           file->index, pkt->stream_index,
+           d->f.index, pkt->stream_index,
            pkt->pos, av_ts2timestr(pkt->dts, &st->time_base));
-    file->nb_streams_warn = pkt->stream_index + 1;
+    d->nb_streams_warn = pkt->stream_index + 1;
 }
 
 static void ifile_duration_update(Demuxer *d, InputStream *ist,
@@ -264,7 +267,7 @@ static void *input_thread(void *arg)
         /* the following test is needed in case new streams appear
            dynamically in stream : we ignore them */
         if (pkt->stream_index >= f->nb_streams) {
-            report_new_stream(f, pkt);
+            report_new_stream(d, pkt);
             av_packet_unref(pkt);
             continue;
         }
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 10/20] fftools/ffmpeg_demux: log when the demuxer thread terminates
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (7 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 09/20] fftools/ffmpeg: move nb_streams_warn from InputFile to Demuxer Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 11/20] fftools/ffmpeg: factor out copying metadata/chapters from of_open() Anton Khirnov
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

Similar to what is done for muxing, may be useful for debugging.
---
 fftools/ffmpeg_demux.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 040213b392..29cff4b471 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -256,6 +256,12 @@ static void *input_thread(void *arg)
                 /* fallthrough to the error path */
             }
 
+            if (ret == AVERROR_EOF)
+                av_log(NULL, AV_LOG_VERBOSE, "EOF in input file %d\n", f->index);
+            else
+                av_log(NULL, AV_LOG_ERROR, "Error demuxing input file %d: %s\n",
+                       f->index, av_err2str(ret));
+
             break;
         }
 
@@ -317,6 +323,8 @@ finish:
 
     av_packet_free(&pkt);
 
+    av_log(NULL, AV_LOG_VERBOSE, "Terminating demuxer thread %d\n", f->index);
+
     return NULL;
 }
 
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 11/20] fftools/ffmpeg: factor out copying metadata/chapters from of_open()
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (8 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 10/20] fftools/ffmpeg_demux: log when the demuxer thread terminates Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 12/20] fftools/ffmpeg_mux_init: avoid modifying OptionsContext.chapters_input_file Anton Khirnov
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

This code shares variables like OptionsContext.metadata_*_manual, so it
makes sense to group it together.
---
 fftools/ffmpeg_mux_init.c | 123 ++++++++++++++++++++------------------
 1 file changed, 66 insertions(+), 57 deletions(-)

diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index aa958052d1..cd46f441cf 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1533,6 +1533,70 @@ static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFor
     return 0;
 }
 
+static void copy_meta(Muxer *mux, OptionsContext *o)
+{
+    OutputFile      *of = &mux->of;
+    AVFormatContext *oc = mux->fc;
+
+    /* copy metadata */
+    for (int i = 0; i < o->nb_metadata_map; i++) {
+        char *p;
+        int in_file_index = strtol(o->metadata_map[i].u.str, &p, 0);
+
+        if (in_file_index >= nb_input_files) {
+            av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d while processing metadata maps\n", in_file_index);
+            exit_program(1);
+        }
+        copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc,
+                      in_file_index >= 0 ?
+                      input_files[in_file_index]->ctx : NULL, o);
+    }
+
+    /* copy chapters */
+    if (o->chapters_input_file >= nb_input_files) {
+        if (o->chapters_input_file == INT_MAX) {
+            /* copy chapters from the first input file that has them*/
+            o->chapters_input_file = -1;
+            for (int i = 0; i < nb_input_files; i++)
+                if (input_files[i]->ctx->nb_chapters) {
+                    o->chapters_input_file = i;
+                    break;
+                }
+        } else {
+            av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n",
+                   o->chapters_input_file);
+            exit_program(1);
+        }
+    }
+    if (o->chapters_input_file >= 0)
+        copy_chapters(input_files[o->chapters_input_file], of, oc,
+                      !o->metadata_chapters_manual);
+
+    /* copy global metadata by default */
+    if (!o->metadata_global_manual && nb_input_files){
+        av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
+                     AV_DICT_DONT_OVERWRITE);
+        if(o->recording_time != INT64_MAX)
+            av_dict_set(&oc->metadata, "duration", NULL, 0);
+        av_dict_set(&oc->metadata, "creation_time", NULL, 0);
+        av_dict_set(&oc->metadata, "company_name", NULL, 0);
+        av_dict_set(&oc->metadata, "product_name", NULL, 0);
+        av_dict_set(&oc->metadata, "product_version", NULL, 0);
+    }
+    if (!o->metadata_streams_manual)
+        for (int i = 0; i < of->nb_streams; i++) {
+            OutputStream *ost = of->streams[i];
+            InputStream *ist;
+            if (ost->source_index < 0)         /* this is true e.g. for attached files */
+                continue;
+            ist = input_streams[ost->source_index];
+            av_dict_copy(&ost->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
+            if (ost->enc_ctx) {
+                av_dict_set(&ost->st->metadata, "encoder", NULL, 0);
+            }
+        }
+}
+
 static int set_dispositions(OutputFile *of, AVFormatContext *ctx)
 {
     int nb_streams[AVMEDIA_TYPE_NB]   = { 0 };
@@ -1839,63 +1903,8 @@ int of_open(OptionsContext *o, const char *filename)
     }
     oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
 
-    /* copy metadata */
-    for (i = 0; i < o->nb_metadata_map; i++) {
-        char *p;
-        int in_file_index = strtol(o->metadata_map[i].u.str, &p, 0);
-
-        if (in_file_index >= nb_input_files) {
-            av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d while processing metadata maps\n", in_file_index);
-            exit_program(1);
-        }
-        copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc,
-                      in_file_index >= 0 ?
-                      input_files[in_file_index]->ctx : NULL, o);
-    }
-
-    /* copy chapters */
-    if (o->chapters_input_file >= nb_input_files) {
-        if (o->chapters_input_file == INT_MAX) {
-            /* copy chapters from the first input file that has them*/
-            o->chapters_input_file = -1;
-            for (i = 0; i < nb_input_files; i++)
-                if (input_files[i]->ctx->nb_chapters) {
-                    o->chapters_input_file = i;
-                    break;
-                }
-        } else {
-            av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n",
-                   o->chapters_input_file);
-            exit_program(1);
-        }
-    }
-    if (o->chapters_input_file >= 0)
-        copy_chapters(input_files[o->chapters_input_file], of, oc,
-                      !o->metadata_chapters_manual);
-
-    /* copy global metadata by default */
-    if (!o->metadata_global_manual && nb_input_files){
-        av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
-                     AV_DICT_DONT_OVERWRITE);
-        if(o->recording_time != INT64_MAX)
-            av_dict_set(&oc->metadata, "duration", NULL, 0);
-        av_dict_set(&oc->metadata, "creation_time", NULL, 0);
-        av_dict_set(&oc->metadata, "company_name", NULL, 0);
-        av_dict_set(&oc->metadata, "product_name", NULL, 0);
-        av_dict_set(&oc->metadata, "product_version", NULL, 0);
-    }
-    if (!o->metadata_streams_manual)
-        for (int i = 0; i < of->nb_streams; i++) {
-            OutputStream *ost = of->streams[i];
-            InputStream *ist;
-            if (ost->source_index < 0)         /* this is true e.g. for attached files */
-                continue;
-            ist = input_streams[ost->source_index];
-            av_dict_copy(&ost->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
-            if (ost->enc_ctx) {
-                av_dict_set(&ost->st->metadata, "encoder", NULL, 0);
-            }
-        }
+    /* copy metadata and chapters from input files */
+    copy_meta(mux, o);
 
     of_add_programs(oc, o);
     of_add_metadata(of, oc, o);
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 12/20] fftools/ffmpeg_mux_init: avoid modifying OptionsContext.chapters_input_file
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (9 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 11/20] fftools/ffmpeg: factor out copying metadata/chapters from of_open() Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 13/20] fftools/ffmpeg_mux_init: constify metadata specifier arguments Anton Khirnov
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

Use a local variable instead. This will allow making OptionsContext
const in future commits.
---
 fftools/ffmpeg_mux_init.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index cd46f441cf..f608376cf0 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1537,6 +1537,7 @@ static void copy_meta(Muxer *mux, OptionsContext *o)
 {
     OutputFile      *of = &mux->of;
     AVFormatContext *oc = mux->fc;
+    int chapters_input_file = o->chapters_input_file;
 
     /* copy metadata */
     for (int i = 0; i < o->nb_metadata_map; i++) {
@@ -1553,23 +1554,23 @@ static void copy_meta(Muxer *mux, OptionsContext *o)
     }
 
     /* copy chapters */
-    if (o->chapters_input_file >= nb_input_files) {
-        if (o->chapters_input_file == INT_MAX) {
+    if (chapters_input_file >= nb_input_files) {
+        if (chapters_input_file == INT_MAX) {
             /* copy chapters from the first input file that has them*/
-            o->chapters_input_file = -1;
+            chapters_input_file = -1;
             for (int i = 0; i < nb_input_files; i++)
                 if (input_files[i]->ctx->nb_chapters) {
-                    o->chapters_input_file = i;
+                    chapters_input_file = i;
                     break;
                 }
         } else {
             av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n",
-                   o->chapters_input_file);
+                   chapters_input_file);
             exit_program(1);
         }
     }
-    if (o->chapters_input_file >= 0)
-        copy_chapters(input_files[o->chapters_input_file], of, oc,
+    if (chapters_input_file >= 0)
+        copy_chapters(input_files[chapters_input_file], of, oc,
                       !o->metadata_chapters_manual);
 
     /* copy global metadata by default */
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 13/20] fftools/ffmpeg_mux_init: constify metadata specifier arguments
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (10 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 12/20] fftools/ffmpeg_mux_init: avoid modifying OptionsContext.chapters_input_file Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 14/20] fftools/ffmpeg_mux_init: drop a duplicated block in copy_metadata() Anton Khirnov
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

---
 fftools/ffmpeg_mux_init.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index f608376cf0..a471bbf469 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1272,7 +1272,7 @@ static void of_add_programs(AVFormatContext *oc, const OptionsContext *o)
  * @param index for type c/p, chapter/program index is written here
  * @param stream_spec for type s, the stream specifier is written here
  */
-static void parse_meta_type(char *arg, char *type, int *index, const char **stream_spec)
+static void parse_meta_type(const char *arg, char *type, int *index, const char **stream_spec)
 {
     if (*arg) {
         *type = *arg;
@@ -1443,7 +1443,7 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *o
     return 0;
 }
 
-static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFormatContext *ic, OptionsContext *o)
+static int copy_metadata(const char *outspec, const char *inspec, AVFormatContext *oc, AVFormatContext *ic, OptionsContext *o)
 {
     AVDictionary **meta_in = NULL;
     AVDictionary **meta_out = NULL;
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 14/20] fftools/ffmpeg_mux_init: drop a duplicated block in copy_metadata()
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (11 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 13/20] fftools/ffmpeg_mux_init: constify metadata specifier arguments Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 21:51   ` Michael Niedermayer
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 15/20] fftools/ffmpeg_mux_init: stop using OptionsContext as storage " Anton Khirnov
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

It does the same thing as the block right below it.
---
 fftools/ffmpeg_mux_init.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index a471bbf469..9e0164ba19 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1455,16 +1455,6 @@ static int copy_metadata(const char *outspec, const char *inspec, AVFormatContex
     parse_meta_type(inspec,  &type_in,  &idx_in,  &istream_spec);
     parse_meta_type(outspec, &type_out, &idx_out, &ostream_spec);
 
-    if (!ic) {
-        if (type_out == 'g' || !*outspec)
-            o->metadata_global_manual = 1;
-        if (type_out == 's' || !*outspec)
-            o->metadata_streams_manual = 1;
-        if (type_out == 'c' || !*outspec)
-            o->metadata_chapters_manual = 1;
-        return 0;
-    }
-
     if (type_in == 'g' || type_out == 'g')
         o->metadata_global_manual = 1;
     if (type_in == 's' || type_out == 's')
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 15/20] fftools/ffmpeg_mux_init: stop using OptionsContext as storage in copy_metadata()
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (12 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 14/20] fftools/ffmpeg_mux_init: drop a duplicated block in copy_metadata() Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 16/20] fftools/ffmpeg_mux_init: stop modifying some OptionsContext fields Anton Khirnov
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

It should be input-only to this code. Will allow making it const in
future commits.
---
 fftools/ffmpeg.h          |  3 ---
 fftools/ffmpeg_mux_init.c | 24 ++++++++++++++++--------
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index a124b1b045..8a50cd8d4b 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -148,9 +148,6 @@ typedef struct OptionsContext {
     AudioChannelMap *audio_channel_maps; /* one info entry per -map_channel */
     int           nb_audio_channel_maps; /* number of (valid) -map_channel settings */
 #endif
-    int metadata_global_manual;
-    int metadata_streams_manual;
-    int metadata_chapters_manual;
     const char **attachments;
     int       nb_attachments;
 
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 9e0164ba19..96584e960b 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1443,7 +1443,10 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *o
     return 0;
 }
 
-static int copy_metadata(const char *outspec, const char *inspec, AVFormatContext *oc, AVFormatContext *ic, OptionsContext *o)
+static int copy_metadata(const char *outspec, const char *inspec,
+                         AVFormatContext *oc, AVFormatContext *ic,
+                         int *metadata_global_manual, int *metadata_streams_manual,
+                         int *metadata_chapters_manual, OptionsContext *o)
 {
     AVDictionary **meta_in = NULL;
     AVDictionary **meta_out = NULL;
@@ -1456,11 +1459,11 @@ static int copy_metadata(const char *outspec, const char *inspec, AVFormatContex
     parse_meta_type(outspec, &type_out, &idx_out, &ostream_spec);
 
     if (type_in == 'g' || type_out == 'g')
-        o->metadata_global_manual = 1;
+        *metadata_global_manual = 1;
     if (type_in == 's' || type_out == 's')
-        o->metadata_streams_manual = 1;
+        *metadata_streams_manual = 1;
     if (type_in == 'c' || type_out == 'c')
-        o->metadata_chapters_manual = 1;
+        *metadata_chapters_manual = 1;
 
     /* ic is NULL when just disabling automatic mappings */
     if (!ic)
@@ -1528,6 +1531,9 @@ static void copy_meta(Muxer *mux, OptionsContext *o)
     OutputFile      *of = &mux->of;
     AVFormatContext *oc = mux->fc;
     int chapters_input_file = o->chapters_input_file;
+    int metadata_global_manual   = 0;
+    int metadata_streams_manual  = 0;
+    int metadata_chapters_manual = 0;
 
     /* copy metadata */
     for (int i = 0; i < o->nb_metadata_map; i++) {
@@ -1540,7 +1546,9 @@ static void copy_meta(Muxer *mux, OptionsContext *o)
         }
         copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc,
                       in_file_index >= 0 ?
-                      input_files[in_file_index]->ctx : NULL, o);
+                      input_files[in_file_index]->ctx : NULL,
+                      &metadata_global_manual, &metadata_streams_manual,
+                      &metadata_chapters_manual, o);
     }
 
     /* copy chapters */
@@ -1561,10 +1569,10 @@ static void copy_meta(Muxer *mux, OptionsContext *o)
     }
     if (chapters_input_file >= 0)
         copy_chapters(input_files[chapters_input_file], of, oc,
-                      !o->metadata_chapters_manual);
+                      !metadata_chapters_manual);
 
     /* copy global metadata by default */
-    if (!o->metadata_global_manual && nb_input_files){
+    if (!metadata_global_manual && nb_input_files){
         av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
                      AV_DICT_DONT_OVERWRITE);
         if(o->recording_time != INT64_MAX)
@@ -1574,7 +1582,7 @@ static void copy_meta(Muxer *mux, OptionsContext *o)
         av_dict_set(&oc->metadata, "product_name", NULL, 0);
         av_dict_set(&oc->metadata, "product_version", NULL, 0);
     }
-    if (!o->metadata_streams_manual)
+    if (!metadata_streams_manual)
         for (int i = 0; i < of->nb_streams; i++) {
             OutputStream *ost = of->streams[i];
             InputStream *ist;
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 16/20] fftools/ffmpeg_mux_init: stop modifying some OptionsContext fields
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (13 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 15/20] fftools/ffmpeg_mux_init: stop using OptionsContext as storage " Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 17/20] fftools/ffmpeg_mux_init: move code creating streams into a new function Anton Khirnov
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

Specifically recording_time and stop_time - use local variables instead.
OptionsContext should be input-only to this code. Will allow making it
const in future commits.
---
 fftools/ffmpeg_mux_init.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 96584e960b..d25dace105 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1575,7 +1575,7 @@ static void copy_meta(Muxer *mux, OptionsContext *o)
     if (!metadata_global_manual && nb_input_files){
         av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
                      AV_DICT_DONT_OVERWRITE);
-        if(o->recording_time != INT64_MAX)
+        if (of->recording_time != INT64_MAX)
             av_dict_set(&oc->metadata, "duration", NULL, 0);
         av_dict_set(&oc->metadata, "creation_time", NULL, 0);
         av_dict_set(&oc->metadata, "company_name", NULL, 0);
@@ -1671,18 +1671,21 @@ int of_open(OptionsContext *o, const char *filename)
     AVDictionary *unused_opts = NULL;
     const AVDictionaryEntry *e = NULL;
 
-    if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) {
-        o->stop_time = INT64_MAX;
+    int64_t recording_time = o->recording_time;
+    int64_t stop_time      = o->stop_time;
+
+    if (stop_time != INT64_MAX && recording_time != INT64_MAX) {
+        stop_time = INT64_MAX;
         av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
     }
 
-    if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) {
+    if (stop_time != INT64_MAX && recording_time == INT64_MAX) {
         int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time;
-        if (o->stop_time <= start_time) {
+        if (stop_time <= start_time) {
             av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n");
             exit_program(1);
         } else {
-            o->recording_time = o->stop_time - start_time;
+            recording_time = stop_time - start_time;
         }
     }
 
@@ -1690,7 +1693,7 @@ int of_open(OptionsContext *o, const char *filename)
     of  = &mux->of;
 
     of->index          = nb_output_files - 1;
-    of->recording_time = o->recording_time;
+    of->recording_time = recording_time;
     of->start_time     = o->start_time;
     of->shortest       = o->shortest;
 
@@ -1712,8 +1715,8 @@ int of_open(OptionsContext *o, const char *filename)
         want_sdp = 0;
 
     of->format = oc->oformat;
-    if (o->recording_time != INT64_MAX)
-        oc->duration = o->recording_time;
+    if (recording_time != INT64_MAX)
+        oc->duration = recording_time;
 
     oc->interrupt_callback = int_cb;
 
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 17/20] fftools/ffmpeg_mux_init: move code creating streams into a new function
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (14 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 16/20] fftools/ffmpeg_mux_init: stop modifying some OptionsContext fields Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 18/20] fftools/ffmpeg_mux_init: stop modifying OptionsContext.*_disable Anton Khirnov
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

Makes it easy to see where all the streams are created. Will also be
useful in the following commit.
---
 fftools/ffmpeg_mux_init.c | 72 +++++++++++++++++++++------------------
 1 file changed, 39 insertions(+), 33 deletions(-)

diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index d25dace105..6687ba872a 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1062,6 +1062,42 @@ loop_end:
     }
 }
 
+static void create_streams(Muxer *mux, OptionsContext *o)
+{
+    /* create streams for all unlabeled output pads */
+    for (int i = 0; i < nb_filtergraphs; i++) {
+        FilterGraph *fg = filtergraphs[i];
+        for (int j = 0; j < fg->nb_outputs; j++) {
+            OutputFilter *ofilter = fg->outputs[j];
+
+            if (!ofilter->out_tmp || ofilter->out_tmp->name)
+                continue;
+
+            switch (ofilter->type) {
+            case AVMEDIA_TYPE_VIDEO:    o->video_disable    = 1; break;
+            case AVMEDIA_TYPE_AUDIO:    o->audio_disable    = 1; break;
+            case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break;
+            }
+            init_output_filter(ofilter, o, mux);
+        }
+    }
+
+    if (!o->nb_stream_maps) {
+        /* pick the "best" stream of each type */
+        if (!o->video_disable)
+            map_auto_video(mux, o);
+        if (!o->audio_disable)
+            map_auto_audio(mux, o);
+        if (!o->subtitle_disable)
+            map_auto_subtitle(mux, o);
+        if (!o->data_disable)
+            map_auto_data(mux, o);
+    } else {
+        for (int i = 0; i < o->nb_stream_maps; i++)
+            map_manual(mux, o, &o->stream_maps[i]);
+    }
+}
+
 static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_us)
 {
     OutputFile *of = &mux->of;
@@ -1666,7 +1702,7 @@ int of_open(OptionsContext *o, const char *filename)
 {
     Muxer *mux;
     AVFormatContext *oc;
-    int i, j, err;
+    int err;
     OutputFile *of;
     AVDictionary *unused_opts = NULL;
     const AVDictionaryEntry *e = NULL;
@@ -1728,38 +1764,8 @@ int of_open(OptionsContext *o, const char *filename)
                                            AVFMT_FLAG_BITEXACT);
     }
 
-    /* create streams for all unlabeled output pads */
-    for (i = 0; i < nb_filtergraphs; i++) {
-        FilterGraph *fg = filtergraphs[i];
-        for (j = 0; j < fg->nb_outputs; j++) {
-            OutputFilter *ofilter = fg->outputs[j];
-
-            if (!ofilter->out_tmp || ofilter->out_tmp->name)
-                continue;
-
-            switch (ofilter->type) {
-            case AVMEDIA_TYPE_VIDEO:    o->video_disable    = 1; break;
-            case AVMEDIA_TYPE_AUDIO:    o->audio_disable    = 1; break;
-            case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break;
-            }
-            init_output_filter(ofilter, o, mux);
-        }
-    }
-
-    if (!o->nb_stream_maps) {
-        /* pick the "best" stream of each type */
-        if (!o->video_disable)
-            map_auto_video(mux, o);
-        if (!o->audio_disable)
-            map_auto_audio(mux, o);
-        if (!o->subtitle_disable)
-            map_auto_subtitle(mux, o);
-        if (!o->data_disable)
-            map_auto_data(mux, o);
-    } else {
-        for (int i = 0; i < o->nb_stream_maps; i++)
-            map_manual(mux, o, &o->stream_maps[i]);
-    }
+    /* create all output streams for this file */
+    create_streams(mux, o);
 
     of_add_attachments(mux, o);
 
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 18/20] fftools/ffmpeg_mux_init: stop modifying OptionsContext.*_disable
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (15 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 17/20] fftools/ffmpeg_mux_init: move code creating streams into a new function Anton Khirnov
@ 2022-10-18 12:36 ` Anton Khirnov
  2022-10-18 12:37 ` [FFmpeg-devel] [PATCH 19/20] fftools/ffmpeg_demux: stop modifying OptionsContext Anton Khirnov
  2022-10-18 12:37 ` [FFmpeg-devel] [PATCH 20/20] fftools/ffmpeg_[de]mux: constify all uses of OptionsContext Anton Khirnov
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:36 UTC (permalink / raw)
  To: ffmpeg-devel

The current code will override the *_disable fields (set by -vn/-an
options) when creating output streams for unlabeled complex filtergraph
outputs, in order to disable automatic mapping for the corresponding
media type.

However, this will apply not only to automatic mappings, but to manual
ones as well, which should not happen. Avoid this by adding local
variables that are used only for automatic mappings.
---
 fftools/ffmpeg_mux_init.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 6687ba872a..7c19cb7442 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1064,6 +1064,11 @@ loop_end:
 
 static void create_streams(Muxer *mux, OptionsContext *o)
 {
+    int auto_disable_v = o->video_disable;
+    int auto_disable_a = o->audio_disable;
+    int auto_disable_s = o->subtitle_disable;
+    int auto_disable_d = o->data_disable;
+
     /* create streams for all unlabeled output pads */
     for (int i = 0; i < nb_filtergraphs; i++) {
         FilterGraph *fg = filtergraphs[i];
@@ -1074,9 +1079,9 @@ static void create_streams(Muxer *mux, OptionsContext *o)
                 continue;
 
             switch (ofilter->type) {
-            case AVMEDIA_TYPE_VIDEO:    o->video_disable    = 1; break;
-            case AVMEDIA_TYPE_AUDIO:    o->audio_disable    = 1; break;
-            case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break;
+            case AVMEDIA_TYPE_VIDEO:    auto_disable_v = 1; break;
+            case AVMEDIA_TYPE_AUDIO:    auto_disable_a = 1; break;
+            case AVMEDIA_TYPE_SUBTITLE: auto_disable_s = 1; break;
             }
             init_output_filter(ofilter, o, mux);
         }
@@ -1084,13 +1089,13 @@ static void create_streams(Muxer *mux, OptionsContext *o)
 
     if (!o->nb_stream_maps) {
         /* pick the "best" stream of each type */
-        if (!o->video_disable)
+        if (!auto_disable_v)
             map_auto_video(mux, o);
-        if (!o->audio_disable)
+        if (!auto_disable_a)
             map_auto_audio(mux, o);
-        if (!o->subtitle_disable)
+        if (!auto_disable_s)
             map_auto_subtitle(mux, o);
-        if (!o->data_disable)
+        if (!auto_disable_d)
             map_auto_data(mux, o);
     } else {
         for (int i = 0; i < o->nb_stream_maps; i++)
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 19/20] fftools/ffmpeg_demux: stop modifying OptionsContext
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (16 preceding siblings ...)
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 18/20] fftools/ffmpeg_mux_init: stop modifying OptionsContext.*_disable Anton Khirnov
@ 2022-10-18 12:37 ` Anton Khirnov
  2022-10-18 12:37 ` [FFmpeg-devel] [PATCH 20/20] fftools/ffmpeg_[de]mux: constify all uses of OptionsContext Anton Khirnov
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:37 UTC (permalink / raw)
  To: ffmpeg-devel

It should be input-only to this code.
---
 fftools/ffmpeg_demux.c | 39 ++++++++++++++++++++++-----------------
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 29cff4b471..4ce92862cb 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -772,18 +772,23 @@ int ifile_open(OptionsContext *o, const char *filename)
     char *    data_codec_name = NULL;
     int scan_all_pmts_set = 0;
 
-    if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) {
-        o->stop_time = INT64_MAX;
+    int64_t start_time     = o->start_time;
+    int64_t start_time_eof = o->start_time_eof;
+    int64_t stop_time      = o->stop_time;
+    int64_t recording_time = o->recording_time;
+
+    if (stop_time != INT64_MAX && recording_time != INT64_MAX) {
+        stop_time = INT64_MAX;
         av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
     }
 
-    if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) {
-        int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time;
-        if (o->stop_time <= start_time) {
+    if (stop_time != INT64_MAX && recording_time == INT64_MAX) {
+        int64_t start = start_time == AV_NOPTS_VALUE ? 0 : start_time;
+        if (stop_time <= start) {
             av_log(NULL, AV_LOG_ERROR, "-to value smaller than -ss; aborting.\n");
             exit_program(1);
         } else {
-            o->recording_time = o->stop_time - start_time;
+            recording_time = stop_time - start;
         }
     }
 
@@ -908,32 +913,32 @@ int ifile_open(OptionsContext *o, const char *filename)
         }
     }
 
-    if (o->start_time != AV_NOPTS_VALUE && o->start_time_eof != AV_NOPTS_VALUE) {
+    if (start_time != AV_NOPTS_VALUE && start_time_eof != AV_NOPTS_VALUE) {
         av_log(NULL, AV_LOG_WARNING, "Cannot use -ss and -sseof both, using -ss for %s\n", filename);
-        o->start_time_eof = AV_NOPTS_VALUE;
+        start_time_eof = AV_NOPTS_VALUE;
     }
 
-    if (o->start_time_eof != AV_NOPTS_VALUE) {
-        if (o->start_time_eof >= 0) {
+    if (start_time_eof != AV_NOPTS_VALUE) {
+        if (start_time_eof >= 0) {
             av_log(NULL, AV_LOG_ERROR, "-sseof value must be negative; aborting\n");
             exit_program(1);
         }
         if (ic->duration > 0) {
-            o->start_time = o->start_time_eof + ic->duration;
-            if (o->start_time < 0) {
+            start_time = start_time_eof + ic->duration;
+            if (start_time < 0) {
                 av_log(NULL, AV_LOG_WARNING, "-sseof value seeks to before start of file %s; ignored\n", filename);
-                o->start_time = AV_NOPTS_VALUE;
+                start_time = AV_NOPTS_VALUE;
             }
         } else
             av_log(NULL, AV_LOG_WARNING, "Cannot use -sseof, duration of %s not known\n", filename);
     }
-    timestamp = (o->start_time == AV_NOPTS_VALUE) ? 0 : o->start_time;
+    timestamp = (start_time == AV_NOPTS_VALUE) ? 0 : start_time;
     /* add the stream start time */
     if (!o->seek_timestamp && ic->start_time != AV_NOPTS_VALUE)
         timestamp += ic->start_time;
 
     /* if seeking requested, we execute it */
-    if (o->start_time != AV_NOPTS_VALUE) {
+    if (start_time != AV_NOPTS_VALUE) {
         int64_t seek_timestamp = timestamp;
 
         if (!(ic->iformat->flags & AVFMT_SEEK_TO_PTS)) {
@@ -968,8 +973,8 @@ int ifile_open(OptionsContext *o, const char *filename)
     f->ctx        = ic;
     f->index      = nb_input_files - 1;
     f->ist_index  = nb_input_streams - ic->nb_streams;
-    f->start_time = o->start_time;
-    f->recording_time = o->recording_time;
+    f->start_time = start_time;
+    f->recording_time = recording_time;
     f->input_sync_ref = o->input_sync_ref;
     f->input_ts_offset = o->input_ts_offset;
     f->ts_offset  = o->input_ts_offset - (copy_ts ? (start_at_zero && ic->start_time != AV_NOPTS_VALUE ? ic->start_time : 0) : timestamp);
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [FFmpeg-devel] [PATCH 20/20] fftools/ffmpeg_[de]mux: constify all uses of OptionsContext
  2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
                   ` (17 preceding siblings ...)
  2022-10-18 12:37 ` [FFmpeg-devel] [PATCH 19/20] fftools/ffmpeg_demux: stop modifying OptionsContext Anton Khirnov
@ 2022-10-18 12:37 ` Anton Khirnov
  18 siblings, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-10-18 12:37 UTC (permalink / raw)
  To: ffmpeg-devel

---
 fftools/ffmpeg.h          |  4 ++--
 fftools/ffmpeg_demux.c    |  6 +++---
 fftools/ffmpeg_mux_init.c | 42 +++++++++++++++++++--------------------
 fftools/ffmpeg_opt.c      |  2 +-
 4 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 8a50cd8d4b..0724914f27 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -715,7 +715,7 @@ int hwaccel_decode_init(AVCodecContext *avctx);
  */
 int of_stream_init(OutputFile *of, OutputStream *ost);
 int of_write_trailer(OutputFile *of);
-int of_open(OptionsContext *o, const char *filename);
+int of_open(const OptionsContext *o, const char *filename);
 void of_close(OutputFile **pof);
 
 /*
@@ -734,7 +734,7 @@ int64_t of_filesize(OutputFile *of);
 AVChapter * const *
 of_get_chapters(OutputFile *of, unsigned int *nb_chapters);
 
-int ifile_open(OptionsContext *o, const char *filename);
+int ifile_open(const OptionsContext *o, const char *filename);
 void ifile_close(InputFile **f);
 
 /**
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 4ce92862cb..eb9fa9132b 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -452,7 +452,7 @@ void ifile_close(InputFile **pf)
     av_freep(pf);
 }
 
-static const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *st,
+static const AVCodec *choose_decoder(const OptionsContext *o, AVFormatContext *s, AVStream *st,
                                      enum HWAccelID hwaccel_id, enum AVHWDeviceType hwaccel_device_type)
 
 {
@@ -514,7 +514,7 @@ static int guess_input_channel_layout(InputStream *ist)
 
 /* Add all the streams from the given input file to the global
  * list of input streams. */
-static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
+static void add_input_streams(const OptionsContext *o, AVFormatContext *ic)
 {
     int i, ret;
 
@@ -756,7 +756,7 @@ static void dump_attachment(AVStream *st, const char *filename)
     avio_close(out);
 }
 
-int ifile_open(OptionsContext *o, const char *filename)
+int ifile_open(const OptionsContext *o, const char *filename)
 {
     Demuxer   *d;
     InputFile *f;
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 7c19cb7442..0ddb7b94dc 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -97,7 +97,7 @@ static int check_opt_bitexact(void *ctx, const AVDictionary *opts,
     return 0;
 }
 
-static int choose_encoder(OptionsContext *o, AVFormatContext *s,
+static int choose_encoder(const OptionsContext *o, AVFormatContext *s,
                           OutputStream *ost, const AVCodec **enc)
 {
     enum AVMediaType type = ost->st->codecpar->codec_type;
@@ -170,7 +170,7 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV
     return ret;
 }
 
-static OutputStream *new_output_stream(Muxer *mux, OptionsContext *o,
+static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o,
                                        enum AVMediaType type, int source_index)
 {
     AVFormatContext *oc = mux->fc;
@@ -368,7 +368,7 @@ static OutputStream *new_output_stream(Muxer *mux, OptionsContext *o,
     return ost;
 }
 
-static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc,
+static char *get_ost_filters(const OptionsContext *o, AVFormatContext *oc,
                              OutputStream *ost)
 {
     AVStream *st = ost->st;
@@ -388,7 +388,7 @@ static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc,
                      "null" : "anull");
 }
 
-static void check_streamcopy_filters(OptionsContext *o, AVFormatContext *oc,
+static void check_streamcopy_filters(const OptionsContext *o, AVFormatContext *oc,
                                      const OutputStream *ost, enum AVMediaType type)
 {
     if (ost->filters_script || ost->filters) {
@@ -419,7 +419,7 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str)
     }
 }
 
-static OutputStream *new_video_stream(Muxer *mux, OptionsContext *o, int source_index)
+static OutputStream *new_video_stream(Muxer *mux, const OptionsContext *o, int source_index)
 {
     AVFormatContext *oc = mux->fc;
     AVStream *st;
@@ -658,7 +658,7 @@ static OutputStream *new_video_stream(Muxer *mux, OptionsContext *o, int source_
     return ost;
 }
 
-static OutputStream *new_audio_stream(Muxer *mux, OptionsContext *o, int source_index)
+static OutputStream *new_audio_stream(Muxer *mux, const OptionsContext *o, int source_index)
 {
     AVFormatContext *oc = mux->fc;
     AVStream *st;
@@ -756,7 +756,7 @@ static OutputStream *new_audio_stream(Muxer *mux, OptionsContext *o, int source_
     return ost;
 }
 
-static OutputStream *new_data_stream(Muxer *mux, OptionsContext *o, int source_index)
+static OutputStream *new_data_stream(Muxer *mux, const OptionsContext *o, int source_index)
 {
     OutputStream *ost;
 
@@ -769,7 +769,7 @@ static OutputStream *new_data_stream(Muxer *mux, OptionsContext *o, int source_i
     return ost;
 }
 
-static OutputStream *new_unknown_stream(Muxer *mux, OptionsContext *o, int source_index)
+static OutputStream *new_unknown_stream(Muxer *mux, const OptionsContext *o, int source_index)
 {
     OutputStream *ost;
 
@@ -782,14 +782,14 @@ static OutputStream *new_unknown_stream(Muxer *mux, OptionsContext *o, int sourc
     return ost;
 }
 
-static OutputStream *new_attachment_stream(Muxer *mux, OptionsContext *o, int source_index)
+static OutputStream *new_attachment_stream(Muxer *mux, const OptionsContext *o, int source_index)
 {
     OutputStream *ost = new_output_stream(mux, o, AVMEDIA_TYPE_ATTACHMENT, source_index);
     ost->finished    = 1;
     return ost;
 }
 
-static OutputStream *new_subtitle_stream(Muxer *mux, OptionsContext *o, int source_index)
+static OutputStream *new_subtitle_stream(Muxer *mux, const OptionsContext *o, int source_index)
 {
     AVStream *st;
     OutputStream *ost;
@@ -811,7 +811,7 @@ static OutputStream *new_subtitle_stream(Muxer *mux, OptionsContext *o, int sour
     return ost;
 }
 
-static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
+static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o,
                                Muxer *mux)
 {
     OutputStream *ost;
@@ -852,7 +852,7 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
     avfilter_inout_free(&ofilter->out_tmp);
 }
 
-static void map_auto_video(Muxer *mux, OptionsContext *o)
+static void map_auto_video(Muxer *mux, const OptionsContext *o)
 {
     AVFormatContext *oc = mux->fc;
     InputStream *ist;
@@ -898,7 +898,7 @@ static void map_auto_video(Muxer *mux, OptionsContext *o)
         new_video_stream(mux, o, idx);
 }
 
-static void map_auto_audio(Muxer *mux, OptionsContext *o)
+static void map_auto_audio(Muxer *mux, const OptionsContext *o)
 {
     AVFormatContext *oc = mux->fc;
     InputStream *ist;
@@ -937,7 +937,7 @@ static void map_auto_audio(Muxer *mux, OptionsContext *o)
         new_audio_stream(mux, o, idx);
 }
 
-static void map_auto_subtitle(Muxer *mux, OptionsContext *o)
+static void map_auto_subtitle(Muxer *mux, const OptionsContext *o)
 {
     AVFormatContext *oc = mux->fc;
     char *subtitle_codec_name = NULL;
@@ -975,7 +975,7 @@ static void map_auto_subtitle(Muxer *mux, OptionsContext *o)
         }
 }
 
-static void map_auto_data(Muxer *mux, OptionsContext *o)
+static void map_auto_data(Muxer *mux, const OptionsContext *o)
 {
     AVFormatContext *oc = mux->fc;
     /* Data only if codec id match */
@@ -989,7 +989,7 @@ static void map_auto_data(Muxer *mux, OptionsContext *o)
     }
 }
 
-static void map_manual(Muxer *mux, OptionsContext *o, const StreamMap *map)
+static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map)
 {
     InputStream *ist;
 
@@ -1062,7 +1062,7 @@ loop_end:
     }
 }
 
-static void create_streams(Muxer *mux, OptionsContext *o)
+static void create_streams(Muxer *mux, const OptionsContext *o)
 {
     int auto_disable_v = o->video_disable;
     int auto_disable_a = o->audio_disable;
@@ -1194,7 +1194,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u
     return 0;
 }
 
-static void of_add_attachments(Muxer *mux, OptionsContext *o)
+static void of_add_attachments(Muxer *mux, const OptionsContext *o)
 {
     OutputStream *ost;
     int err;
@@ -1487,7 +1487,7 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *o
 static int copy_metadata(const char *outspec, const char *inspec,
                          AVFormatContext *oc, AVFormatContext *ic,
                          int *metadata_global_manual, int *metadata_streams_manual,
-                         int *metadata_chapters_manual, OptionsContext *o)
+                         int *metadata_chapters_manual, const OptionsContext *o)
 {
     AVDictionary **meta_in = NULL;
     AVDictionary **meta_out = NULL;
@@ -1567,7 +1567,7 @@ static int copy_metadata(const char *outspec, const char *inspec,
     return 0;
 }
 
-static void copy_meta(Muxer *mux, OptionsContext *o)
+static void copy_meta(Muxer *mux, const OptionsContext *o)
 {
     OutputFile      *of = &mux->of;
     AVFormatContext *oc = mux->fc;
@@ -1703,7 +1703,7 @@ static int set_dispositions(OutputFile *of, AVFormatContext *ctx)
     return 0;
 }
 
-int of_open(OptionsContext *o, const char *filename)
+int of_open(const OptionsContext *o, const char *filename)
 {
     Muxer *mux;
     AVFormatContext *oc;
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 38916304bc..d8de283fc2 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -1186,7 +1186,7 @@ static const OptionGroupDef groups[] = {
 };
 
 static int open_files(OptionGroupList *l, const char *inout,
-                      int (*open_file)(OptionsContext*, const char*))
+                      int (*open_file)(const OptionsContext*, const char*))
 {
     int i, ret;
 
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/20] fftools/ffmpeg_mux_init: drop a duplicated block in copy_metadata()
  2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 14/20] fftools/ffmpeg_mux_init: drop a duplicated block in copy_metadata() Anton Khirnov
@ 2022-10-18 21:51   ` Michael Niedermayer
  2022-11-08 12:46     ` Anton Khirnov
  0 siblings, 1 reply; 24+ messages in thread
From: Michael Niedermayer @ 2022-10-18 21:51 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 1211 bytes --]

On Tue, Oct 18, 2022 at 02:36:55PM +0200, Anton Khirnov wrote:
> It does the same thing as the block right below it.
> ---
>  fftools/ffmpeg_mux_init.c | 10 ----------
>  1 file changed, 10 deletions(-)

This seems to make a difference for
ffmpeg -i meta.flac -map_metadata:s -1 -vcodec mpeg4 -t 0.1  -y /tmp/tmp3x.mkv

The metadata in meta.flac is a bit odd though

Input #0, flac, from '/home/michael/videos/meta.flac':
  Metadata:
    al              : Hyper fast Audio and Video encoder
                    : usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
                    : 
                    : Main options:
....
                    : -param1            <double> E.V.. scaler param 1
    x               : öäü?ß^x²€
    encoder         : Lavf54.0.100
  Duration: 00:03:07.66, start: 0.000000, bitrate: 706 kb/s
  Stream #0:0: Audio: flac, 48000 Hz, stereo, s16
At least one output file must be specified



[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

"Nothing to hide" only works if the folks in power share the values of
you and everyone you know entirely and always will -- Tom Scott


[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/20] fftools/ffmpeg_mux_init: drop a duplicated block in copy_metadata()
  2022-10-18 21:51   ` Michael Niedermayer
@ 2022-11-08 12:46     ` Anton Khirnov
  2022-11-14  9:24       ` Anton Khirnov
  2022-11-14 22:21       ` Michael Niedermayer
  0 siblings, 2 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-11-08 12:46 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Quoting Michael Niedermayer (2022-10-18 23:51:22)
> On Tue, Oct 18, 2022 at 02:36:55PM +0200, Anton Khirnov wrote:
> > It does the same thing as the block right below it.
> > ---
> >  fftools/ffmpeg_mux_init.c | 10 ----------
> >  1 file changed, 10 deletions(-)
> 
> This seems to make a difference for
> ffmpeg -i meta.flac -map_metadata:s -1 -vcodec mpeg4 -t 0.1  -y /tmp/tmp3x.mkv
> 
> The metadata in meta.flac is a bit odd though
> 
> Input #0, flac, from '/home/michael/videos/meta.flac':
>   Metadata:
>     al              : Hyper fast Audio and Video encoder
>                     : usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
>                     : 
>                     : Main options:
> ....
>                     : -param1            <double> E.V.. scaler param 1
>     x               : öäü?ß^x²€

Is this before or after?

If I'm reading the code correctly, no metadata should be copied after my
patch, which IMO is more consistent with the docs.

-- 
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/20] fftools/ffmpeg_mux_init: drop a duplicated block in copy_metadata()
  2022-11-08 12:46     ` Anton Khirnov
@ 2022-11-14  9:24       ` Anton Khirnov
  2022-11-14 22:21       ` Michael Niedermayer
  1 sibling, 0 replies; 24+ messages in thread
From: Anton Khirnov @ 2022-11-14  9:24 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Will push the rest of this set soonish if noone has further comments.

-- 
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/20] fftools/ffmpeg_mux_init: drop a duplicated block in copy_metadata()
  2022-11-08 12:46     ` Anton Khirnov
  2022-11-14  9:24       ` Anton Khirnov
@ 2022-11-14 22:21       ` Michael Niedermayer
  1 sibling, 0 replies; 24+ messages in thread
From: Michael Niedermayer @ 2022-11-14 22:21 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 1499 bytes --]

On Tue, Nov 08, 2022 at 01:46:57PM +0100, Anton Khirnov wrote:
> Quoting Michael Niedermayer (2022-10-18 23:51:22)
> > On Tue, Oct 18, 2022 at 02:36:55PM +0200, Anton Khirnov wrote:
> > > It does the same thing as the block right below it.
> > > ---
> > >  fftools/ffmpeg_mux_init.c | 10 ----------
> > >  1 file changed, 10 deletions(-)
> > 
> > This seems to make a difference for
> > ffmpeg -i meta.flac -map_metadata:s -1 -vcodec mpeg4 -t 0.1  -y /tmp/tmp3x.mkv
> > 
> > The metadata in meta.flac is a bit odd though
> > 
> > Input #0, flac, from '/home/michael/videos/meta.flac':
> >   Metadata:
> >     al              : Hyper fast Audio and Video encoder
> >                     : usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
> >                     : 
> >                     : Main options:
> > ....
> >                     : -param1            <double> E.V.. scaler param 1
> >     x               : öäü?ß^x²€
> 
> Is this before or after?
> 
> If I'm reading the code correctly, no metadata should be copied after my
> patch, which IMO is more consistent with the docs.

sorry for the delay, the metadata disappears as you describe after the patch

thx

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Into a blind darkness they enter who follow after the Ignorance,
they as if into a greater darkness enter who devote themselves
to the Knowledge alone. -- Isha Upanishad

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2022-11-14 22:21 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-18 12:36 [FFmpeg-devel] [PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 02/20] fftools/ffmpeg_demux: add demuxer private data Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 03/20] fftools/ffmpeg: drop init_input_threads() Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 04/20] fftools/ffmpeg: move closing the input file into a separate function Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 05/20] fftools/ffmpeg: drop free_input_threads() Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 06/20] fftools/ffmpeg: move threading fields from InputFile to Demuxer Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 07/20] fftools/ffmpeg: move duration/time_base " Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 08/20] fftools/ffmpeg_demux: do not log to the demuxer context Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 09/20] fftools/ffmpeg: move nb_streams_warn from InputFile to Demuxer Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 10/20] fftools/ffmpeg_demux: log when the demuxer thread terminates Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 11/20] fftools/ffmpeg: factor out copying metadata/chapters from of_open() Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 12/20] fftools/ffmpeg_mux_init: avoid modifying OptionsContext.chapters_input_file Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 13/20] fftools/ffmpeg_mux_init: constify metadata specifier arguments Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 14/20] fftools/ffmpeg_mux_init: drop a duplicated block in copy_metadata() Anton Khirnov
2022-10-18 21:51   ` Michael Niedermayer
2022-11-08 12:46     ` Anton Khirnov
2022-11-14  9:24       ` Anton Khirnov
2022-11-14 22:21       ` Michael Niedermayer
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 15/20] fftools/ffmpeg_mux_init: stop using OptionsContext as storage " Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 16/20] fftools/ffmpeg_mux_init: stop modifying some OptionsContext fields Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 17/20] fftools/ffmpeg_mux_init: move code creating streams into a new function Anton Khirnov
2022-10-18 12:36 ` [FFmpeg-devel] [PATCH 18/20] fftools/ffmpeg_mux_init: stop modifying OptionsContext.*_disable Anton Khirnov
2022-10-18 12:37 ` [FFmpeg-devel] [PATCH 19/20] fftools/ffmpeg_demux: stop modifying OptionsContext Anton Khirnov
2022-10-18 12:37 ` [FFmpeg-devel] [PATCH 20/20] fftools/ffmpeg_[de]mux: constify all uses of OptionsContext Anton Khirnov

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git