Browse code

avformat/asfenc: write group_mutual_exclusion_objects for audio on multiple languages

Improves streaming compatibility with Windows Media Services. Also tested for
compatilbility in Windows Media Player, Windows Media ASF Viewer and VLC.

This version of the patch only writes exclusion among audio streams, therefore
choosing a subtitle language should be possible independently of audio language.

Signed-off-by: Marton Balint <cus@passwd.hu>

Marton Balint authored on 2016/02/06 07:46:25
Showing 3 changed files
... ...
@@ -147,6 +147,14 @@ const ff_asf_guid ff_asf_extended_stream_properties_object = {
147 147
     0xcb, 0xa5, 0xe6, 0x14, 0x72, 0xc6, 0x32, 0x43, 0x83, 0x99, 0xa9, 0x69, 0x52, 0x06, 0x5b, 0x5a
148 148
 };
149 149
 
150
+const ff_asf_guid ff_asf_group_mutual_exclusion_object = {
151
+    0x40, 0x5a, 0x46, 0xd1, 0x79, 0x5a, 0x38, 0x43, 0xb7, 0x1b, 0xe3, 0x6b, 0x8f, 0xd6, 0xc2, 0x49
152
+};
153
+
154
+const ff_asf_guid ff_asf_mutex_language = {
155
+    0x00, 0x2a, 0xe2, 0xd6, 0xda, 0x35, 0xd1, 0x11, 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe
156
+};
157
+
150 158
 /* List of official tags at http://msdn.microsoft.com/en-us/library/dd743066(VS.85).aspx */
151 159
 const AVMetadataConv ff_asf_metadata_conv[] = {
152 160
     { "WM/AlbumArtist",          "album_artist"     },
... ...
@@ -100,6 +100,8 @@ extern const ff_asf_guid ff_asf_content_encryption;
100 100
 extern const ff_asf_guid ff_asf_ext_content_encryption;
101 101
 extern const ff_asf_guid ff_asf_digital_signature;
102 102
 extern const ff_asf_guid ff_asf_extended_stream_properties_object;
103
+extern const ff_asf_guid ff_asf_group_mutual_exclusion_object;
104
+extern const ff_asf_guid ff_asf_mutex_language;
103 105
 
104 106
 extern const AVMetadataConv ff_asf_metadata_conv[];
105 107
 
... ...
@@ -396,6 +396,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
396 396
     int64_t header_offset, cur_pos, hpos;
397 397
     int bit_rate;
398 398
     int64_t duration;
399
+    int audio_language_counts[128] = { 0 };
399 400
 
400 401
     ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL);
401 402
 
... ...
@@ -444,6 +445,8 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
444 444
                     asf->streams[n].stream_language_index = asf->nb_languages;
445 445
                     asf->nb_languages++;
446 446
                 }
447
+                if (enc->codec_type == AVMEDIA_TYPE_AUDIO)
448
+                    audio_language_counts[asf->streams[n].stream_language_index]++;
447 449
             }
448 450
         } else {
449 451
             asf->streams[n].stream_language_index = 128;
... ...
@@ -484,6 +487,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
484 484
     if (asf->nb_languages) {
485 485
         int64_t hpos2;
486 486
         int i;
487
+        int nb_audio_languages = 0;
487 488
 
488 489
         hpos2 = put_header(pb, &ff_asf_language_guid);
489 490
         avio_wl16(pb, asf->nb_languages);
... ...
@@ -493,6 +497,25 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
493 493
         }
494 494
         end_header(pb, hpos2);
495 495
 
496
+        for (i = 0; i < asf->nb_languages; i++)
497
+            if (audio_language_counts[i])
498
+                nb_audio_languages++;
499
+
500
+        if (nb_audio_languages > 1) {
501
+            hpos2 = put_header(pb, &ff_asf_group_mutual_exclusion_object);
502
+            ff_put_guid(pb, &ff_asf_mutex_language);
503
+            avio_wl16(pb, nb_audio_languages);
504
+            for (i = 0; i < asf->nb_languages; i++) {
505
+                if (audio_language_counts[i]) {
506
+                    avio_wl16(pb, audio_language_counts[i]);
507
+                    for (n = 0; n < s->nb_streams; n++)
508
+                        if (asf->streams[n].stream_language_index == i && s->streams[n]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
509
+                            avio_wl16(pb, n + 1);
510
+                }
511
+            }
512
+            end_header(pb, hpos2);
513
+        }
514
+
496 515
         for (n = 0; n < s->nb_streams; n++) {
497 516
             int64_t es_pos;
498 517
             if (asf->streams[n].stream_language_index > 127)