mkv.cpp 228 KB
Newer Older
Steve Lhomme's avatar
Steve Lhomme committed
1
2
3
/*****************************************************************************
 * mkv.cpp : matroska demuxer
 *****************************************************************************
4
 * Copyright (C) 2003-2004 the VideoLAN team
Steve Lhomme's avatar
Steve Lhomme committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 * $Id$
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Steve Lhomme <steve.lhomme@free.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
Steve Lhomme's avatar
Steve Lhomme committed
23
24
25
26
27
28
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/

29
30
31
32
33
/* config.h may include inttypes.h, so make sure we define that option
 * early enough. */
#define __STDC_FORMAT_MACROS 1
#define __STDC_CONSTANT_MACROS 1

34
35
36
37
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

38
39
#include <inttypes.h>

40
#include <vlc_common.h>
41
#include <vlc_plugin.h>
Steve Lhomme's avatar
Steve Lhomme committed
42
43
44
45
46
47

#ifdef HAVE_TIME_H
#   include <time.h>                                               /* time() */
#endif


zorglub's avatar
zorglub committed
48
#include <vlc_codecs.h>               /* BITMAPINFOHEADER, WAVEFORMATEX */
49
#include <vlc_iso_lang.h>
Steve Lhomme's avatar
Steve Lhomme committed
50
#include "vlc_meta.h"
zorglub's avatar
zorglub committed
51
52
53
#include <vlc_charset.h>
#include <vlc_input.h>
#include <vlc_demux.h>
Steve Lhomme's avatar
Steve Lhomme committed
54
55
56
57
58
59

#include <iostream>
#include <cassert>
#include <typeinfo>
#include <string>
#include <vector>
60
#include <algorithm>
Steve Lhomme's avatar
Steve Lhomme committed
61
62
63
64
65
66
67
68
69
70
71

#ifdef HAVE_DIRENT_H
#   include <dirent.h>
#endif

/* libebml and matroska */
#include "ebml/EbmlHead.h"
#include "ebml/EbmlSubHead.h"
#include "ebml/EbmlStream.h"
#include "ebml/EbmlContexts.h"
#include "ebml/EbmlVoid.h"
72
#include "ebml/EbmlVersion.h"
Steve Lhomme's avatar
Steve Lhomme committed
73
74
75
#include "ebml/StdIOCallback.h"

#include "matroska/KaxAttachments.h"
76
#include "matroska/KaxAttached.h"
Steve Lhomme's avatar
Steve Lhomme committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "matroska/KaxBlock.h"
#include "matroska/KaxBlockData.h"
#include "matroska/KaxChapters.h"
#include "matroska/KaxCluster.h"
#include "matroska/KaxClusterData.h"
#include "matroska/KaxContexts.h"
#include "matroska/KaxCues.h"
#include "matroska/KaxCuesData.h"
#include "matroska/KaxInfo.h"
#include "matroska/KaxInfoData.h"
#include "matroska/KaxSeekHead.h"
#include "matroska/KaxSegment.h"
#include "matroska/KaxTag.h"
#include "matroska/KaxTags.h"
#include "matroska/KaxTagMulti.h"
#include "matroska/KaxTracks.h"
#include "matroska/KaxTrackAudio.h"
#include "matroska/KaxTrackVideo.h"
#include "matroska/KaxTrackEntryData.h"
#include "matroska/KaxContentEncoding.h"
97
#include "matroska/KaxVersion.h"
Steve Lhomme's avatar
Steve Lhomme committed
98
99
100

#include "ebml/StdIOCallback.h"

101
102
103
104
105
106
#if LIBMATROSKA_VERSION < 0x000706
START_LIBMATROSKA_NAMESPACE
extern const EbmlSemanticContext MATROSKA_DLL_API KaxMatroska_Context;
END_LIBMATROSKA_NAMESPACE
#endif

107
108
#include "vlc_keys.h"

Steve Lhomme's avatar
Steve Lhomme committed
109
110
111
112
113
114
115
extern "C" {
   #include "mp4/libmp4.h"
}
#ifdef HAVE_ZLIB_H
#   include <zlib.h>
#endif

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );

vlc_module_begin();
    set_shortname( "Matroska" );
    set_description( N_("Matroska stream demuxer" ) );
    set_capability( "demux", 50 );
    set_callbacks( Open, Close );
    set_category( CAT_INPUT );
    set_subcategory( SUBCAT_INPUT_DEMUX );

    add_bool( "mkv-use-ordered-chapters", 1, NULL,
            N_("Ordered chapters"),
            N_("Play ordered chapters as specified in the segment."), true );

    add_bool( "mkv-use-chapter-codec", 1, NULL,
            N_("Chapter codecs"),
            N_("Use chapter codecs found in the segment."), true );

    add_bool( "mkv-preload-local-dir", 1, NULL,
            N_("Preload Directory"),
            N_("Preload matroska files from the same family in the same directory (not good for broken files)."), true );

    add_bool( "mkv-seek-percent", 0, NULL,
            N_("Seek based on percent not time"),
            N_("Seek based on percent not time."), true );

    add_bool( "mkv-use-dummy", 0, NULL,
            N_("Dummy Elements"),
            N_("Read and discard unknown EBML elements (not good for broken files)."), true );

    add_shortcut( "mka" );
    add_shortcut( "mkv" );
vlc_module_end();



156
157
158
159
160
#define MATROSKA_COMPRESSION_NONE  -1
#define MATROSKA_COMPRESSION_ZLIB   0
#define MATROSKA_COMPRESSION_BLIB   1
#define MATROSKA_COMPRESSION_LZOX   2
#define MATROSKA_COMPRESSION_HEADER 3
Steve Lhomme's avatar
Steve Lhomme committed
161

162
163
#define MKVD_TIMECODESCALE 1000000

164
165
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#undef ATTRIBUTE_PACKED
166
#undef PRAGMA_PACK_BEGIN
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#undef PRAGMA_PACK_END

#if defined(__GNUC__)
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
#define ATTRIBUTE_PACKED __attribute__ ((packed))
#define PRAGMA_PACK 0
#endif
#endif

#if !defined(ATTRIBUTE_PACKED)
#define ATTRIBUTE_PACKED
#define PRAGMA_PACK 1
#endif

#if PRAGMA_PACK
#pragma pack(1)
#endif

/*************************************
*  taken from libdvdnav / libdvdread
**************************************/

/**
 * DVD Time Information.
 */
typedef struct {
  uint8_t hour;
  uint8_t minute;
  uint8_t second;
  uint8_t frame_u; /* The two high bits are the frame rate. */
} ATTRIBUTE_PACKED dvd_time_t;

/**
 * User Operations.
 */
typedef struct {
#ifdef WORDS_BIGENDIAN
204
205
  unsigned char zero                           : 7; /* 25-31 */
  unsigned char video_pres_mode_change         : 1; /* 24 */
206
 
207
208
209
210
211
212
213
214
  unsigned char karaoke_audio_pres_mode_change : 1; /* 23 */
  unsigned char angle_change                   : 1;
  unsigned char subpic_stream_change           : 1;
  unsigned char audio_stream_change            : 1;
  unsigned char pause_on                       : 1;
  unsigned char still_off                      : 1;
  unsigned char button_select_or_activate      : 1;
  unsigned char resume                         : 1; /* 16 */
215
 
216
217
218
219
220
221
222
223
  unsigned char chapter_menu_call              : 1; /* 15 */
  unsigned char angle_menu_call                : 1;
  unsigned char audio_menu_call                : 1;
  unsigned char subpic_menu_call               : 1;
  unsigned char root_menu_call                 : 1;
  unsigned char title_menu_call                : 1;
  unsigned char backward_scan                  : 1;
  unsigned char forward_scan                   : 1; /* 8 */
224
 
225
226
227
228
229
230
231
232
  unsigned char next_pg_search                 : 1; /* 7 */
  unsigned char prev_or_top_pg_search          : 1;
  unsigned char time_or_chapter_search         : 1;
  unsigned char go_up                          : 1;
  unsigned char stop                           : 1;
  unsigned char title_play                     : 1;
  unsigned char chapter_search_or_play         : 1;
  unsigned char title_or_time_play             : 1; /* 0 */
233
#else
234
235
  unsigned char video_pres_mode_change         : 1; /* 24 */
  unsigned char zero                           : 7; /* 25-31 */
236
 
237
238
239
240
241
242
243
244
  unsigned char resume                         : 1; /* 16 */
  unsigned char button_select_or_activate      : 1;
  unsigned char still_off                      : 1;
  unsigned char pause_on                       : 1;
  unsigned char audio_stream_change            : 1;
  unsigned char subpic_stream_change           : 1;
  unsigned char angle_change                   : 1;
  unsigned char karaoke_audio_pres_mode_change : 1; /* 23 */
245
 
246
247
248
249
250
251
252
253
  unsigned char forward_scan                   : 1; /* 8 */
  unsigned char backward_scan                  : 1;
  unsigned char title_menu_call                : 1;
  unsigned char root_menu_call                 : 1;
  unsigned char subpic_menu_call               : 1;
  unsigned char audio_menu_call                : 1;
  unsigned char angle_menu_call                : 1;
  unsigned char chapter_menu_call              : 1; /* 15 */
254
 
255
256
257
258
259
260
261
262
  unsigned char title_or_time_play             : 1; /* 0 */
  unsigned char chapter_search_or_play         : 1;
  unsigned char title_play                     : 1;
  unsigned char stop                           : 1;
  unsigned char go_up                          : 1;
  unsigned char time_or_chapter_search         : 1;
  unsigned char prev_or_top_pg_search          : 1;
  unsigned char next_pg_search                 : 1; /* 7 */
263
264
265
266
267
268
269
270
271
272
273
274
#endif
} ATTRIBUTE_PACKED user_ops_t;

/**
 * Type to store per-command data.
 */
typedef struct {
  uint8_t bytes[8];
} ATTRIBUTE_PACKED vm_cmd_t;
#define COMMAND_DATA_SIZE 8

/**
275
 * PCI General Information
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
 */
typedef struct {
  uint32_t nv_pck_lbn;      /**< sector address of this nav pack */
  uint16_t vobu_cat;        /**< 'category' of vobu */
  uint16_t zero1;           /**< reserved */
  user_ops_t vobu_uop_ctl;  /**< UOP of vobu */
  uint32_t vobu_s_ptm;      /**< start presentation time of vobu */
  uint32_t vobu_e_ptm;      /**< end presentation time of vobu */
  uint32_t vobu_se_e_ptm;   /**< end ptm of sequence end in vobu */
  dvd_time_t e_eltm;        /**< Cell elapsed time */
  char vobu_isrc[32];
} ATTRIBUTE_PACKED pci_gi_t;

/**
 * Non Seamless Angle Information
 */
typedef struct {
  uint32_t nsml_agl_dsta[9];  /**< address of destination vobu in AGL_C#n */
} ATTRIBUTE_PACKED nsml_agli_t;

296
297
/**
 * Highlight General Information
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
 *
 * For btngrX_dsp_ty the bits have the following meaning:
 * 000b: normal 4/3 only buttons
 * XX1b: wide (16/9) buttons
 * X1Xb: letterbox buttons
 * 1XXb: pan&scan buttons
 */
typedef struct {
  uint16_t hli_ss; /**< status, only low 2 bits 0: no buttons, 1: different 2: equal 3: eual except for button cmds */
  uint32_t hli_s_ptm;              /**< start ptm of hli */
  uint32_t hli_e_ptm;              /**< end ptm of hli */
  uint32_t btn_se_e_ptm;           /**< end ptm of button select */
#ifdef WORDS_BIGENDIAN
  unsigned char zero1 : 2;          /**< reserved */
  unsigned char btngr_ns : 2;       /**< number of button groups 1, 2 or 3 with 36/18/12 buttons */
  unsigned char zero2 : 1;          /**< reserved */
  unsigned char btngr1_dsp_ty : 3;  /**< display type of subpic stream for button group 1 */
  unsigned char zero3 : 1;          /**< reserved */
  unsigned char btngr2_dsp_ty : 3;  /**< display type of subpic stream for button group 2 */
  unsigned char zero4 : 1;          /**< reserved */
  unsigned char btngr3_dsp_ty : 3;  /**< display type of subpic stream for button group 3 */
#else
  unsigned char btngr1_dsp_ty : 3;
  unsigned char zero2 : 1;
  unsigned char btngr_ns : 2;
  unsigned char zero1 : 2;
  unsigned char btngr3_dsp_ty : 3;
  unsigned char zero4 : 1;
  unsigned char btngr2_dsp_ty : 3;
  unsigned char zero3 : 1;
#endif
  uint8_t btn_ofn;     /**< button offset number range 0-255 */
330
  uint8_t btn_ns;      /**< number of valid buttons  <= 36/18/12 (low 6 bits) */
331
332
333
334
335
336
337
  uint8_t nsl_btn_ns;  /**< number of buttons selectable by U_BTNNi (low 6 bits)   nsl_btn_ns <= btn_ns */
  uint8_t zero5;       /**< reserved */
  uint8_t fosl_btnn;   /**< forcedly selected button  (low 6 bits) */
  uint8_t foac_btnn;   /**< forcedly activated button (low 6 bits) */
} ATTRIBUTE_PACKED hl_gi_t;


zorglub's avatar
zorglub committed
338
339
/**
 * Button Color Information Table
340
341
342
343
 * Each entry beeing a 32bit word that contains the color indexs and alpha
 * values to use.  They are all represented by 4 bit number and stored
 * like this [Ci3, Ci2, Ci1, Ci0, A3, A2, A1, A0].   The actual palette
 * that the indexes reference is in the PGC.
zorglub's avatar
zorglub committed
344
 * \todo split the uint32_t into a struct
345
346
347
348
349
 */
typedef struct {
  uint32_t btn_coli[3][2];  /**< [button color number-1][select:0/action:1] */
} ATTRIBUTE_PACKED btn_colit_t;

zorglub's avatar
zorglub committed
350
/**
351
352
353
354
355
356
357
358
 * Button Information
 *
 * NOTE: I've had to change the structure from the disk layout to get
 * the packing to work with Sun's Forte C compiler.
 * The 4 and 7 bytes are 'rotated' was: ABC DEF GHIJ  is: ABCG DEFH IJ
 */
typedef struct {
#ifdef WORDS_BIGENDIAN
359
360
361
362
  uint32        btn_coln         : 2;  /**< button color number */
  uint32        x_start          : 10; /**< x start offset within the overlay */
  uint32        zero1            : 2;  /**< reserved */
  uint32        x_end            : 10; /**< x end offset within the overlay */
363

364
365
  uint32        zero3            : 2;  /**< reserved */
  uint32        up               : 6;  /**< button index when pressing up */
366

367
368
369
370
  uint32        auto_action_mode : 2;  /**< 0: no, 1: activated if selected */
  uint32        y_start          : 10; /**< y start offset within the overlay */
  uint32        zero2            : 2;  /**< reserved */
  uint32        y_end            : 10; /**< y end offset within the overlay */
371

372
373
  uint32        zero4            : 2;  /**< reserved */
  uint32        down             : 6;  /**< button index when pressing down */
374
375
376
377
378
  unsigned char zero5            : 2;  /**< reserved */
  unsigned char left             : 6;  /**< button index when pressing left */
  unsigned char zero6            : 2;  /**< reserved */
  unsigned char right            : 6;  /**< button index when pressing right */
#else
379
380
381
382
  uint32        x_end            : 10;
  uint32        zero1            : 2;
  uint32        x_start          : 10;
  uint32        btn_coln         : 2;
383

384
385
  uint32        up               : 6;
  uint32        zero3            : 2;
386

387
388
389
390
  uint32        y_end            : 10;
  uint32        zero2            : 2;
  uint32        y_start          : 10;
  uint32        auto_action_mode : 2;
391

392
393
  uint32        down             : 6;
  uint32        zero4            : 2;
394
395
396
397
398
399
400
401
402
  unsigned char left             : 6;
  unsigned char zero5            : 2;
  unsigned char right            : 6;
  unsigned char zero6            : 2;
#endif
  vm_cmd_t cmd;
} ATTRIBUTE_PACKED btni_t;

/**
403
 * Highlight Information
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
 */
typedef struct {
  hl_gi_t     hl_gi;
  btn_colit_t btn_colit;
  btni_t      btnit[36];
} ATTRIBUTE_PACKED hli_t;

/**
 * PCI packet
 */
typedef struct {
  pci_gi_t    pci_gi;
  nsml_agli_t nsml_agli;
  hli_t       hli;
  uint8_t     zero1[189];
} ATTRIBUTE_PACKED pci_t;


#if PRAGMA_PACK
#pragma pack()
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////////////


Steve Lhomme's avatar
Steve Lhomme committed
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
/**
 * What's between a directory and a filename?
 */
#if defined( WIN32 )
    #define DIRECTORY_SEPARATOR '\\'
#else
    #define DIRECTORY_SEPARATOR '/'
#endif

using namespace LIBMATROSKA_NAMESPACE;
using namespace std;

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
#ifdef HAVE_ZLIB_H
block_t *block_zlib_decompress( vlc_object_t *p_this, block_t *p_in_block ) {
    int result, dstsize, n;
    unsigned char *dst;
    block_t *p_block;
    z_stream d_stream;

    d_stream.zalloc = (alloc_func)0;
    d_stream.zfree = (free_func)0;
    d_stream.opaque = (voidpf)0;
    result = inflateInit(&d_stream);
    if( result != Z_OK )
    {
        msg_Dbg( p_this, "inflateInit() failed. Result: %d", result );
        return NULL;
    }

    d_stream.next_in = (Bytef *)p_in_block->p_buffer;
    d_stream.avail_in = p_in_block->i_buffer;
    n = 0;
    p_block = block_New( p_this, 0 );
    dst = NULL;
    do
    {
        n++;
        p_block = block_Realloc( p_block, 0, n * 1000 );
        dst = (unsigned char *)p_block->p_buffer;
        d_stream.next_out = (Bytef *)&dst[(n - 1) * 1000];
        d_stream.avail_out = 1000;
        result = inflate(&d_stream, Z_NO_FLUSH);
        if( ( result != Z_OK ) && ( result != Z_STREAM_END ) )
        {
            msg_Dbg( p_this, "Zlib decompression failed. Result: %d", result );
            return NULL;
        }
    }
    while( ( d_stream.avail_out == 0 ) && ( d_stream.avail_in != 0 ) &&
           ( result != Z_STREAM_END ) );

    dstsize = d_stream.total_out;
    inflateEnd( &d_stream );

    p_block = block_Realloc( p_block, 0, dstsize );
    p_block->i_buffer = dstsize;
    block_Release( p_in_block );

    return p_block;
}
#endif

/**
 * Helper function to print the mkv parse tree
 */
496
static void MkvTree( demux_t & demuxer, int i_level, const char *psz_format, ... )
Steve Lhomme's avatar
Steve Lhomme committed
497
498
499
500
{
    va_list args;
    if( i_level > 9 )
    {
501
        msg_Err( &demuxer, "too deep tree" );
Steve Lhomme's avatar
Steve Lhomme committed
502
503
504
        return;
    }
    va_start( args, psz_format );
505
    static const char psz_foo[] = "|   |   |   |   |   |   |   |   |   |";
Steve Lhomme's avatar
Steve Lhomme committed
506
507
508
509
510
    char *psz_foo2 = (char*)malloc( ( i_level * 4 + 3 + strlen( psz_format ) ) * sizeof(char) );
    strncpy( psz_foo2, psz_foo, 4 * i_level );
    psz_foo2[ 4 * i_level ] = '+';
    psz_foo2[ 4 * i_level + 1 ] = ' ';
    strcpy( &psz_foo2[ 4 * i_level + 2 ], psz_format );
511
    __msg_GenericVa( VLC_OBJECT(&demuxer),VLC_MSG_DBG, "mkv", psz_foo2, args );
Steve Lhomme's avatar
Steve Lhomme committed
512
513
514
    free( psz_foo2 );
    va_end( args );
}
515

Steve Lhomme's avatar
Steve Lhomme committed
516
517
518
519
520
521
522
/*****************************************************************************
 * Stream managment
 *****************************************************************************/
class vlc_stream_io_callback: public IOCallback
{
  private:
    stream_t       *s;
523
524
    bool     mb_eof;
    bool     b_owner;
Steve Lhomme's avatar
Steve Lhomme committed
525
526

  public:
527
    vlc_stream_io_callback( stream_t *, bool );
528
529
530
531
532
533

    virtual ~vlc_stream_io_callback()
    {
        if( b_owner )
            stream_Delete( s );
    }
Steve Lhomme's avatar
Steve Lhomme committed
534
535
536
537
538
539
540
541
542
543
544
545
546
547

    virtual uint32   read            ( void *p_buffer, size_t i_size);
    virtual void     setFilePointer  ( int64_t i_offset, seek_mode mode = seek_beginning );
    virtual size_t   write           ( const void *p_buffer, size_t i_size);
    virtual uint64   getFilePointer  ( void );
    virtual void     close           ( void );
};

/*****************************************************************************
 * Ebml Stream parser
 *****************************************************************************/
class EbmlParser
{
  public:
548
    EbmlParser( EbmlStream *es, EbmlElement *el_start, demux_t *p_demux );
549
    virtual ~EbmlParser( void );
Steve Lhomme's avatar
Steve Lhomme committed
550
551
552

    void Up( void );
    void Down( void );
553
    void Reset( demux_t *p_demux );
Steve Lhomme's avatar
Steve Lhomme committed
554
555
    EbmlElement *Get( void );
    void        Keep( void );
556
    EbmlElement *UnGet( uint64 i_block_pos, uint64 i_cluster_pos );
Steve Lhomme's avatar
Steve Lhomme committed
557

558
559
560
561
    int  GetLevel( void );

    /* Is the provided element presents in our upper elements */
    bool IsTopPresent( EbmlElement * );
Steve Lhomme's avatar
Steve Lhomme committed
562
563
564
565
566

  private:
    EbmlStream  *m_es;
    int         mi_level;
    EbmlElement *m_el[10];
567
    int64_t      mi_remain_size[10];
Steve Lhomme's avatar
Steve Lhomme committed
568
569
570
571

    EbmlElement *m_got;

    int         mi_user_level;
572
573
    bool  mb_keep;
    bool  mb_dummy;
Steve Lhomme's avatar
Steve Lhomme committed
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
};


/*****************************************************************************
 * Some functions to manipulate memory
 *****************************************************************************/
#define GetFOURCC( p )  __GetFOURCC( (uint8_t*)p )
static vlc_fourcc_t __GetFOURCC( uint8_t *p )
{
    return VLC_FOURCC( p[0], p[1], p[2], p[3] );
}

/*****************************************************************************
 * definitions of structures and functions used by this plugins
 *****************************************************************************/
typedef struct
{
591
592
//    ~mkv_track_t();

593
594
    bool   b_default;
    bool   b_enabled;
Steve Lhomme's avatar
Steve Lhomme committed
595
    unsigned int i_number;
Steve Lhomme's avatar
Steve Lhomme committed
596

Steve Lhomme's avatar
Steve Lhomme committed
597
598
    int          i_extra_data;
    uint8_t      *p_extra_data;
Steve Lhomme's avatar
Steve Lhomme committed
599
600
601
602
603

    char         *psz_codec;

    uint64_t     i_default_duration;
    float        f_timecodescale;
604
    mtime_t      i_last_dts;
Steve Lhomme's avatar
Steve Lhomme committed
605
606
607
608
609
610

    /* video */
    es_format_t fmt;
    float       f_fps;
    es_out_id_t *p_es;

611
612
613
    /* audio */
    unsigned int i_original_rate;

614
    bool      b_inited;
Steve Lhomme's avatar
Steve Lhomme committed
615
616
617
618
619
    /* data to be send first */
    int             i_data_init;
    uint8_t         *p_data_init;

    /* hack : it's for seek */
620
621
    bool      b_search_keyframe;
    bool      b_silent;
Steve Lhomme's avatar
Steve Lhomme committed
622
623

    /* informative */
624
625
626
627
628
    const char   *psz_codec_name;
    const char   *psz_codec_settings;
    const char   *psz_codec_info_url;
    const char   *psz_codec_download_url;

Steve Lhomme's avatar
Steve Lhomme committed
629
    /* encryption/compression */
630
631
    int                    i_compression_type;
    KaxContentCompSettings *p_compression_data;
Steve Lhomme's avatar
Steve Lhomme committed
632
633
634
635
636
637
638
639
640
641
642

} mkv_track_t;

typedef struct
{
    int     i_track;
    int     i_block_number;

    int64_t i_position;
    int64_t i_time;

643
    bool b_key;
Steve Lhomme's avatar
Steve Lhomme committed
644
645
} mkv_index_t;

646
647
class demux_sys_t;

648
649
650
651
652
653
654
655
const binary MATROSKA_DVD_LEVEL_SS   = 0x30;
const binary MATROSKA_DVD_LEVEL_LU   = 0x2A;
const binary MATROSKA_DVD_LEVEL_TT   = 0x28;
const binary MATROSKA_DVD_LEVEL_PGC  = 0x20;
const binary MATROSKA_DVD_LEVEL_PG   = 0x18;
const binary MATROSKA_DVD_LEVEL_PTT  = 0x10;
const binary MATROSKA_DVD_LEVEL_CN   = 0x08;

656
class chapter_codec_cmds_c
657
{
658
public:
659
    chapter_codec_cmds_c( demux_sys_t & demuxer, int codec_id = -1)
Steve Lhomme's avatar
Steve Lhomme committed
660
661
    :p_private_data(NULL)
    ,i_codec_id( codec_id )
662
    ,sys( demuxer )
663
    {}
664
 
665
    virtual ~chapter_codec_cmds_c()
Steve Lhomme's avatar
Steve Lhomme committed
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
    {
        delete p_private_data;
        std::vector<KaxChapterProcessData*>::iterator indexe = enter_cmds.begin();
        while ( indexe != enter_cmds.end() )
        {
            delete (*indexe);
            indexe++;
        }
        std::vector<KaxChapterProcessData*>::iterator indexl = leave_cmds.begin();
        while ( indexl != leave_cmds.end() )
        {
            delete (*indexl);
            indexl++;
        }
        std::vector<KaxChapterProcessData*>::iterator indexd = during_cmds.begin();
        while ( indexd != during_cmds.end() )
        {
            delete (*indexd);
            indexd++;
        }
    }
Steve Lhomme's avatar
Steve Lhomme committed
687

688
689
    void SetPrivate( const KaxChapterProcessPrivate & private_data )
    {
Steve Lhomme's avatar
Steve Lhomme committed
690
        p_private_data = new KaxChapterProcessPrivate( private_data );
691
692
693
    }

    void AddCommand( const KaxChapterProcessCommand & command );
694
 
695
696
697
    /// \return wether the codec has seeked in the files or not
    virtual bool Enter() { return false; }
    virtual bool Leave() { return false; }
698
    virtual std::string GetCodecName( bool f_for_title = false ) const { return ""; }
699
    virtual int16 GetTitleNumber() { return -1; }
700

Steve Lhomme's avatar
Steve Lhomme committed
701
    KaxChapterProcessPrivate *p_private_data;
702

703
protected:
Steve Lhomme's avatar
Steve Lhomme committed
704
705
706
    std::vector<KaxChapterProcessData*> enter_cmds;
    std::vector<KaxChapterProcessData*> during_cmds;
    std::vector<KaxChapterProcessData*> leave_cmds;
707
708

    int i_codec_id;
709
    demux_sys_t & sys;
710
711
};

712
class dvd_command_interpretor_c
713
{
Steve Lhomme's avatar
Steve Lhomme committed
714
public:
715
716
    dvd_command_interpretor_c( demux_sys_t & demuxer )
    :sys( demuxer )
717
    {
718
719
720
721
722
723
724
725
726
        memset( p_PRMs, 0, sizeof(p_PRMs) );
        p_PRMs[ 0x80 + 1 ] = 15;
        p_PRMs[ 0x80 + 2 ] = 62;
        p_PRMs[ 0x80 + 3 ] = 1;
        p_PRMs[ 0x80 + 4 ] = 1;
        p_PRMs[ 0x80 + 7 ] = 1;
        p_PRMs[ 0x80 + 8 ] = 1;
        p_PRMs[ 0x80 + 16 ] = 0xFFFFu;
        p_PRMs[ 0x80 + 18 ] = 0xFFFFu;
727
    }
728
 
729
    bool Interpret( const binary * p_command, size_t i_size = 8 );
730
 
731
732
733
734
735
736
737
    uint16 GetPRM( size_t index ) const
    {
        if ( index < 256 )
            return p_PRMs[ index ];
        else return 0;
    }

Steve Lhomme's avatar
Steve Lhomme committed
738
739
740
    uint16 GetGPRM( size_t index ) const
    {
        if ( index >= 0 && index < 16 )
741
            return p_PRMs[ index ];
Steve Lhomme's avatar
Steve Lhomme committed
742
743
        else return 0;
    }
744

Steve Lhomme's avatar
Steve Lhomme committed
745
746
747
    uint16 GetSPRM( size_t index ) const
    {
        // 21,22,23 reserved for future use
748
749
        if ( index >= 0x80 && index < 0x95 )
            return p_PRMs[ index ];
Steve Lhomme's avatar
Steve Lhomme committed
750
751
        else return 0;
    }
752

753
754
755
756
757
758
759
760
761
    bool SetPRM( size_t index, uint16 value )
    {
        if ( index >= 0 && index < 16 )
        {
            p_PRMs[ index ] = value;
            return true;
        }
        return false;
    }
762
 
Steve Lhomme's avatar
Steve Lhomme committed
763
764
765
    bool SetGPRM( size_t index, uint16 value )
    {
        if ( index >= 0 && index < 16 )
766
        {
767
            p_PRMs[ index ] = value;
Steve Lhomme's avatar
Steve Lhomme committed
768
            return true;
769
        }
Steve Lhomme's avatar
Steve Lhomme committed
770
771
        return false;
    }
772

Steve Lhomme's avatar
Steve Lhomme committed
773
774
    bool SetSPRM( size_t index, uint16 value )
    {
775
        if ( index > 0x80 && index <= 0x8D && index != 0x8C )
776
        {
777
            p_PRMs[ index ] = value;
Steve Lhomme's avatar
Steve Lhomme committed
778
            return true;
779
        }
Steve Lhomme's avatar
Steve Lhomme committed
780
781
        return false;
    }
782

783
protected:
784
785
786
787
    std::string GetRegTypeName( bool b_value, uint16 value ) const
    {
        std::string result;
        char s_value[6], s_reg_value[6];
788
        sprintf( s_value, "%.5d", value );
789
790
791
792
793
794
795
796
797

        if ( b_value )
        {
            result = "value (";
            result += s_value;
            result += ")";
        }
        else if ( value < 0x80 )
        {
798
            sprintf( s_reg_value, "%.5d", GetPRM( value ) );
799
800
801
802
803
804
805
806
            result = "GPreg[";
            result += s_value;
            result += "] (";
            result += s_reg_value;
            result += ")";
        }
        else
        {
807
            sprintf( s_reg_value, "%.5d", GetPRM( value ) );
808
809
810
811
812
813
814
815
816
817
            result = "SPreg[";
            result += s_value;
            result += "] (";
            result += s_reg_value;
            result += ")";
        }
        return result;
    }

    uint16       p_PRMs[256];
818
    demux_sys_t  & sys;
819
 
820
    // DVD command IDs
821
822
823
824

    // Tests
    // wether it's a comparison on the value or register
    static const uint16 CMD_DVD_TEST_VALUE          = 0x80;
825
826
827
828
829
830
831
    static const uint16 CMD_DVD_IF_GPREG_AND        = (1 << 4);
    static const uint16 CMD_DVD_IF_GPREG_EQUAL      = (2 << 4);
    static const uint16 CMD_DVD_IF_GPREG_NOT_EQUAL  = (3 << 4);
    static const uint16 CMD_DVD_IF_GPREG_SUP_EQUAL  = (4 << 4);
    static const uint16 CMD_DVD_IF_GPREG_SUP        = (5 << 4);
    static const uint16 CMD_DVD_IF_GPREG_INF_EQUAL  = (6 << 4);
    static const uint16 CMD_DVD_IF_GPREG_INF        = (7 << 4);
832
 
833
834
835
836
837
838
839
840
841
842
    static const uint16 CMD_DVD_NOP                    = 0x0000;
    static const uint16 CMD_DVD_GOTO_LINE              = 0x0001;
    static const uint16 CMD_DVD_BREAK                  = 0x0002;
    // Links
    static const uint16 CMD_DVD_NOP2                   = 0x2001;
    static const uint16 CMD_DVD_LINKPGCN               = 0x2004;
    static const uint16 CMD_DVD_LINKPGN                = 0x2006;
    static const uint16 CMD_DVD_LINKCN                 = 0x2007;
    static const uint16 CMD_DVD_JUMP_TT                = 0x3002;
    static const uint16 CMD_DVD_JUMPVTS_TT             = 0x3003;
843
    static const uint16 CMD_DVD_JUMPVTS_PTT            = 0x3005;
844
845
846
847
848
    static const uint16 CMD_DVD_JUMP_SS                = 0x3006;
    static const uint16 CMD_DVD_CALLSS_VTSM1           = 0x3008;
    //
    static const uint16 CMD_DVD_SET_HL_BTNN2           = 0x4600;
    static const uint16 CMD_DVD_SET_HL_BTNN_LINKPGCN1  = 0x4604;
849
    static const uint16 CMD_DVD_SET_STREAM             = 0x5100;
850
851
852
853
854
855
856
857
858
859
860
    static const uint16 CMD_DVD_SET_GPRMMD             = 0x5300;
    static const uint16 CMD_DVD_SET_HL_BTNN1           = 0x5600;
    static const uint16 CMD_DVD_SET_HL_BTNN_LINKPGCN2  = 0x5604;
    static const uint16 CMD_DVD_SET_HL_BTNN_LINKCN     = 0x5607;
    // Operations
    static const uint16 CMD_DVD_MOV_SPREG_PREG         = 0x6100;
    static const uint16 CMD_DVD_GPREG_MOV_VALUE        = 0x7100;
    static const uint16 CMD_DVD_SUB_GPREG              = 0x7400;
    static const uint16 CMD_DVD_MULT_GPREG             = 0x7500;
    static const uint16 CMD_DVD_GPREG_DIV_VALUE        = 0x7600;
    static const uint16 CMD_DVD_GPREG_AND_VALUE        = 0x7900;
861
 
862
    // callbacks when browsing inside CodecPrivate
863
    static bool MatchIsDomain     ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
864
    static bool MatchIsVMG        ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
865
    static bool MatchVTSNumber    ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
866
    static bool MatchVTSMNumber   ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
867
868
869
870
871
    static bool MatchTitleNumber  ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
    static bool MatchPgcType      ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
    static bool MatchPgcNumber    ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
    static bool MatchChapterNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
    static bool MatchCellNumber   ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
872
873
};

874
class dvd_chapter_codec_c : public chapter_codec_cmds_c
875
{
Steve Lhomme's avatar
Steve Lhomme committed
876
public:
877
    dvd_chapter_codec_c( demux_sys_t & sys )
878
    :chapter_codec_cmds_c( sys, 1 )
879
880
    {}

Steve Lhomme's avatar
Steve Lhomme committed
881
882
    bool Enter();
    bool Leave();
883
    std::string GetCodecName( bool f_for_title = false ) const;
884
    int16 GetTitleNumber();
885
886
};

887
888
889
890
891
892
893
894
class matroska_script_interpretor_c
{
public:
    matroska_script_interpretor_c( demux_sys_t & demuxer )
    :sys( demuxer )
    {}

    bool Interpret( const binary * p_command, size_t i_size );
895
 
896
897
    // DVD command IDs
    static const std::string CMD_MS_GOTO_AND_PLAY;
898
 
899
900
901
902
903
904
905
protected:
    demux_sys_t  & sys;
};

const std::string matroska_script_interpretor_c::CMD_MS_GOTO_AND_PLAY = "GotoAndPlay";


906
907
class matroska_script_codec_c : public chapter_codec_cmds_c
{
908
909
public:
    matroska_script_codec_c( demux_sys_t & sys )
910
    :chapter_codec_cmds_c( sys, 0 )
911
912
913
914
915
916
917
    ,interpretor( sys )
    {}

    bool Enter();
    bool Leave();

protected:
918
    matroska_script_interpretor_c interpretor;
919
920
921
};

class chapter_translation_c
922
923
{
public:
Steve Lhomme's avatar
Steve Lhomme committed
924
925
926
927
928
929
930
931
932
933
    chapter_translation_c()
        :p_translated(NULL)
    {}

    ~chapter_translation_c()
    {
        delete p_translated;
    }

    KaxChapterTranslateID  *p_translated;
934
935
936
937
    unsigned int           codec_id;
    std::vector<uint64_t>  editions;
};

938
class chapter_item_c
939
940
{
public:
941
    chapter_item_c()
942
943
944
945
946
    :i_start_time(0)
    ,i_end_time(-1)
    ,i_user_start_time(-1)
    ,i_user_end_time(-1)
    ,i_seekpoint_num(-1)
947
    ,b_display_seekpoint(true)
948
    ,b_user_display(false)
949
    ,psz_parent(NULL)
950
    ,b_is_leaving(false)
951
    {}
952

953
    virtual ~chapter_item_c()
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
    {
        std::vector<chapter_codec_cmds_c*>::iterator index = codecs.begin();
        while ( index != codecs.end() )
        {
            delete (*index);
            index++;
        }
        std::vector<chapter_item_c*>::iterator index_ = sub_chapters.begin();
        while ( index_ != sub_chapters.end() )
        {
            delete (*index_);
            index_++;
        }
    }

969
    int64_t RefreshChapters( bool b_ordered, int64_t i_prev_user_time );
970
    int PublishChapters( input_title_t & title, int & i_user_chapters, int i_level = 0 );
971
    virtual chapter_item_c * FindTimecode( mtime_t i_timecode, const chapter_item_c * p_current, bool & b_found );
972
    void Append( const chapter_item_c & edition );
973
    chapter_item_c * FindChapter( int64_t i_find_uid );
974
975
976
    virtual chapter_item_c *BrowseCodecPrivate( unsigned int codec_id,
                                    bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
                                    const void *p_cookie,
977
                                    size_t i_cookie_size );
978
    std::string                 GetCodecName( bool f_for_title = false ) const;
979
    bool                        ParentOf( const chapter_item_c & item ) const;
980
    int16                       GetTitleNumber( ) const;
981
 
982
    int64_t                     i_start_time, i_end_time;
983
    int64_t                     i_user_start_time, i_user_end_time; /* the time in the stream when an edition is ordered */
984
    std::vector<chapter_item_c*> sub_chapters;
985
    int                         i_seekpoint_num;
986
    int64_t                     i_uid;
987
    bool                        b_display_seekpoint;
988
    bool                        b_user_display;
989
    std::string                 psz_name;
990
    chapter_item_c              *psz_parent;
991
    bool                        b_is_leaving;
992
 
993
    std::vector<chapter_codec_cmds_c*> codecs;
994

995
    static bool CompareTimecode( const chapter_item_c * itemA, const chapter_item_c * itemB )
996
    {
997
        return ( itemA->i_user_start_time < itemB->i_user_start_time || (itemA->i_user_start_time == itemB->i_user_start_time && itemA->i_user_end_time < itemB->i_user_end_time) );
998
    }
999

1000
1001
    bool Enter( bool b_do_subchapters );
    bool Leave( bool b_do_subchapters );
1002
    bool EnterAndLeave( chapter_item_c *p_item, bool b_enter = true );
1003
1004
};

1005
class chapter_edition_c : public chapter_item_c
1006
1007
{
public:
1008
    chapter_edition_c()
1009
    :b_ordered(false)
1010
    {}
1011
 
1012
1013
    void RefreshChapters( );
    mtime_t Duration() const;
1014
    std::string GetMainName() const;
1015
    chapter_item_c * FindTimecode( mtime_t i_timecode, const chapter_item_c * p_current );
1016
 
1017
    bool                        b_ordered;
1018
1019
};

1020
class matroska_segment_c
Steve Lhomme's avatar
Steve Lhomme committed
1021
1022
{
public:
1023
    matroska_segment_c( demux_sys_t & demuxer, EbmlStream & estream )
1024
        :segment(NULL)
1025
        ,es(estream)
1026
        ,i_timescale(MKVD_TIMECODESCALE)
1027
        ,i_duration(-1)
1028
        ,i_start_time(0)
1029
1030
1031
        ,i_cues_position(-1)
        ,i_chapters_position(-1)
        ,i_tags_position(-1)
Steve Lhomme's avatar
Steve Lhomme committed
1032
        ,cluster(NULL)
1033
1034
        ,i_block_pos(0)
        ,i_cluster_pos(0)
1035
        ,i_start_pos(0)
Steve Lhomme's avatar
Steve Lhomme committed
1036
1037
1038
        ,p_segment_uid(NULL)
        ,p_prev_segment_uid(NULL)
        ,p_next_segment_uid(NULL)
1039
        ,b_cues(false)
Steve Lhomme's avatar
Steve Lhomme committed
1040
        ,i_index(0)
1041
        ,i_index_max(1024)
Steve Lhomme's avatar
Steve Lhomme committed
1042
1043
1044
1045
1046
        ,psz_muxing_application(NULL)
        ,psz_writing_application(NULL)
        ,psz_segment_filename(NULL)
        ,psz_title(NULL)
        ,psz_date_utc(NULL)
1047
        ,i_default_edition(0)
1048
        ,sys(demuxer)
1049
        ,ep(NULL)
1050
        ,b_preloaded(false)
1051
    {
Steve Lhomme's avatar
Steve Lhomme committed
1052
        p_indexes = (mkv_index_t*)malloc( sizeof( mkv_index_t ) * i_index_max );
1053
    }
Steve Lhomme's avatar
Steve Lhomme committed
1054

1055
    virtual ~matroska_segment_c()
1056
    {
1057
1058
        for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
        {
1059
            delete tracks[i_track]->p_compression_data;
1060
            es_format_Clean( &tracks[i_track]->fmt );
1061
1062
            free( tracks[i_track]->p_extra_data );
            free( tracks[i_track]->psz_codec );
1063
            delete tracks[i_track];
1064
        }
1065

1066
1067
1068
1069
1070
1071
        free( psz_writing_application );
        free( psz_muxing_application );
        free( psz_segment_filename );
        free( psz_title );
        free( psz_date_utc );
        free( p_indexes );
1072

1073
        delete ep;
1074
        delete segment;
Steve Lhomme's avatar
Steve Lhomme committed
1075
1076
1077
        delete p_segment_uid;
        delete p_prev_segment_uid;
        delete p_next_segment_uid;
1078
1079
1080
1081
1082
1083
1084

        std::vector<chapter_edition_c*>::iterator index = stored_editions.begin();
        while ( index != stored_editions.end() )
        {
            delete (*index);
            index++;
        }
Steve Lhomme's avatar
Steve Lhomme committed
1085
1086
1087
1088
1089
1090
        std::vector<chapter_translation_c*>::iterator indext = translations.begin();
        while ( indext != translations.end() )
        {
            delete (*indext);
            indext++;
        }
1091
1092
1093
1094
1095
1096
        std::vector<KaxSegmentFamily*>::iterator indexf = families.begin();
        while ( indexf != families.end() )
        {
            delete (*indexf);
            indexf++;
        }
1097
1098
    }

1099
    KaxSegment              *segment;
1100
    EbmlStream              & es;
Steve Lhomme's avatar
Steve Lhomme committed
1101
1102
1103
1104
1105

    /* time scale */
    uint64_t                i_timescale;

    /* duration of the segment */
1106
    mtime_t                 i_duration;
1107
    mtime_t                 i_start_time;
Steve Lhomme's avatar
Steve Lhomme committed
1108
1109

    /* all tracks */
1110
    std::vector<mkv_track_t*> tracks;
Steve Lhomme's avatar
Steve Lhomme committed
1111
1112
1113
1114
1115
1116
1117

    /* from seekhead */
    int64_t                 i_cues_position;
    int64_t                 i_chapters_position;
    int64_t                 i_tags_position;

    KaxCluster              *cluster;
1118
1119
    uint64                  i_block_pos;
    uint64                  i_cluster_pos;
1120
    int64_t                 i_start_pos;
Steve Lhomme's avatar
Steve Lhomme committed
1121
1122
1123
    KaxSegmentUID           *p_segment_uid;
    KaxPrevUID              *p_prev_segment_uid;
    KaxNextUID              *p_next_segment_uid;
Steve Lhomme's avatar
Steve Lhomme committed
1124

1125
    bool              b_cues;
Steve Lhomme's avatar
Steve Lhomme committed
1126
1127
    int                     i_index;
    int                     i_index_max;
Steve Lhomme's avatar
Steve Lhomme committed
1128
    mkv_index_t             *p_indexes;
Steve Lhomme's avatar
Steve Lhomme committed
1129
1130
1131
1132
1133
1134
1135
1136

    /* info */
    char                    *psz_muxing_application;
    char                    *psz_writing_application;
    char                    *psz_segment_filename;
    char                    *psz_title;
    char                    *psz_date_utc;

1137
1138
1139
    /* !!!!! GCC 3.3 bug on Darwin !!!!! */
    /* when you remove this variable the compiler issues an atomicity error */
    /* this variable only works when using std::vector<chapter_edition_c> */
1140
1141
    std::vector<chapter_edition_c*> stored_editions;
    int                             i_default_edition;
1142

Steve Lhomme's avatar
Steve Lhomme committed
1143
    std::vector<chapter_translation_c*> translations;
1144
    std::vector<KaxSegmentFamily*>  families;
1145
 
1146
    demux_sys_t                    & sys;
1147
1148
    EbmlParser                     *ep;
    bool                           b_preloaded;
1149

1150
    bool Preload( );
1151
    bool PreloadFamily( const matroska_segment_c & segment );
Steve Lhomme's avatar
Steve Lhomme committed
1152
    void ParseInfo( KaxInfo *info );
1153
    void ParseAttachments( KaxAttachments *attachments );
Steve Lhomme's avatar
Steve Lhomme committed
1154
1155
1156
    void ParseChapters( KaxChapters *chapters );
    void ParseSeekHead( KaxSeekHead *seekhead );
    void ParseTracks( KaxTracks *tracks );
1157
    void ParseChapterAtom( int i_level, KaxChapterAtom *ca, chapter_item_c & chapters );
Steve Lhomme's avatar
Steve Lhomme committed
1158
    void ParseTrackEntry( KaxTrackEntry *m );
1159
    void ParseCluster( );
1160
    void IndexAppendCluster( KaxCluster *cluster );
1161
1162
1163
    void LoadCues( );
    void LoadTags( );
    void InformationCreate( );
1164
    void Seek( mtime_t i_date, mtime_t i_time_offset );
1165
1166
1167
1168
1169
#if LIBMATROSKA_VERSION >= 0x000800
    int BlockGet( KaxBlock * &, KaxSimpleBlock * &, int64_t *, int64_t *, int64_t *);
#else
    int BlockGet( KaxBlock * &, int64_t *, int64_t *, int64_t *);
#endif
1170
    bool Select( mtime_t i_start_time );
1171
    void UnSelect( );
1172

1173
    static bool CompareSegmentUIDs( const matroska_segment_c * item_a, const matroska_segment_c * item_b );
1174
1175
};

1176
// class holding hard-linked segment together in the playback order
1177
class virtual_segment_c
1178
1179
{
public:
1180
    virtual_segment_c( matroska_segment_c *p_segment )
1181
1182
1183
        :p_editions(NULL)
        ,i_sys_title(0)
        ,i_current_segment(0)
1184
1185
        ,i_current_edition(-1)
        ,psz_current_chapter(NULL)
1186
1187
    {
        linked_segments.push_back( p_segment );
1188

Steve Lhomme's avatar
Steve Lhomme committed
1189
1190
1191
        AppendUID( p_segment->p_segment_uid );
        AppendUID( p_segment->p_prev_segment_uid );
        AppendUID( p_segment->p_next_segment_uid );
1192
    }
1193
1194

    void Sort();
1195
    size_t AddSegment( matroska_segment_c *p_segment );