[FFmpeg-devel] [PATCH] ffmpeg_opt: remove the stats metadata added by mkvmerge.
Nicolas George
george at nsup.org
Thu Apr 6 13:27:43 EEST 2017
They are probably not valid for the resulting file.
They look like this:
BPS : 40665
BPS-eng : 40665
DURATION : 00:00:20.000000000
DURATION-eng : 00:00:20.000000000
NUMBER_OF_FRAMES: 10
NUMBER_OF_FRAMES-eng: 10
NUMBER_OF_BYTES : 101664
NUMBER_OF_BYTES-eng: 101664
_STATISTICS_WRITING_APP: mkvmerge v9.8.0 ('Kuglblids') 64bit
_STATISTICS_WRITING_APP-eng: mkvmerge v9.8.0 ('Kuglblids') 64bit
_STATISTICS_WRITING_DATE_UTC: 2017-04-06 08:22:08
_STATISTICS_WRITING_DATE_UTC-eng: 2017-04-06 08:22:08
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
_STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Signed-off-by: Nicolas George <george at nsup.org>
---
ffmpeg_opt.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 48 insertions(+), 1 deletion(-)
Note: as written in a comment, this code ignores the return value of
av_dict_set(), because the surrounding code ignores the return value of
av_dict_copy(). A lot of unchecked errors happen in this function, but I am
not reworking a 2700-lines function today.
diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index d1fe8742ff..f72f38796a 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -497,6 +497,53 @@ static void parse_meta_type(char *arg, char *type, int *index, const char **stre
*type = 'g';
}
+/**
+ * Copy a dictionary except the stats metadata added by mkvmerge.
+ * They are probably not valid for the resulting file.
+ *
+ * FIXME Return values are ignored by the surrounding code and here.
+ */
+static void dict_copy_nostats(AVDictionary **dst, const AVDictionary *src)
+{
+ AVDictionaryEntry *t;
+ const char *tags = NULL, *p, *q;
+ size_t len;
+
+ t = av_dict_get(src, "_STATISTICS_TAGS", NULL, AV_DICT_MATCH_CASE);
+ if (t)
+ tags = t->value;
+ t = NULL;
+ while ((t = av_dict_get(src, "", t, AV_DICT_IGNORE_SUFFIX))) {
+ if (av_strstart(t->key, "_STATISTICS_", NULL))
+ continue;
+ if (tags) {
+ /* tags is a space-separated list of stats tags */
+ p = tags;
+ while (*p) {
+ q = strchr(p, ' ');
+ len = q ? q - p : strlen(p);
+ if (!q)
+ q = p + strlen(p);
+#define ff_islower(c) ((unsigned)((c) - 'a') < 26)
+ if (!memcmp(t->key, p, len) &&
+ (!t->key[len] ||
+ /* also remove TAG-lng */
+ (t->key[len] == '-' &&
+ ff_islower(t->key[len + 1]) &&
+ ff_islower(t->key[len + 2]) &&
+ ff_islower(t->key[len + 3]) &&
+ !t->key[len + 4])))
+ break;
+#undef ff_islower
+ for (p += len; *p == ' '; p++);
+ }
+ if (*p) /* match found => do not copy */
+ continue;
+ }
+ av_dict_set(dst, t->key, t->value, AV_DICT_DONT_OVERWRITE);
+ }
+}
+
static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFormatContext *ic, OptionsContext *o)
{
AVDictionary **meta_in = NULL;
@@ -2546,7 +2593,7 @@ loop_end:
if (output_streams[i]->source_index < 0) /* this is true e.g. for attached files */
continue;
ist = input_streams[output_streams[i]->source_index];
- av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
+ dict_copy_nostats(&output_streams[i]->st->metadata, ist->st->metadata);
if (!output_streams[i]->stream_copy) {
av_dict_set(&output_streams[i]->st->metadata, "encoder", NULL, 0);
}
--
2.11.0
More information about the ffmpeg-devel
mailing list