Coverage Report

Created: 2026-06-30 07:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/demux/mkv/matroska_segment_parse.cpp
Line
Count
Source
1
/*****************************************************************************
2
 * matroska_segment_parse.cpp : matroska demuxer
3
 *****************************************************************************
4
 * Copyright (C) 2003-2010 VLC authors and VideoLAN
5
 *
6
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *          Steve Lhomme <steve.lhomme@free.fr>
8
 *
9
 * This program is free software; you can redistribute it and/or modify it
10
 * under the terms of the GNU Lesser General Public License as published by
11
 * the Free Software Foundation; either version 2.1 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program; if not, write to the Free Software Foundation,
21
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22
 *****************************************************************************/
23
#include "mkv.hpp"
24
#include "matroska_segment.hpp"
25
#include "chapters.hpp"
26
#include "demux.hpp"
27
#include "Ebml_parser.hpp"
28
#include "Ebml_dispatcher.hpp"
29
#include "string_dispatcher.hpp"
30
#include "util.hpp"
31
#include "chapter_command_script.hpp"
32
33
extern "C" {
34
#include "../vobsub.h"
35
#include "../xiph.h"
36
#include "../windows_audio_commons.h"
37
#include "../mp4/libmp4.h"
38
}
39
40
#include "vlc_colors.h"
41
42
#include <vlc_iso_lang.h>
43
#include <vlc_codecs.h>
44
#include <stdexcept>
45
#include <limits>
46
#include <algorithm>
47
48
namespace mkv {
49
50
/* GetFourCC helper */
51
107
#define GetFOURCC( p )  __GetFOURCC( (uint8_t*)p )
52
static vlc_fourcc_t __GetFOURCC( uint8_t *p )
53
107
{
54
107
    return VLC_FOURCC( p[0], p[1], p[2], p[3] );
55
107
}
56
57
static inline void fill_extra_data_alac( mkv_track_t *p_tk )
58
0
{
59
0
    if( p_tk->i_extra_data <= 0 ) return;
60
0
    p_tk->fmt.p_extra = malloc( p_tk->i_extra_data + 12 );
61
0
    if( unlikely( !p_tk->fmt.p_extra ) ) return;
62
0
    p_tk->fmt.i_extra = p_tk->i_extra_data + 12;
63
0
    uint8_t *p_extra = static_cast<uint8_t*>( p_tk->fmt.p_extra );
64
    /* 12 bytes + "ALAC Specific Info (24 bytes) (required)" from
65
       https://github.com/macosforge/alac/blob/master/ALACMagicCookieDescription.txt */
66
0
    SetDWBE( p_extra, p_tk->fmt.i_extra );
67
0
    memcpy( p_extra + 4, "alac", 4 );
68
0
    SetDWBE( p_extra + 8, p_tk->i_extra_data );
69
0
    memcpy( p_extra + 12, p_tk->p_extra_data, p_tk->i_extra_data );
70
0
}
71
72
static inline void fill_extra_data( mkv_track_t *p_tk, unsigned int offset )
73
3.32k
{
74
3.32k
    if(p_tk->i_extra_data <= offset) return;
75
2.21k
    p_tk->fmt.i_extra = p_tk->i_extra_data - offset;
76
2.21k
    p_tk->fmt.p_extra = xmalloc( p_tk->fmt.i_extra );
77
2.21k
    if(!p_tk->fmt.p_extra) { p_tk->fmt.i_extra = 0; return; };
78
2.21k
    memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data + offset, p_tk->fmt.i_extra );
79
2.21k
}
80
81
/*****************************************************************************
82
 * Some functions to manipulate memory
83
 *****************************************************************************/
84
static inline const char * ToUTF8Const( const UTFstring &u )
85
4.14k
{
86
4.14k
    return u.GetUTF8().c_str();
87
4.14k
}
88
89
static inline char * ToUTF8( const UTFstring &u )
90
4.14k
{
91
4.14k
    return strdup( ToUTF8Const(u) );
92
4.14k
}
93
94
/*****************************************************************************
95
 * ParseSeekHead:
96
 *****************************************************************************/
97
void matroska_segment_c::ParseSeekHead( KaxSeekHead *seekhead )
98
1.87k
{
99
1.87k
    EbmlElement *l;
100
101
1.87k
    i_seekhead_count++;
102
103
1.87k
    if( !sys.b_seekable )
104
0
        return;
105
106
1.87k
    EbmlParser eparser ( &es, seekhead, &sys.demuxer );
107
108
9.95k
    while( ( l = eparser.Get() ) != NULL )
109
8.07k
    {
110
8.07k
        if( MKV_IS_ID( l, KaxSeek ) )
111
7.75k
        {
112
7.75k
            EbmlId id = EBML_ID(EbmlVoid);
113
7.75k
            int64_t i_pos = -1;
114
115
#ifdef MKV_DEBUG
116
            msg_Dbg( &sys.demuxer, "|   |   + Seek" );
117
#endif
118
7.75k
            eparser.Down();
119
7.75k
            try
120
7.75k
            {
121
22.8k
                while( ( l = eparser.Get() ) != NULL )
122
15.1k
                {
123
15.1k
                    if( unlikely( !l->ValidateSize() ) )
124
0
                    {
125
0
                        msg_Err( &sys.demuxer,"%s too big... skipping it",  EBML_NAME(l) );
126
0
                        continue;
127
0
                    }
128
15.1k
                    if( MKV_IS_ID( l, KaxSeekID ) )
129
7.07k
                    {
130
7.07k
                        KaxSeekID &sid = *static_cast<KaxSeekID*>( l );
131
7.07k
                        sid.ReadData( es.I_O() );
132
7.07k
                        id = EbmlId( sid.GetBuffer(), sid.GetSize() );
133
7.07k
                    }
134
8.03k
                    else if( MKV_IS_ID( l, KaxSeekPosition ) )
135
6.96k
                    {
136
6.96k
                        KaxSeekPosition &spos = *static_cast<KaxSeekPosition*>( l );
137
6.96k
                        spos.ReadData( es.I_O() );
138
6.96k
                        i_pos = (int64_t)segment->GetGlobalPosition( static_cast<uint64_t>( spos ) );
139
6.96k
                    }
140
1.07k
                    else if ( !MKV_IS_ID( l, EbmlVoid ) && !MKV_IS_ID( l, EbmlCrc32 ))
141
0
                    {
142
                        /* Many mkvmerge files hit this case. It seems to be a broken SeekHead */
143
0
                        msg_Dbg( &sys.demuxer, "|   |   + Unknown (%s)", EBML_NAME(l) );
144
0
                    }
145
15.1k
                }
146
7.75k
            }
147
7.75k
            catch(...)
148
7.75k
            {
149
0
                msg_Err( &sys.demuxer,"Error while reading %s",  EBML_NAME(l) );
150
0
            }
151
7.75k
            eparser.Up();
152
153
7.75k
            if( i_pos >= 0 )
154
6.96k
            {
155
6.96k
                if( id == EBML_ID(KaxCluster) )
156
2.44k
                {
157
2.44k
                    _seeker.add_cluster_position( i_pos );
158
2.44k
                }
159
4.52k
                else if( id == EBML_ID(KaxCues) )
160
901
                {
161
901
                    msg_Dbg( &sys.demuxer, "|   - cues at %" PRId64, i_pos );
162
901
                    LoadSeekHeadItem( EBML_INFO(KaxCues), i_pos );
163
901
                }
164
3.62k
                else if( id == EBML_ID(KaxInfo) )
165
964
                {
166
964
                    msg_Dbg( &sys.demuxer, "|   - info at %" PRId64, i_pos );
167
964
                    LoadSeekHeadItem( EBML_INFO(KaxInfo), i_pos );
168
964
                }
169
2.66k
                else if( id == EBML_ID(KaxChapters) )
170
329
                {
171
329
                    msg_Dbg( &sys.demuxer, "|   - chapters at %" PRId64, i_pos );
172
329
                    LoadSeekHeadItem( EBML_INFO(KaxChapters), i_pos );
173
329
                }
174
2.33k
                else if( id == EBML_ID(KaxTags) )
175
304
                {
176
304
                    msg_Dbg( &sys.demuxer, "|   - tags at %" PRId64, i_pos );
177
304
                    LoadSeekHeadItem( EBML_INFO(KaxTags), i_pos );
178
304
                }
179
2.02k
                else if( id == EBML_ID(KaxSeekHead) )
180
449
                {
181
449
                    msg_Dbg( &sys.demuxer, "|   - chained seekhead at %" PRId64, i_pos );
182
449
                    LoadSeekHeadItem( EBML_INFO(KaxSeekHead), i_pos );
183
449
                }
184
1.57k
                else if( id == EBML_ID(KaxTracks) )
185
910
                {
186
910
                    msg_Dbg( &sys.demuxer, "|   - tracks at %" PRId64, i_pos );
187
910
                    LoadSeekHeadItem( EBML_INFO(KaxTracks), i_pos );
188
910
                }
189
669
                else if( id == EBML_ID(KaxAttachments) )
190
34
                {
191
34
                    msg_Dbg( &sys.demuxer, "|   - attachments at %" PRId64, i_pos );
192
34
                    LoadSeekHeadItem( EBML_INFO(KaxAttachments), i_pos );
193
34
                }
194
#ifdef MKV_DEBUG
195
                else if( id != EBML_ID(KaxCluster) && id != EBML_ID(EbmlVoid) &&
196
                         id != EBML_ID(EbmlCrc32))
197
                    msg_Dbg( &sys.demuxer, "|   - unknown seekhead reference at %" PRId64, i_pos );
198
#endif
199
6.96k
            }
200
7.75k
        }
201
322
        else if ( !MKV_IS_ID( l, EbmlVoid ) && !MKV_IS_ID( l, EbmlCrc32 ))
202
33
            msg_Dbg( &sys.demuxer, "|   |   + ParseSeekHead Unknown (%s)", EBML_NAME(l) );
203
8.07k
    }
204
1.87k
}
205
206
207
/*****************************************************************************
208
 * ParseTrackEntry:
209
 *****************************************************************************/
210
8.61k
#define ONLY_FMT(t) if(vars.tk->fmt.i_cat != t ## _ES) return
211
void matroska_segment_c::ParseTrackEntry( const KaxTrackEntry *m )
212
5.37k
{
213
5.37k
    bool bSupported = true;
214
215
5.37k
    uint8_t ttype;
216
5.37k
    try {
217
5.37k
        KaxTrackType & pTrackType = GetMandatoryChild<KaxTrackType>(*m);
218
5.37k
        ttype = pTrackType;
219
5.37k
    } catch (const MissingMandatory & err) {
220
518
        msg_Dbg( &sys.demuxer, "%s", err.what());
221
518
        ttype = 0;
222
518
    }
223
224
5.37k
    enum es_format_category_e es_cat;
225
5.37k
    switch( ttype )
226
5.37k
    {
227
1.66k
        case track_audio:
228
1.66k
            es_cat = AUDIO_ES;
229
1.66k
            break;
230
2.22k
        case track_video:
231
2.22k
            es_cat = VIDEO_ES;
232
2.22k
            break;
233
935
        case track_subtitle:
234
936
        case track_buttons:
235
936
            es_cat = SPU_ES;
236
936
            break;
237
544
        default:
238
544
            es_cat = UNKNOWN_ES;
239
544
            break;
240
5.37k
    }
241
242
    /* Init the track */
243
5.37k
    mkv_track_t *p_track = new mkv_track_t(es_cat);
244
245
5.37k
    MkvTree( sys.demuxer, 2, "Track Entry" );
246
247
5.37k
    struct MetaDataCapture {
248
5.37k
      matroska_segment_c * obj;
249
5.37k
      mkv_track_t        * tk;
250
5.37k
      demux_t            * p_demuxer;
251
5.37k
      bool&                bSupported;
252
5.37k
      int                  level;
253
5.37k
      std::string          lang;
254
5.37k
      bool                 lang_is_ietf;
255
5.37k
      struct {
256
5.37k
        unsigned int i_crop_right;
257
5.37k
        unsigned int i_crop_left;
258
5.37k
        unsigned int i_crop_top;
259
5.37k
        unsigned int i_crop_bottom;
260
5.37k
        unsigned int i_display_unit;
261
5.37k
        unsigned int i_display_width;
262
5.37k
        unsigned int i_display_height;
263
264
5.37k
        unsigned int chroma_sit_vertical;
265
5.37k
        unsigned int chroma_sit_horizontal;
266
5.37k
      } track_video_info;
267
268
5.37k
      struct {
269
5.37k
          float yaw;
270
5.37k
          float pitch;
271
5.37k
          float roll;
272
5.37k
      } pose;
273
274
5.37k
    } metadata_payload = {
275
5.37k
      this, p_track, &sys.demuxer, bSupported, 3, "eng", false, { }, { }
276
5.37k
    };
277
278
5.37k
    MKV_SWITCH_CREATE( EbmlTypeDispatcher, MetaDataHandlers, MetaDataCapture )
279
5.37k
    {
280
5.37k
        MKV_SWITCH_INIT();
281
282
5.37k
        static void debug (MetaDataCapture const& vars, char const * fmt, ...) VLC_FORMAT( 2, 3 )
283
65.7k
        {
284
65.7k
            va_list args; va_start( args, fmt );
285
65.7k
            MkvTree_va( *vars.p_demuxer, vars.level, fmt, args);
286
65.7k
            va_end( args );
287
65.7k
        }
288
5.37k
        E_CASE( KaxTrackNumber, tnum )
289
5.95k
        {
290
5.95k
            vars.tk->i_number = static_cast<uint32_t>( tnum );
291
5.95k
            debug( vars, "Track Number=%u", vars.tk->i_number );
292
5.95k
        }
293
5.37k
        E_CASE( KaxTrackUID, tuid )
294
5.37k
        {
295
4.81k
            debug( vars, "Track UID=%x", static_cast<uint32_t>( tuid ) );
296
4.81k
        }
297
5.37k
        E_CASE( KaxTrackType, ttype )
298
5.37k
        {
299
4.90k
            const char *psz_type;
300
301
4.90k
            switch( static_cast<uint8_t>( ttype ) )
302
4.90k
            {
303
1.68k
                case track_audio:
304
1.68k
                    psz_type = "audio";
305
1.68k
                    break;
306
2.25k
                case track_video:
307
2.25k
                    psz_type = "video";
308
2.25k
                    break;
309
935
                case track_subtitle:
310
935
                    psz_type = "subtitle";
311
935
                    break;
312
1
                case track_buttons:
313
1
                    psz_type = "buttons";
314
1
                    break;
315
33
                default:
316
33
                    psz_type = "unknown";
317
33
                    break;
318
4.90k
            }
319
320
4.90k
            debug( vars, "Track Type=%s", psz_type ) ;
321
4.90k
        }
322
        E_CASE( KaxTrackFlagEnabled, fenb ) // UNUSED
323
5.37k
        {
324
1.11k
            vars.tk->b_enabled = static_cast<uint32_t>( fenb );
325
1.11k
            debug( vars, "Track Enabled=%u", vars.tk->b_enabled );
326
1.11k
        }
327
5.37k
        E_CASE( KaxTrackFlagDefault, fdef )
328
5.37k
        {
329
2.69k
            vars.tk->b_default = static_cast<uint32_t>( fdef );
330
2.69k
            debug( vars, "Track Default=%u", vars.tk->b_default );
331
2.69k
        }
332
        E_CASE( KaxTrackFlagForced, ffor ) // UNUSED
333
5.37k
        {
334
1.11k
            vars.tk->b_forced = static_cast<uint32_t>( ffor );
335
336
1.11k
            debug( vars, "Track Forced=%u", vars.tk->b_forced );
337
1.11k
        }
338
        E_CASE( KaxTrackFlagLacing, lac ) // UNUSED
339
5.37k
        {
340
3.60k
            debug( vars, "Track Lacing=%d", static_cast<uint32_t>( lac ) ) ;
341
3.60k
        }
342
        E_CASE( KaxTrackMinCache, cmin ) // UNUSED
343
5.37k
        {
344
2.35k
            debug( vars, "Track MinCache=%d", static_cast<uint32_t>( cmin ) ) ;
345
2.35k
        }
346
        E_CASE( KaxTrackMaxCache, cmax ) // UNUSED
347
5.37k
        {
348
117
            debug( vars, "Track MaxCache=%d", static_cast<uint32_t>( cmax ) ) ;
349
117
        }
350
5.37k
        E_CASE( KaxTrackDefaultDuration, defd )
351
5.37k
        {
352
1.44k
            vars.tk->i_default_duration = VLC_TICK_FROM_NS(static_cast<uint64_t>(defd));
353
1.44k
            debug( vars, "Track Default Duration=%" PRId64, vars.tk->i_default_duration );
354
1.44k
        }
355
5.37k
        E_CASE( KaxTrackTimestampScale, ttcs )
356
5.37k
        {
357
1.56k
            vars.tk->f_timecodescale = static_cast<float>( ttcs );
358
1.56k
            if ( vars.tk->f_timecodescale <= 0 ) vars.tk->f_timecodescale = 1.0;
359
1.56k
            debug( vars, "Track TimeCodeScale=%f", vars.tk->f_timecodescale ) ;
360
1.56k
        }
361
        E_CASE( KaxMaxBlockAdditionID, mbl ) // UNUSED
362
5.37k
        {
363
1.38k
            debug( vars, "Track Max BlockAdditionID=%d", static_cast<uint32_t>( mbl ) ) ;
364
1.38k
        }
365
5.37k
        E_CASE( KaxTrackName, tname )
366
5.37k
        {
367
1.06k
            free(vars.tk->fmt.psz_description);
368
1.06k
            vars.tk->fmt.psz_description = ToUTF8( UTFstring( tname ) );
369
1.06k
            debug( vars, "Track Name=%s", vars.tk->fmt.psz_description ? vars.tk->fmt.psz_description : "(null)" );
370
1.06k
        }
371
5.37k
        E_CASE( KaxTrackLanguage, lang )
372
5.37k
        {
373
3.46k
            const std::string slang ( lang );
374
3.46k
            size_t pos = slang.find_first_of( '-' );
375
3.46k
            const std::string l = std::string::npos ? slang.substr(0, pos) : slang;
376
3.46k
            debug( vars, "Track Language=`%s'", !l.empty() ? l.c_str() : "(null)" );
377
3.46k
            if (!vars.lang_is_ietf)
378
3.46k
            {
379
3.46k
                vars.lang = l;
380
3.46k
            }
381
3.46k
        }
382
5.37k
#if LIBMATROSKA_VERSION >= 0x010406
383
5.37k
        E_CASE( KaxLanguageIETF, lang )
384
5.37k
        {
385
2
            vars.lang_is_ietf = true;
386
2
            const std::string slang ( lang );
387
2
            size_t pos = slang.find_first_of( '-' );
388
2
            vars.lang = pos != std::string::npos ? slang.substr(0, pos) : slang;
389
2
            debug( vars, "IETF Track Language=`%s'", !vars.lang.empty() ? vars.lang.c_str() : "(null)" );
390
2
        }
391
5.37k
#endif
392
5.37k
        E_CASE( KaxCodecID, codecid )
393
5.37k
        {
394
4.86k
            vars.tk->codec = std::string( codecid );
395
4.86k
            debug( vars, "Track CodecId=%s", std::string( codecid ).c_str() ) ;
396
4.86k
        }
397
5.37k
        E_CASE( KaxCodecPrivate, cpriv )
398
5.37k
        {
399
2.73k
            vars.tk->i_extra_data = cpriv.GetSize();
400
2.73k
            if( vars.tk->i_extra_data > 0 )
401
2.73k
            {
402
2.73k
                free( vars.tk->p_extra_data );
403
2.73k
                vars.tk->p_extra_data = static_cast<uint8_t*>( malloc( vars.tk->i_extra_data ) );
404
405
2.73k
                if( likely( vars.tk->p_extra_data ) )
406
2.73k
                    memcpy( vars.tk->p_extra_data, cpriv.GetBuffer(),
407
2.73k
                            vars.tk->i_extra_data );
408
2.73k
            }
409
2.73k
            debug( vars, "Track CodecPrivate size=%" PRId64, cpriv.GetSize() );
410
2.73k
        }
411
5.37k
        E_CASE( KaxCodecName, cname )
412
5.37k
        {
413
0
            vars.tk->str_codec_name = static_cast<UTFstring const&>( cname ).GetUTF8();
414
0
            debug( vars, "Track Codec Name=%s", vars.tk->str_codec_name.c_str() ) ;
415
0
        }
416
        //AttachmentLink
417
        E_CASE( KaxCodecDecodeAll, cdall ) // UNUSED
418
5.37k
        {
419
1.11k
            debug( vars, "Track Codec Decode All=%u", static_cast<uint8_t>( cdall ) ) ;
420
1.11k
        }
421
        E_CASE( KaxTrackOverlay, tovr ) // UNUSED
422
5.37k
        {
423
0
            debug( vars, "Track Overlay=%u", static_cast<uint32_t>( tovr ) ) ;
424
0
        }
425
5.37k
#if LIBMATROSKA_VERSION >= 0x010401
426
5.37k
        E_CASE( KaxCodecDelay, codecdelay )
427
5.37k
        {
428
0
            vars.tk->i_codec_delay = VLC_TICK_FROM_NS(static_cast<uint64_t>( codecdelay ));
429
0
            msg_Dbg( vars.p_demuxer, "|   |   |   + Track Codec Delay=%" PRIu64,
430
0
                     vars.tk->i_codec_delay );
431
0
        }
432
5.37k
        E_CASE( KaxSeekPreRoll, spr )
433
5.37k
        {
434
0
            vars.tk->i_seek_preroll = VLC_TICK_FROM_NS(static_cast<uint64_t>( spr ));
435
0
            debug( vars, "Track Seek Preroll=%" PRIu64, vars.tk->i_seek_preroll );
436
0
        }
437
5.37k
#endif
438
5.37k
        E_CASE( KaxContentEncodings, cencs )
439
5.37k
        {
440
689
            debug( vars, "Content Encodings" );
441
442
689
            if ( cencs.ListSize () > 1 )
443
0
            {
444
0
                msg_Err( vars.p_demuxer, "Multiple Compression method not supported" );
445
0
                vars.bSupported = false;
446
0
            }
447
448
689
            vars.level += 1;
449
689
            dispatcher.iterate( cencs.begin(), cencs.end(), &vars );
450
689
            vars.level -= 1;
451
689
        }
452
5.37k
        E_CASE( KaxContentEncoding, cenc )
453
5.37k
        {
454
689
            debug( vars, "Content Encoding" );
455
456
689
            vars.level += 1;
457
689
            dispatcher.iterate( cenc.begin(), cenc.end(), &vars );
458
689
            vars.level -= 1;
459
689
        }
460
5.37k
        E_CASE( KaxContentEncodingOrder, encord )
461
5.37k
        {
462
367
            debug( vars, "Order: %i", static_cast<uint32_t>( encord ) );
463
367
        }
464
5.37k
        E_CASE( KaxContentEncodingScope, encscope )
465
5.37k
        {
466
369
            vars.tk->i_encoding_scope = static_cast<uint32_t>( encscope );
467
369
            debug( vars, "Scope: %i", vars.tk->i_encoding_scope );
468
369
        }
469
5.37k
        E_CASE( KaxContentEncodingType, enctype )
470
5.37k
        {
471
368
            debug( vars, "Type: %i", static_cast<uint32_t>( enctype ) );
472
368
        }
473
5.37k
        E_CASE( KaxContentCompression, compr )
474
5.37k
        {
475
688
            debug( vars, "Content Compression" );
476
            //Default compression type is 0 (Zlib)
477
688
            vars.tk->i_compression_type = MATROSKA_COMPRESSION_ZLIB;
478
479
688
            vars.level += 1;
480
688
            dispatcher.iterate( compr.begin(), compr.end(), &vars );
481
688
            vars.level -= 1;
482
688
        }
483
5.37k
        E_CASE( KaxContentCompAlgo, compalg )
484
5.37k
        {
485
680
            vars.tk->i_compression_type = static_cast<uint32_t>( compalg );
486
680
            debug( vars, "Compression Algorithm: %i", vars.tk->i_compression_type );
487
680
            if ( ( vars.tk->i_compression_type != MATROSKA_COMPRESSION_ZLIB ) &&
488
301
                 ( vars.tk->i_compression_type != MATROSKA_COMPRESSION_LZOX ) &&
489
126
                 ( vars.tk->i_compression_type != MATROSKA_COMPRESSION_HEADER ) )
490
0
            {
491
0
                msg_Err( vars.p_demuxer, "Track Compression method %d not supported", vars.tk->i_compression_type );
492
0
                vars.bSupported = false;
493
0
            }
494
680
        }
495
5.37k
        E_CASE( KaxContentCompSettings, kccs )
496
5.37k
        {
497
125
            debug( vars, "Compression Settings" );
498
125
            delete vars.tk->p_compression_data;
499
125
            vars.tk->p_compression_data = new KaxContentCompSettings( kccs );
500
125
        }
501
5.37k
        E_CASE( KaxTrackVideo, tkv )
502
5.37k
        {
503
1.02k
            ONLY_FMT(VIDEO);
504
985
            debug( vars, "Track Video");
505
506
985
            mkv_track_t *tk = vars.tk;
507
508
985
            tk->f_fps = 0.0;
509
510
985
            if( tk->i_default_duration > 1000 ) /* Broken ffmpeg mux info when non set fps */
511
699
            {
512
699
                tk->fmt.video.i_frame_rate_base = static_cast<unsigned>( tk->i_default_duration );
513
699
                tk->fmt.video.i_frame_rate = 1000000;
514
699
            }
515
516
985
            vars.level += 1;
517
985
            dispatcher.iterate (tkv.begin (), tkv.end (), &vars );
518
985
            vars.level -= 1;
519
520
985
            unsigned int i_crop_top    = vars.track_video_info.i_crop_top;
521
985
            unsigned int i_crop_right  = vars.track_video_info.i_crop_right;
522
985
            unsigned int i_crop_bottom = vars.track_video_info.i_crop_bottom;
523
985
            unsigned int i_crop_left   = vars.track_video_info.i_crop_left;
524
525
985
            unsigned int i_display_unit   = vars.track_video_info.i_display_unit;
526
985
            unsigned int i_display_width  = vars.track_video_info.i_display_width;
527
985
            unsigned int i_display_height = vars.track_video_info.i_display_height;
528
529
985
            if (vars.track_video_info.chroma_sit_vertical || vars.track_video_info.chroma_sit_horizontal)
530
11
            {
531
11
                switch (vars.track_video_info.chroma_sit_vertical)
532
11
                {
533
0
                case 0: // unspecified
534
10
                case 2: // center
535
10
                    if (vars.track_video_info.chroma_sit_horizontal == 1) // left
536
10
                        tk->fmt.video.chroma_location = CHROMA_LOCATION_LEFT;
537
0
                    else if (vars.track_video_info.chroma_sit_horizontal == 2) // half
538
0
                        tk->fmt.video.chroma_location = CHROMA_LOCATION_CENTER;
539
0
                    else
540
0
                        debug( vars, "unsupported chroma Siting %u/%u",
541
0
                               vars.track_video_info.chroma_sit_horizontal,
542
0
                               vars.track_video_info.chroma_sit_vertical);
543
10
                    break;
544
1
                case 1: // top
545
1
                    if (vars.track_video_info.chroma_sit_horizontal == 1) // left
546
1
                        tk->fmt.video.chroma_location = CHROMA_LOCATION_TOP_LEFT;
547
0
                    else if (vars.track_video_info.chroma_sit_horizontal == 2) // half
548
0
                        tk->fmt.video.chroma_location = CHROMA_LOCATION_TOP_CENTER;
549
0
                    else
550
0
                        debug( vars, "unsupported chroma Siting %u/%u",
551
0
                               vars.track_video_info.chroma_sit_horizontal,
552
0
                               vars.track_video_info.chroma_sit_vertical);
553
1
                    break;
554
11
                }
555
11
            }
556
557
985
            unsigned int h_crop;
558
985
            if (add_overflow(i_crop_left, i_crop_right, &h_crop))
559
0
            {
560
0
                debug( vars, "invalid horizontal crop %u+%u",
561
0
                              i_crop_left, i_crop_right );
562
0
                i_crop_left = i_crop_right = 0;
563
0
            }
564
985
            else if (unlikely(h_crop >= tk->fmt.video.i_width))
565
17
            {
566
17
                debug( vars, "Horizontal crop (left=%u, right=%u) "
567
17
                             "greater than the picture width (%u)",
568
17
                              i_crop_left, i_crop_right, tk->fmt.video.i_width );
569
17
                i_crop_left = i_crop_right = 0;
570
17
            }
571
572
985
            unsigned int v_crop;
573
985
            if (add_overflow(i_crop_top, i_crop_bottom, &v_crop))
574
0
            {
575
0
                debug( vars, "invalid vertical crop %u+%u",
576
0
                              i_crop_top, i_crop_bottom);
577
0
                i_crop_top = i_crop_bottom = 0;
578
0
            }
579
985
            if (unlikely(v_crop >= tk->fmt.video.i_height))
580
22
            {
581
22
                debug( vars, "Vertical crop (top=%u, bottom=%u) "
582
22
                             "greater than the picture height (%u)",
583
22
                              i_crop_top, i_crop_bottom, tk->fmt.video.i_height );
584
22
                i_crop_top = i_crop_bottom = 0;
585
22
            }
586
587
985
            tk->fmt.video.i_x_offset      = i_crop_left;
588
985
            tk->fmt.video.i_y_offset      = i_crop_top;
589
985
            tk->fmt.video.i_visible_width = tk->fmt.video.i_width -
590
985
                                            (i_crop_left + i_crop_right);
591
985
            tk->fmt.video.i_visible_height = tk->fmt.video.i_height -
592
985
                                            (i_crop_top + i_crop_bottom);
593
594
985
            if (i_display_unit == 0 && i_display_width == 0)
595
527
                i_display_width = tk->fmt.video.i_width;
596
985
            if (i_display_unit == 0 && i_display_height == 0)
597
540
                i_display_height = tk->fmt.video.i_height;
598
599
985
            if (i_display_height && i_display_width)
600
962
            {
601
962
                switch (i_display_unit)
602
962
                {
603
953
                    case 0: // pixels
604
953
                    case 1: // centimeters
605
953
                    case 2: // inches
606
953
                        vlc_ureduce( &tk->fmt.video.i_sar_num, &tk->fmt.video.i_sar_den,
607
953
                                     i_display_width * tk->fmt.video.i_visible_height,
608
953
                                     i_display_height * tk->fmt.video.i_visible_width, 0);
609
953
                        break;
610
9
                    case 3: // display aspect ratio
611
9
                        vlc_ureduce( &tk->fmt.video.i_sar_num, &tk->fmt.video.i_sar_den,
612
9
                                     i_display_height * tk->fmt.video.i_visible_width,
613
9
                                     i_display_width * tk->fmt.video.i_visible_height, 0);
614
9
                        break;
615
962
                }
616
962
            }
617
985
        }
618
5.37k
#if LIBMATROSKA_VERSION >= 0x010400
619
5.37k
        E_CASE( KaxVideoAlphaMode, mode )
620
5.37k
        {
621
8
            ONLY_FMT(VIDEO);
622
8
            debug( vars, "Track Video Alpha Mode %u", static_cast<uint8_t>( mode ) ) ;
623
8
            vars.tk->b_has_alpha = static_cast<uint8_t>( mode ) == 1;
624
8
        }
625
5.37k
#endif
626
5.37k
#if LIBMATROSKA_VERSION >= 0x010406
627
5.37k
        E_CASE( KaxVideoProjection, proj )
628
5.37k
        {
629
2
            ONLY_FMT(VIDEO);
630
2
            debug( vars, "Track Video Projection" ) ;
631
632
2
            vars.level += 1;
633
2
            dispatcher.iterate (proj.begin (), proj.end (), &vars );
634
2
            vars.level -= 1;
635
2
        }
636
5.37k
        E_CASE( KaxVideoProjectionType, fint )
637
5.37k
        {
638
0
            ONLY_FMT(VIDEO);
639
0
            switch (static_cast<uint8_t>( fint ))
640
0
            {
641
0
            case 0:
642
0
                vars.tk->fmt.video.projection_mode = PROJECTION_MODE_RECTANGULAR;
643
0
                break;
644
0
            case 1:
645
0
                vars.tk->fmt.video.projection_mode = PROJECTION_MODE_EQUIRECTANGULAR;
646
0
                break;
647
0
            case 2:
648
0
                vars.tk->fmt.video.projection_mode = PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD;
649
0
                break;
650
0
            default:
651
0
                debug( vars, "Track Video Projection %u not supported", static_cast<uint8_t>( fint ) ) ;
652
0
                break;
653
0
            }
654
0
        }
655
5.37k
        E_CASE( KaxVideoProjectionPoseYaw, pose )
656
5.37k
        {
657
2
            ONLY_FMT(VIDEO);
658
2
            vars.pose.yaw = static_cast<float>( pose );
659
2
        }
660
5.37k
        E_CASE( KaxVideoProjectionPosePitch, pose )
661
5.37k
        {
662
0
            ONLY_FMT(VIDEO);
663
0
            vars.pose.pitch = static_cast<float>( pose );
664
0
        }
665
5.37k
        E_CASE( KaxVideoProjectionPoseRoll, pose )
666
5.37k
        {
667
2
            ONLY_FMT(VIDEO);
668
2
            vars.pose.roll = static_cast<float>( pose );
669
2
        }
670
5.37k
#endif
671
        E_CASE( KaxVideoFlagInterlaced, fint ) // UNUSED
672
5.37k
        {
673
225
            ONLY_FMT(VIDEO);
674
225
            debug( vars, "Track Video Interlaced=%u", static_cast<uint8_t>( fint ) ) ;
675
225
        }
676
        E_CASE( KaxVideoStereoMode, stereo ) // UNUSED
677
5.37k
        {
678
1
            ONLY_FMT(VIDEO);
679
1
            vars.tk->fmt.video.b_multiview_right_eye_first = false;
680
1
            switch (static_cast<uint8_t>( stereo ))
681
1
            {
682
0
            case 0: vars.tk->fmt.video.multiview_mode = MULTIVIEW_2D;         break;
683
0
            case 1: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_SBS; break;
684
0
            case 2: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_TB;  break;
685
0
            case 3: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_TB;
686
0
                    vars.tk->fmt.video.b_multiview_right_eye_first = true;    break;
687
0
            case 4: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_CHECKERBOARD;
688
0
                    vars.tk->fmt.video.b_multiview_right_eye_first = true;    break;
689
0
            case 5: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_CHECKERBOARD; break;
690
0
            case 6: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_ROW;
691
0
                    vars.tk->fmt.video.b_multiview_right_eye_first = true;    break;
692
0
            case 7: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_ROW; break;
693
1
            case 8: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_COL;
694
1
                    vars.tk->fmt.video.b_multiview_right_eye_first = true;    break;
695
0
            case 9: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_COL; break;
696
0
            case 11: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_SBS;
697
0
                     vars.tk->fmt.video.b_multiview_right_eye_first = true;    break;
698
0
            case 13: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_FRAME; break;
699
0
            case 14: vars.tk->fmt.video.multiview_mode = MULTIVIEW_STEREO_FRAME;
700
0
                    vars.tk->fmt.video.b_multiview_right_eye_first = true;    break;
701
0
            default:
702
0
            case 10: case 12:
703
0
                debug( vars, " unsupported Stereo Mode=%u", static_cast<uint8_t>( stereo ) ) ;
704
1
            }
705
1
            debug( vars, "Track Video Stereo Mode=%u", static_cast<uint8_t>( stereo ) ) ;
706
1
        }
707
5.37k
        E_CASE( KaxVideoPixelWidth, vwidth )
708
5.37k
        {
709
968
            ONLY_FMT(VIDEO);
710
968
            vars.tk->fmt.video.i_width += static_cast<uint32_t>( vwidth );
711
968
            debug( vars, "width=%u", vars.tk->fmt.video.i_width );
712
968
        }
713
5.37k
        E_CASE( KaxVideoPixelHeight, vheight )
714
5.37k
        {
715
965
            ONLY_FMT(VIDEO);
716
965
            vars.tk->fmt.video.i_height += static_cast<uint32_t>( vheight );
717
965
            debug( vars, "height=%u", vars.tk->fmt.video.i_height );
718
965
        }
719
5.37k
        E_CASE( KaxVideoDisplayWidth, vwidth )
720
5.37k
        {
721
458
            ONLY_FMT(VIDEO);
722
458
            vars.track_video_info.i_display_width = static_cast<uint32_t>( vwidth );
723
458
            debug( vars, "display width=%u", vars.track_video_info.i_display_width );
724
458
        }
725
5.37k
        E_CASE( KaxVideoDisplayHeight, vheight )
726
5.37k
        {
727
445
            ONLY_FMT(VIDEO);
728
445
            vars.track_video_info.i_display_height = static_cast<uint32_t>( vheight );
729
445
            debug( vars, "display height=%u", vars.track_video_info.i_display_height );
730
445
        }
731
5.37k
        E_CASE( KaxVideoPixelCropBottom, cropval )
732
5.37k
        {
733
41
            ONLY_FMT(VIDEO);
734
41
            vars.track_video_info.i_crop_bottom = static_cast<uint32_t>( cropval );
735
41
            debug( vars, "crop pixel bottom=%u", vars.track_video_info.i_crop_bottom );
736
41
        }
737
5.37k
        E_CASE( KaxVideoPixelCropTop, cropval )
738
5.37k
        {
739
41
            ONLY_FMT(VIDEO);
740
41
            vars.track_video_info.i_crop_top = static_cast<uint32_t>( cropval );
741
41
            debug( vars, "crop pixel top=%u", vars.track_video_info.i_crop_top );
742
41
        }
743
5.37k
        E_CASE( KaxVideoPixelCropRight, cropval )
744
5.37k
        {
745
41
            ONLY_FMT(VIDEO);
746
41
            vars.track_video_info.i_crop_right = static_cast<uint32_t>( cropval );
747
41
            debug( vars, "crop pixel right=%u", vars.track_video_info.i_crop_right );
748
41
        }
749
5.37k
        E_CASE( KaxVideoPixelCropLeft, cropval )
750
5.37k
        {
751
41
            ONLY_FMT(VIDEO);
752
41
            vars.track_video_info.i_crop_left = static_cast<uint32_t>( cropval );
753
41
            debug( vars, "crop pixel left=%u", vars.track_video_info.i_crop_left );
754
41
        }
755
5.37k
        E_CASE( KaxVideoDisplayUnit, vdmode )
756
5.37k
        {
757
9
            ONLY_FMT(VIDEO);
758
9
            vars.track_video_info.i_display_unit = static_cast<uint8_t>( vdmode );
759
9
            const char *psz_unit;
760
9
            switch (vars.track_video_info.i_display_unit)
761
9
            {
762
0
            case 0:  psz_unit = "pixels"; break;
763
0
            case 1:  psz_unit = "centimeters"; break;
764
0
            case 2:  psz_unit = "inches"; break;
765
9
            case 3:  psz_unit = "dar"; break;
766
0
            default: psz_unit = "unknown"; break;
767
9
            }
768
9
            debug( vars, "Track Video Display Unit=%s", psz_unit );
769
9
        }
770
        E_CASE( KaxVideoAspectRatio, ratio ) // UNUSED
771
5.37k
        {
772
0
            ONLY_FMT(VIDEO);
773
0
            debug( vars, "Track Video Aspect Ratio Type=%u", static_cast<uint8_t>( ratio ) ) ;
774
0
        }
775
5.37k
        E_CASE( KaxVideoFrameRate, vfps )
776
5.37k
        {
777
2
            ONLY_FMT(VIDEO);
778
2
            vars.tk->f_fps = std::max( static_cast<float>(vfps) , 1.0f );
779
2
            debug( vars, "fps=%f", vars.tk->f_fps );
780
2
        }
781
5.37k
        E_CASE( KaxVideoColourSpace, colourspace )
782
5.37k
        {
783
25
            ONLY_FMT(VIDEO);
784
25
            if ( colourspace.ValidateSize() )
785
25
            {
786
25
                vars.tk->uncompressed_fourcc = GetFOURCC( colourspace.GetBuffer() );
787
25
                debug( vars, "Colour Space=%4.4s", (const char*)&vars.tk->uncompressed_fourcc );
788
25
            }
789
25
        }
790
5.37k
#if LIBMATROSKA_VERSION >= 0x010405
791
5.37k
        E_CASE( KaxVideoColour, colours)
792
5.37k
        {
793
29
            debug( vars, "Video Colors");
794
29
            if (vars.tk->fmt.i_cat != VIDEO_ES ) {
795
0
                msg_Err( vars.p_demuxer, "Video colors elements not allowed for this track" );
796
0
                return;
797
0
            }
798
29
            vars.level += 1;
799
29
            dispatcher.iterate (colours.begin (), colours.end (), &vars );
800
29
            vars.level -= 1;
801
29
        }
802
5.37k
        E_CASE( KaxVideoColourRange, range )
803
5.37k
        {
804
18
            ONLY_FMT(VIDEO);
805
18
            const char *name = nullptr;
806
18
            switch( static_cast<uint8_t>(range) )
807
18
            {
808
13
            case 1:
809
13
                vars.tk->fmt.video.color_range = COLOR_RANGE_LIMITED;
810
13
                name ="limited";
811
13
                break;
812
5
            case 2:
813
5
                vars.tk->fmt.video.color_range = COLOR_RANGE_FULL;
814
5
                name ="full";
815
5
                break;
816
0
            case 3: // Matrix coefficients + Transfer characteristics
817
0
            default:
818
0
                debug( vars, "Unsupported Colour Range=%d", static_cast<uint8_t>(range) );
819
18
            }
820
18
            if (name != nullptr) debug( vars, "Range=%s", name );
821
18
        }
822
5.37k
        E_CASE( KaxVideoColourTransferCharacter, transfer )
823
5.37k
        {
824
3
            ONLY_FMT(VIDEO);
825
3
            vars.tk->fmt.video.transfer = iso_23001_transfer_to_vlc( static_cast<uint8_t>(transfer) );
826
3
            const char *name = nullptr;
827
3
            switch( static_cast<uint8_t>(transfer) )
828
3
            {
829
0
            case 1: name = "BT-709";
830
0
                break;
831
0
            case 4: name = "BT.470BM";
832
0
                break;
833
0
            case 5: name = "BT.470BG";
834
0
                break;
835
0
            case 6: name = "SMPTE 170M";
836
0
                break;
837
0
            case 7: name = "SMPTE 240M";
838
0
                break;
839
0
            case 8: name = "linear";
840
0
                break;
841
0
            case 13: name = "sRGB/sYCC";
842
0
                break;
843
3
            case 16: name = "BT.2100 PQ";
844
3
                break;
845
0
            case 18: name = "HLG";
846
0
                break;
847
0
            case 9:  // Log
848
0
            case 10: // Log SQRT
849
0
            case 11: // IEC 61966-2-4
850
0
            case 12: // ITU-R BT.1361 Extended Colour Gamut
851
0
            case 14: // ITU-R BT.2020 10 bit
852
0
            case 15: // ITU-R BT.2020 12 bit
853
0
            case 17: // SMPTE ST 428-1
854
0
            default:
855
0
                break;
856
3
            }
857
3
            if (vars.tk->fmt.video.transfer == TRANSFER_FUNC_UNDEF)
858
0
                debug( vars, "Unsupported Colour Transfer=%d", static_cast<uint8_t>(transfer) );
859
3
            else if (name == nullptr)
860
0
                debug( vars, "Colour Transfer=%d", static_cast<uint8_t>(transfer) );
861
3
            else
862
3
                debug( vars, "Colour Transfer=%s", name );
863
3
        }
864
5.37k
        E_CASE( KaxVideoColourPrimaries, primaries )
865
5.37k
        {
866
2
            ONLY_FMT(VIDEO);
867
2
            vars.tk->fmt.video.primaries = iso_23001_primaries_to_vlc( static_cast<uint8_t>(primaries) );
868
2
            const char *name = nullptr;
869
2
            switch( static_cast<uint8_t>(primaries) )
870
2
            {
871
0
            case 1: name = "BT-709";
872
0
                break;
873
0
            case 4: name = "BT.470M";
874
0
                break;
875
0
            case 5: name = "BT.470BG";
876
0
                break;
877
0
            case 6: name = "SMPTE 170M";
878
0
                break;
879
0
            case 7: name = "SMPTE 240M";
880
0
                break;
881
2
            case 9: name = "BT.2020";
882
2
                break;
883
0
            case 8:  // FILM
884
0
            case 10: // SMPTE ST 428-1
885
0
            case 22: // JEDEC P22 phosphors
886
0
            default:
887
0
                break;
888
2
            }
889
2
            if (vars.tk->fmt.video.primaries == COLOR_PRIMARIES_UNDEF)
890
0
                debug( vars, "Unsupported Colour Primaries=%d", static_cast<uint8_t>(primaries) );
891
2
            else if (name == nullptr)
892
0
                debug( vars, "Colour Primaries=%" PRIu8, static_cast<uint8_t>(primaries) );
893
2
            else
894
2
                debug( vars, "Colour Primaries=%s", name );
895
2
        }
896
5.37k
        E_CASE( KaxVideoColourMatrix, matrix )
897
5.37k
        {
898
8
            ONLY_FMT(VIDEO);
899
8
            vars.tk->fmt.video.space = iso_23001_matrix_coeffs_to_vlc( static_cast<uint8_t>(matrix) );
900
8
            const char *name = nullptr;
901
8
            switch( static_cast<uint8_t>(matrix) )
902
8
            {
903
0
            case 1: name = "BT-709";
904
0
                break;
905
0
            case 6: name = "SMPTE 170M";
906
0
                break;
907
0
            case 7: name = "SMPTE 240M";
908
0
                break;
909
3
            case 9: name = "BT.2020 Non-constant Luminance";
910
3
                break;
911
0
            case 10: name = "BT.2020 Constant Luminance";
912
0
                break;
913
5
            case 0: // Identity
914
5
            case 2: // unspecified
915
5
            case 3: // reserved
916
5
            case 4: // US FCC 73.682
917
5
            case 5: // ITU-R BT.470BG
918
5
            case 8: // YCoCg
919
5
            case 11: // SMPTE ST 2085
920
5
            case 12: // Chroma-derived Non-constant Luminance
921
5
            case 13: // Chroma-derived Constant Luminance
922
5
            case 14: // ITU-R BT.2100
923
5
            default:
924
5
                break;
925
8
            }
926
8
            if (vars.tk->fmt.video.space == COLOR_SPACE_UNDEF)
927
5
                debug( vars, "Unsupported Colour Matrix=%d", static_cast<uint8_t>(matrix) );
928
3
            else if (name == nullptr)
929
0
                debug( vars, "Colour Matrix=%d", static_cast<uint8_t>(matrix) );
930
3
            else
931
3
                debug( vars, "Colour Matrix=%s", name );
932
8
        }
933
5.37k
        E_CASE( KaxVideoChromaSitHorz, chroma_hor )
934
5.37k
        {
935
11
            ONLY_FMT(VIDEO);
936
11
            const char *name = nullptr;
937
11
            vars.track_video_info.chroma_sit_horizontal = static_cast<uint8_t>(chroma_hor);
938
11
            switch( static_cast<uint8_t>(chroma_hor) )
939
11
            {
940
0
            case 0: name = "unspecified"; break;
941
11
            case 1: name = "left";        break;
942
0
            case 2: name = "center";      break;
943
0
            default:
944
0
                debug( vars, "Unsupported Horizontal Chroma Siting=%d", static_cast<uint8_t>(chroma_hor) );
945
11
            }
946
11
            if (name != nullptr) debug( vars, "Chroma Siting Horizontal=%s", name);
947
11
        }
948
5.37k
        E_CASE( KaxVideoChromaSitVert, chroma_ver )
949
5.37k
        {
950
11
            ONLY_FMT(VIDEO);
951
11
            const char *name = nullptr;
952
11
            vars.track_video_info.chroma_sit_vertical = static_cast<uint8_t>(chroma_ver);
953
11
            switch( static_cast<uint8_t>(chroma_ver) )
954
11
            {
955
0
            case 0: name = "unspecified"; break;
956
1
            case 1: name = "left";        break;
957
10
            case 2: name = "center";      break;
958
0
            default:
959
0
                debug( vars, "Unsupported Vertical Chroma Siting=%d", static_cast<uint8_t>(chroma_ver) );
960
11
            }
961
11
            if (name != nullptr) debug( vars, "Chroma Siting Vertical=%s", name);
962
11
        }
963
5.37k
        E_CASE( KaxVideoColourMaxCLL, maxCLL )
964
5.37k
        {
965
3
            ONLY_FMT(VIDEO);
966
3
            debug( vars, "Video Max Pixel Brightness");
967
3
            vars.tk->fmt.video.lighting.MaxCLL = static_cast<uint16_t>(maxCLL);
968
3
        }
969
5.37k
        E_CASE( KaxVideoColourMaxFALL, maxFALL )
970
5.37k
        {
971
2
            ONLY_FMT(VIDEO);
972
2
            debug( vars, "Video Max Frame Brightness");
973
2
            vars.tk->fmt.video.lighting.MaxFALL = static_cast<uint16_t>(maxFALL);
974
2
        }
975
5.37k
        E_CASE( KaxVideoColourMasterMeta, mastering )
976
5.37k
        {
977
2
            debug( vars, "Video Mastering Metadata");
978
2
            if (vars.tk->fmt.i_cat != VIDEO_ES ) {
979
0
                msg_Err( vars.p_demuxer, "Video metadata elements not allowed for this track" );
980
0
                return;
981
0
            }
982
2
            vars.level += 1;
983
2
            dispatcher.iterate (mastering.begin (), mastering.end (), &vars );
984
2
            vars.level -= 1;
985
2
        }
986
5.37k
        E_CASE( KaxVideoLuminanceMax, maxLum )
987
5.37k
        {
988
2
            ONLY_FMT(VIDEO);
989
2
            debug( vars, "Video Luminance Max");
990
2
            vars.tk->fmt.video.mastering.max_luminance = static_cast<float>(maxLum) * 10000.f;
991
2
        }
992
5.37k
        E_CASE( KaxVideoLuminanceMin, minLum )
993
5.37k
        {
994
2
            ONLY_FMT(VIDEO);
995
2
            debug( vars, "Video Luminance Min");
996
2
            vars.tk->fmt.video.mastering.min_luminance = static_cast<float>(minLum) * 10000.f;
997
2
        }
998
5.37k
        E_CASE( KaxVideoGChromaX, chroma )
999
5.37k
        {
1000
2
            ONLY_FMT(VIDEO);
1001
2
            debug( vars, "Video Green Chroma X");
1002
2
            vars.tk->fmt.video.mastering.primaries[0] = static_cast<float>(chroma) * 50000.f;
1003
2
        }
1004
5.37k
        E_CASE( KaxVideoGChromaY, chroma )
1005
5.37k
        {
1006
2
            ONLY_FMT(VIDEO);
1007
2
            debug( vars, "Video Green Chroma Y");
1008
2
            vars.tk->fmt.video.mastering.primaries[1] = static_cast<float>(chroma) * 50000.f;
1009
2
        }
1010
5.37k
        E_CASE( KaxVideoBChromaX, chroma )
1011
5.37k
        {
1012
2
            ONLY_FMT(VIDEO);
1013
2
            debug( vars, "Video Blue Chroma X");
1014
2
            vars.tk->fmt.video.mastering.primaries[2] = static_cast<float>(chroma) * 50000.f;
1015
2
        }
1016
5.37k
        E_CASE( KaxVideoBChromaY, chroma )
1017
5.37k
        {
1018
2
            ONLY_FMT(VIDEO);
1019
2
            debug( vars, "Video Blue Chroma Y");
1020
2
            vars.tk->fmt.video.mastering.primaries[3] = static_cast<float>(chroma) * 50000.f;
1021
2
        }
1022
5.37k
        E_CASE( KaxVideoRChromaX, chroma )
1023
5.37k
        {
1024
2
            ONLY_FMT(VIDEO);
1025
2
            debug( vars, "Video Red Chroma X");
1026
2
            vars.tk->fmt.video.mastering.primaries[4] = static_cast<float>(chroma) * 50000.f;
1027
2
        }
1028
5.37k
        E_CASE( KaxVideoRChromaY, chroma )
1029
5.37k
        {
1030
2
            ONLY_FMT(VIDEO);
1031
2
            debug( vars, "Video Red Chroma Y");
1032
2
            vars.tk->fmt.video.mastering.primaries[5] = static_cast<float>(chroma) * 50000.f;
1033
2
        }
1034
5.37k
        E_CASE( KaxVideoWhitePointChromaX, white )
1035
5.37k
        {
1036
2
            ONLY_FMT(VIDEO);
1037
2
            debug( vars, "Video WhitePoint X");
1038
2
            vars.tk->fmt.video.mastering.white_point[0] = static_cast<float>(white) * 50000.f;
1039
2
        }
1040
5.37k
        E_CASE( KaxVideoWhitePointChromaY, white )
1041
5.37k
        {
1042
2
            ONLY_FMT(VIDEO);
1043
2
            debug( vars, "Video WhitePoint Y");
1044
2
            vars.tk->fmt.video.mastering.white_point[1] = static_cast<float>(white) * 50000.f;
1045
2
        }
1046
5.37k
#endif
1047
5.37k
        E_CASE( KaxTrackAudio, tka ) {
1048
1.35k
            ONLY_FMT(AUDIO);
1049
1.30k
            debug( vars, "Track Audio");
1050
1.30k
            vars.level += 1;
1051
1.30k
            dispatcher.iterate( tka.begin(), tka.end(), &vars );
1052
1.30k
            vars.level -= 1;
1053
1.30k
        }
1054
5.37k
        E_CASE( KaxAudioSamplingFreq, afreq )
1055
5.37k
        {
1056
1.28k
            ONLY_FMT(AUDIO);
1057
1.28k
            float const value = static_cast<float>( afreq );
1058
1059
1.28k
            vars.tk->i_original_rate  = value;
1060
1.28k
            vars.tk->fmt.audio.i_rate = value;
1061
1062
1.28k
            debug( vars, "afreq=%d", vars.tk->fmt.audio.i_rate ) ;
1063
1.28k
        }
1064
5.37k
        E_CASE( KaxAudioOutputSamplingFreq, afreq )
1065
5.37k
        {
1066
212
            ONLY_FMT(AUDIO);
1067
212
            vars.tk->fmt.audio.i_rate = static_cast<float>( afreq );
1068
212
            debug( vars, "aoutfreq=%d", vars.tk->fmt.audio.i_rate ) ;
1069
212
        }
1070
5.37k
        E_CASE( KaxAudioChannels, achan )
1071
5.37k
        {
1072
1.26k
            ONLY_FMT(AUDIO);
1073
1.26k
            vars.tk->fmt.audio.i_channels = static_cast<uint8_t>( achan );
1074
1.26k
            debug( vars, "achan=%u", vars.tk->fmt.audio.i_channels );
1075
1.26k
        }
1076
5.37k
        E_CASE( KaxAudioBitDepth, abits )
1077
5.37k
        {
1078
128
            ONLY_FMT(AUDIO);
1079
128
            vars.tk->fmt.audio.i_bitspersample = static_cast<uint8_t>( abits );
1080
128
            debug( vars, "abits=%u", vars.tk->fmt.audio.i_bitspersample);
1081
128
        }
1082
5.37k
        E_CASE ( EbmlVoid, ) {
1083
51
          VLC_UNUSED( vars );
1084
51
        }
1085
8.90k
        E_CASE_DEFAULT(element) {
1086
8.90k
            debug( vars, "Unknown (%s)", EBML_NAME(&element) );
1087
8.90k
        }
1088
5.37k
    };
1089
1090
5.37k
    MetaDataHandlers::Dispatcher().iterate ( m->begin(), m->end(), &metadata_payload );
1091
1092
5.37k
    if( p_track->i_number == 0 )
1093
86
    {
1094
86
        msg_Warn( &sys.demuxer, "Missing KaxTrackNumber, discarding track!" );
1095
86
        delete p_track;
1096
86
        return;
1097
86
    }
1098
1099
5.28k
    if ( bSupported )
1100
5.28k
    {
1101
5.28k
        auto *iso_lang = vlc_find_iso639(metadata_payload.lang.c_str(), false);
1102
5.28k
        if (iso_lang == nullptr)
1103
5.28k
            msg_Dbg( &sys.demuxer, "Unknown language '%s'!", metadata_payload.lang.c_str() );
1104
5.28k
        free(p_track->fmt.psz_language);
1105
5.28k
        p_track->fmt.psz_language = strdup(metadata_payload.lang.c_str());
1106
1107
5.28k
        vlc_viewpoint_from_euler( &p_track->fmt.video.pose,
1108
5.28k
                                  metadata_payload.pose.yaw,
1109
5.28k
                                  metadata_payload.pose.pitch,
1110
5.28k
                                  metadata_payload.pose.roll);
1111
1112
5.28k
#ifdef HAVE_ZLIB
1113
5.28k
        if( p_track->i_compression_type == MATROSKA_COMPRESSION_ZLIB &&
1114
387
            p_track->i_encoding_scope & MATROSKA_ENCODING_SCOPE_PRIVATE &&
1115
0
            p_track->i_extra_data && p_track->p_extra_data &&
1116
0
            zlib_decompress_extra( &sys.demuxer, *p_track ) )
1117
0
        {
1118
0
            msg_Err(&sys.demuxer, "Couldn't handle the track %u compression", p_track->i_number );
1119
0
            delete p_track;
1120
0
            return;
1121
0
        }
1122
5.28k
#endif
1123
5.28k
        if( p_track->i_compression_type == MATROSKA_COMPRESSION_LZOX &&
1124
175
            p_track->i_encoding_scope & MATROSKA_ENCODING_SCOPE_PRIVATE &&
1125
0
            p_track->i_extra_data && p_track->p_extra_data &&
1126
0
            !lzo1x_decompress_extra( &sys.demuxer, *p_track ) )
1127
0
        {
1128
0
            msg_Err(&sys.demuxer, "Couldn't handle the track %u compression", p_track->i_number );
1129
0
            delete p_track;
1130
0
            return;
1131
0
        }
1132
5.28k
        if( p_track->i_compression_type == MATROSKA_COMPRESSION_HEADER &&
1133
126
            p_track->p_compression_data == NULL )
1134
1
        {
1135
1
            msg_Err(&sys.demuxer, "Track %u header compression missing header data", p_track->i_number );
1136
1
            delete p_track;
1137
1
            return;
1138
1
        }
1139
1140
5.28k
        if( !TrackInit( p_track ) )
1141
51
        {
1142
51
            msg_Err(&sys.demuxer, "Couldn't init track %u", p_track->i_number );
1143
51
            delete p_track;
1144
51
            return;
1145
51
        }
1146
1147
5.23k
        tracks.insert( std::make_pair( p_track->i_number, std::unique_ptr<mkv_track_t>(p_track) ) ); // TODO: add warning if two tracks have the same key
1148
5.23k
    }
1149
0
    else
1150
0
    {
1151
0
        msg_Err( &sys.demuxer, "Track Entry %u not supported", p_track->i_number );
1152
0
        delete p_track;
1153
0
    }
1154
5.28k
}
1155
1156
#undef ONLY_FMT
1157
1158
/*****************************************************************************
1159
 * ParseTracks:
1160
 *****************************************************************************/
1161
void matroska_segment_c::ParseTracks( KaxTracks *tracks )
1162
2.58k
{
1163
    /* Master elements */
1164
2.58k
    if ( !ReadMaster( *tracks ) )
1165
2
        return;
1166
1167
2.58k
    struct Capture {
1168
2.58k
      matroska_segment_c * obj;
1169
2.58k
      demux_t            * p_demuxer;
1170
1171
2.58k
    } payload = {
1172
2.58k
      this, &sys.demuxer
1173
2.58k
    };
1174
1175
2.58k
    MKV_SWITCH_CREATE( EbmlTypeDispatcher, TrackHandlers, struct Capture )
1176
2.58k
    {
1177
2.58k
        MKV_SWITCH_INIT();
1178
1179
5.37k
        E_CASE( KaxTrackEntry, track_number ) {
1180
5.37k
            vars.obj->ParseTrackEntry( &track_number );
1181
5.37k
        }
1182
2.58k
        E_CASE( EbmlVoid, ) {
1183
19
            VLC_UNUSED( vars );
1184
19
        }
1185
4.07k
        E_CASE_DEFAULT(element) {
1186
4.07k
            MkvTree( *vars.p_demuxer, 2, "Unknown (%s)", EBML_NAME(&element) );
1187
4.07k
        }
1188
2.58k
    };
1189
1190
2.58k
    TrackHandlers::Dispatcher().iterate( tracks->begin(), tracks->end(), &payload );
1191
1192
2.58k
    for (auto &track : matroska_segment_c::tracks)
1193
4.92k
    {
1194
4.92k
        pcr_shift = std::max(pcr_shift, track.second->i_codec_delay);
1195
4.92k
    }
1196
2.58k
}
1197
1198
/*****************************************************************************
1199
 * ParseInfo:
1200
 *****************************************************************************/
1201
void matroska_segment_c::ParseInfo( KaxInfo *info )
1202
1.58k
{
1203
1.58k
    EbmlMaster  *m = info;
1204
1205
1.58k
    if ( !ReadMaster( *info ) )
1206
0
        return;
1207
1208
1.58k
    struct InfoHandlerPayload {
1209
1.58k
        demux_t            * p_demuxer;
1210
1.58k
        matroska_segment_c * obj;
1211
1.58k
        EbmlMaster        *&   m;
1212
1.58k
        double             f_duration;
1213
1214
1.58k
    } captures = { &sys.demuxer, this, m, -1. };
1215
1216
1.58k
    MKV_SWITCH_CREATE(EbmlTypeDispatcher, InfoHandlers, InfoHandlerPayload)
1217
1.58k
    {
1218
1.58k
        MKV_SWITCH_INIT();
1219
1220
1.58k
        static void debug (InfoHandlerPayload& vars, char const * fmt, ...) VLC_FORMAT( 2, 3 )
1221
7.46k
        {
1222
7.46k
            va_list args; va_start( args, fmt );
1223
7.46k
            MkvTree_va( *vars.p_demuxer, 2, fmt, args);
1224
7.46k
            va_end( args );
1225
7.46k
        }
1226
1.58k
        E_CASE( KaxSegmentUID, uid )
1227
1.58k
        {
1228
1.04k
            if ( vars.obj->p_segment_uid == NULL )
1229
1.04k
            {
1230
1.04k
                vars.obj->p_segment_uid = new KaxSegmentUID( uid );
1231
1.04k
            }
1232
1.04k
            debug( vars, "UID=%" PRIx64, *reinterpret_cast<uint64_t*>( vars.obj->p_segment_uid->GetBuffer() ) );
1233
1.04k
        }
1234
1.58k
        E_CASE( KaxPrevUID, uid )
1235
1.58k
        {
1236
0
            if ( vars.obj->p_prev_segment_uid == NULL )
1237
0
            {
1238
0
                vars.obj->p_prev_segment_uid = new KaxPrevUID( uid );
1239
0
                vars.obj->b_ref_external_segments = true;
1240
0
            }
1241
0
            debug( vars, "PrevUID=%" PRIx64, *reinterpret_cast<uint64_t*>( vars.obj->p_prev_segment_uid->GetBuffer() ) );
1242
0
        }
1243
1.58k
        E_CASE( KaxNextUID, uid )
1244
1.58k
        {
1245
0
            if ( vars.obj->p_next_segment_uid == NULL )
1246
0
            {
1247
0
                vars.obj->p_next_segment_uid = new KaxNextUID( uid );
1248
0
                vars.obj->b_ref_external_segments = true;
1249
0
            }
1250
0
            debug( vars, "NextUID=%" PRIx64, *reinterpret_cast<uint64_t*>( vars.obj->p_next_segment_uid->GetBuffer() ) );
1251
0
        }
1252
1.58k
        E_CASE( KaxTimestampScale, tcs )
1253
1.58k
        {
1254
726
            vars.obj->i_timescale = static_cast<uint64_t>( tcs );
1255
726
            debug( vars, "TimecodeScale=%" PRId64, vars.obj->i_timescale );
1256
726
        }
1257
1.58k
        E_CASE( KaxDuration, dur )
1258
1.58k
        {
1259
706
            vars.f_duration = static_cast<double>( dur );
1260
706
            debug( vars, "Duration=%.0f", vars.f_duration );
1261
706
        }
1262
1.58k
        E_CASE( KaxMuxingApp, mapp )
1263
1.58k
        {
1264
1.39k
            free(vars.obj->psz_muxing_application);
1265
1.39k
            vars.obj->psz_muxing_application = ToUTF8( UTFstring( mapp ) );
1266
1.39k
            debug( vars, "Muxing Application=%s", vars.obj->psz_muxing_application );
1267
1.39k
        }
1268
1.58k
        E_CASE( KaxWritingApp, wapp )
1269
1.58k
        {
1270
1.39k
            free(vars.obj->psz_writing_application);
1271
1.39k
            vars.obj->psz_writing_application = ToUTF8( UTFstring( wapp ) );
1272
1.39k
            debug( vars, "Writing Application=%s", vars.obj->psz_writing_application );
1273
1.39k
        }
1274
1.58k
        E_CASE( KaxSegmentFilename, sfn )
1275
1.58k
        {
1276
0
            debug( vars, "Segment Filename=%s", ToUTF8Const( UTFstring( sfn ) ) );
1277
0
        }
1278
1.58k
        E_CASE( KaxTitle, title )
1279
1.58k
        {
1280
299
            free(vars.obj->psz_title);
1281
299
            vars.obj->psz_title = ToUTF8( UTFstring( title ) );
1282
299
            debug( vars, "Title=%s", vars.obj->psz_title );
1283
299
        }
1284
1.58k
        E_CASE( KaxSegmentFamily, uid )
1285
1.58k
        {
1286
0
            vars.obj->families.push_back( new KaxSegmentFamily(uid) );
1287
0
            debug( vars, "Family=%" PRIx64, *reinterpret_cast<uint64_t*>( uid.GetBuffer() ) );
1288
0
        }
1289
1.58k
        E_CASE( KaxDateUTC, date )
1290
1.58k
        {
1291
1.01k
            struct tm tmres;
1292
1.01k
            char   buffer[25];
1293
1.01k
            time_t i_date = date.GetEpochDate();
1294
1295
1.01k
            if( gmtime_r( &i_date, &tmres ) &&
1296
1.01k
                strftime( buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Y",
1297
1.01k
                          &tmres ) )
1298
1.01k
            {
1299
1.01k
                debug( vars, "Date=%s", buffer );
1300
1.01k
            }
1301
1.01k
        }
1302
1.58k
        E_CASE( KaxChapterTranslate, trans )
1303
1.58k
        {
1304
0
            MKV_SWITCH_CREATE( EbmlTypeDispatcher, TranslationHandler, chapter_translation_c* )
1305
0
            {
1306
0
                MKV_SWITCH_INIT();
1307
1308
0
                E_CASE( KaxChapterTranslateEditionUID, uid )
1309
0
                {
1310
0
                    vars->editions.push_back( static_cast<uint64_t>( uid ) );
1311
0
                }
1312
0
                E_CASE( KaxChapterTranslateCodec, codec_id )
1313
0
                {
1314
0
                    vars->codec_id = static_cast<uint32_t>( codec_id );
1315
0
                }
1316
0
                E_CASE( KaxChapterTranslateID, translated_id )
1317
0
                {
1318
0
                    delete vars->p_translated;
1319
0
                    vars->p_translated = new KaxChapterTranslateID( translated_id );
1320
0
                }
1321
0
            };
1322
0
            try
1323
0
            {
1324
0
                if ( !vars.obj->ReadMaster( trans ) )
1325
0
                    return;
1326
1327
0
                chapter_translation_c *p_translate = new chapter_translation_c();
1328
1329
0
                TranslationHandler::Dispatcher().iterate(
1330
0
                    trans.begin(), trans.end(), &p_translate
1331
0
                );
1332
1333
0
                if (p_translate->isValid())
1334
0
                    vars.obj->translations.push_back( p_translate );
1335
0
                else
1336
0
                    delete p_translate;
1337
0
            }
1338
0
            catch(...)
1339
0
            {
1340
0
                msg_Err( vars.p_demuxer, "Error while reading Chapter Translate");
1341
0
            }
1342
0
        }
1343
1.58k
        E_CASE( EbmlVoid, )
1344
1.58k
        {
1345
4
            VLC_UNUSED( vars );
1346
4
        }
1347
1.58k
        E_CASE_DEFAULT(element)
1348
1.58k
        {
1349
897
            debug( vars, "Unknown (%s)", EBML_NAME(&element) );
1350
897
        }
1351
1.58k
    };
1352
1353
1.58k
    InfoHandlers::Dispatcher().iterate( m->begin(), m->end(), &captures );
1354
1355
1.58k
    if( captures.f_duration != -1. )
1356
705
        i_duration = VLC_TICK_FROM_NS( captures.f_duration * i_timescale );
1357
1.58k
}
1358
1359
1360
/*****************************************************************************
1361
 * ParseChapterAtom
1362
 *****************************************************************************/
1363
void matroska_segment_c::ParseChapterAtom( int i_level, KaxChapterAtom *ca, chapter_item_c & chapters )
1364
3.34k
{
1365
3.34k
    MkvTree( sys.demuxer, 3, "ChapterAtom (level=%d)", i_level );
1366
1367
3.34k
    struct ChapterPayload {
1368
3.34k
        matroska_segment_c * const       obj;
1369
3.34k
        demux_t            * const p_demuxer;
1370
3.34k
        chapter_item_c     &        chapters;
1371
1372
3.34k
        int& i_level;
1373
3.34k
        int level;
1374
1375
3.34k
    } payload = {
1376
3.34k
        this, &sys.demuxer, chapters,
1377
3.34k
        i_level, 4
1378
3.34k
    };
1379
1380
3.34k
    MKV_SWITCH_CREATE( EbmlTypeDispatcher, ChapterAtomHandlers, ChapterPayload )
1381
3.34k
    {
1382
3.34k
        MKV_SWITCH_INIT();
1383
1384
3.34k
        static void debug (ChapterPayload const& vars, char const * fmt, ...) VLC_FORMAT( 2, 3 )
1385
19.5k
        {
1386
19.5k
            va_list args; va_start( args, fmt );
1387
19.5k
            MkvTree_va( *vars.p_demuxer, vars.level, fmt, args);
1388
19.5k
            va_end( args );
1389
19.5k
        }
1390
3.34k
        E_CASE( KaxChapterUID, uid )
1391
3.34k
        {
1392
3.20k
            vars.chapters.i_uid = static_cast<uint64_t>( uid );
1393
3.20k
            debug( vars, "ChapterUID=%" PRIx64, vars.chapters.i_uid );
1394
3.20k
        }
1395
3.34k
        E_CASE( KaxChapterFlagHidden, flag )
1396
3.34k
        {
1397
2.75k
            vars.chapters.b_display_seekpoint = static_cast<uint8_t>( flag ) == 0;
1398
2.75k
            debug( vars, "ChapterFlagHidden=%s", vars.chapters.b_display_seekpoint ? "no" : "yes" );
1399
2.75k
        }
1400
3.34k
        E_CASE( KaxChapterSegmentUID, uid )
1401
3.34k
        {
1402
0
            delete vars.chapters.p_segment_uid;
1403
0
            vars.chapters.p_segment_uid = new KaxChapterSegmentUID( uid );
1404
0
            vars.obj->b_ref_external_segments = true;
1405
1406
0
            debug( vars, "ChapterSegmentUID=%" PRIx64, *reinterpret_cast<uint64_t*>( vars.chapters.p_segment_uid->GetBuffer() ) );
1407
0
        }
1408
3.34k
        E_CASE( KaxChapterSegmentEditionUID, euid )
1409
3.34k
        {
1410
0
            delete vars.chapters.p_segment_edition_uid;
1411
0
            vars.chapters.p_segment_edition_uid = new KaxChapterSegmentEditionUID( euid );
1412
1413
0
            debug( vars, "ChapterSegmentEditionUID=%x",
1414
#if LIBMATROSKA_VERSION < 0x010300
1415
              *reinterpret_cast<uint32_t*>( vars.chapters.p_segment_edition_uid->GetBuffer() )
1416
#else
1417
0
              static_cast<uint32_t>( *vars.chapters.p_segment_edition_uid )
1418
0
#endif
1419
0
            );
1420
0
        }
1421
3.34k
        E_CASE( KaxChapterTimeStart, start )
1422
3.34k
        {
1423
3.21k
            vars.chapters.i_start_time = VLC_TICK_FROM_NS(static_cast<uint64_t>( start ));
1424
3.21k
            debug( vars, "ChapterTimeStart=%" PRId64, vars.chapters.i_start_time );
1425
3.21k
        }
1426
3.34k
        E_CASE( KaxChapterTimeEnd, end )
1427
3.34k
        {
1428
555
            vars.chapters.i_end_time = VLC_TICK_FROM_NS(static_cast<uint64_t>( end ));
1429
555
            debug( vars, "ChapterTimeEnd=%" PRId64, *vars.chapters.i_end_time );
1430
555
        }
1431
3.34k
        E_CASE( KaxChapterDisplay, chapter_display )
1432
3.34k
        {
1433
3.29k
            debug( vars, "ChapterDisplay" );
1434
1435
3.29k
            vars.level += 1;
1436
3.29k
            dispatcher.iterate( chapter_display.begin(), chapter_display.end(), &vars );
1437
3.29k
            vars.level -= 1;
1438
3.29k
        }
1439
3.34k
        E_CASE( KaxChapterString, name )
1440
3.34k
        {
1441
3.21k
            std::string str_name( UTFstring( name ).GetUTF8() );
1442
1443
3.26k
            for ( int k = 0; k < vars.i_level; k++)
1444
51
                vars.chapters.str_name += '+';
1445
1446
3.21k
            vars.chapters.str_name += ' ';
1447
3.21k
            vars.chapters.str_name += str_name;
1448
3.21k
            vars.chapters.b_user_display = true;
1449
1450
3.21k
            debug( vars, "ChapterString=%s", str_name.c_str() );
1451
3.21k
        }
1452
3.34k
        E_CASE( KaxChapterLanguage, lang )
1453
3.34k
        {
1454
3.11k
            debug( vars, "ChapterLanguage=%s", static_cast<std::string const&>( lang ).c_str() );
1455
3.11k
        }
1456
3.34k
        E_CASE( KaxChapterCountry, ct )
1457
3.34k
        {
1458
121
            debug( vars, "ChapterCountry=%s", static_cast<std::string const&>( ct ).c_str() );
1459
121
        }
1460
1461
3.34k
        E_CASE( KaxChapterProcess, cp )
1462
3.34k
        {
1463
39
            debug( vars, "ChapterProcess" );
1464
1465
39
            if ( !var_InheritBool( vars.p_demuxer, "mkv-use-chapter-codec") )
1466
0
                return;
1467
1468
39
            chapter_codec_cmds_c *p_ccodec = NULL;
1469
1470
39
            for (auto proc : cp)
1471
50
            {
1472
50
                if( MKV_CHECKED_PTR_DECL_CONST( p_codec_id, KaxChapterProcessCodecID, proc ) )
1473
35
                {
1474
35
                    if ( p_codec_id->GetValue() == MATROSKA_CHAPTER_CODEC_NATIVE )
1475
35
                    {
1476
35
                       auto interpreter = vars.obj->sys.GetMatroskaScriptInterpreter();
1477
35
                       if (unlikely(interpreter == nullptr))
1478
0
                            debug( vars, "failed to get the Matroska Script interpreter ");
1479
35
                       else
1480
35
                            p_ccodec = new matroska_script_codec_c(
1481
35
                            vlc_object_logger( &vars.obj->sys.demuxer ),
1482
35
                            vars.obj->sys, *interpreter
1483
35
                            );
1484
35
                    }
1485
0
                    else if ( p_codec_id->GetValue() == MATROSKA_CHAPTER_CODEC_DVD )
1486
0
                    {
1487
0
                        auto interepreter = vars.obj->sys.GetDVDInterpretor();
1488
0
                        if (unlikely(interepreter == nullptr))
1489
0
                            debug( vars, "failed to get the DVD interpreter ");
1490
0
                        else
1491
0
                            p_ccodec = new dvd_chapter_codec_c( vlc_object_logger( &vars.obj->sys.demuxer ), vars.obj->sys, *interepreter );
1492
0
                    }
1493
35
                    break;
1494
35
                }
1495
50
            }
1496
1497
39
            if ( p_ccodec != NULL )
1498
35
            {
1499
35
                for (auto k : cp)
1500
79
                {
1501
79
                    if( MKV_CHECKED_PTR_DECL_CONST( p_private, KaxChapterProcessPrivate, k ) )
1502
0
                    {
1503
0
                        p_ccodec->SetPrivate( *p_private );
1504
0
                    }
1505
79
                    else if ( MKV_CHECKED_PTR_DECL_CONST( cmd, KaxChapterProcessCommand, k ) )
1506
25
                    {
1507
25
                        p_ccodec->AddCommand( *cmd );
1508
25
                    }
1509
79
                }
1510
35
                vars.chapters.codecs.push_back( p_ccodec );
1511
35
            }
1512
39
        }
1513
3.34k
        E_CASE( KaxChapterAtom, atom )
1514
3.34k
        {
1515
81
            chapter_item_c *new_sub_chapter = new chapter_item_c();
1516
81
            new_sub_chapter->p_parent = &vars.chapters;
1517
1518
81
            vars.obj->ParseChapterAtom( vars.i_level+1, &atom, *new_sub_chapter );
1519
81
            vars.chapters.sub_chapters.push_back( new_sub_chapter );
1520
81
        }
1521
3.34k
    };
1522
1523
3.34k
    ChapterAtomHandlers::Dispatcher().iterate( ca->begin(), ca->end(), &payload );
1524
3.34k
}
1525
1526
/*****************************************************************************
1527
 * ParseAttachments:
1528
 *****************************************************************************/
1529
void matroska_segment_c::ParseAttachments( KaxAttachments *attachments )
1530
59
{
1531
59
    if ( !ReadMaster( *attachments ))
1532
0
        return;
1533
1534
59
    KaxAttached *attachedFile = FindChild<KaxAttached>( *attachments );
1535
1536
143
    while( attachedFile )
1537
84
    {
1538
84
        if (attachedFile->GetSize() > 0 )
1539
84
        try {
1540
84
            KaxFileData  &img_data     = GetMandatoryChild<KaxFileData>( *attachedFile );
1541
84
            std::string attached_filename( UTFstring( GetMandatoryChild<KaxFileName>( *attachedFile ) ).GetUTF8() );
1542
84
            auto new_attachment = vlc_input_attachment_New( attached_filename.c_str(),
1543
84
                                                            GetMandatoryChild<KaxMimeType>( *attachedFile ).GetValue().c_str(),
1544
84
                                                            nullptr,
1545
84
                                                            img_data.GetBuffer(),
1546
84
                                                            img_data.GetSize() );
1547
84
            if (new_attachment)
1548
78
            {
1549
78
                msg_Dbg( &sys.demuxer, "|   |   - %s (%s)", new_attachment->psz_name,
1550
78
                        new_attachment->psz_mime );
1551
1552
78
                if( !strncmp( new_attachment->psz_mime, "image/", 6 ) )
1553
64
                {
1554
64
                    char *psz_url;
1555
64
                    if( asprintf( &psz_url, "attachment://%s",
1556
64
                                new_attachment->psz_name ) >= 0 )
1557
64
                    {
1558
64
                        if( !sys.meta )
1559
24
                            sys.meta = vlc_meta_New();
1560
64
                        vlc_meta_SetArtURL( sys.meta, psz_url );
1561
64
                        free( psz_url );
1562
64
                    }
1563
64
                }
1564
78
                sys.stored_attachments.push_back( vlc::wrap_cptr( new_attachment,
1565
78
                                                                &vlc_input_attachment_Release ) );
1566
78
            }
1567
84
        } catch (const MissingMandatory & err) {
1568
6
            msg_Dbg( &sys.demuxer, "%s", err.what());
1569
6
        }
1570
84
        attachedFile = FindNextChild<KaxAttached>( *attachments, *attachedFile );
1571
84
    }
1572
59
}
1573
1574
/*****************************************************************************
1575
 * ParseChapters:
1576
 *****************************************************************************/
1577
void matroska_segment_c::ParseChapters( KaxChapters *chapters )
1578
501
{
1579
501
    if ( !ReadMaster( *chapters ) )
1580
0
        return;
1581
1582
501
    MKV_SWITCH_CREATE( EbmlTypeDispatcher, KaxChapterHandler, matroska_segment_c )
1583
501
    {
1584
501
        MKV_SWITCH_INIT();
1585
501
        E_CASE( KaxEditionEntry, entry )
1586
693
        {
1587
693
            struct EditionPayload {
1588
693
                matroska_segment_c * const obj;
1589
693
                demux_t            * const p_demuxer;
1590
693
                chapter_edition_c  * const p_edition;
1591
1592
693
            } data = { &vars, &vars.sys.demuxer, new chapter_edition_c };
1593
1594
693
            MKV_SWITCH_CREATE( EbmlTypeDispatcher, KaxEditionHandler, EditionPayload )
1595
693
            {
1596
693
                MKV_SWITCH_INIT();
1597
693
                E_CASE( KaxChapterAtom, chapter_atom )
1598
3.26k
                {
1599
3.26k
                    chapter_item_c *new_sub_chapter = new chapter_item_c();
1600
3.26k
                    vars.obj->ParseChapterAtom( 0, &chapter_atom, *new_sub_chapter );
1601
3.26k
                    vars.p_edition->sub_chapters.push_back( new_sub_chapter );
1602
3.26k
                }
1603
693
                E_CASE( KaxEditionUID, euid )
1604
693
                {
1605
552
                    vars.p_edition->i_uid = static_cast<uint64_t> ( euid );
1606
552
                }
1607
693
                E_CASE( KaxEditionFlagOrdered, flag_ordered )
1608
693
                {
1609
130
                    vars.p_edition->b_ordered = var_InheritBool(vars.p_demuxer, "mkv-use-ordered-chapters") && static_cast<uint8_t>( flag_ordered );
1610
130
                }
1611
693
                E_CASE( KaxEditionFlagDefault, flag_default )
1612
693
                {
1613
497
                    if( static_cast<uint8_t>( flag_default ) )
1614
116
                        vars.obj->i_default_edition = vars.obj->stored_editions.size();
1615
497
                }
1616
693
                E_CASE( KaxEditionFlagHidden, flag_hidden )
1617
693
                {
1618
409
                    vars.p_edition->b_hidden = static_cast<uint8_t>( flag_hidden ) != 0;
1619
409
                }
1620
693
                E_CASE( EbmlVoid, el )
1621
693
                {
1622
1
                    VLC_UNUSED( el );
1623
1
                    VLC_UNUSED( vars );
1624
1
                }
1625
693
                E_CASE_DEFAULT( el )
1626
900
                {
1627
900
                    msg_Dbg( vars.p_demuxer, "|   |   |   + Unknown (%s)", EBML_NAME(&el) );
1628
900
                }
1629
693
            };
1630
693
            KaxEditionHandler::Dispatcher().iterate( entry.begin(), entry.end(), &data );
1631
1632
693
            data.obj->stored_editions.push_back( data.p_edition );
1633
693
        }
1634
501
        E_CASE( EbmlVoid, el ) {
1635
0
            VLC_UNUSED( el );
1636
0
            VLC_UNUSED( vars );
1637
0
        }
1638
501
        E_CASE_DEFAULT( el )
1639
501
        {
1640
76
            msg_Dbg( &vars.sys.demuxer, "|   |   + Unknown (%s)", EBML_NAME(&el) );
1641
76
        }
1642
501
    };
1643
1644
501
    KaxChapterHandler::Dispatcher().iterate( chapters->begin(), chapters->end(), this );
1645
501
}
1646
1647
bool matroska_segment_c::ParseCluster( KaxCluster *cluster, bool b_update_start_time, ScopeMode read_fully )
1648
2.50k
{
1649
2.50k
    if (!sys.b_seekable)
1650
0
        return false;
1651
1652
2.50k
    if ( !ReadMaster( *cluster, read_fully ) )
1653
3
        return false;
1654
1655
2.49k
    auto *p_ctc = FindChild<KaxClusterTimestamp>(*cluster);
1656
2.49k
    if( p_ctc == nullptr )
1657
49
    {
1658
49
        msg_Err( &sys.demuxer, "Detected cluster without mandatory timecode" );
1659
49
        return false;
1660
49
    }
1661
1662
2.45k
    cluster->InitTimestamp( static_cast<uint64_t>( *p_ctc ), i_timescale );
1663
2.45k
    _seeker.add_cluster( cluster );
1664
1665
2.45k
    if( b_update_start_time )
1666
654
        i_mk_start_time = VLC_TICK_FROM_NS( cluster->GlobalTimestamp() );
1667
1668
2.45k
    return true;
1669
2.49k
}
1670
1671
1.27k
#define ONLY_FMT(t) if(vars.p_tk->fmt.i_cat != t ## _ES) \
1672
1.27k
    throw std::runtime_error( "Mismatching track type" );
1673
1674
bool matroska_segment_c::TrackInit( mkv_track_t * p_tk )
1675
5.28k
{
1676
5.28k
    if( p_tk->codec.empty() )
1677
452
    {
1678
452
        msg_Err( &sys.demuxer, "Empty codec id" );
1679
452
        p_tk->fmt.i_codec = VLC_CODEC_UNKNOWN;
1680
452
        return true;
1681
452
    }
1682
1683
4.83k
    struct HandlerPayload {
1684
4.83k
        matroska_segment_c * obj;
1685
4.83k
        mkv_track_t        * p_tk;
1686
4.83k
        es_format_t        * p_fmt;
1687
4.83k
        demux_t            * p_demuxer;
1688
4.83k
    } captures = {
1689
4.83k
        this, p_tk, &p_tk->fmt, &sys.demuxer
1690
4.83k
    };
1691
1692
4.83k
    MKV_SWITCH_CREATE( StringDispatcher, TrackCodecHandlers, HandlerPayload )
1693
4.83k
    {
1694
4.83k
        MKV_SWITCH_INIT();
1695
1696
4.83k
        S_CASE("V_MS/VFW/FOURCC") {
1697
45
            if( vars.p_tk->i_extra_data < (int)sizeof( VLC_BITMAPINFOHEADER ) )
1698
0
            {
1699
0
                msg_Err(vars.p_demuxer, "missing/invalid VLC_BITMAPINFOHEADER" );
1700
0
                vars.p_fmt->i_codec = VLC_CODEC_UNKNOWN;
1701
0
            }
1702
45
            else
1703
45
            {
1704
45
                ONLY_FMT(VIDEO);
1705
45
                VLC_BITMAPINFOHEADER *p_bih = (VLC_BITMAPINFOHEADER*)vars.p_tk->p_extra_data;
1706
1707
45
                vars.p_fmt->video.i_width = GetDWLE( &p_bih->biWidth );
1708
45
                vars.p_fmt->video.i_height= GetDWLE( &p_bih->biHeight );
1709
45
                vars.p_fmt->i_codec       = GetFOURCC( &p_bih->biCompression );
1710
1711
                /* Very unlikely yet possible: bug #5659*/
1712
45
                const size_t min_extra = std::min(static_cast<size_t>(GetDWLE(&p_bih->biSize)),
1713
45
                                                  vars.p_tk->i_extra_data);
1714
45
                if ( min_extra > sizeof( VLC_BITMAPINFOHEADER ))
1715
0
                {
1716
0
                    vars.p_fmt->i_extra = min_extra - sizeof( VLC_BITMAPINFOHEADER );
1717
0
                    vars.p_fmt->p_extra = xmalloc( vars.p_fmt->i_extra );
1718
0
                    if (likely(vars.p_fmt->p_extra != NULL))
1719
0
                        memcpy( vars.p_fmt->p_extra, &p_bih[1], vars.p_fmt->i_extra );
1720
0
                    else
1721
0
                        vars.p_fmt->i_extra = 0;
1722
0
                }
1723
45
                else if( vars.p_fmt->i_codec == VLC_FOURCC('W','V','C','1') )
1724
0
                {
1725
0
                    vars.p_fmt->video.i_width = 0;
1726
0
                    vars.p_fmt->video.i_height = 0;
1727
0
                    vars.p_fmt->b_packetized = false;
1728
0
                }
1729
45
            }
1730
45
            vars.p_tk->b_dts_only = true;
1731
45
        }
1732
4.83k
        S_CASE("V_MPEG1") {
1733
1
            vars.p_fmt->i_codec = VLC_CODEC_MPGV;
1734
1
            fill_extra_data( vars.p_tk, 0 );
1735
1
        }
1736
4.83k
        S_CASE("V_MPEG2") {
1737
49
            vars.p_fmt->i_codec = VLC_CODEC_MPGV;
1738
49
            if (vars.obj->psz_muxing_application != NULL &&
1739
0
                    strstr(vars.obj->psz_muxing_application,"libmakemkv"))
1740
0
                vars.p_fmt->b_packetized = false;
1741
49
            fill_extra_data( vars.p_tk, 0 );
1742
49
        }
1743
4.83k
        S_CASE("V_THEORA") {
1744
583
            vars.p_fmt->i_codec = VLC_CODEC_THEORA;
1745
583
            vars.p_tk->b_pts_only = true;
1746
583
            fill_extra_data( vars.p_tk, 0 );
1747
583
        }
1748
4.83k
        static void v_real_helper (vlc_fourcc_t codec, HandlerPayload& vars)
1749
4.83k
        {
1750
109
            vars.p_fmt->i_codec   = codec;
1751
1752
            /* Extract the framerate from the header */
1753
109
            uint8_t *p = vars.p_tk->p_extra_data;
1754
1755
109
            if (
1756
109
                vars.p_tk->i_extra_data >= 26 && !memcmp(p+4, "VIDORV", 6) && strchr("34", p[10]) && p[11] == '0')
1757
87
            {
1758
87
                ONLY_FMT(VIDEO);
1759
78
                vars.p_tk->fmt.video.i_frame_rate      = p[22] << 24 | p[23] << 16 | p[24] << 8 | p[25] << 0;
1760
78
                vars.p_tk->fmt.video.i_frame_rate_base = 65536;
1761
78
            }
1762
1763
100
            fill_extra_data( vars.p_tk, 26 );
1764
100
        }
1765
4.83k
        S_CASE("V_REAL/RV10") { v_real_helper (VLC_CODEC_RV10, vars ); }
1766
4.83k
        S_CASE("V_REAL/RV20") { v_real_helper (VLC_CODEC_RV20, vars ); }
1767
4.83k
        S_CASE("V_REAL/RV30") { v_real_helper (VLC_CODEC_RV30, vars ); }
1768
4.83k
        S_CASE("V_REAL/RV40") { v_real_helper (VLC_CODEC_RV40, vars ); }
1769
4.83k
        S_CASE("V_DIRAC")     {
1770
0
            vars.p_fmt->i_codec = VLC_CODEC_DIRAC;
1771
0
        }
1772
4.83k
        S_CASE("V_VP8") {
1773
212
            vars.p_fmt->i_codec = VLC_CODEC_VP8;
1774
212
            if (vars.p_tk->b_has_alpha)
1775
8
                vars.p_fmt->i_level = 0x1000; // mark as containing alpha data
1776
212
            vars.p_tk->b_pts_only = true;
1777
212
        }
1778
4.83k
        S_CASE("V_VP9") {
1779
8
            vars.p_fmt->i_codec = VLC_CODEC_VP9;
1780
8
            if (vars.p_tk->b_has_alpha)
1781
0
                vars.p_fmt->i_level = 0x1000; // mark as containing alpha data
1782
8
            vars.p_tk->b_pts_only = true;
1783
1784
8
            fill_extra_data( vars.p_tk, 0 );
1785
8
            if (vars.p_tk->fmt.i_extra)
1786
0
            {
1787
0
                const auto * VP9CodecFeatures = static_cast<const uint8_t*>(vars.p_tk->fmt.p_extra);
1788
0
                size_t remain = vars.p_tk->fmt.i_extra;
1789
0
                while (remain >= 3)
1790
0
                {
1791
0
                    uint8_t length = VP9CodecFeatures[1];
1792
0
                    switch (VP9CodecFeatures[0])
1793
0
                    {
1794
0
                        case 1: // Profile
1795
0
                            if (length == 1)
1796
0
                                vars.p_fmt->i_profile = VP9CodecFeatures[2];
1797
0
                            break;
1798
0
                        case 2: // Level
1799
0
                            if (length == 1) {
1800
0
                                if (es_format_HasVpxAlpha(vars.p_fmt))
1801
0
                                    vars.p_fmt->i_level |= VP9CodecFeatures[2];
1802
0
                                else
1803
0
                                    vars.p_fmt->i_level = VP9CodecFeatures[2];
1804
0
                            }
1805
0
                            break;
1806
0
                        case 3: // Bit Depth
1807
0
                        case 4: // Chroma Subsampling
1808
0
                        default:
1809
0
                            break;
1810
0
                    }
1811
0
                    if (remain < 1 + 1 + length)
1812
0
                        break;
1813
0
                    VP9CodecFeatures += 1 + 1 + length;
1814
0
                    remain -= 1 + 1 + length;
1815
0
                }
1816
0
            }
1817
8
        }
1818
4.83k
        S_CASE("V_AV1") {
1819
612
            vars.p_fmt->i_codec = VLC_CODEC_AV1;
1820
612
            vars.p_tk->b_pts_only = true;
1821
1822
612
            fill_extra_data( vars.p_tk, 0 );
1823
612
            if (vars.p_fmt->i_extra <= 4)
1824
605
                vars.p_fmt->b_packetized = false; // force full extradata by the packetizer
1825
612
        }
1826
4.83k
        S_CASE("V_CAVS") {
1827
0
            vars.p_fmt->i_codec = VLC_CODEC_CAVS;
1828
0
        }
1829
4.83k
        S_CASE("V_AVS2") {
1830
0
            vars.p_fmt->i_codec = VLC_CODEC_CAVS2;
1831
0
        }
1832
4.83k
        S_CASE("V_AVS3") {
1833
0
            vars.p_fmt->i_codec = VLC_CODEC_CAVS3;
1834
0
        }
1835
4.83k
        S_CASE("V_MPEG4/MS/V3") {
1836
0
            vars.p_fmt->i_codec = VLC_CODEC_DIV3;
1837
0
        }
1838
4.83k
        S_CASE("V_MPEG4/ISO/AVC") {
1839
317
            vars.p_fmt->i_codec = VLC_FOURCC( 'a','v','c','1' );
1840
317
            fill_extra_data( vars.p_tk, 0 );
1841
317
        }
1842
4.83k
        S_CASE_GLOB("V_MPEG4/ISO*") {
1843
116
            vars.p_fmt->i_codec = VLC_CODEC_MP4V;
1844
116
            fill_extra_data( vars.p_tk, 0 );
1845
116
        }
1846
4.83k
        S_CASE("V_MPEGH/ISO/HEVC") {
1847
42
            vars.p_tk->fmt.i_codec = VLC_CODEC_HEVC;
1848
1849
42
            uint8_t* p_extra = (uint8_t*) vars.p_tk->p_extra_data;
1850
1851
            /* HACK: if we found invalid format, made by mkvmerge < 16.0.0,
1852
             *       we try to fix it. They fixed it in 16.0.0. */
1853
42
            const char* app = vars.obj->psz_writing_application;
1854
42
            if( p_extra && vars.p_tk->i_extra_data >= 3 &&
1855
41
                    p_extra[0] == 0 && (p_extra[1] != 0 || p_extra[2] > 1) )
1856
0
            {
1857
0
                msg_Warn(vars.p_demuxer,
1858
0
                        "Invalid HEVC reserved bits in mkv file "
1859
0
                        "made by %s, fixing it", app ? app : "unknown app");
1860
0
                p_extra[0] = 0x01;
1861
0
            }
1862
1863
42
            fill_extra_data( vars.p_tk, 0 );
1864
42
        }
1865
4.83k
        S_CASE("V_MPEGI/ISO/VVC") {
1866
0
            vars.p_tk->fmt.i_codec = VLC_CODEC_VVC;
1867
0
            fill_extra_data( vars.p_tk, 0 );
1868
0
        }
1869
4.83k
        S_CASE("V_QUICKTIME") {
1870
0
            ONLY_FMT(VIDEO);
1871
0
            if( vars.p_tk->i_extra_data > 4 )
1872
0
            {
1873
0
                MP4_Box_t *p_box = MP4_BoxNew(ATOM_root);
1874
0
                if( p_box )
1875
0
                {
1876
0
                    stream_t *p_mp4_stream = vlc_stream_MemoryNew( VLC_OBJECT(vars.p_demuxer),
1877
0
                                                                   vars.p_tk->p_extra_data,
1878
0
                                                                   vars.p_tk->i_extra_data,
1879
0
                                                                   true );
1880
0
                    if( p_mp4_stream )
1881
0
                    {
1882
0
                        p_box->i_type = GetFOURCC( vars.p_tk->p_extra_data );
1883
0
                        p_box->i_size = p_box->i_shortsize = vars.p_tk->i_extra_data;
1884
0
                        if( MP4_ReadBox_sample_vide( p_mp4_stream, p_box ) )
1885
0
                        {
1886
0
                            const MP4_Box_data_sample_vide_t *p_sample = p_box->data.p_sample_vide;
1887
0
                            vars.p_fmt->i_codec = p_box->i_type;
1888
0
                            if( p_sample->i_width && p_sample->i_height )
1889
0
                            {
1890
0
                                vars.p_tk->fmt.video.i_width = p_sample->i_width;
1891
0
                                vars.p_tk->fmt.video.i_height = p_sample->i_height;
1892
0
                            }
1893
0
                            vars.p_fmt->p_extra = malloc( p_sample->i_qt_image_description );
1894
0
                            if( vars.p_fmt->p_extra )
1895
0
                            {
1896
0
                                vars.p_fmt->i_extra = p_sample->i_qt_image_description;
1897
0
                                memcpy( vars.p_fmt->p_extra,
1898
0
                                        p_sample->p_qt_image_description, vars.p_fmt->i_extra );
1899
0
                            }
1900
0
                        }
1901
0
                        vlc_stream_Delete( p_mp4_stream );
1902
0
                    }
1903
0
                    MP4_BoxFree( p_box );
1904
0
                }
1905
0
            }
1906
0
            else throw std::runtime_error ("invalid extradata when handling V_QUICKTIME/*");
1907
0
        }
1908
4.83k
        S_CASE("V_MJPEG") {
1909
6
            vars.p_fmt->i_codec = VLC_CODEC_MJPG;
1910
6
            vars.p_tk->b_pts_only = true;
1911
6
        }
1912
4.83k
        S_CASE("V_UNCOMPRESSED") {
1913
26
            if (vars.p_tk->uncompressed_fourcc == 0)
1914
26
                msg_Dbg( vars.p_demuxer, "uncompressed format with no FourCC");
1915
25
            else
1916
25
            {
1917
25
                const char *desc = vlc_fourcc_GetDescription(VIDEO_ES, vars.p_tk->uncompressed_fourcc);
1918
25
                if (desc[0])
1919
25
                {
1920
25
                    vars.p_fmt->i_codec = vars.p_tk->uncompressed_fourcc;
1921
25
                    msg_Dbg( vars.p_demuxer, "uncompressed format codec=%4.4s", (const char*)&vars.p_tk->uncompressed_fourcc );
1922
25
                }
1923
0
                else
1924
0
                {
1925
0
                    msg_Dbg( vars.p_demuxer, "uncompressed format unknown video codec=%4.4s", (const char*)&vars.p_tk->uncompressed_fourcc );
1926
0
                }
1927
25
            }
1928
26
        }
1929
4.83k
        S_CASE("V_FFV1") {
1930
0
            vars.p_fmt->i_codec = VLC_CODEC_FFV1;
1931
0
            fill_extra_data( vars.p_tk, 0 );
1932
0
        }
1933
4.83k
        S_CASE("V_PRORES") {
1934
1
            vars.p_fmt->i_codec = VLC_CODEC_PRORES;
1935
1
            fill_extra_data( vars.p_tk, 0 );
1936
1
        }
1937
4.83k
        S_CASE("A_MS/ACM") {
1938
7
            mkv_track_t * p_tk = vars.p_tk;
1939
7
            es_format_t * p_fmt = &vars.p_tk->fmt;
1940
1941
7
            if( p_tk->i_extra_data < (int)sizeof( WAVEFORMATEX ) )
1942
0
            {
1943
0
                msg_Err( vars.p_demuxer, "missing/invalid WAVEFORMATEX" );
1944
0
                p_tk->fmt.i_codec = VLC_CODEC_UNKNOWN;
1945
0
            }
1946
7
            else
1947
7
            {
1948
7
                ONLY_FMT(AUDIO);
1949
7
                WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_tk->p_extra_data;
1950
1951
7
                p_tk->fmt.audio.i_channels   = GetWLE( &p_wf->nChannels );
1952
7
                p_tk->fmt.audio.i_rate = GetDWLE( &p_wf->nSamplesPerSec );
1953
7
                p_tk->fmt.i_bitrate    = GetDWLE( &p_wf->nAvgBytesPerSec ) * 8;
1954
7
                p_tk->fmt.audio.i_blockalign = GetWLE( &p_wf->nBlockAlign );
1955
7
                p_tk->fmt.audio.i_bitspersample = GetWLE( &p_wf->wBitsPerSample );
1956
1957
7
                p_tk->fmt.i_extra            = GetWLE( &p_wf->cbSize );
1958
7
                if ( (size_t)p_tk->fmt.i_extra > p_tk->i_extra_data - sizeof( WAVEFORMATEX ) )
1959
6
                    p_tk->fmt.i_extra = 0;
1960
7
                if( p_tk->fmt.i_extra != 0 )
1961
1
                {
1962
1
                    p_tk->fmt.p_extra = xmalloc( p_tk->fmt.i_extra );
1963
1
                    if( p_tk->fmt.p_extra )
1964
1
                        memcpy( p_tk->fmt.p_extra, &p_wf[1], p_tk->fmt.i_extra );
1965
0
                    else
1966
0
                        p_tk->fmt.i_extra = 0;
1967
1
                }
1968
1969
7
                if( p_wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1970
0
                    p_tk->i_extra_data >= sizeof(WAVEFORMATEXTENSIBLE) )
1971
0
                {
1972
0
                    WAVEFORMATEXTENSIBLE *p_wext = container_of(p_wf, WAVEFORMATEXTENSIBLE, Format);
1973
0
                    GUID subFormat = p_wext->SubFormat;
1974
1975
0
                    sf_tag_to_fourcc( &subFormat,  &p_tk->fmt.i_codec, NULL);
1976
                    /* FIXME should we use Samples */
1977
1978
0
                    if( p_tk->fmt.audio.i_channels > 2 &&
1979
0
                        ( p_tk->fmt.i_codec != VLC_CODEC_UNKNOWN ) )
1980
0
                    {
1981
0
                        uint32_t wfextcm = GetDWLE( &p_wext->dwChannelMask );
1982
0
                        int match;
1983
0
                        unsigned i_channel_mask = getChannelMask( &wfextcm,
1984
0
                                                                  p_tk->fmt.audio.i_channels,
1985
0
                                                                  &match );
1986
0
                        p_tk->fmt.i_codec = vlc_fourcc_GetCodecAudio( p_tk->fmt.i_codec,
1987
0
                                                                      p_tk->fmt.audio.i_bitspersample );
1988
0
                        if( i_channel_mask )
1989
0
                        {
1990
0
                            p_tk->i_chans_to_reorder = aout_CheckChannelReorder(
1991
0
                                pi_channels_aout, NULL,
1992
0
                                i_channel_mask,
1993
0
                                p_tk->pi_chan_table );
1994
1995
0
                            p_tk->fmt.audio.i_physical_channels = i_channel_mask;
1996
0
                        }
1997
0
                    }
1998
0
                }
1999
7
                else
2000
7
                {
2001
7
                    wf_tag_to_fourcc( GetWLE( &p_wf->wFormatTag ), &p_tk->fmt.i_codec, NULL );
2002
7
                    if( p_wf->wFormatTag == WAVE_FORMAT_AAC_LATM )
2003
0
                    {
2004
0
                        p_tk->fmt.i_original_fourcc = VLC_FOURCC('L','A','T','M');
2005
0
                    }
2006
7
                    else if( p_wf->wFormatTag == WAVE_FORMAT_AAC_ADTS )
2007
0
                    {
2008
0
                        p_tk->fmt.i_original_fourcc = VLC_FOURCC('A','D','T','S');
2009
0
                    }
2010
7
                }
2011
2012
7
                if( p_tk->fmt.i_codec == VLC_CODEC_UNKNOWN )
2013
7
                    msg_Err( vars.p_demuxer, "Unrecognized wf tag: 0x%x", GetWLE( &p_wf->wFormatTag ) );
2014
7
            }
2015
7
            p_fmt->b_packetized = !p_fmt->audio.i_blockalign;
2016
7
        }
2017
4.83k
        static void A_MPEG_helper_ (HandlerPayload& vars) {
2018
202
            vars.p_tk->fmt.i_codec = VLC_CODEC_MPGA;
2019
202
            vars.p_fmt->b_packetized = false;
2020
202
        }
2021
4.83k
        S_CASE("A_MPEG/L3") { A_MPEG_helper_(vars); }
2022
4.83k
        S_CASE("A_MPEG/L2") { A_MPEG_helper_(vars); }
2023
4.83k
        S_CASE("A_MPEG/L1") { A_MPEG_helper_(vars); }
2024
4.83k
        S_CASE("A_AC3") {
2025
45
            ONLY_FMT(AUDIO);
2026
            // the AC-3 default duration cannot be trusted, see #8512
2027
45
            if ( vars.p_tk->fmt.audio.i_rate == 8000 )
2028
16
            {
2029
16
                vars.p_tk->b_no_duration = true;
2030
16
                vars.p_tk->i_default_duration = 0;
2031
16
            }
2032
2033
45
            vars.p_fmt->i_codec = VLC_CODEC_A52;
2034
45
            vars.p_fmt->b_packetized = false;
2035
45
        }
2036
4.83k
        S_CASE("A_ATRAC/AT1") {
2037
0
            ONLY_FMT(AUDIO);
2038
0
            vars.p_fmt->i_codec = VLC_CODEC_ATRAC1;
2039
0
            vars.p_tk->fmt.audio.i_blockalign = vars.p_tk->fmt.audio.i_channels * 212;
2040
0
        }
2041
4.83k
        S_CASE("A_EAC3") {
2042
0
            vars.p_fmt->i_codec = VLC_CODEC_EAC3;
2043
0
            vars.p_fmt->b_packetized = false;
2044
0
        }
2045
4.83k
        S_CASE("A_DTS")  {
2046
88
            vars.p_fmt->i_codec = VLC_CODEC_DTS;
2047
88
            vars.p_fmt->b_packetized = false;
2048
88
        }
2049
4.83k
        S_CASE("A_MLP")  { vars.p_fmt->i_codec = VLC_CODEC_MLP; }
2050
4.83k
        S_CASE("A_TRUEHD") { /* FIXME when more samples arrive */
2051
0
            vars.p_fmt->i_codec = VLC_CODEC_TRUEHD;
2052
0
            vars.p_fmt->b_packetized = false;
2053
0
        }
2054
4.83k
        S_CASE("A_FLAC") {
2055
45
            vars.p_fmt->i_codec = VLC_CODEC_FLAC;
2056
45
            fill_extra_data( vars.p_tk, 0 );
2057
45
        }
2058
4.83k
        S_CASE("A_VORBIS") {
2059
562
            vars.p_fmt->i_codec = VLC_CODEC_VORBIS;
2060
562
            fill_extra_data( vars.p_tk, 0 );
2061
562
        }
2062
4.83k
        static void A_OPUS__helper(HandlerPayload& vars) {
2063
13
            ONLY_FMT(AUDIO);
2064
12
            vars.p_fmt->i_codec = VLC_CODEC_OPUS;
2065
12
            vars.p_tk->b_no_duration = true;
2066
12
            if( !vars.p_tk->fmt.audio.i_rate )
2067
0
            {
2068
0
                msg_Err( vars.p_demuxer,"No sampling rate, defaulting to 48kHz");
2069
0
                vars.p_fmt->audio.i_rate = 48000;
2070
0
            }
2071
12
            const uint8_t tags[16] = {'O','p','u','s','T','a','g','s',
2072
12
                                       0, 0, 0, 0, 0, 0, 0, 0};
2073
12
            size_t ps[2] = { vars.p_tk->i_extra_data, 16 };
2074
12
            const void *pkt[2] = { static_cast<const void *>( vars.p_tk->p_extra_data ),
2075
12
                                   static_cast<const void *>( tags ) };
2076
2077
12
            if( xiph_PackHeaders( &vars.p_fmt->i_extra,
2078
12
                &vars.p_fmt->p_extra,
2079
12
                ps, pkt, 2 ) )
2080
12
                msg_Err( vars.p_demuxer, "Couldn't pack OPUS headers");
2081
12
        }
2082
4.83k
        S_CASE("A_OPUS")                { A_OPUS__helper( vars ); }
2083
4.83k
        S_CASE("A_OPUS/EXPERIMENTAL")   { A_OPUS__helper( vars ); }
2084
4.83k
        static void A_AAC_MPEG__helper(HandlerPayload& vars, int i_profile, bool sbr = false) {
2085
18
            ONLY_FMT(AUDIO);
2086
18
            int i_srate;
2087
2088
18
            mkv_track_t * p_tk = vars.p_tk;
2089
2090
18
            static const unsigned int i_sample_rates[] =
2091
18
            {
2092
18
                96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
2093
18
                16000, 12000, 11025,  8000,  7350,     0,     0,     0
2094
18
            };
2095
2096
18
            p_tk->fmt.i_codec = VLC_CODEC_MP4A;
2097
2098
141
            for( i_srate = 0; i_srate < 13; i_srate++ )
2099
141
            {
2100
141
                if( i_sample_rates[i_srate] == p_tk->i_original_rate )
2101
18
                    break;
2102
141
            }
2103
2104
18
            msg_Dbg (vars.p_demuxer, "profile=%d srate=%d", i_profile, i_srate );
2105
2106
18
            p_tk->fmt.i_extra = sbr ? 5 : 2;
2107
18
            p_tk->fmt.p_extra = xmalloc( p_tk->fmt.i_extra );
2108
18
            ((uint8_t*)p_tk->fmt.p_extra)[0] = ((i_profile + 1) << 3) | ((i_srate&0xe) >> 1);
2109
18
            ((uint8_t*)p_tk->fmt.p_extra)[1] = ((i_srate & 0x1) << 7) | (p_tk->fmt.audio.i_channels << 3);
2110
2111
18
            if (sbr) {
2112
17
                int syncExtensionType = 0x2B7;
2113
17
                int iDSRI;
2114
112
                for (iDSRI=0; iDSRI<13; iDSRI++)
2115
109
                    if( i_sample_rates[iDSRI] == p_tk->fmt.audio.i_rate )
2116
14
                        break;
2117
17
                ((uint8_t*)p_tk->fmt.p_extra)[2] = (syncExtensionType >> 3) & 0xFF;
2118
17
                ((uint8_t*)p_tk->fmt.p_extra)[3] = ((syncExtensionType & 0x7) << 5) | 5;
2119
17
                ((uint8_t*)p_tk->fmt.p_extra)[4] = ((1 & 0x1) << 7) | (iDSRI << 3);
2120
17
            }
2121
2122
18
        }
2123
4.83k
        S_CASE("A_AAC/MPEG2/MAIN")   { A_AAC_MPEG__helper( vars, 0 ); }
2124
4.83k
        S_CASE("A_AAC/MPEG4/MAIN")   { A_AAC_MPEG__helper( vars, 0 ); }
2125
4.83k
        S_CASE("A_AAC/MPEG2/LC")     { A_AAC_MPEG__helper( vars, 1 ); }
2126
4.83k
        S_CASE("A_AAC/MPEG4/LC")     { A_AAC_MPEG__helper( vars, 1 ); }
2127
4.83k
        S_CASE("A_AAC/MPEG2/SSR")    { A_AAC_MPEG__helper( vars, 2 ); }
2128
4.83k
        S_CASE("A_AAC/MPEG4/SSR")    { A_AAC_MPEG__helper( vars, 2 ); }
2129
4.83k
        S_CASE("A_AAC/MPEG4/LTP")    { A_AAC_MPEG__helper( vars, 3 ); }
2130
4.83k
        S_CASE("A_AAC/MPEG2/LC/SBR") { A_AAC_MPEG__helper( vars, 1, true ); }
2131
4.83k
        S_CASE("A_AAC/MPEG4/LC/SBR") { A_AAC_MPEG__helper( vars, 1, true ); }
2132
4.83k
        S_CASE("A_AAC/MPEG4/") { A_AAC_MPEG__helper( vars, 3 ); } // see #4250
2133
4.83k
        S_CASE("A_AAC/MPEG2/") { A_AAC_MPEG__helper( vars, 3 ); } // backward compatibility
2134
4.83k
        S_CASE("A_AAC") {
2135
506
            vars.p_tk->fmt.i_codec = VLC_CODEC_MP4A;
2136
506
            fill_extra_data( vars.p_tk, 0 );
2137
506
        }
2138
4.83k
        S_CASE("A_ALAC") {
2139
0
            vars.p_tk->fmt.i_codec = VLC_CODEC_ALAC;
2140
0
            fill_extra_data_alac( vars.p_tk );
2141
0
        }
2142
4.83k
        S_CASE("A_WAVPACK4") {
2143
0
            vars.p_tk->fmt.i_codec = VLC_CODEC_WAVPACK;
2144
0
            fill_extra_data( vars.p_tk, 0);
2145
0
        }
2146
4.83k
        S_CASE("A_TTA1") {
2147
12
            ONLY_FMT(AUDIO);
2148
12
            mkv_track_t * p_tk  = vars.p_tk;
2149
12
            es_format_t * p_fmt = vars.p_fmt;
2150
2151
12
            p_fmt->i_codec = VLC_CODEC_TTA;
2152
12
            if( p_tk->i_extra_data > 0 )
2153
0
            {
2154
0
                fill_extra_data( p_tk, 0 );
2155
0
            }
2156
12
            else
2157
12
            {
2158
12
                p_fmt->i_extra = 30;
2159
12
                p_fmt->p_extra = xmalloc( p_fmt->i_extra );
2160
12
                uint8_t *p_extra = (uint8_t*)p_fmt->p_extra;
2161
12
                memcpy( &p_extra[ 0], "TTA1", 4 );
2162
12
                SetWLE( &p_extra[ 4], 1 );
2163
12
                SetWLE( &p_extra[ 6], p_fmt->audio.i_channels );
2164
12
                SetWLE( &p_extra[ 8], p_fmt->audio.i_bitspersample );
2165
12
                SetDWLE( &p_extra[10], p_fmt->audio.i_rate );
2166
12
                SetDWLE( &p_extra[14], 0xffffffff );
2167
12
                memset( &p_extra[18], 0, 30  - 18 );
2168
12
            }
2169
12
        }
2170
4.83k
        static void A_PCM__helper (HandlerPayload& vars, vlc_fourcc_t i_codec) {
2171
0
            ONLY_FMT(AUDIO);
2172
0
            vars.p_fmt->i_codec = i_codec;
2173
0
            vars.p_fmt->audio.i_blockalign = ( vars.p_fmt->audio.i_bitspersample + 7 ) / 8 * vars.p_fmt->audio.i_channels;
2174
2175
0
        }
2176
4.83k
        S_CASE("A_PCM/INT/BIG")    { A_PCM__helper ( vars, VLC_FOURCC( 't','w','o','s' ) ); }
2177
4.83k
        S_CASE("A_PCM/INT/LIT")    { A_PCM__helper ( vars, VLC_FOURCC( 'a','r','a','w' ) ); }
2178
4.83k
        S_CASE("A_PCM/FLOAT/IEEE") { A_PCM__helper ( vars, VLC_FOURCC( 'a','f','l','t' ) ) ;}
2179
4.83k
        S_CASE("A_REAL/14_4") {
2180
0
            ONLY_FMT(AUDIO);
2181
0
            vars.p_fmt->i_codec = VLC_CODEC_RA_144;
2182
0
            vars.p_fmt->audio.i_channels = 1;
2183
0
            vars.p_fmt->audio.i_rate = 8000;
2184
0
            vars.p_fmt->audio.i_blockalign = 0x14;
2185
0
        }
2186
4.83k
        static bool A_REAL__is_valid (HandlerPayload& vars) {
2187
103
            ONLY_FMT(AUDIO);
2188
101
            uint8_t *p = vars.p_tk->p_extra_data;
2189
2190
101
            if (vars.p_tk->i_extra_data <= SIZEOF_REALAUDIO_PRIVATE)
2191
0
                return false;
2192
2193
101
            if( memcmp( p, ".ra", 3 ) ) {
2194
0
                msg_Err( vars.p_demuxer, "Invalid Real ExtraData 0x%4.4s", (char *)p );
2195
0
                vars.p_tk->fmt.i_codec = VLC_CODEC_UNKNOWN;
2196
0
                return false;
2197
0
            }
2198
2199
101
            return true;
2200
101
        }
2201
4.83k
        static void A_REAL__helper (HandlerPayload& vars, vlc_fourcc_t i_codec) {
2202
101
            mkv_track_t        * p_tk = vars.p_tk;
2203
2204
101
            p_tk->fmt.i_codec = i_codec;
2205
2206
101
            Cook_PrivateTrackData * p_realaudio = new Cook_PrivateTrackData(
2207
101
                p_tk->p_extra_data,
2208
101
                p_tk->i_extra_data
2209
101
            );
2210
101
            p_tk->p_sys = p_realaudio;
2211
2212
101
            if( unlikely( !p_realaudio ) )
2213
0
                throw std::runtime_error ("Cook_PrivateTrackData is NULL when handling A_REAL/28_8");
2214
2215
101
            if( unlikely( !p_realaudio->Init() ) )
2216
8
                throw std::runtime_error ("Cook_PrivateTrackData::Init() failed when handling A_REAL/28_8");
2217
2218
93
            if (i_codec == VLC_CODEC_COOK || i_codec == VLC_CODEC_ATRAC3)
2219
93
                p_tk->fmt.audio.i_blockalign = p_realaudio->i_subpacket_size;
2220
0
            else // VLC_CODEC_RA_288
2221
0
                p_tk->fmt.audio.i_blockalign = p_realaudio->coded_frame_size;
2222
2223
93
            p_tk->fmt.audio.i_rate          = p_realaudio->i_rate;
2224
93
            p_tk->fmt.audio.i_bitspersample = p_realaudio->i_bitspersample;
2225
93
            p_tk->fmt.audio.i_channels      = p_realaudio->i_channels;
2226
93
            msg_Dbg(vars.p_demuxer, "%d channels %d bits %d Hz",p_tk->fmt.audio.i_channels, p_tk->fmt.audio.i_bitspersample, p_tk->fmt.audio.i_rate);
2227
2228
93
            fill_extra_data( p_tk, p_tk->fmt.i_codec == VLC_CODEC_RA_288 ? 0 : 78);
2229
93
        }
2230
4.83k
        S_CASE("A_REAL/COOK") {
2231
103
            if (!A_REAL__is_valid (vars))
2232
0
                return;
2233
2234
103
            A_REAL__helper (vars, VLC_CODEC_COOK);
2235
103
        }
2236
4.83k
        S_CASE("A_REAL/ATRC") {
2237
0
            if (!A_REAL__is_valid (vars))
2238
0
                return;
2239
2240
0
            A_REAL__helper (vars, VLC_CODEC_ATRAC3);
2241
0
        }
2242
4.83k
        S_CASE("A_REAL/28_8") {
2243
0
            if (!A_REAL__is_valid (vars))
2244
0
                return;
2245
2246
0
            A_REAL__helper (vars, VLC_CODEC_RA_288);
2247
0
        }
2248
4.83k
        S_CASE("A_QUICKTIME/QDM2") {
2249
0
            vars.p_fmt->i_cat   = AUDIO_ES;
2250
0
            vars.p_fmt->i_codec = VLC_CODEC_QDM2;
2251
2252
0
            fill_extra_data( vars.p_tk, 0 );
2253
0
        }
2254
4.83k
        S_CASE("A_QUICKTIME/QDMC") {
2255
0
            vars.p_fmt->i_cat   = AUDIO_ES;
2256
0
            vars.p_fmt->i_codec = VLC_CODEC_QDMC;
2257
2258
0
            fill_extra_data( vars.p_tk, 0 );
2259
0
        }
2260
4.83k
        S_CASE_GLOB("A_QUICKTIME/*") {
2261
37
            if (vars.p_tk->i_extra_data < 4)
2262
0
                throw std::runtime_error ("invalid extradata when handling A_QUICKTIME/*");
2263
2264
37
            vars.p_fmt->i_cat = AUDIO_ES;
2265
37
            vars.p_fmt->i_codec = GetFOURCC(vars.p_tk->p_extra_data);
2266
2267
37
            fill_extra_data( vars.p_tk, 0 );
2268
37
        }
2269
4.83k
        S_CASE("S_KATE") {
2270
0
            ONLY_FMT(SPU);
2271
0
            vars.p_fmt->i_codec = VLC_CODEC_KATE;
2272
0
            vars.p_fmt->subs.psz_encoding = strdup( "UTF-8" );
2273
2274
0
            fill_extra_data( vars.p_tk, 0 );
2275
0
        }
2276
4.83k
        S_CASE("S_TEXT/ASCII") {
2277
0
            ONLY_FMT(SPU);
2278
0
            vars.p_fmt->i_codec = VLC_CODEC_SUBT;
2279
0
            vars.p_fmt->subs.psz_encoding = strdup( "ASCII" );
2280
0
        }
2281
4.83k
        S_CASE("S_TEXT/UTF8") {
2282
293
            ONLY_FMT(SPU);
2283
287
            vars.p_tk->fmt.i_codec = VLC_CODEC_SUBT;
2284
287
            vars.p_tk->fmt.subs.psz_encoding = strdup( "UTF-8" );
2285
287
        }
2286
4.83k
        S_CASE("S_TEXT/USF") {
2287
6
            ONLY_FMT(SPU);
2288
6
            vars.p_tk->fmt.i_codec = VLC_CODEC_USF;
2289
6
            vars.p_tk->fmt.subs.psz_encoding = strdup( "UTF-8" );
2290
6
            fill_extra_data( vars.p_tk, 0 );
2291
6
        }
2292
4.83k
        static void SSA__helper (HandlerPayload& vars) {
2293
267
            ONLY_FMT(SPU);
2294
242
            vars.p_tk->fmt.i_codec = VLC_CODEC_SSA;
2295
242
            vars.p_tk->fmt.subs.psz_encoding = strdup( "UTF-8" );
2296
242
            fill_extra_data( vars.p_tk, 0 );
2297
242
        }
2298
4.83k
        S_CASE("S_TEXT/SSA") { SSA__helper( vars ); }
2299
4.83k
        S_CASE("S_TEXT/ASS") { SSA__helper( vars ); }
2300
4.83k
        S_CASE("S_SSA")      { SSA__helper( vars ); }
2301
4.83k
        S_CASE("S_ASS")      { SSA__helper( vars ); }
2302
4.83k
        S_CASE("S_VOBSUB") {
2303
378
            ONLY_FMT(SPU);
2304
378
            mkv_track_t * p_tk = vars.p_tk;
2305
2306
378
            p_tk->fmt.i_codec = VLC_CODEC_SPU;
2307
378
            p_tk->b_no_duration = true;
2308
378
            if( likely( p_tk->i_extra_data && p_tk->fmt.i_cat == SPU_ES ) )
2309
376
            {
2310
376
                vobsub_extra_parse( VLC_OBJECT(vars.p_demuxer), &p_tk->fmt.subs,
2311
376
                                    p_tk->p_extra_data, p_tk->i_extra_data );
2312
376
            }
2313
378
        }
2314
4.83k
        S_CASE("S_DVBSUB")
2315
4.83k
        {
2316
1
            ONLY_FMT(SPU);
2317
1
            vars.p_fmt->i_codec = VLC_CODEC_DVBS;
2318
2319
1
            if( vars.p_tk->i_extra_data < 4 )
2320
0
                throw std::runtime_error( "not enough codec data for S_DVBSUB" );
2321
2322
1
            uint16_t page_id = GetWBE( &vars.p_tk->p_extra_data[0] );
2323
1
            uint16_t ancillary_id = GetWBE( &vars.p_tk->p_extra_data[2] );
2324
2325
1
            vars.p_fmt->subs.dvb.i_id = ( ancillary_id << 16 ) | page_id;
2326
1
        }
2327
4.83k
        S_CASE("S_HDMV/PGS") {
2328
0
            vars.p_fmt->i_codec = VLC_CODEC_BD_PG;
2329
0
        }
2330
4.83k
        S_CASE("S_HDMV/TEXTST") {
2331
0
            vars.p_fmt->i_codec = VLC_CODEC_BD_TEXT;
2332
0
        }
2333
4.83k
        S_CASE("D_WEBVTT/SUBTITLES") {
2334
0
            ONLY_FMT(SPU);
2335
0
            vars.p_fmt->i_codec = VLC_CODEC_WEBVTT;
2336
0
            vars.p_fmt->subs.psz_encoding = strdup( "UTF-8");
2337
0
        }
2338
4.83k
        S_CASE("S_TEXT/WEBVTT") {
2339
0
            ONLY_FMT(SPU);
2340
0
            vars.p_fmt->i_codec = VLC_CODEC_WEBVTT;
2341
0
            vars.p_fmt->subs.psz_encoding = strdup( "UTF-8");
2342
0
            fill_extra_data( vars.p_tk, 0 );
2343
0
        }
2344
4.83k
        S_CASE("B_VOBBTN") {
2345
0
            vars.p_fmt->i_cat = DATA_ES;
2346
0
        }
2347
4.83k
        S_CASE_DEFAULT(str) {
2348
122
            msg_Err( vars.p_demuxer, "unknown codec id=`%s'", str );
2349
122
            vars.p_tk->fmt.i_codec = VLC_CODEC_UNKNOWN;
2350
122
        }
2351
4.83k
    };
2352
2353
4.83k
    try {
2354
4.83k
        TrackCodecHandlers::Dispatcher().send( p_tk->codec.c_str(), &captures );
2355
4.83k
    }
2356
4.83k
    catch (std::exception const& e)
2357
4.83k
    {
2358
51
        msg_Err( &sys.demuxer, "Error when trying to initiate track (codec: %s): %s",
2359
51
          p_tk->codec.c_str(), e.what () );
2360
51
        return false;
2361
51
    }
2362
2363
4.78k
    return true;
2364
4.83k
}
2365
2366
} // namespace