ffmpeg-devel
Threads by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
October 2022
- 88 participants
- 289 discussions
[PATCH 01/20] fftools/ffmpeg_opt: move opening input files to ffmpeg_demux.c
by Anton Khirnov 14 Nov '22
by Anton Khirnov 14 Nov '22
14 Nov '22
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
2
23
[PATCH v2] avcodec/tiff: add read support for compressed rgb floating point formats
by mindmark@gmail.com 14 Nov '22
by mindmark@gmail.com 14 Nov '22
14 Nov '22
From: Mark Reid <mindmark(a)gmail.com>
floating point uses a slightly different predictor technique describe here
http://chriscox.org/TIFFTN3d1.pdf
Here is a link the test files, if someone could add them to fate me
https://www.dropbox.com/s/fg59h2os4gb4wug/tiff_fate_samples.zip
---
libavcodec/tiff.c | 68 ++++++++++++++++++++++
tests/fate/image.mak | 20 ++++++-
tests/ref/fate/tiff-lzw-rgbaf32le | 6 ++
tests/ref/fate/tiff-lzw-rgbf32le | 6 ++
tests/ref/fate/tiff-uncompressed-rgbaf32le | 6 ++
tests/ref/fate/tiff-uncompressed-rgbf32le | 6 ++
tests/ref/fate/tiff-zip-rgbaf32le | 6 ++
tests/ref/fate/tiff-zip-rgbf32le | 6 ++
8 files changed, 123 insertions(+), 1 deletion(-)
create mode 100644 tests/ref/fate/tiff-lzw-rgbaf32le
create mode 100644 tests/ref/fate/tiff-lzw-rgbf32le
create mode 100644 tests/ref/fate/tiff-uncompressed-rgbaf32le
create mode 100644 tests/ref/fate/tiff-uncompressed-rgbf32le
create mode 100644 tests/ref/fate/tiff-zip-rgbaf32le
create mode 100644 tests/ref/fate/tiff-zip-rgbf32le
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index 3a610ada85..ce31a40e37 100644
--- a/libavcodec/tiff.c
+++ b/libavcodec/tiff.c
@@ -2249,6 +2249,74 @@ again:
}
}
+ /* Floating point predictor
+ TIFF Technical Note 3 http://chriscox.org/TIFFTN3d1.pdf */
+ if (s->predictor == 3) {
+ int channels = s->bppcount;
+ int group_size;
+ uint8_t *tmpbuf;
+ int bpc;
+
+ dst = five_planes ? five_planes : p->data[plane];
+ soff = s->bpp >> 3;
+ if (s->planar) {
+ soff = FFMAX(soff / s->bppcount, 1);
+ channels = 1;
+ }
+ ssize = s->width * soff;
+ bpc = FFMAX(soff / s->bppcount, 1); /* Bytes per component */
+ group_size = s->width * channels;
+
+ tmpbuf = av_malloc(ssize);
+ if (!tmpbuf)
+ return AVERROR(ENOMEM);
+
+ if (s->avctx->pix_fmt == AV_PIX_FMT_RGBF32LE ||
+ s->avctx->pix_fmt == AV_PIX_FMT_RGBAF32LE) {
+ for (i = 0; i < decoded_height; i++) {
+ /* Copy first sample byte for each channel */
+ for (j = 0; j < channels; j++)
+ tmpbuf[j] = dst[j];
+
+ /* Decode horizontal differences */
+ for (j = channels; j < ssize; j++)
+ tmpbuf[j] = dst[j] + tmpbuf[j-channels];
+
+ /* Combine shuffled bytes from their separate groups. Each
+ byte of every floating point value in a row of pixels is
+ split and combined into separate groups. A group of all
+ the sign/exponents bytes in the row and groups for each
+ of the upper, mid, and lower mantissa bytes in the row. */
+ for (j = 0; j < group_size; j++) {
+ for (int k = 0; k < bpc; k++) {
+ dst[bpc * j + k] = tmpbuf[(bpc - k - 1) * group_size + j];
+ }
+ }
+ dst += stride;
+ }
+ } else if (s->avctx->pix_fmt == AV_PIX_FMT_RGBF32BE ||
+ s->avctx->pix_fmt == AV_PIX_FMT_RGBAF32BE) {
+ /* Same as LE only the shuffle at the end is reversed */
+ for (i = 0; i < decoded_height; i++) {
+ for (j = 0; j < channels; j++)
+ tmpbuf[j] = dst[j];
+
+ for (j = channels; j < ssize; j++)
+ tmpbuf[j] = dst[j] + tmpbuf[j-channels];
+
+ for (j = 0; j < group_size; j++) {
+ for (int k = 0; k < bpc; k++) {
+ dst[bpc * j + k] = tmpbuf[k * group_size + j];
+ }
+ }
+ dst += stride;
+ }
+ } else {
+ av_log(s->avctx, AV_LOG_ERROR, "unsupported floating point pixel format\n");
+ }
+ av_free(tmpbuf);
+ }
+
if (s->photometric == TIFF_PHOTOMETRIC_WHITE_IS_ZERO) {
int c = (s->avctx->pix_fmt == AV_PIX_FMT_PAL8 ? (1<<s->bpp) - 1 : 255);
dst = p->data[plane];
diff --git a/tests/fate/image.mak b/tests/fate/image.mak
index 03e794dc48..167c8ccf2c 100644
--- a/tests/fate/image.mak
+++ b/tests/fate/image.mak
@@ -501,7 +501,25 @@ fate-tiff-fax-g3: CMD = framecrc -i $(TARGET_SAMPLES)/CCITT_fax/G31D.TIF
FATE_TIFF += fate-tiff-fax-g3s
fate-tiff-fax-g3s: CMD = framecrc -i $(TARGET_SAMPLES)/CCITT_fax/G31DS.TIF
-FATE_TIFF-$(call DEMDEC, IMAGE2, TIFF) += $(FATE_TIFF)
+FATE_TIFF += fate-tiff-uncompressed-rgbf32le
+fate-tiff-uncompressed-rgbf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/uncompressed_rgbf32le.tif
+
+FATE_TIFF += fate-tiff-uncompressed-rgbaf32le
+fate-tiff-uncompressed-rgbaf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/uncompressed_rgbaf32le.tif
+
+FATE_TIFF += fate-tiff-lzw-rgbf32le
+fate-tiff-lzw-rgbf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/lzw_rgbf32le.tif
+
+FATE_TIFF += fate-tiff-lzw-rgbaf32le
+fate-tiff-lzw-rgbaf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/lzw_rgbaf32le.tif
+
+FATE_TIFF += fate-tiff-zip-rgbf32le
+fate-tiff-zip-rgbf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/zip_rgbf32le.tif
+
+FATE_TIFF += fate-tiff-zip-rgbaf32le
+fate-tiff-zip-rgbaf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/zip_rgbaf32le.tif
+
+FATE_TIFF-$(call FRAMECRC, IMAGE2, TIFF) += $(FATE_TIFF)
FATE_IMAGE_FRAMECRC += $(FATE_TIFF-yes)
fate-tiff: $(FATE_TIFF-yes)
diff --git a/tests/ref/fate/tiff-lzw-rgbaf32le b/tests/ref/fate/tiff-lzw-rgbaf32le
new file mode 100644
index 0000000000..c99aa02ef0
--- /dev/null
+++ b/tests/ref/fate/tiff-lzw-rgbaf32le
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x8
+#sar 0: 0/1
+0, 0, 0, 1, 1024, 0x877e1d5f
diff --git a/tests/ref/fate/tiff-lzw-rgbf32le b/tests/ref/fate/tiff-lzw-rgbf32le
new file mode 100644
index 0000000000..a6d3fabfda
--- /dev/null
+++ b/tests/ref/fate/tiff-lzw-rgbf32le
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x8
+#sar 0: 0/1
+0, 0, 0, 1, 768, 0xad26ed90
diff --git a/tests/ref/fate/tiff-uncompressed-rgbaf32le b/tests/ref/fate/tiff-uncompressed-rgbaf32le
new file mode 100644
index 0000000000..c99aa02ef0
--- /dev/null
+++ b/tests/ref/fate/tiff-uncompressed-rgbaf32le
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x8
+#sar 0: 0/1
+0, 0, 0, 1, 1024, 0x877e1d5f
diff --git a/tests/ref/fate/tiff-uncompressed-rgbf32le b/tests/ref/fate/tiff-uncompressed-rgbf32le
new file mode 100644
index 0000000000..a6d3fabfda
--- /dev/null
+++ b/tests/ref/fate/tiff-uncompressed-rgbf32le
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x8
+#sar 0: 0/1
+0, 0, 0, 1, 768, 0xad26ed90
diff --git a/tests/ref/fate/tiff-zip-rgbaf32le b/tests/ref/fate/tiff-zip-rgbaf32le
new file mode 100644
index 0000000000..c99aa02ef0
--- /dev/null
+++ b/tests/ref/fate/tiff-zip-rgbaf32le
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x8
+#sar 0: 0/1
+0, 0, 0, 1, 1024, 0x877e1d5f
diff --git a/tests/ref/fate/tiff-zip-rgbf32le b/tests/ref/fate/tiff-zip-rgbf32le
new file mode 100644
index 0000000000..a6d3fabfda
--- /dev/null
+++ b/tests/ref/fate/tiff-zip-rgbf32le
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x8
+#sar 0: 0/1
+0, 0, 0, 1, 768, 0xad26ed90
--
2.31.1.windows.1
5
5
Subtitle Filtering 2022
=======================
This is a substantial update to the earlier subtitle filtering patch series.
A primary goal has been to address others' concerns as much as possible on
one side and to provide more clarity and control over the way things are
working. Clarity is is specifically important to allow for a better
understanding of the need for a subtitle start pts value that can be
different from the frame's pts value. This is done by refactoring the
subtitle timing fields in AVFrame, adding a frame field to indicate repeated
subtitle frames, and finally the full removal of the heartbeat
functionality, replaced by a new 'subfeed' filter that provides different
modes for arbitrating subtitle frames in a filter graph. Finally, each
subtitle filter's documentation has been amended by a section describing the
filter's timeline behavior (in v2 update).
The update also includes major improvements to graphicsub2text and lots of
other details.
Versioning is restarting at v1 due to the new submission procedure.
All changes from previous version v24:
AVFrame
=======
* Removed sub_start_time The start time is now added to the subtitle
start_pts during decoding The sub_end_time field is adjusted accordingly
* Renamed sub_end_time to duration which it is effectively after removing
the start_time
* Added a sub-struct 'subtitle_timing' to av frame Contains subtitle_pts
renamed to 'subtitle_timing.start_pts' and 'subtitle_timing.duration'
* Change both fields to (fixed) time_base AV_TIMEBASE
* add repeat_sub field provides a clear indication whether a subtitle frame
is an actual subtitle event or a repeated subtitle frame in a filter
graph
Heartbeat Removal
=================
* completely removed the earlier heartbeat implementation
* filtering arbitration is now implemented in a new filter: 'subfeed'
* subfeed will be auto-inserted for compatiblity with sub2video command
lines
* the new behavior is not exactly identical to the earlier behavior, but it
basically allows to achieve the same results
New 'subfeed' Filter
====================
* a versatile filter for solving all kinds of problems with subtile frame
flow in filter graphs
* Can be inserted at any position in a graph
* Auto-inserted for sub2video command lines (in repeat-mode)
* Allows duration fixup delay input frames with unknown duration and infer
duration from start of subsequent frame
* Provides multiple modes of operation:
* repeat mode (default) Queues input frames Outputs frames at a fixed
(configurable) rate Either sends a matching input frame (repeatedly) or
empty frames otherwise
* scatter mode similar to repeat mode, but splits input frames by
duration into small segments with same content
* forward mode No fixed output rate Useful in combination with duration
fixup or overlap fixup
ffmpeg Tool Changes
===================
* delay subtitle output stream initialization (like for audio and video)
This is needed for example when a format header depends on having
received an initial frame to derive certain header values from
* decoding: set subtitle frame size from decoding context
* re-init graph when subtitle size changes
* always insert subscale filter for sub2video command lines (to ensure
correct scaling)
Subtitle Encoding
=================
* ignore repeated frames for encoding based on repeat_sub field in AVFrame
* support multi-area encoding for text subtitles Subtitle OCR can create
multiple areas at different positions. Previously, the texts were always
squashed into a single area ('subtitle rect'), which was not ideal.
Multiple text areas are now generally supported:
* ASS Encoder Changed to use the 'receive_packet' encoding API A single
frame with multiple text areas will create multiple packets now
* All other text subtitle encoders A newline is inserted between the text
from multiple areas
graphicsub2text (OCR)
=====================
* enhanced preprocessing
* using elbg algorithm for color quantization
* detection and removal of text outlines
* map-based identification of colors per word (text, outline, background)
* add option for duration fixup
* add option to dump preprocessing bitmaps
* Recognize formatting and apply as ASS inline styles
* per word(!)
* paragraph alignment
* positioning
* font names
* font size
* font style (italic, underline, bold)
* text color, outline color
Other Filter Changes
====================
* all: Make sure to forward all link properties (time base, frame rate, w,
h) where appropriate
* overlaytextsubs: request frames on the subtitle input
* overlaytextsubs: disable read-order checking
* overlaytextsubs: improve implementation of render_latest_only
* overlaytextsubs: ensure equal in/out video formats
* splitcc: derive framerate from realtime_latency
* graphicsub2video: implement caching of converted frames
* graphicsub2video: use 1x1 output frame size as long as subtitle size is
unknown (0x0)
Plus a dozen of things I forgot..
softworkz (24):
avcodec,avutil: Move enum AVSubtitleType to avutil, add new and
deprecate old values
avutil/frame: Prepare AVFrame for subtitle handling
avcodec/subtitles: Introduce new frame-based subtitle decoding API
avfilter/subtitles: Update vf_subtitles to use new decoding api
avcodec,avutil: Move ass helper functions to avutil as avpriv_ and
extend ass dialog parsing
avcodec/subtitles: Migrate subtitle encoders to frame-based API
avcodec/subtitles: Replace deprecated enum values
fftools/play,probe: Adjust for subtitle changes
avfilter/subtitles: Add subtitles.c for subtitle frame allocation
avfilter/avfilter: Handle subtitle frames
avfilter/avfilter: Fix hardcoded input index
avfilter/sbuffer: Add sbuffersrc and sbuffersink filters
avfilter/overlaygraphicsubs: Add overlaygraphicsubs and
graphicsub2video filters
avfilter/overlaytextsubs: Add overlaytextsubs and textsubs2video
filters
avfilter/textmod: Add textmod, censor and show_speaker filters
avfilter/stripstyles: Add stripstyles filter
avfilter/splitcc: Add splitcc filter for closed caption handling
avfilter/graphicsub2text: Add new graphicsub2text filter (OCR)
avfilter/subscale: Add filter for scaling and/or re-arranging
graphical subtitles
avfilter/subfeed: add subtitle feed filter
fftools/ffmpeg: Introduce subtitle filtering new frame-based subtitle
encoding
avutil/ass_split: Add parsing of hard-space tags (\h)
avcodec/webvttenc: convert hard-space tags to
doc/APIchanges: update for subtitle filtering changes
configure | 7 +-
doc/APIchanges | 24 +
doc/filters.texi | 756 ++++++++++
fftools/ffmpeg.c | 493 +++----
fftools/ffmpeg.h | 13 +-
fftools/ffmpeg_filter.c | 235 +++-
fftools/ffmpeg_hw.c | 2 +-
fftools/ffmpeg_opt.c | 3 +-
fftools/ffplay.c | 102 +-
fftools/ffprobe.c | 47 +-
libavcodec/Makefile | 56 +-
libavcodec/ass.h | 144 +-
libavcodec/assdec.c | 4 +-
libavcodec/assenc.c | 191 ++-
libavcodec/avcodec.h | 32 +-
libavcodec/ccaption_dec.c | 19 +-
libavcodec/codec_desc.c | 11 +
libavcodec/codec_desc.h | 8 +
libavcodec/decode.c | 56 +-
libavcodec/dvbsubdec.c | 2 +-
libavcodec/dvbsubenc.c | 96 +-
libavcodec/dvdsubdec.c | 2 +-
libavcodec/dvdsubenc.c | 102 +-
libavcodec/encode.c | 57 +-
libavcodec/internal.h | 22 +
libavcodec/jacosubdec.c | 2 +-
libavcodec/libaribb24.c | 2 +-
libavcodec/libzvbi-teletextdec.c | 14 +-
libavcodec/microdvddec.c | 7 +-
libavcodec/movtextdec.c | 3 +-
libavcodec/movtextenc.c | 126 +-
libavcodec/mpl2dec.c | 2 +-
libavcodec/pgssubdec.c | 2 +-
libavcodec/realtextdec.c | 2 +-
libavcodec/samidec.c | 2 +-
libavcodec/srtdec.c | 2 +-
libavcodec/srtenc.c | 116 +-
libavcodec/subviewerdec.c | 2 +-
libavcodec/tests/avcodec.c | 2 -
libavcodec/textdec.c | 4 +-
libavcodec/ttmlenc.c | 114 +-
libavcodec/utils.c | 184 +++
libavcodec/version.h | 2 +-
libavcodec/webvttdec.c | 2 +-
libavcodec/webvttenc.c | 100 +-
libavcodec/xsubdec.c | 2 +-
libavcodec/xsubenc.c | 88 +-
libavfilter/Makefile | 16 +
libavfilter/allfilters.c | 14 +
libavfilter/avfilter.c | 30 +-
libavfilter/avfilter.h | 11 +
libavfilter/avfiltergraph.c | 5 +
libavfilter/buffersink.c | 54 +
libavfilter/buffersink.h | 7 +
libavfilter/buffersrc.c | 72 +
libavfilter/buffersrc.h | 1 +
libavfilter/formats.c | 22 +
libavfilter/formats.h | 3 +
libavfilter/internal.h | 19 +-
libavfilter/sf_graphicsub2text.c | 1132 +++++++++++++++
libavfilter/sf_splitcc.c | 385 +++++
libavfilter/sf_stripstyles.c | 209 +++
libavfilter/sf_subfeed.c | 366 +++++
libavfilter/sf_subscale.c | 884 ++++++++++++
libavfilter/sf_textmod.c | 710 ++++++++++
libavfilter/subtitles.c | 63 +
libavfilter/subtitles.h | 44 +
libavfilter/vf_overlaygraphicsubs.c | 765 ++++++++++
libavfilter/vf_overlaytextsubs.c | 671 +++++++++
libavfilter/vf_subtitles.c | 56 +-
libavutil/Makefile | 4 +
{libavcodec => libavutil}/ass.c | 91 +-
libavutil/ass_internal.h | 135 ++
{libavcodec => libavutil}/ass_split.c | 37 +-
.../ass_split_internal.h | 32 +-
libavutil/frame.c | 211 ++-
libavutil/frame.h | 85 +-
libavutil/subfmt.c | 45 +
libavutil/subfmt.h | 115 ++
libavutil/version.h | 3 +-
tests/ref/fate/filter-overlay-dvdsub-2397 | 182 +--
tests/ref/fate/mov-mp4-ttml-dfxp | 8 +-
tests/ref/fate/mov-mp4-ttml-stpp | 8 +-
tests/ref/fate/sub-dvb | 162 ++-
tests/ref/fate/sub-textenc | 10 +-
tests/ref/fate/sub-ttmlenc | 8 +-
tests/ref/fate/sub-webvttenc | 10 +-
tests/ref/fate/sub2video | 1091 ++++++++++++++-
tests/ref/fate/sub2video_basic | 1239 +++++++++++++++--
tests/ref/fate/sub2video_time_limited | 78 +-
90 files changed, 10991 insertions(+), 1366 deletions(-)
create mode 100644 libavfilter/sf_graphicsub2text.c
create mode 100644 libavfilter/sf_splitcc.c
create mode 100644 libavfilter/sf_stripstyles.c
create mode 100644 libavfilter/sf_subfeed.c
create mode 100644 libavfilter/sf_subscale.c
create mode 100644 libavfilter/sf_textmod.c
create mode 100644 libavfilter/subtitles.c
create mode 100644 libavfilter/subtitles.h
create mode 100644 libavfilter/vf_overlaygraphicsubs.c
create mode 100644 libavfilter/vf_overlaytextsubs.c
rename {libavcodec => libavutil}/ass.c (65%)
create mode 100644 libavutil/ass_internal.h
rename {libavcodec => libavutil}/ass_split.c (93%)
rename libavcodec/ass_split.h => libavutil/ass_split_internal.h (86%)
create mode 100644 libavutil/subfmt.c
create mode 100644 libavutil/subfmt.h
base-commit: c936c319bd54f097cc1d75b1ee1c407d53215d71
Published-As: https://github.com/ffstaging/FFmpeg/releases/tag/pr-ffstaging-18%2Fsoftwork…
Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-18/softworkz/submit_subfiltering-v1
Pull-Request: https://github.com/ffstaging/FFmpeg/pull/18
--
ffmpeg-codebot
13
216
[PATCH] x86/intreadwrite: use intrinsics instead of inline asm for AV_ZERO128
by James Almer 13 Nov '22
by James Almer 13 Nov '22
13 Nov '22
When called inside a loop, the inline asm version results in one pxor
unnecessarely emitted per iteration, as the contents of the __asm__() block are
opaque to the compiler's instruction scheduler.
This is not the case with intrinsics, where pxor will be emitted once with any
half decent compiler.
The code can be adapted to also work with MSVC, but for now, it will work with
the same compilers previously supported (GCC, Clang, etc).
Signed-off-by: James Almer <jamrial(a)gmail.com>
---
configure | 3 +++
libavutil/x86/intreadwrite.h | 15 +++++++--------
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/configure b/configure
index c5a466657f..5bb83f5b5a 100755
--- a/configure
+++ b/configure
@@ -2222,6 +2222,7 @@ HEADERS_LIST="
INTRINSICS_LIST="
intrinsics_neon
+ intrinsics_sse2
"
COMPLEX_FUNCS="
@@ -2636,6 +2637,7 @@ armv6t2_deps="arm"
armv8_deps="aarch64"
neon_deps_any="aarch64 arm"
intrinsics_neon_deps="neon"
+intrinsics_sse2_deps="sse2"
vfp_deps_any="aarch64 arm"
vfpv3_deps="vfp"
setend_deps="arm"
@@ -6207,6 +6209,7 @@ elif enabled loongarch; then
fi
check_cc intrinsics_neon arm_neon.h "int16x8_t test = vdupq_n_s16(0)"
+check_cc intrinsics_sse2 emmintrin.h "__m128i test = _mm_setzero_si128()"
check_ldflags -Wl,--as-needed
check_ldflags -Wl,-z,noexecstack
diff --git a/libavutil/x86/intreadwrite.h b/libavutil/x86/intreadwrite.h
index 40f375b013..4a03e60fc6 100644
--- a/libavutil/x86/intreadwrite.h
+++ b/libavutil/x86/intreadwrite.h
@@ -21,6 +21,9 @@
#ifndef AVUTIL_X86_INTREADWRITE_H
#define AVUTIL_X86_INTREADWRITE_H
+#if HAVE_INTRINSICS_SSE2
+#include <emmintrin.h>
+#endif
#include <stdint.h>
#include "config.h"
#include "libavutil/attributes.h"
@@ -79,20 +82,16 @@ static av_always_inline void AV_COPY128(void *d, const void *s)
#endif /* __SSE__ */
-#ifdef __SSE2__
+#if HAVE_INTRINSICS_SSE2 && defined(__SSE2__)
#define AV_ZERO128 AV_ZERO128
static av_always_inline void AV_ZERO128(void *d)
{
- struct v {uint64_t v[2];};
-
- __asm__("pxor %%xmm0, %%xmm0 \n\t"
- "movdqa %%xmm0, %0 \n\t"
- : "=m"(*(struct v*)d)
- :: "xmm0");
+ __m128i zero = _mm_setzero_si128();
+ _mm_store_si128(d, zero);
}
-#endif /* __SSE2__ */
+#endif /* HAVE_INTRINSICS_SSE2 && defined(__SSE2__) */
#endif /* HAVE_MMX */
--
2.38.1
1
1
12 Nov '22
The DVD subtitle parser handles two types of packets: "normal"
packets with a 16-bit length, and HD-DVD packets that set the
16-bit length to 0 and encode a 32-bit length in the next four
bytes. This implies that HD-DVD packets are at least six bytes
long, but the code didn't actually verify this.
The faulty length check results in an out of bounds read for
zero-length "normal" packets that occur in the input, which are
only 2 bytes long, but get misinterpreted as an HD-DVD packet.
When this happens the parser reads packet_len from beyond the
end of the input buffer. The subtitle stream is not correctly
decoded after this point due to the garbage packet_len.
Fixing this is pretty simple: fix the length check so packets
less than 6 bytes long will not be mistakenly parsed as HD-DVD
packets.
Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0(a)gmail.com>
---
libavcodec/dvdsub_parser.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libavcodec/dvdsub_parser.c b/libavcodec/dvdsub_parser.c
index 44738a73d6..8871b6a383 100644
--- a/libavcodec/dvdsub_parser.c
+++ b/libavcodec/dvdsub_parser.c
@@ -43,7 +43,7 @@ static int dvdsub_parse(AVCodecParserContext *s,
*poutbuf_size = buf_size;
if (pc->packet_index == 0) {
- if (buf_size < 2 || AV_RB16(buf) && buf_size < 6) {
+ if (buf_size < 2 || (AV_RB16(buf) == 0 && buf_size < 6)) {
if (buf_size)
av_log(avctx, AV_LOG_DEBUG, "Parser input %d too small\n", buf_size);
return buf_size;
--
2.35.1
2
1
[PATCH] avcodec: add D3D12VA hardware accelerated H264, HEVC, VP9, and AV1 decoding
by Wu Jianhua 11 Nov '22
by Wu Jianhua 11 Nov '22
11 Nov '22
[PATCH] avcodec: add D3D12VA hardware accelerated H264, HEVC, VP9, and AV1 decoding
Patch attached.
4
12
[PATCH] lavc/hevc_ps: fix process failed when SPS before VPS in hvcC
by 1035567130@qq.com 11 Nov '22
by 1035567130@qq.com 11 Nov '22
11 Nov '22
From: Wang Yaqiang <wangyaqiang03(a)kuaishou.com>
In some videos, SPS will be stored before VPS in hvcC box,
parse SPS does not depend on VPS, so the video is expected to be processed normally.
Added "parsed_vps" parameter to indicate whether VPS have been parsed.
Only VPS have been parsed can be verified during SPS parsing.
Signed-off-by: Wang Yaqiang <wangyaqiang03(a)kuaishou.com>
---
libavcodec/hevc_ps.c | 4 ++--
libavcodec/hevc_ps.h | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c
index f665d8053c..71835d0f36 100644
--- a/libavcodec/hevc_ps.c
+++ b/libavcodec/hevc_ps.c
@@ -464,7 +464,7 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx,
if (!vps_buf)
return AVERROR(ENOMEM);
vps = (HEVCVPS*)vps_buf->data;
-
+ ps->parsed_vps = 1;
av_log(avctx, AV_LOG_DEBUG, "Decoding VPS\n");
nal_size = gb->buffer_end - gb->buffer;
@@ -1272,7 +1272,7 @@ int ff_hevc_decode_nal_sps(GetBitContext *gb, AVCodecContext *avctx,
ret = ff_hevc_parse_sps(sps, gb, &sps_id,
apply_defdispwin,
- ps->vps_list, avctx);
+ ps->parsed_vps ? ps->vps_list : NULL, avctx);
if (ret < 0) {
av_buffer_unref(&sps_buf);
return ret;
diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h
index 2a1bbf6489..e6b694e7f3 100644
--- a/libavcodec/hevc_ps.h
+++ b/libavcodec/hevc_ps.h
@@ -333,6 +333,7 @@ typedef struct HEVCParamSets {
const HEVCVPS *vps;
const HEVCSPS *sps;
const HEVCPPS *pps;
+ int parsed_vps; // indicates VPS has been parsed
} HEVCParamSets;
/**
--
2.33.0
4
10
Hi,
The attached patch adds rendering of ATSC A/53 captions as HEVC SEI messages.
The option name/implementation is aligned with the corresponding libx264 feature.
Thanks
Eran
2
8
[PATCH 1/2] avformat/file: Add a specialized url_check callback for pipe protocol
by Neil Roberts 09 Nov '22
by Neil Roberts 09 Nov '22
09 Nov '22
Using file_check for the pipe protocol doesn't make sense. For example,
for a URL like “pipe:0” it would end up checking whether the “pipe:0”
file exists. This patch instead makes it check the access modes on the
corresponding file descriptor using fcntl.
Signed-off-by: Neil Roberts <bpeeluk(a)yahoo.co.uk>
---
libavformat/file.c | 40 +++++++++++++++++++++++++++++++++++++---
1 file changed, 37 insertions(+), 3 deletions(-)
diff --git a/libavformat/file.c b/libavformat/file.c
index 98c9e81bcb..f17d219cb2 100644
--- a/libavformat/file.c
+++ b/libavformat/file.c
@@ -375,9 +375,8 @@ const URLProtocol ff_file_protocol = {
#if CONFIG_PIPE_PROTOCOL
-static int pipe_open(URLContext *h, const char *filename, int flags)
+static int pipe_get_fd(const char *filename, int flags)
{
- FileContext *c = h->priv_data;
int fd;
char *final;
av_strstart(filename, "pipe:", &filename);
@@ -390,6 +389,14 @@ static int pipe_open(URLContext *h, const char *filename, int flags)
fd = 0;
}
}
+
+ return fd;
+}
+
+static int pipe_open(URLContext *h, const char *filename, int flags)
+{
+ FileContext *c = h->priv_data;
+ int fd = pipe_get_fd(filename, flags);
#if HAVE_SETMODE
setmode(fd, O_BINARY);
#endif
@@ -398,13 +405,40 @@ static int pipe_open(URLContext *h, const char *filename, int flags)
return 0;
}
+static int pipe_check(URLContext *h, int mask)
+{
+ int fd = pipe_get_fd(h->filename, mask);
+ int status_flags = fcntl(fd, F_GETFL);
+ int access;
+
+ if (status_flags == -1)
+ return AVERROR(errno);
+
+ switch (status_flags & O_ACCMODE) {
+ case O_RDONLY:
+ access = AVIO_FLAG_READ;
+ break;
+ case O_WRONLY:
+ access = AVIO_FLAG_WRITE;
+ break;
+ case O_RDWR:
+ access = AVIO_FLAG_READ | AVIO_FLAG_WRITE;
+ break;
+ default:
+ access = 0;
+ break;
+ }
+
+ return access & mask;
+}
+
const URLProtocol ff_pipe_protocol = {
.name = "pipe",
.url_open = pipe_open,
.url_read = file_read,
.url_write = file_write,
.url_get_file_handle = file_get_handle,
- .url_check = file_check,
+ .url_check = pipe_check,
.priv_data_size = sizeof(FileContext),
.priv_data_class = &pipe_class,
.default_whitelist = "crypto,data"
--
2.37.2
2
5
From: Linjie Fu <linjie.fu(a)intel.com>
Wrap the procedure of getting the hardware config from a pixel format
into a function.
Signed-off-by: Linjie Fu <linjie.fu(a)intel.com>
Signed-off-by: Fei Wang <fei.w.wang(a)intel.com>
---
libavcodec/decode.c | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 75373989c6..3b69426c09 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -1156,6 +1156,24 @@ static void hwaccel_uninit(AVCodecContext *avctx)
av_buffer_unref(&avctx->hw_frames_ctx);
}
+static const AVCodecHWConfigInternal *get_hw_config(AVCodecContext *avctx, enum AVPixelFormat fmt)
+{
+ const AVCodecHWConfigInternal *hw_config;
+
+ if (!ffcodec(avctx->codec)->hw_configs)
+ return NULL;
+
+ for (int i = 0;; i++) {
+ hw_config = ffcodec(avctx->codec)->hw_configs[i];
+ if (!hw_config)
+ return NULL;
+ if (hw_config->public.pix_fmt == fmt)
+ return hw_config;
+ }
+
+ return NULL;
+}
+
int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
{
const AVPixFmtDescriptor *desc;
@@ -1213,18 +1231,7 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
break;
}
- if (ffcodec(avctx->codec)->hw_configs) {
- for (i = 0;; i++) {
- hw_config = ffcodec(avctx->codec)->hw_configs[i];
- if (!hw_config)
- break;
- if (hw_config->public.pix_fmt == user_choice)
- break;
- }
- } else {
- hw_config = NULL;
- }
-
+ hw_config = get_hw_config(avctx, user_choice);
if (!hw_config) {
// No config available, so no extra setup required.
ret = user_choice;
--
2.25.1
4
8