Hi folks,

In Matroska specifications you can set a stream as default stream using the 
metadata tag disposition:default. If there is no value, default value is 1, 
implying the stream is default (...by default). Ffmpeg currently supports this 
but only when there are default/non default streams in input file, user has no 
way to set himself what should be default and what shouldn't be. When we're 
outside of this case (often happens) this causes unwanted behavior : when you 
have 2 audio streams nothing will be written in disposition:default so 
according to Matroska standards the 2 streams will be default. If you want to 
set an audio stream as default (because it's in the language you want as 
default for example) you cannot - and by the way "two default streams" doesn't 
make any sense. It's worse if you got subtitles and if you want none as default 
because your player will show subtitles by default, as subtitles streams are 
default streams too.

Sorry if this description is pure mess, here are few links with relevant 
information :
http://thread.gmane.org/gmane.comp.video.ffmpeg.devel/158229
http://article.gmane.org/gmane.comp.video.ffmpeg.devel/158353
http://ffmpeg.org/pipermail/ffmpeg-user/2012-October/010845.html

As stated in the last link users can try to set a metadata tag 
disposition:default but it will be considered as "extra" metadata and not real 
default tag. My patch aims to support this tag so default stream status is 
actually written. My patch doesn't change default (sorry) behavior of Ffmpeg, 
it only enables users set a default stream tag which overrides automatic 
choices of Ffmpeg.

Please note that I'm an extreme beginner in all those topics. I have near no 
experience in multimedia, I have poor programming skills ("skilled" only with 
PHP and very general knowledge in true programming languages, you couldn't even 
state that I'm "programming !") and I never used Git nor mailing lists before, 
I quickly Googled those topics. I simply wanted to enable something in Ffmpeg 
and I don't like begging for others to work for me so I tried it by myself. 
Sorry if I did anything wrong.

I'll use a simple example to show you how my patch works. We'll take a file, 
Video.avi, with 1 video and 1 audio streams. We'll convert it to Video.mkv, 
with 1 video stream and 2 duplicated audio streams. We'll set the video stream 
and the first audio stream as default.

Original Ffmpeg behavior :
ffmpeg -i Video.avi -map 0:0 -map 0:1 -map 0:1 -metadata:s:v:0 
disposition:default=1 -metadata:s:a:0 disposition:default=1 -metadata:s:a:1 
disposition:default=0 Video.mkv
The disposition:default tag is not actually written in those 3 cases. Therefore 
any video player compliant with Matroska specs reads those 3 streams as default.

With my patch :
ffmpeg -i Video.avi -map 0:0 -map 0:1 -map 0:1 -metadata:s:v:0 
disposition:default=1 -metadata:s:a:0 disposition:default=1 -metadata:s:a:1 
disposition:default=0 Video.mkv
Video stream (#0) : disposition:default=1 : The video stream is set as default 
so it is read as default (doesn't change with the case above)
Audio stream #0 : disposition:default=1 : This audio stream is set as default 
so it is read as default
Audio stream #1 : disposition:default=0 : This audio stream is set as not 
default so it is not read as default (this changes with the case above)

Thanks for reviewing


--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -842,9 +842,13 @@ static int mkv_write_track(AVFormatContext *s, 
MatroskaMuxContext *mkv,
     }
 
     // The default value for TRACKFLAGDEFAULT is 1, so add element
-    // if we need to clear it.
+    // if we need to clear it or if it is user defined.
     if (default_stream_exists && !(st->disposition & AV_DISPOSITION_DEFAULT))
+        // There is a default stream and it is not the current one
         put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, !!(st->disposition & 
AV_DISPOSITION_DEFAULT));
+    else if (tag = av_dict_get(st->metadata, "disposition:default", NULL, 0))
+        // User manually set a value for disposition:default
+        put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, strtoul(tag->value, 
NULL, 10));
 
     if (st->disposition & AV_DISPOSITION_FORCED)
         put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGFORCED, 1);
@@ -1141,6 +1145,7 @@ static int mkv_write_tag(AVFormatContext *s, AVDictionary 
*m, unsigned int eleme
 
     while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) {
         if (av_strcasecmp(t->key, "title") &&
+            av_strcasecmp(t->key, "disposition:default") &&
             av_strcasecmp(t->key, "stereo_mode") &&
             av_strcasecmp(t->key, "encoding_tool")) {
             ret = mkv_write_simpletag(s->pb, t);
@@ -1158,7 +1163,7 @@ static int mkv_check_tag(AVDictionary *m)
     AVDictionaryEntry *t = NULL;
 
     while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX)))
-        if (av_strcasecmp(t->key, "title") && av_strcasecmp(t->key, 
"stereo_mode"))
+        if (av_strcasecmp(t->key, "title") && av_strcasecmp(t->key, 
"disposition:default") && av_strcasecmp(t->key, "stereo_mode"))
             return 1;
 
     return 0;
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to