00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdlib.h>
00029
00030 #include <vlc/vlc.h>
00031
00032 #ifdef HAVE_TIME_H
00033 # include <time.h>
00034 #endif
00035
00036 #include <vlc/input.h>
00037
00038 #include <codecs.h>
00039 #include "iso_lang.h"
00040 #include "vlc_meta.h"
00041
00042 #include <iostream>
00043 #include <cassert>
00044 #include <typeinfo>
00045 #include <string>
00046 #include <vector>
00047 #include <algorithm>
00048
00049 #ifdef HAVE_DIRENT_H
00050 # include <dirent.h>
00051 #endif
00052
00053
00054 #include "ebml/EbmlHead.h"
00055 #include "ebml/EbmlSubHead.h"
00056 #include "ebml/EbmlStream.h"
00057 #include "ebml/EbmlContexts.h"
00058 #include "ebml/EbmlVoid.h"
00059 #include "ebml/EbmlVersion.h"
00060 #include "ebml/StdIOCallback.h"
00061
00062 #include "matroska/KaxAttachments.h"
00063 #include "matroska/KaxBlock.h"
00064 #include "matroska/KaxBlockData.h"
00065 #include "matroska/KaxChapters.h"
00066 #include "matroska/KaxCluster.h"
00067 #include "matroska/KaxClusterData.h"
00068 #include "matroska/KaxContexts.h"
00069 #include "matroska/KaxCues.h"
00070 #include "matroska/KaxCuesData.h"
00071 #include "matroska/KaxInfo.h"
00072 #include "matroska/KaxInfoData.h"
00073 #include "matroska/KaxSeekHead.h"
00074 #include "matroska/KaxSegment.h"
00075 #include "matroska/KaxTag.h"
00076 #include "matroska/KaxTags.h"
00077 #include "matroska/KaxTagMulti.h"
00078 #include "matroska/KaxTracks.h"
00079 #include "matroska/KaxTrackAudio.h"
00080 #include "matroska/KaxTrackVideo.h"
00081 #include "matroska/KaxTrackEntryData.h"
00082 #include "matroska/KaxContentEncoding.h"
00083 #include "matroska/KaxVersion.h"
00084
00085 #include "ebml/StdIOCallback.h"
00086
00087 #if LIBMATROSKA_VERSION < 0x000706
00088 START_LIBMATROSKA_NAMESPACE
00089 extern const EbmlSemanticContext MATROSKA_DLL_API KaxMatroska_Context;
00090 END_LIBMATROSKA_NAMESPACE
00091 #endif
00092
00093 #include "vlc_keys.h"
00094
00095 extern "C" {
00096 #include "mp4/libmp4.h"
00097 }
00098 #ifdef HAVE_ZLIB_H
00099 # include <zlib.h>
00100 #endif
00101
00102 #define MATROSKA_COMPRESSION_NONE -1
00103 #define MATROSKA_COMPRESSION_ZLIB 0
00104 #define MATROSKA_COMPRESSION_BLIB 1
00105 #define MATROSKA_COMPRESSION_LZOX 2
00106 #define MATROSKA_COMPRESSION_HEADER 3
00107
00108 #define MKVD_TIMECODESCALE 1000000
00109
00111 #undef ATTRIBUTE_PACKED
00112 #undef PRAGMA_PACK_BEGIN
00113 #undef PRAGMA_PACK_END
00114
00115 #if defined(__GNUC__)
00116 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
00117 #define ATTRIBUTE_PACKED __attribute__ ((packed))
00118 #define PRAGMA_PACK 0
00119 #endif
00120 #endif
00121
00122 #if !defined(ATTRIBUTE_PACKED)
00123 #define ATTRIBUTE_PACKED
00124 #define PRAGMA_PACK 1
00125 #endif
00126
00127 #if PRAGMA_PACK
00128 #pragma pack(1)
00129 #endif
00130
00131
00132
00133
00134
00138 typedef struct {
00139 uint8_t hour;
00140 uint8_t minute;
00141 uint8_t second;
00142 uint8_t frame_u;
00143 } ATTRIBUTE_PACKED dvd_time_t;
00144
00148 typedef struct {
00149 #ifdef WORDS_BIGENDIAN
00150 unsigned char zero : 7;
00151 unsigned char video_pres_mode_change : 1;
00152
00153 unsigned char karaoke_audio_pres_mode_change : 1;
00154 unsigned char angle_change : 1;
00155 unsigned char subpic_stream_change : 1;
00156 unsigned char audio_stream_change : 1;
00157 unsigned char pause_on : 1;
00158 unsigned char still_off : 1;
00159 unsigned char button_select_or_activate : 1;
00160 unsigned char resume : 1;
00161
00162 unsigned char chapter_menu_call : 1;
00163 unsigned char angle_menu_call : 1;
00164 unsigned char audio_menu_call : 1;
00165 unsigned char subpic_menu_call : 1;
00166 unsigned char root_menu_call : 1;
00167 unsigned char title_menu_call : 1;
00168 unsigned char backward_scan : 1;
00169 unsigned char forward_scan : 1;
00170
00171 unsigned char next_pg_search : 1;
00172 unsigned char prev_or_top_pg_search : 1;
00173 unsigned char time_or_chapter_search : 1;
00174 unsigned char go_up : 1;
00175 unsigned char stop : 1;
00176 unsigned char title_play : 1;
00177 unsigned char chapter_search_or_play : 1;
00178 unsigned char title_or_time_play : 1;
00179 #else
00180 unsigned char video_pres_mode_change : 1;
00181 unsigned char zero : 7;
00182
00183 unsigned char resume : 1;
00184 unsigned char button_select_or_activate : 1;
00185 unsigned char still_off : 1;
00186 unsigned char pause_on : 1;
00187 unsigned char audio_stream_change : 1;
00188 unsigned char subpic_stream_change : 1;
00189 unsigned char angle_change : 1;
00190 unsigned char karaoke_audio_pres_mode_change : 1;
00191
00192 unsigned char forward_scan : 1;
00193 unsigned char backward_scan : 1;
00194 unsigned char title_menu_call : 1;
00195 unsigned char root_menu_call : 1;
00196 unsigned char subpic_menu_call : 1;
00197 unsigned char audio_menu_call : 1;
00198 unsigned char angle_menu_call : 1;
00199 unsigned char chapter_menu_call : 1;
00200
00201 unsigned char title_or_time_play : 1;
00202 unsigned char chapter_search_or_play : 1;
00203 unsigned char title_play : 1;
00204 unsigned char stop : 1;
00205 unsigned char go_up : 1;
00206 unsigned char time_or_chapter_search : 1;
00207 unsigned char prev_or_top_pg_search : 1;
00208 unsigned char next_pg_search : 1;
00209 #endif
00210 } ATTRIBUTE_PACKED user_ops_t;
00211
00215 typedef struct {
00216 uint8_t bytes[8];
00217 } ATTRIBUTE_PACKED vm_cmd_t;
00218 #define COMMAND_DATA_SIZE 8
00219
00223 typedef struct {
00224 uint32_t nv_pck_lbn;
00225 uint16_t vobu_cat;
00226 uint16_t zero1;
00227 user_ops_t vobu_uop_ctl;
00228 uint32_t vobu_s_ptm;
00229 uint32_t vobu_e_ptm;
00230 uint32_t vobu_se_e_ptm;
00231 dvd_time_t e_eltm;
00232 char vobu_isrc[32];
00233 } ATTRIBUTE_PACKED pci_gi_t;
00234
00238 typedef struct {
00239 uint32_t nsml_agl_dsta[9];
00240 } ATTRIBUTE_PACKED nsml_agli_t;
00241
00251 typedef struct {
00252 uint16_t hli_ss;
00253 uint32_t hli_s_ptm;
00254 uint32_t hli_e_ptm;
00255 uint32_t btn_se_e_ptm;
00256 #ifdef WORDS_BIGENDIAN
00257 unsigned char zero1 : 2;
00258 unsigned char btngr_ns : 2;
00259 unsigned char zero2 : 1;
00260 unsigned char btngr1_dsp_ty : 3;
00261 unsigned char zero3 : 1;
00262 unsigned char btngr2_dsp_ty : 3;
00263 unsigned char zero4 : 1;
00264 unsigned char btngr3_dsp_ty : 3;
00265 #else
00266 unsigned char btngr1_dsp_ty : 3;
00267 unsigned char zero2 : 1;
00268 unsigned char btngr_ns : 2;
00269 unsigned char zero1 : 2;
00270 unsigned char btngr3_dsp_ty : 3;
00271 unsigned char zero4 : 1;
00272 unsigned char btngr2_dsp_ty : 3;
00273 unsigned char zero3 : 1;
00274 #endif
00275 uint8_t btn_ofn;
00276 uint8_t btn_ns;
00277 uint8_t nsl_btn_ns;
00278 uint8_t zero5;
00279 uint8_t fosl_btnn;
00280 uint8_t foac_btnn;
00281 } ATTRIBUTE_PACKED hl_gi_t;
00282
00283
00292 typedef struct {
00293 uint32_t btn_coli[3][2];
00294 } ATTRIBUTE_PACKED btn_colit_t;
00295
00303 typedef struct {
00304 #ifdef WORDS_BIGENDIAN
00305 uint32 btn_coln : 2;
00306 uint32 x_start : 10;
00307 uint32 zero1 : 2;
00308 uint32 x_end : 10;
00310 uint32 zero3 : 2;
00311 uint32 up : 6;
00313 uint32 auto_action_mode : 2;
00314 uint32 y_start : 10;
00315 uint32 zero2 : 2;
00316 uint32 y_end : 10;
00318 uint32 zero4 : 2;
00319 uint32 down : 6;
00320 unsigned char zero5 : 2;
00321 unsigned char left : 6;
00322 unsigned char zero6 : 2;
00323 unsigned char right : 6;
00324 #else
00325 uint32 x_end : 10;
00326 uint32 zero1 : 2;
00327 uint32 x_start : 10;
00328 uint32 btn_coln : 2;
00329
00330 uint32 up : 6;
00331 uint32 zero3 : 2;
00332
00333 uint32 y_end : 10;
00334 uint32 zero2 : 2;
00335 uint32 y_start : 10;
00336 uint32 auto_action_mode : 2;
00337
00338 uint32 down : 6;
00339 uint32 zero4 : 2;
00340 unsigned char left : 6;
00341 unsigned char zero5 : 2;
00342 unsigned char right : 6;
00343 unsigned char zero6 : 2;
00344 #endif
00345 vm_cmd_t cmd;
00346 } ATTRIBUTE_PACKED btni_t;
00347
00351 typedef struct {
00352 hl_gi_t hl_gi;
00353 btn_colit_t btn_colit;
00354 btni_t btnit[36];
00355 } ATTRIBUTE_PACKED hli_t;
00356
00360 typedef struct {
00361 pci_gi_t pci_gi;
00362 nsml_agli_t nsml_agli;
00363 hli_t hli;
00364 uint8_t zero1[189];
00365 } ATTRIBUTE_PACKED pci_t;
00366
00367
00368 #if PRAGMA_PACK
00369 #pragma pack()
00370 #endif
00371
00372
00373
00377 #if defined( WIN32 )
00378 #define DIRECTORY_SEPARATOR '\\'
00379 #else
00380 #define DIRECTORY_SEPARATOR '/'
00381 #endif
00382
00383 using namespace LIBMATROSKA_NAMESPACE;
00384 using namespace std;
00385
00386
00387
00388
00389 static int Open ( vlc_object_t * );
00390 static void Close( vlc_object_t * );
00391
00392 vlc_module_begin();
00393 set_shortname( "Matroska" );
00394 set_description( _("Matroska stream demuxer" ) );
00395 set_capability( "demux2", 50 );
00396 set_callbacks( Open, Close );
00397 set_category( CAT_INPUT );
00398 set_subcategory( SUBCAT_INPUT_DEMUX );
00399
00400 add_bool( "mkv-use-ordered-chapters", 1, NULL,
00401 N_("Ordered chapters"),
00402 N_("Play ordered chapters as specified in the segment."), VLC_TRUE );
00403
00404 add_bool( "mkv-use-chapter-codec", 1, NULL,
00405 N_("Chapter codecs"),
00406 N_("Use chapter codecs found in the segment."), VLC_TRUE );
00407
00408 add_bool( "mkv-preload-local-dir", 1, NULL,
00409 N_("Preload Directory"),
00410 N_("Preload matroska files from the same family in the same directory (not good for broken files)."), VLC_TRUE );
00411
00412 add_bool( "mkv-seek-percent", 0, NULL,
00413 N_("Seek based on percent not time"),
00414 N_("Seek based on percent not time."), VLC_TRUE );
00415
00416 add_bool( "mkv-use-dummy", 0, NULL,
00417 N_("Dummy Elements"),
00418 N_("Read and discard unknown EBML elements (not good for broken files)."), VLC_TRUE );
00419
00420 add_shortcut( "mka" );
00421 add_shortcut( "mkv" );
00422 vlc_module_end();
00423
00424
00425
00426
00427 #ifdef HAVE_ZLIB_H
00428 block_t *block_zlib_decompress( vlc_object_t *p_this, block_t *p_in_block ) {
00429 int result, dstsize, n;
00430 unsigned char *dst;
00431 block_t *p_block;
00432 z_stream d_stream;
00433
00434 d_stream.zalloc = (alloc_func)0;
00435 d_stream.zfree = (free_func)0;
00436 d_stream.opaque = (voidpf)0;
00437 result = inflateInit(&d_stream);
00438 if( result != Z_OK )
00439 {
00440 msg_Dbg( p_this, "inflateInit() failed. Result: %d", result );
00441 return NULL;
00442 }
00443
00444 d_stream.next_in = (Bytef *)p_in_block->p_buffer;
00445 d_stream.avail_in = p_in_block->i_buffer;
00446 n = 0;
00447 p_block = block_New( p_this, 0 );
00448 dst = NULL;
00449 do
00450 {
00451 n++;
00452 p_block = block_Realloc( p_block, 0, n * 1000 );
00453 dst = (unsigned char *)p_block->p_buffer;
00454 d_stream.next_out = (Bytef *)&dst[(n - 1) * 1000];
00455 d_stream.avail_out = 1000;
00456 result = inflate(&d_stream, Z_NO_FLUSH);
00457 if( ( result != Z_OK ) && ( result != Z_STREAM_END ) )
00458 {
00459 msg_Dbg( p_this, "Zlib decompression failed. Result: %d", result );
00460 return NULL;
00461 }
00462 }
00463 while( ( d_stream.avail_out == 0 ) && ( d_stream.avail_in != 0 ) &&
00464 ( result != Z_STREAM_END ) );
00465
00466 dstsize = d_stream.total_out;
00467 inflateEnd( &d_stream );
00468
00469 p_block = block_Realloc( p_block, 0, dstsize );
00470 p_block->i_buffer = dstsize;
00471 block_Release( p_in_block );
00472
00473 return p_block;
00474 }
00475 #endif
00476
00480 static void MkvTree( demux_t & demuxer, int i_level, char *psz_format, ... )
00481 {
00482 va_list args;
00483 if( i_level > 9 )
00484 {
00485 msg_Err( &demuxer, "too deep tree" );
00486 return;
00487 }
00488 va_start( args, psz_format );
00489 static char *psz_foo = "| | | | | | | | | |";
00490 char *psz_foo2 = (char*)malloc( ( i_level * 4 + 3 + strlen( psz_format ) ) * sizeof(char) );
00491 strncpy( psz_foo2, psz_foo, 4 * i_level );
00492 psz_foo2[ 4 * i_level ] = '+';
00493 psz_foo2[ 4 * i_level + 1 ] = ' ';
00494 strcpy( &psz_foo2[ 4 * i_level + 2 ], psz_format );
00495 __msg_GenericVa( VLC_OBJECT(&demuxer), VLC_MSG_DBG, "mkv", psz_foo2, args );
00496 free( psz_foo2 );
00497 va_end( args );
00498 }
00499
00500
00501
00502
00503 class vlc_stream_io_callback: public IOCallback
00504 {
00505 private:
00506 stream_t *s;
00507 vlc_bool_t mb_eof;
00508 vlc_bool_t b_owner;
00509
00510 public:
00511 vlc_stream_io_callback( stream_t *, vlc_bool_t );
00512
00513 virtual ~vlc_stream_io_callback()
00514 {
00515 if( b_owner )
00516 stream_Delete( s );
00517 }
00518
00519 virtual uint32 read ( void *p_buffer, size_t i_size);
00520 virtual void setFilePointer ( int64_t i_offset, seek_mode mode = seek_beginning );
00521 virtual size_t write ( const void *p_buffer, size_t i_size);
00522 virtual uint64 getFilePointer ( void );
00523 virtual void close ( void );
00524 };
00525
00526
00527
00528
00529 class EbmlParser
00530 {
00531 public:
00532 EbmlParser( EbmlStream *es, EbmlElement *el_start, demux_t *p_demux );
00533 virtual ~EbmlParser( void );
00534
00535 void Up( void );
00536 void Down( void );
00537 void Reset( demux_t *p_demux );
00538 EbmlElement *Get( void );
00539 void Keep( void );
00540 EbmlElement *UnGet( uint64 i_block_pos, uint64 i_cluster_pos );
00541
00542 int GetLevel( void );
00543
00544 private:
00545 EbmlStream *m_es;
00546 int mi_level;
00547 EbmlElement *m_el[10];
00548 int64_t mi_remain_size[10];
00549
00550 EbmlElement *m_got;
00551
00552 int mi_user_level;
00553 vlc_bool_t mb_keep;
00554 vlc_bool_t mb_dummy;
00555 };
00556
00557
00558
00559
00560
00561 #define GetFOURCC( p ) __GetFOURCC( (uint8_t*)p )
00562 static vlc_fourcc_t __GetFOURCC( uint8_t *p )
00563 {
00564 return VLC_FOURCC( p[0], p[1], p[2], p[3] );
00565 }
00566
00567
00568
00569
00570 typedef struct
00571 {
00572
00573
00574 vlc_bool_t b_default;
00575 vlc_bool_t b_enabled;
00576 unsigned int i_number;
00577
00578 int i_extra_data;
00579 uint8_t *p_extra_data;
00580
00581 char *psz_codec;
00582
00583 uint64_t i_default_duration;
00584 float f_timecodescale;
00585 mtime_t i_last_dts;
00586
00587
00588 es_format_t fmt;
00589 float f_fps;
00590 es_out_id_t *p_es;
00591
00592
00593 unsigned int i_original_rate;
00594
00595 vlc_bool_t b_inited;
00596
00597 int i_data_init;
00598 uint8_t *p_data_init;
00599
00600
00601 vlc_bool_t b_search_keyframe;
00602 vlc_bool_t b_silent;
00603
00604
00605 char *psz_codec_name;
00606 char *psz_codec_settings;
00607 char *psz_codec_info_url;
00608 char *psz_codec_download_url;
00609
00610
00611 int i_compression_type;
00612 KaxContentCompSettings *p_compression_data;
00613
00614 } mkv_track_t;
00615
00616 typedef struct
00617 {
00618 int i_track;
00619 int i_block_number;
00620
00621 int64_t i_position;
00622 int64_t i_time;
00623
00624 vlc_bool_t b_key;
00625 } mkv_index_t;
00626
00627 class demux_sys_t;
00628
00629 const binary MATROSKA_DVD_LEVEL_SS = 0x30;
00630 const binary MATROSKA_DVD_LEVEL_LU = 0x2A;
00631 const binary MATROSKA_DVD_LEVEL_TT = 0x28;
00632 const binary MATROSKA_DVD_LEVEL_PGC = 0x20;
00633 const binary MATROSKA_DVD_LEVEL_PG = 0x18;
00634 const binary MATROSKA_DVD_LEVEL_PTT = 0x10;
00635 const binary MATROSKA_DVD_LEVEL_CN = 0x08;
00636
00637 class chapter_codec_cmds_c
00638 {
00639 public:
00640 chapter_codec_cmds_c( demux_sys_t & demuxer, int codec_id = -1)
00641 :p_private_data(NULL)
00642 ,i_codec_id( codec_id )
00643 ,sys( demuxer )
00644 {}
00645
00646 virtual ~chapter_codec_cmds_c()
00647 {
00648 delete p_private_data;
00649 std::vector<KaxChapterProcessData*>::iterator indexe = enter_cmds.begin();
00650 while ( indexe != enter_cmds.end() )
00651 {
00652 delete (*indexe);
00653 indexe++;
00654 }
00655 std::vector<KaxChapterProcessData*>::iterator indexl = leave_cmds.begin();
00656 while ( indexl != leave_cmds.end() )
00657 {
00658 delete (*indexl);
00659 indexl++;
00660 }
00661 std::vector<KaxChapterProcessData*>::iterator indexd = during_cmds.begin();
00662 while ( indexd != during_cmds.end() )
00663 {
00664 delete (*indexd);
00665 indexd++;
00666 }
00667 }
00668
00669 void SetPrivate( const KaxChapterProcessPrivate & private_data )
00670 {
00671 p_private_data = new KaxChapterProcessPrivate( private_data );
00672 }
00673
00674 void AddCommand( const KaxChapterProcessCommand & command );
00675
00677 virtual bool Enter() { return false; }
00678 virtual bool Leave() { return false; }
00679 virtual std::string GetCodecName( bool f_for_title = false ) const { return ""; }
00680 virtual int16 GetTitleNumber() { return -1; }
00681
00682 KaxChapterProcessPrivate *p_private_data;
00683
00684 protected:
00685 std::vector<KaxChapterProcessData*> enter_cmds;
00686 std::vector<KaxChapterProcessData*> during_cmds;
00687 std::vector<KaxChapterProcessData*> leave_cmds;
00688
00689 int i_codec_id;
00690 demux_sys_t & sys;
00691 };
00692
00693 class dvd_command_interpretor_c
00694 {
00695 public:
00696 dvd_command_interpretor_c( demux_sys_t & demuxer )
00697 :sys( demuxer )
00698 {
00699 memset( p_PRMs, 0, sizeof(p_PRMs) );
00700 p_PRMs[ 0x80 + 1 ] = 15;
00701 p_PRMs[ 0x80 + 2 ] = 62;
00702 p_PRMs[ 0x80 + 3 ] = 1;
00703 p_PRMs[ 0x80 + 4 ] = 1;
00704 p_PRMs[ 0x80 + 7 ] = 1;
00705 p_PRMs[ 0x80 + 8 ] = 1;
00706 p_PRMs[ 0x80 + 16 ] = 0xFFFFu;
00707 p_PRMs[ 0x80 + 18 ] = 0xFFFFu;
00708 }
00709
00710 bool Interpret( const binary * p_command, size_t i_size = 8 );
00711
00712 uint16 GetPRM( size_t index ) const
00713 {
00714 if ( index < 256 )
00715 return p_PRMs[ index ];
00716 else return 0;
00717 }
00718
00719 uint16 GetGPRM( size_t index ) const
00720 {
00721 if ( index >= 0 && index < 16 )
00722 return p_PRMs[ index ];
00723 else return 0;
00724 }
00725
00726 uint16 GetSPRM( size_t index ) const
00727 {
00728
00729 if ( index >= 0x80 && index < 0x95 )
00730 return p_PRMs[ index ];
00731 else return 0;
00732 }
00733
00734 bool SetPRM( size_t index, uint16 value )
00735 {
00736 if ( index >= 0 && index < 16 )
00737 {
00738 p_PRMs[ index ] = value;
00739 return true;
00740 }
00741 return false;
00742 }
00743
00744 bool SetGPRM( size_t index, uint16 value )
00745 {
00746 if ( index >= 0 && index < 16 )
00747 {
00748 p_PRMs[ index ] = value;
00749 return true;
00750 }
00751 return false;
00752 }
00753
00754 bool SetSPRM( size_t index, uint16 value )
00755 {
00756 if ( index > 0x80 && index <= 0x8D && index != 0x8C )
00757 {
00758 p_PRMs[ index ] = value;
00759 return true;
00760 }
00761 return false;
00762 }
00763
00764 protected:
00765 std::string GetRegTypeName( bool b_value, uint16 value ) const
00766 {
00767 std::string result;
00768 char s_value[6], s_reg_value[6];
00769 sprintf( s_value, "%.5d", value );
00770
00771 if ( b_value )
00772 {
00773 result = "value (";
00774 result += s_value;
00775 result += ")";
00776 }
00777 else if ( value < 0x80 )
00778 {
00779 sprintf( s_reg_value, "%.5d", GetPRM( value ) );
00780 result = "GPreg[";
00781 result += s_value;
00782 result += "] (";
00783 result += s_reg_value;
00784 result += ")";
00785 }
00786 else
00787 {
00788 sprintf( s_reg_value, "%.5d", GetPRM( value ) );
00789 result = "SPreg[";
00790 result += s_value;
00791 result += "] (";
00792 result += s_reg_value;
00793 result += ")";
00794 }
00795 return result;
00796 }
00797
00798 uint16 p_PRMs[256];
00799 demux_sys_t & sys;
00800
00801
00802
00803
00804
00805 static const uint16 CMD_DVD_TEST_VALUE = 0x80;
00806 static const uint16 CMD_DVD_IF_GPREG_AND = (1 << 4);
00807 static const uint16 CMD_DVD_IF_GPREG_EQUAL = (2 << 4);
00808 static const uint16 CMD_DVD_IF_GPREG_NOT_EQUAL = (3 << 4);
00809 static const uint16 CMD_DVD_IF_GPREG_SUP_EQUAL = (4 << 4);
00810 static const uint16 CMD_DVD_IF_GPREG_SUP = (5 << 4);
00811 static const uint16 CMD_DVD_IF_GPREG_INF_EQUAL = (6 << 4);
00812 static const uint16 CMD_DVD_IF_GPREG_INF = (7 << 4);
00813
00814 static const uint16 CMD_DVD_NOP = 0x0000;
00815 static const uint16 CMD_DVD_GOTO_LINE = 0x0001;
00816 static const uint16 CMD_DVD_BREAK = 0x0002;
00817
00818 static const uint16 CMD_DVD_NOP2 = 0x2001;
00819 static const uint16 CMD_DVD_LINKPGCN = 0x2004;
00820 static const uint16 CMD_DVD_LINKPGN = 0x2006;
00821 static const uint16 CMD_DVD_LINKCN = 0x2007;
00822 static const uint16 CMD_DVD_JUMP_TT = 0x3002;
00823 static const uint16 CMD_DVD_JUMPVTS_TT = 0x3003;
00824 static const uint16 CMD_DVD_JUMPVTS_PTT = 0x3005;
00825 static const uint16 CMD_DVD_JUMP_SS = 0x3006;
00826 static const uint16 CMD_DVD_CALLSS_VTSM1 = 0x3008;
00827
00828 static const uint16 CMD_DVD_SET_HL_BTNN2 = 0x4600;
00829 static const uint16 CMD_DVD_SET_HL_BTNN_LINKPGCN1 = 0x4604;
00830 static const uint16 CMD_DVD_SET_STREAM = 0x5100;
00831 static const uint16 CMD_DVD_SET_GPRMMD = 0x5300;
00832 static const uint16 CMD_DVD_SET_HL_BTNN1 = 0x5600;
00833 static const uint16 CMD_DVD_SET_HL_BTNN_LINKPGCN2 = 0x5604;
00834 static const uint16 CMD_DVD_SET_HL_BTNN_LINKCN = 0x5607;
00835
00836 static const uint16 CMD_DVD_MOV_SPREG_PREG = 0x6100;
00837 static const uint16 CMD_DVD_GPREG_MOV_VALUE = 0x7100;
00838 static const uint16 CMD_DVD_SUB_GPREG = 0x7400;
00839 static const uint16 CMD_DVD_MULT_GPREG = 0x7500;
00840 static const uint16 CMD_DVD_GPREG_DIV_VALUE = 0x7600;
00841 static const uint16 CMD_DVD_GPREG_AND_VALUE = 0x7900;
00842
00843
00844 static bool MatchIsDomain ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
00845 static bool MatchIsVMG ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
00846 static bool MatchVTSNumber ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
00847 static bool MatchVTSMNumber ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
00848 static bool MatchTitleNumber ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
00849 static bool MatchPgcType ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
00850 static bool MatchPgcNumber ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
00851 static bool MatchChapterNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
00852 static bool MatchCellNumber ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
00853 };
00854
00855 class dvd_chapter_codec_c : public chapter_codec_cmds_c
00856 {
00857 public:
00858 dvd_chapter_codec_c( demux_sys_t & sys )
00859 :chapter_codec_cmds_c( sys, 1 )
00860 {}
00861
00862 bool Enter();
00863 bool Leave();
00864 std::string GetCodecName( bool f_for_title = false ) const;
00865 int16 GetTitleNumber();
00866 };
00867
00868 class matroska_script_interpretor_c
00869 {
00870 public:
00871 matroska_script_interpretor_c( demux_sys_t & demuxer )
00872 :sys( demuxer )
00873 {}
00874
00875 bool Interpret( const binary * p_command, size_t i_size );
00876
00877
00878 static const std::string CMD_MS_GOTO_AND_PLAY;
00879
00880 protected:
00881 demux_sys_t & sys;
00882 };
00883
00884 const std::string matroska_script_interpretor_c::CMD_MS_GOTO_AND_PLAY = "GotoAndPlay";
00885
00886
00887 class matroska_script_codec_c : public chapter_codec_cmds_c
00888 {
00889 public:
00890 matroska_script_codec_c( demux_sys_t & sys )
00891 :chapter_codec_cmds_c( sys, 0 )
00892 ,interpretor( sys )
00893 {}
00894
00895 bool Enter();
00896 bool Leave();
00897
00898 protected:
00899 matroska_script_interpretor_c interpretor;
00900 };
00901
00902 class chapter_translation_c
00903 {
00904 public:
00905 chapter_translation_c()
00906 :p_translated(NULL)
00907 {}
00908
00909 ~chapter_translation_c()
00910 {
00911 delete p_translated;
00912 }
00913
00914 KaxChapterTranslateID *p_translated;
00915 unsigned int codec_id;
00916 std::vector<uint64_t> editions;
00917 };
00918
00919 class chapter_item_c
00920 {
00921 public:
00922 chapter_item_c()
00923 :i_start_time(0)
00924 ,i_end_time(-1)
00925 ,i_user_start_time(-1)
00926 ,i_user_end_time(-1)
00927 ,i_seekpoint_num(-1)
00928 ,b_display_seekpoint(true)
00929 ,b_user_display(false)
00930 ,psz_parent(NULL)
00931 ,b_is_leaving(false)
00932 {}
00933
00934 virtual ~chapter_item_c()
00935 {
00936 std::vector<chapter_codec_cmds_c*>::iterator index = codecs.begin();
00937 while ( index != codecs.end() )
00938 {
00939 delete (*index);
00940 index++;
00941 }
00942 std::vector<chapter_item_c*>::iterator index_ = sub_chapters.begin();
00943 while ( index_ != sub_chapters.end() )
00944 {
00945 delete (*index_);
00946 index_++;
00947 }
00948 }
00949
00950 int64_t RefreshChapters( bool b_ordered, int64_t i_prev_user_time );
00951 int PublishChapters( input_title_t & title, int & i_user_chapters, int i_level = 0 );
00952 virtual chapter_item_c * FindTimecode( mtime_t i_timecode, const chapter_item_c * p_current, bool & b_found );
00953 void Append( const chapter_item_c & edition );
00954 chapter_item_c * FindChapter( int64_t i_find_uid );
00955 virtual chapter_item_c *BrowseCodecPrivate( unsigned int codec_id,
00956 bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
00957 const void *p_cookie,
00958 size_t i_cookie_size );
00959 std::string GetCodecName( bool f_for_title = false ) const;
00960 bool ParentOf( const chapter_item_c & item ) const;
00961 int16 GetTitleNumber( ) const;
00962
00963 int64_t i_start_time, i_end_time;
00964 int64_t i_user_start_time, i_user_end_time;
00965 std::vector<chapter_item_c*> sub_chapters;
00966 int i_seekpoint_num;
00967 int64_t i_uid;
00968 bool b_display_seekpoint;
00969 bool b_user_display;
00970 std::string psz_name;
00971 chapter_item_c *psz_parent;
00972 bool b_is_leaving;
00973
00974 std::vector<chapter_codec_cmds_c*> codecs;
00975
00976 static bool CompareTimecode( const chapter_item_c * itemA, const chapter_item_c * itemB )
00977 {
00978 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) );
00979 }
00980
00981 bool Enter( bool b_do_subchapters );
00982 bool Leave( bool b_do_subchapters );
00983 bool EnterAndLeave( chapter_item_c *p_item, bool b_enter = true );
00984 };
00985
00986 class chapter_edition_c : public chapter_item_c
00987 {
00988 public:
00989 chapter_edition_c()
00990 :b_ordered(false)
00991 {}
00992
00993 void RefreshChapters( );
00994 mtime_t Duration() const;
00995 std::string GetMainName() const;
00996 chapter_item_c * FindTimecode( mtime_t i_timecode, const chapter_item_c * p_current );
00997
00998 bool b_ordered;
00999 };
01000
01001 class matroska_segment_c
01002 {
01003 public:
01004 matroska_segment_c( demux_sys_t & demuxer, EbmlStream & estream )
01005 :segment(NULL)
01006 ,es(estream)
01007 ,i_timescale(MKVD_TIMECODESCALE)
01008 ,i_duration(-1)
01009 ,i_start_time(0)
01010 ,i_cues_position(-1)
01011 ,i_chapters_position(-1)
01012 ,i_tags_position(-1)
01013 ,cluster(NULL)
01014 ,i_block_pos(0)
01015 ,i_cluster_pos(0)
01016 ,i_start_pos(0)
01017 ,p_segment_uid(NULL)
01018 ,p_prev_segment_uid(NULL)
01019 ,p_next_segment_uid(NULL)
01020 ,b_cues(VLC_FALSE)
01021 ,i_index(0)
01022 ,i_index_max(1024)
01023 ,psz_muxing_application(NULL)
01024 ,psz_writing_application(NULL)
01025 ,psz_segment_filename(NULL)
01026 ,psz_title(NULL)
01027 ,psz_date_utc(NULL)
01028 ,i_default_edition(0)
01029 ,sys(demuxer)
01030 ,ep(NULL)
01031 ,b_preloaded(false)
01032 {
01033 p_indexes = (mkv_index_t*)malloc( sizeof( mkv_index_t ) * i_index_max );
01034 }
01035
01036 virtual ~matroska_segment_c()
01037 {
01038 for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
01039 {
01040 if ( tracks[i_track]->p_compression_data )
01041 {
01042 delete tracks[i_track]->p_compression_data;
01043 }
01044 es_format_Clean( &tracks[i_track]->fmt );
01045 if( tracks[i_track]->p_extra_data )
01046 free( tracks[i_track]->p_extra_data );
01047 if( tracks[i_track]->psz_codec )
01048 free( tracks[i_track]->psz_codec );
01049 delete tracks[i_track];
01050 }
01051
01052 if( psz_writing_application )
01053 {
01054 free( psz_writing_application );
01055 }
01056 if( psz_muxing_application )
01057 {
01058 free( psz_muxing_application );
01059 }
01060 if( psz_segment_filename )
01061 {
01062 free( psz_segment_filename );
01063 }
01064 if( psz_title )
01065 {
01066 free( psz_title );
01067 }
01068 if( psz_date_utc )
01069 {
01070 free( psz_date_utc );
01071 }
01072 if ( p_indexes )
01073 free( p_indexes );
01074
01075 delete ep;
01076 delete segment;
01077 delete p_segment_uid;
01078 delete p_prev_segment_uid;
01079 delete p_next_segment_uid;
01080
01081 std::vector<chapter_edition_c*>::iterator index = stored_editions.begin();
01082 while ( index != stored_editions.end() )
01083 {
01084 delete (*index);
01085 index++;
01086 }
01087 std::vector<chapter_translation_c*>::iterator indext = translations.begin();
01088 while ( indext != translations.end() )
01089 {
01090 delete (*indext);
01091 indext++;
01092 }
01093 std::vector<KaxSegmentFamily*>::iterator indexf = families.begin();
01094 while ( indexf != families.end() )
01095 {
01096 delete (*indexf);
01097 indexf++;
01098 }
01099 }
01100
01101 KaxSegment *segment;
01102 EbmlStream & es;
01103
01104
01105 uint64_t i_timescale;
01106
01107
01108 mtime_t i_duration;
01109 mtime_t i_start_time;
01110
01111
01112 std::vector<mkv_track_t*> tracks;
01113
01114
01115 int64_t i_cues_position;
01116 int64_t i_chapters_position;
01117 int64_t i_tags_position;
01118
01119 KaxCluster *cluster;
01120 uint64 i_block_pos;
01121 uint64 i_cluster_pos;
01122 int64_t i_start_pos;
01123 KaxSegmentUID *p_segment_uid;
01124 KaxPrevUID *p_prev_segment_uid;
01125 KaxNextUID *p_next_segment_uid;
01126
01127 vlc_bool_t b_cues;
01128 int i_index;
01129 int i_index_max;
01130 mkv_index_t *p_indexes;
01131
01132
01133 char *psz_muxing_application;
01134 char *psz_writing_application;
01135 char *psz_segment_filename;
01136 char *psz_title;
01137 char *psz_date_utc;
01138
01139
01140
01141
01142 std::vector<chapter_edition_c*> stored_editions;
01143 int i_default_edition;
01144
01145 std::vector<chapter_translation_c*> translations;
01146 std::vector<KaxSegmentFamily*> families;
01147
01148 demux_sys_t & sys;
01149 EbmlParser *ep;
01150 bool b_preloaded;
01151
01152 bool Preload( );
01153 bool PreloadFamily( const matroska_segment_c & segment );
01154 void ParseInfo( KaxInfo *info );
01155 void ParseChapters( KaxChapters *chapters );
01156 void ParseSeekHead( KaxSeekHead *seekhead );
01157 void ParseTracks( KaxTracks *tracks );
01158 void ParseChapterAtom( int i_level, KaxChapterAtom *ca, chapter_item_c & chapters );
01159 void ParseTrackEntry( KaxTrackEntry *m );
01160 void ParseCluster( );
01161 void IndexAppendCluster( KaxCluster *cluster );
01162 void LoadCues( );
01163 void LoadTags( );
01164 void InformationCreate( );
01165 void Seek( mtime_t i_date, mtime_t i_time_offset );
01166 #if LIBMATROSKA_VERSION >= 0x000800
01167 int BlockGet( KaxBlock * &, KaxSimpleBlock * &, int64_t *, int64_t *, int64_t *);
01168 #else
01169 int BlockGet( KaxBlock * &, int64_t *, int64_t *, int64_t *);
01170 #endif
01171 bool Select( mtime_t i_start_time );
01172 void UnSelect( );
01173
01174 static bool CompareSegmentUIDs( const matroska_segment_c * item_a, const matroska_segment_c * item_b );
01175 };
01176
01177
01178 class virtual_segment_c
01179 {
01180 public:
01181 virtual_segment_c( matroska_segment_c *p_segment )
01182 :p_editions(NULL)
01183 ,i_sys_title(0)
01184 ,i_current_segment(0)
01185 ,i_current_edition(-1)
01186 ,psz_current_chapter(NULL)
01187 {
01188 linked_segments.push_back( p_segment );
01189
01190 AppendUID( p_segment->p_segment_uid );
01191 AppendUID( p_segment->p_prev_segment_uid );
01192 AppendUID( p_segment->p_next_segment_uid );
01193 }
01194
01195 void Sort();
01196 size_t AddSegment( matroska_segment_c *p_segment );
01197 void PreloadLinked( );
01198 mtime_t Duration( ) const;
01199 void LoadCues( );
01200 void Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset, chapter_item_c *psz_chapter );
01201
01202 inline chapter_edition_c *Edition()
01203 {
01204 if ( i_current_edition >= 0 && size_t(i_current_edition) < p_editions->size() )
01205 return (*p_editions)[i_current_edition];
01206 return NULL;
01207 }
01208
01209 matroska_segment_c * Segment() const
01210 {
01211 if ( linked_segments.size() == 0 || i_current_segment >= linked_segments.size() )
01212 return NULL;
01213 return linked_segments[i_current_segment];
01214 }
01215
01216 inline chapter_item_c *CurrentChapter() {
01217 return psz_current_chapter;
01218 }
01219
01220 bool SelectNext()
01221 {
01222 if ( i_current_segment < linked_segments.size()-1 )
01223 {
01224 i_current_segment++;
01225 return true;
01226 }
01227 return false;
01228 }
01229
01230 bool FindUID( KaxSegmentUID & uid ) const
01231 {
01232 for ( size_t i=0; i<linked_uids.size(); i++ )
01233 {
01234 if ( linked_uids[i] == uid )
01235 return true;
01236 }
01237 return false;
01238 }
01239
01240 bool UpdateCurrentToChapter( demux_t & demux );
01241 void PrepareChapters( );
01242
01243 chapter_item_c *BrowseCodecPrivate( unsigned int codec_id,
01244 bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
01245 const void *p_cookie,
01246 size_t i_cookie_size );
01247 chapter_item_c *FindChapter( int64_t i_find_uid );
01248
01249 std::vector<chapter_edition_c*> *p_editions;
01250 int i_sys_title;
01251
01252 protected:
01253 std::vector<matroska_segment_c*> linked_segments;
01254 std::vector<KaxSegmentUID> linked_uids;
01255 size_t i_current_segment;
01256
01257 int i_current_edition;
01258 chapter_item_c *psz_current_chapter;
01259
01260 void AppendUID( const EbmlBinary * UID );
01261 };
01262
01263 class matroska_stream_c
01264 {
01265 public:
01266 matroska_stream_c( demux_sys_t & demuxer )
01267 :p_in(NULL)
01268 ,p_es(NULL)
01269 ,sys(demuxer)
01270 {}
01271
01272 virtual ~matroska_stream_c()
01273 {
01274 delete p_in;
01275 delete p_es;
01276 }
01277
01278 IOCallback *p_in;
01279 EbmlStream *p_es;
01280
01281 std::vector<matroska_segment_c*> segments;
01282
01283 demux_sys_t & sys;
01284 };
01285
01286 typedef struct
01287 {
01288 VLC_COMMON_MEMBERS
01289
01290 demux_t *p_demux;
01291 vlc_mutex_t lock;
01292
01293 vlc_bool_t b_moved;
01294 vlc_bool_t b_clicked;
01295 vlc_bool_t b_key;
01296
01297 } event_thread_t;
01298
01299 class demux_sys_t
01300 {
01301 public:
01302 demux_sys_t( demux_t & demux )
01303 :demuxer(demux)
01304 ,i_pts(0)
01305 ,i_start_pts(0)
01306 ,i_chapter_time(0)
01307 ,meta(NULL)
01308 ,i_current_title(0)
01309 ,p_current_segment(NULL)
01310 ,dvd_interpretor( *this )
01311 ,f_duration(-1.0)
01312 ,b_ui_hooked(false)
01313 ,p_input(NULL)
01314 ,b_pci_packet_set(false)
01315 ,p_ev(NULL)
01316 {
01317 vlc_mutex_init( &demuxer, &lock_demuxer );
01318 }
01319
01320 virtual ~demux_sys_t()
01321 {
01322 StopUiThread();
01323 size_t i;
01324 for ( i=0; i<streams.size(); i++ )
01325 delete streams[i];
01326 for ( i=0; i<opened_segments.size(); i++ )
01327 delete opened_segments[i];
01328 for ( i=0; i<used_segments.size(); i++ )
01329 delete used_segments[i];
01330 if( meta ) vlc_meta_Delete( meta );
01331
01332 while( titles.size() )
01333 { vlc_input_title_Delete( titles.back() ); titles.pop_back();}
01334
01335 vlc_mutex_destroy( &lock_demuxer );
01336 }
01337
01338
01339 demux_t & demuxer;
01340
01341 mtime_t i_pts;
01342 mtime_t i_start_pts;
01343 mtime_t i_chapter_time;
01344
01345 vlc_meta_t *meta;
01346
01347 std::vector<input_title_t*> titles;
01348 size_t i_current_title;
01349
01350 std::vector<matroska_stream_c*> streams;
01351 std::vector<matroska_segment_c*> opened_segments;
01352 std::vector<virtual_segment_c*> used_segments;
01353 virtual_segment_c *p_current_segment;
01354
01355 dvd_command_interpretor_c dvd_interpretor;
01356
01357
01358 float f_duration;
01359
01360 matroska_segment_c *FindSegment( const EbmlBinary & uid ) const;
01361 chapter_item_c *BrowseCodecPrivate( unsigned int codec_id,
01362 bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
01363 const void *p_cookie,
01364 size_t i_cookie_size,
01365 virtual_segment_c * & p_segment_found );
01366 chapter_item_c *FindChapter( int64_t i_find_uid, virtual_segment_c * & p_segment_found );
01367
01368 void PreloadFamily( const matroska_segment_c & of_segment );
01369 void PreloadLinked( matroska_segment_c *p_segment );
01370 bool PreparePlayback( virtual_segment_c *p_new_segment );
01371 matroska_stream_c *AnalyseAllSegmentsFound( demux_t *p_demux, EbmlStream *p_estream, bool b_initial = false );
01372 void JumpTo( virtual_segment_c & p_segment, chapter_item_c * p_chapter );
01373
01374 void StartUiThread();
01375 void StopUiThread();
01376 bool b_ui_hooked;
01377 inline void SwapButtons();
01378
01379
01380 input_thread_t *p_input;
01381 pci_t pci_packet;
01382 bool b_pci_packet_set;
01383 uint8_t palette[4][4];
01384 vlc_mutex_t lock_demuxer;
01385
01386
01387 event_thread_t *p_ev;
01388 static int EventThread( vlc_object_t *p_this );
01389 static int EventMouse( vlc_object_t *p_this, char const *psz_var,
01390 vlc_value_t oldval, vlc_value_t newval, void *p_data );
01391 static int EventKey( vlc_object_t *p_this, char const *psz_var,
01392 vlc_value_t oldval, vlc_value_t newval, void *p_data );
01393
01394
01395
01396 protected:
01397 virtual_segment_c *VirtualFromSegments( matroska_segment_c *p_segment ) const;
01398 bool IsUsedSegment( matroska_segment_c &p_segment ) const;
01399 };
01400
01401 static int Demux ( demux_t * );
01402 static int Control( demux_t *, int, va_list );
01403 static void Seek ( demux_t *, mtime_t i_date, double f_percent, chapter_item_c *psz_chapter );
01404
01405 #define MKV_IS_ID( el, C ) ( EbmlId( (*el) ) == C::ClassInfos.GlobalId )
01406
01407 static inline char * ToUTF8( const UTFstring &u )
01408 {
01409 return strdup( u.GetUTF8().c_str() );
01410 }
01411
01412
01413
01414
01415 static int Open( vlc_object_t * p_this )
01416 {
01417 demux_t *p_demux = (demux_t*)p_this;
01418 demux_sys_t *p_sys;
01419 matroska_stream_c *p_stream;
01420 matroska_segment_c *p_segment;
01421 uint8_t *p_peek;
01422 std::string s_path, s_filename;
01423 vlc_stream_io_callback *p_io_callback;
01424 EbmlStream *p_io_stream;
01425
01426
01427 if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;
01428
01429
01430 if( p_peek[0] != 0x1a || p_peek[1] != 0x45 ||
01431 p_peek[2] != 0xdf || p_peek[3] != 0xa3 ) return VLC_EGENERIC;
01432
01433
01434 p_demux->pf_demux = Demux;
01435 p_demux->pf_control = Control;
01436 p_demux->p_sys = p_sys = new demux_sys_t( *p_demux );
01437
01438 p_io_callback = new vlc_stream_io_callback( p_demux->s, VLC_FALSE );
01439 p_io_stream = new EbmlStream( *p_io_callback );
01440
01441 if( p_io_stream == NULL )
01442 {
01443 msg_Err( p_demux, "failed to create EbmlStream" );
01444 delete p_io_callback;
01445 delete p_sys;
01446 return VLC_EGENERIC;
01447 }
01448
01449 p_stream = p_sys->AnalyseAllSegmentsFound( p_demux, p_io_stream, true );
01450 if( p_stream == NULL )
01451 {
01452 msg_Err( p_demux, "cannot find KaxSegment" );
01453 goto error;
01454 }
01455 p_sys->streams.push_back( p_stream );
01456
01457 p_stream->p_in = p_io_callback;
01458 p_stream->p_es = p_io_stream;
01459
01460 for (size_t i=0; i<p_stream->segments.size(); i++)
01461 {
01462 p_stream->segments[i]->Preload();
01463 }
01464
01465 p_segment = p_stream->segments[0];
01466 if( p_segment->cluster != NULL )
01467 {
01468 msg_Warn( p_demux, "cannot find any cluster, damaged file ?" );
01469
01470
01471 p_stream->p_in->setFilePointer( p_segment->cluster->GetElementPosition() );
01472 }
01473
01474 if (config_GetInt( p_demux, "mkv-preload-local-dir" ))
01475 {
01476
01477 if (p_demux->psz_path[0] != '\0' && !strcmp(p_demux->psz_access, ""))
01478 {
01479
01480
01481 s_path = p_demux->psz_path;
01482 if (s_path.at(s_path.length() - 1) == DIRECTORY_SEPARATOR)
01483 {
01484 s_path = s_path.substr(0,s_path.length()-1);
01485 }
01486 else
01487 {
01488 if (s_path.find_last_of(DIRECTORY_SEPARATOR) > 0)
01489 {
01490 s_path = s_path.substr(0,s_path.find_last_of(DIRECTORY_SEPARATOR));
01491 }
01492 }
01493
01494 struct dirent *p_file_item;
01495 DIR *p_src_dir = opendir(s_path.c_str());
01496
01497 if (p_src_dir != NULL)
01498 {
01499 while ((p_file_item = (dirent *) readdir(p_src_dir)))
01500 {
01501 if (strlen(p_file_item->d_name) > 4)
01502 {
01503 s_filename = s_path + DIRECTORY_SEPARATOR + p_file_item->d_name;
01504
01505 #ifdef WIN32
01506 if (!strcasecmp(s_filename.c_str(), p_demux->psz_path))
01507 #else
01508 if (!s_filename.compare(p_demux->psz_path))
01509 #endif
01510 continue;
01511
01512 #if defined(__GNUC__) && (__GNUC__ < 3)
01513 if (!s_filename.compare("mkv", s_filename.length() - 3, 3) ||
01514 !s_filename.compare("mka", s_filename.length() - 3, 3))
01515 #else
01516 if (!s_filename.compare(s_filename.length() - 3, 3, "mkv") ||
01517 !s_filename.compare(s_filename.length() - 3, 3, "mka"))
01518 #endif
01519 {
01520
01521 stream_t *p_file_stream = stream_UrlNew( p_demux, s_filename.c_str());
01522 if ( p_file_stream != NULL )
01523 {
01524 vlc_stream_io_callback *p_file_io = new vlc_stream_io_callback( p_file_stream, VLC_TRUE );
01525 EbmlStream *p_estream = new EbmlStream(*p_file_io);
01526
01527 p_stream = p_sys->AnalyseAllSegmentsFound( p_demux, p_estream );
01528
01529 if ( p_stream == NULL )
01530 {
01531 msg_Dbg( p_demux, "the file '%s' will not be used", s_filename.c_str() );
01532 delete p_estream;
01533 delete p_file_io;
01534 }
01535 else
01536 {
01537 p_stream->p_in = p_file_io;
01538 p_stream->p_es = p_estream;
01539 p_sys->streams.push_back( p_stream );
01540 }
01541 }
01542 else
01543 {
01544 msg_Dbg( p_demux, "the file '%s' cannot be opened", s_filename.c_str() );
01545 }
01546 }
01547 }
01548 }
01549 closedir( p_src_dir );
01550 }
01551 }
01552
01553 p_sys->PreloadFamily( *p_segment );
01554 }
01555
01556 p_sys->PreloadLinked( p_segment );
01557
01558 if ( !p_sys->PreparePlayback( NULL ) )
01559 {
01560 msg_Err( p_demux, "cannot use the segment" );
01561 goto error;
01562 }
01563
01564 p_sys->StartUiThread();
01565
01566 return VLC_SUCCESS;
01567
01568 error:
01569 delete p_sys;
01570 return VLC_EGENERIC;
01571 }
01572
01573
01574
01575
01576 static void Close( vlc_object_t *p_this )
01577 {
01578 demux_t *p_demux = (demux_t*)p_this;
01579 demux_sys_t *p_sys = p_demux->p_sys;
01580
01581 delete p_sys;
01582 }
01583
01584
01585
01586
01587 static int Control( demux_t *p_demux, int i_query, va_list args )
01588 {
01589 demux_sys_t *p_sys = p_demux->p_sys;
01590 int64_t *pi64;
01591 double *pf, f;
01592 int i_skp;
01593 size_t i_idx;
01594
01595 vlc_meta_t **pp_meta;
01596
01597 switch( i_query )
01598 {
01599 case DEMUX_GET_META:
01600 pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
01601 *pp_meta = vlc_meta_Duplicate( p_sys->meta );
01602 return VLC_SUCCESS;
01603
01604 case DEMUX_GET_LENGTH:
01605 pi64 = (int64_t*)va_arg( args, int64_t * );
01606 if( p_sys->f_duration > 0.0 )
01607 {
01608 *pi64 = (int64_t)(p_sys->f_duration * 1000);
01609 return VLC_SUCCESS;
01610 }
01611 return VLC_EGENERIC;
01612
01613 case DEMUX_GET_POSITION:
01614 pf = (double*)va_arg( args, double * );
01615 if ( p_sys->f_duration > 0.0 )
01616 *pf = (double)(p_sys->i_pts >= p_sys->i_start_pts ? p_sys->i_pts : p_sys->i_start_pts ) / (1000.0 * p_sys->f_duration);
01617 return VLC_SUCCESS;
01618
01619 case DEMUX_SET_POSITION:
01620 f = (double)va_arg( args, double );
01621 Seek( p_demux, -1, f, NULL );
01622 return VLC_SUCCESS;
01623
01624 case DEMUX_GET_TIME:
01625 pi64 = (int64_t*)va_arg( args, int64_t * );
01626 *pi64 = p_sys->i_pts;
01627 return VLC_SUCCESS;
01628
01629 case DEMUX_GET_TITLE_INFO:
01630 if( p_sys->titles.size() )
01631 {
01632 input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
01633 int *pi_int = (int*)va_arg( args, int* );
01634
01635 *pi_int = p_sys->titles.size();
01636 *ppp_title = (input_title_t**)malloc( sizeof( input_title_t**) * p_sys->titles.size() );
01637
01638 for( size_t i = 0; i < p_sys->titles.size(); i++ )
01639 {
01640 (*ppp_title)[i] = vlc_input_title_Duplicate( p_sys->titles[i] );
01641 }
01642
01643 return VLC_SUCCESS;
01644 }
01645 return VLC_EGENERIC;
01646
01647 case DEMUX_SET_TITLE:
01648
01649 i_idx = (int)va_arg( args, int );
01650 if( i_idx < p_sys->used_segments.size() )
01651 {
01652 p_sys->JumpTo( *p_sys->used_segments[i_idx], NULL );
01653 return VLC_SUCCESS;
01654 }
01655 return VLC_EGENERIC;
01656
01657 case DEMUX_SET_SEEKPOINT:
01658 i_skp = (int)va_arg( args, int );
01659
01660
01661 if( p_sys->titles.size() && i_skp < p_sys->titles[p_sys->i_current_title]->i_seekpoint)
01662 {
01663 Seek( p_demux, (int64_t)p_sys->titles[p_sys->i_current_title]->seekpoint[i_skp]->i_time_offset, -1, NULL);
01664 p_demux->info.i_seekpoint |= INPUT_UPDATE_SEEKPOINT;
01665 p_demux->info.i_seekpoint = i_skp;
01666 return VLC_SUCCESS;
01667 }
01668 return VLC_EGENERIC;
01669
01670 case DEMUX_SET_TIME:
01671 case DEMUX_GET_FPS:
01672 default:
01673 return VLC_EGENERIC;
01674 }
01675 }
01676
01677 #if LIBMATROSKA_VERSION >= 0x000800
01678 int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_simpleblock, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration )
01679 #else
01680 int matroska_segment_c::BlockGet( KaxBlock * & pp_block, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration )
01681 #endif
01682 {
01683 #if LIBMATROSKA_VERSION >= 0x000800
01684 pp_simpleblock = NULL;
01685 #endif
01686 pp_block = NULL;
01687 *pi_ref1 = 0;
01688 *pi_ref2 = 0;
01689
01690 for( ;; )
01691 {
01692 EbmlElement *el = NULL;
01693 int i_level;
01694
01695 if ( ep == NULL )
01696 return VLC_EGENERIC;
01697
01698 #if LIBMATROSKA_VERSION >= 0x000800
01699 if( pp_simpleblock != NULL || ((el = ep->Get()) == NULL && pp_block != NULL) )
01700 #else
01701 if( (el = ep->Get()) == NULL && pp_block != NULL )
01702 #endif
01703 {
01704
01705 #define idx p_indexes[i_index - 1]
01706 if( i_index > 0 && idx.i_time == -1 )
01707 {
01708 #if LIBMATROSKA_VERSION >= 0x000800
01709 if ( pp_simpleblock != NULL )
01710 idx.i_time = pp_simpleblock->GlobalTimecode() / (mtime_t)1000;
01711 else
01712 #endif
01713 idx.i_time = (*pp_block).GlobalTimecode() / (mtime_t)1000;
01714 idx.b_key = *pi_ref1 == 0 ? VLC_TRUE : VLC_FALSE;
01715 }
01716 #undef idx
01717 return VLC_SUCCESS;
01718 }
01719
01720 i_level = ep->GetLevel();
01721
01722 if( el == NULL )
01723 {
01724 if( i_level > 1 )
01725 {
01726 ep->Up();
01727 continue;
01728 }
01729 msg_Warn( &sys.demuxer, "EOF" );
01730 return VLC_EGENERIC;
01731 }
01732
01733
01734 switch ( i_level )
01735 {
01736 case 1:
01737 if( MKV_IS_ID( el, KaxCluster ) )
01738 {
01739 cluster = (KaxCluster*)el;
01740 i_cluster_pos = cluster->GetElementPosition();
01741
01742
01743 if( i_index == 0 ||
01744 ( i_index > 0 && p_indexes[i_index - 1].i_position < (int64_t)cluster->GetElementPosition() ) )
01745 {
01746 IndexAppendCluster( cluster );
01747 }
01748
01749
01750 for (size_t i=0; i<tracks.size(); i++)
01751 {
01752 tracks[i]->b_silent = VLC_FALSE;
01753 }
01754
01755 ep->Down();
01756 }
01757 else if( MKV_IS_ID( el, KaxCues ) )
01758 {
01759 msg_Warn( &sys.demuxer, "find KaxCues FIXME" );
01760 return VLC_EGENERIC;
01761 }
01762 else
01763 {
01764 msg_Dbg( &sys.demuxer, "unknown (%s)", typeid( el ).name() );
01765 }
01766 break;
01767 case 2:
01768 if( MKV_IS_ID( el, KaxClusterTimecode ) )
01769 {
01770 KaxClusterTimecode &ctc = *(KaxClusterTimecode*)el;
01771
01772 ctc.ReadData( es.I_O(), SCOPE_ALL_DATA );
01773 cluster->InitTimecode( uint64( ctc ), i_timescale );
01774 }
01775 else if( MKV_IS_ID( el, KaxClusterSilentTracks ) )
01776 {
01777 ep->Down();
01778 }
01779 else if( MKV_IS_ID( el, KaxBlockGroup ) )
01780 {
01781 i_block_pos = el->GetElementPosition();
01782 ep->Down();
01783 }
01784 #if LIBMATROSKA_VERSION >= 0x000800
01785 else if( MKV_IS_ID( el, KaxSimpleBlock ) )
01786 {
01787 pp_simpleblock = (KaxSimpleBlock*)el;
01788
01789 pp_simpleblock->ReadData( es.I_O() );
01790 pp_simpleblock->SetParent( *cluster );
01791 }
01792 #endif
01793 break;
01794 case 3:
01795 if( MKV_IS_ID( el, KaxBlock ) )
01796 {
01797 pp_block = (KaxBlock*)el;
01798
01799 pp_block->ReadData( es.I_O() );
01800 pp_block->SetParent( *cluster );
01801
01802 ep->Keep();
01803 }
01804 else if( MKV_IS_ID( el, KaxBlockDuration ) )
01805 {
01806 KaxBlockDuration &dur = *(KaxBlockDuration*)el;
01807
01808 dur.ReadData( es.I_O() );
01809 *pi_duration = uint64( dur );
01810 }
01811 else if( MKV_IS_ID( el, KaxReferenceBlock ) )
01812 {
01813 KaxReferenceBlock &ref = *(KaxReferenceBlock*)el;
01814
01815 ref.ReadData( es.I_O() );
01816 if( *pi_ref1 == 0 )
01817 {
01818 *pi_ref1 = int64( ref ) * cluster->GlobalTimecodeScale();
01819 }
01820 else if( *pi_ref2 == 0 )
01821 {
01822 *pi_ref2 = int64( ref ) * cluster->GlobalTimecodeScale();
01823 }
01824 }
01825 else if( MKV_IS_ID( el, KaxClusterSilentTrackNumber ) )
01826 {
01827 KaxClusterSilentTrackNumber &track_num = *(KaxClusterSilentTrackNumber*)el;
01828 track_num.ReadData( es.I_O() );
01829
01830 for (size_t i=0; i<tracks.size(); i++)
01831 {
01832 if ( tracks[i]->i_number == uint32(track_num))
01833 {
01834 tracks[i]->b_silent = VLC_TRUE;
01835 break;
01836 }
01837 }
01838 }
01839 break;
01840 default:
01841 msg_Err( &sys.demuxer, "invalid level = %d", i_level );
01842 return VLC_EGENERIC;
01843 }
01844 }
01845 }
01846
01847 static block_t *MemToBlock( demux_t *p_demux, uint8_t *p_mem, int i_mem, size_t offset)
01848 {
01849 block_t *p_block;
01850 if( !(p_block = block_New( p_demux, i_mem + offset ) ) ) return NULL;
01851 memcpy( p_block->p_buffer + offset, p_mem, i_mem );
01852
01853 return p_block;
01854 }
01855
01856 #if LIBMATROSKA_VERSION >= 0x000800
01857 static void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock,
01858 mtime_t i_pts, mtime_t i_duration, bool f_mandatory )
01859 #else
01860 static void BlockDecode( demux_t *p_demux, KaxBlock *block, mtime_t i_pts,
01861 mtime_t i_duration, bool f_mandatory )
01862 #endif
01863 {
01864 demux_sys_t *p_sys = p_demux->p_sys;
01865 matroska_segment_c *p_segment = p_sys->p_current_segment->Segment();
01866
01867 size_t i_track;
01868 unsigned int i;
01869 vlc_bool_t b;
01870
01871 #define tk p_segment->tracks[i_track]
01872 for( i_track = 0; i_track < p_segment->tracks.size(); i_track++ )
01873 {
01874 #if LIBMATROSKA_VERSION >= 0x000800
01875 if( (block != NULL && tk->i_number == block->TrackNum()) ||
01876 (simpleblock != NULL && tk->i_number == simpleblock->TrackNum()))
01877 #else
01878 if( tk->i_number == block->TrackNum() )
01879 #endif
01880 {
01881 break;
01882 }
01883 }
01884
01885 if( i_track >= p_segment->tracks.size() )
01886 {
01887 msg_Err( p_demux, "invalid track number=%d", block->TrackNum() );
01888 return;
01889 }
01890 if( tk->fmt.i_cat != NAV_ES && tk->p_es == NULL )
01891 {
01892 msg_Err( p_demux, "unknown track number=%d", block->TrackNum() );
01893 return;
01894 }
01895 if( i_pts + i_duration < p_sys->i_start_pts && tk->fmt.i_cat == AUDIO_ES )
01896 {
01897 return;
01898 }
01899
01900 if ( tk->fmt.i_cat != NAV_ES )
01901 {
01902 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
01903
01904 if( !b )
01905 {
01906 tk->b_inited = VLC_FALSE;
01907 return;
01908 }
01909 }
01910
01911
01912
01913 if( !tk->b_inited && tk->i_data_init > 0 )
01914 {
01915 block_t *p_init;
01916
01917 msg_Dbg( p_demux, "sending header (%d bytes)", tk->i_data_init );
01918 p_init = MemToBlock( p_demux, tk->p_data_init, tk->i_data_init, 0 );
01919 if( p_init ) es_out_Send( p_demux->out, tk->p_es, p_init );
01920 }
01921 tk->b_inited = VLC_TRUE;
01922
01923
01924 #if LIBMATROSKA_VERSION >= 0x000800
01925 for( i = 0;
01926 (block != NULL && i < block->NumberFrames()) || (simpleblock != NULL && i < simpleblock->NumberFrames());
01927 i++ )
01928 #else
01929 for( i = 0; i < block->NumberFrames(); i++ )
01930 #endif
01931 {
01932 block_t *p_block;
01933 DataBuffer *data;
01934 #if LIBMATROSKA_VERSION >= 0x000800
01935 if ( simpleblock != NULL )
01936 {
01937 data = &simpleblock->GetBuffer(i);
01938
01939 f_mandatory = simpleblock->IsDiscardable() || simpleblock->IsKeyframe();
01940 }
01941 else
01942 #endif
01943 data = &block->GetBuffer(i);
01944
01945 if( tk->i_compression_type == MATROSKA_COMPRESSION_HEADER && tk->p_compression_data != NULL )
01946 p_block = MemToBlock( p_demux, data->Buffer(), data->Size(), tk->p_compression_data->GetSize() );
01947 else
01948 p_block = MemToBlock( p_demux, data->Buffer(), data->Size(), 0 );
01949
01950 if( p_block == NULL )
01951 {
01952 break;
01953 }
01954
01955 #if defined(HAVE_ZLIB_H)
01956 if( tk->i_compression_type == MATROSKA_COMPRESSION_ZLIB )
01957 {
01958 p_block = block_zlib_decompress( VLC_OBJECT(p_demux), p_block );
01959 }
01960 else
01961 #endif
01962 if( tk->i_compression_type == MATROSKA_COMPRESSION_HEADER )
01963 {
01964 memcpy( p_block->p_buffer, tk->p_compression_data->GetBuffer(), tk->p_compression_data->GetSize() );
01965 }
01966
01967 if ( tk->fmt.i_cat == NAV_ES )
01968 {
01969
01970 if ( p_sys->b_ui_hooked )
01971 {
01972 vlc_mutex_lock( &p_sys->p_ev->lock );
01973 memcpy( &p_sys->pci_packet, &p_block->p_buffer[1], sizeof(pci_t) );
01974 p_sys->SwapButtons();
01975 p_sys->b_pci_packet_set = true;
01976 vlc_mutex_unlock( &p_sys->p_ev->lock );
01977 block_Release( p_block );
01978 }
01979 return;
01980 }
01981
01982 if( tk->fmt.i_cat != VIDEO_ES )
01983 {
01984 p_block->i_dts = p_block->i_pts = i_pts;
01985 }
01986 else
01987 {
01988 if( !strcmp( tk->psz_codec, "V_MS/VFW/FOURCC" ) )
01989 {
01990
01991 p_block->i_pts = 0;
01992 p_block->i_dts = i_pts;
01993 }
01994 else
01995 {
01996 p_block->i_pts = i_pts;
01997 if ( f_mandatory )
01998 p_block->i_dts = p_block->i_pts;
01999 else
02000 p_block->i_dts = min( i_pts, tk->i_last_dts + (tk->i_default_duration >> 10));
02001 p_sys->i_pts = p_block->i_dts;
02002 }
02003 }
02004 tk->i_last_dts = p_block->i_dts;
02005
02006 #if 0
02007 msg_Dbg( p_demux, "block i_dts: "I64Fd" / i_pts: "I64Fd, p_block->i_dts, p_block->i_pts);
02008 #endif
02009 if( strcmp( tk->psz_codec, "S_VOBSUB" ) )
02010 {
02011 p_block->i_length = i_duration * 1000;
02012 }
02013
02014 es_out_Send( p_demux->out, tk->p_es, p_block );
02015
02016
02017 i_pts = 0;
02018 }
02019
02020 #undef tk
02021 }
02022
02023 matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( demux_t *p_demux, EbmlStream *p_estream, bool b_initial )
02024 {
02025 int i_upper_lvl = 0;
02026 size_t i;
02027 EbmlElement *p_l0, *p_l1, *p_l2;
02028 bool b_keep_stream = false, b_keep_segment;
02029
02030
02031 p_l0 = p_estream->FindNextID(EbmlHead::ClassInfos, 0xFFFFFFFFL);
02032 if (p_l0 == NULL)
02033 {
02034 msg_Err( p_demux, "No EBML header found" );
02035 return NULL;
02036 }
02037
02038
02039 p_l0->Read(*p_estream, EbmlHead::ClassInfos.Context, i_upper_lvl, p_l0, true);
02040
02041 EDocType doc_type = GetChild<EDocType>(*static_cast<EbmlHead*>(p_l0));
02042 if (std::string(doc_type) != "matroska")
02043 {
02044 msg_Err( p_demux, "Not a Matroska file : DocType = %s ", std::string(doc_type).c_str());
02045 return NULL;
02046 }
02047
02048 EDocTypeReadVersion doc_read_version = GetChild<EDocTypeReadVersion>(*static_cast<EbmlHead*>(p_l0));
02049 #if LIBMATROSKA_VERSION >= 0x000800
02050 if (uint64(doc_read_version) > 2)
02051 {
02052 msg_Err( p_demux, "This matroska file is needs version "I64Fd" and this VLC only supports version 1 & 2", uint64(doc_read_version));
02053 return NULL;
02054 }
02055 #else
02056 if (uint64(doc_read_version) != 1)
02057 {
02058 msg_Err( p_demux, "This matroska file is needs version "I64Fd" and this VLC only supports version 1", uint64(doc_read_version));
02059 return NULL;
02060 }
02061 #endif
02062
02063 delete p_l0;
02064
02065
02066
02067 p_l0 = p_estream->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFFLL);
02068 if (p_l0 == NULL)
02069 {
02070 return NULL;
02071 }
02072
02073 matroska_stream_c *p_stream1 = new matroska_stream_c( *this );
02074
02075 while (p_l0 != 0)
02076 {
02077 if (EbmlId(*p_l0) == KaxSegment::ClassInfos.GlobalId)
02078 {
02079 EbmlParser *ep;
02080 matroska_segment_c *p_segment1 = new matroska_segment_c( *this, *p_estream );
02081 b_keep_segment = b_initial;
02082
02083 ep = new EbmlParser(p_estream, p_l0, &demuxer );
02084 p_segment1->ep = ep;
02085 p_segment1->segment = (KaxSegment*)p_l0;
02086
02087 while ((p_l1 = ep->Get()))
02088 {
02089 if (MKV_IS_ID(p_l1, KaxInfo))
02090 {
02091
02092 KaxInfo *p_info = static_cast<KaxInfo*>(p_l1);
02093
02094 p_info->Read(*p_estream, KaxInfo::ClassInfos.Context, i_upper_lvl, p_l2, true);
02095 for( i = 0; i < p_info->ListSize(); i++ )
02096 {
02097 EbmlElement *l = (*p_info)[i];
02098
02099 if( MKV_IS_ID( l, KaxSegmentUID ) )
02100 {
02101 KaxSegmentUID *p_uid = static_cast<KaxSegmentUID*>(l);
02102 b_keep_segment = (FindSegment( *p_uid ) == NULL);
02103 if ( !b_keep_segment )
02104 break;
02105 opened_segments.push_back( p_segment1 );
02106 delete p_segment1->p_segment_uid;
02107 p_segment1->p_segment_uid = new KaxSegmentUID(*p_uid);
02108 }
02109 else if( MKV_IS_ID( l, KaxPrevUID ) )
02110 {
02111 p_segment1->p_prev_segment_uid = new KaxPrevUID( *static_cast<KaxPrevUID*>(l) );
02112 }
02113 else if( MKV_IS_ID( l, KaxNextUID ) )
02114 {
02115 p_segment1->p_next_segment_uid = new KaxNextUID( *static_cast<KaxNextUID*>(l) );
02116 }
02117 else if( MKV_IS_ID( l, KaxSegmentFamily ) )
02118 {
02119 KaxSegmentFamily *p_fam = new KaxSegmentFamily( *static_cast<KaxSegmentFamily*>(l) );
02120 p_segment1->families.push_back( p_fam );
02121 }
02122 }
02123 break;
02124 }
02125 }
02126 if ( b_keep_segment )
02127 {
02128 b_keep_stream = true;
02129 p_stream1->segments.push_back( p_segment1 );
02130 }
02131 else
02132 delete p_segment1;
02133 }
02134 if (p_l0->IsFiniteSize() )
02135 {
02136 p_l0->SkipData(*p_estream, KaxMatroska_Context);
02137 p_l0 = p_estream->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFL);
02138 }
02139 else
02140 p_l0 = p_l0->SkipData(*p_estream, KaxSegment_Context);
02141 }
02142
02143 if ( !b_keep_stream )
02144 {
02145 delete p_stream1;
02146 p_stream1 = NULL;
02147 }
02148
02149 return p_stream1;
02150 }
02151
02152 bool matroska_segment_c::Select( mtime_t i_start_time )
02153 {
02154 size_t i_track;
02155
02156
02157 msg_Dbg( &sys.demuxer, "found %d es", (int)tracks.size() );
02158 sys.b_pci_packet_set = false;
02159
02160 for( i_track = 0; i_track < tracks.size(); i_track++ )
02161 {
02162 if( tracks[i_track]->fmt.i_cat == UNKNOWN_ES )
02163 {
02164 msg_Warn( &sys.demuxer, "invalid track[%d, n=%d]", (int)i_track, tracks[i_track]->i_number );
02165 tracks[i_track]->p_es = NULL;
02166 continue;
02167 }
02168
02169 if( !strcmp( tracks[i_track]->psz_codec, "V_MS/VFW/FOURCC" ) )
02170 {
02171 if( tracks[i_track]->i_extra_data < (int)sizeof( BITMAPINFOHEADER ) )
02172 {
02173 msg_Err( &sys.demuxer, "missing/invalid BITMAPINFOHEADER" );
02174 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
02175 }
02176 else
02177 {
02178 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)tracks[i_track]->p_extra_data;
02179
02180 tracks[i_track]->fmt.video.i_width = GetDWLE( &p_bih->biWidth );
02181 tracks[i_track]->fmt.video.i_height= GetDWLE( &p_bih->biHeight );
02182 tracks[i_track]->fmt.i_codec = GetFOURCC( &p_bih->biCompression );
02183
02184 tracks[i_track]->fmt.i_extra = GetDWLE( &p_bih->biSize ) - sizeof( BITMAPINFOHEADER );
02185 if( tracks[i_track]->fmt.i_extra > 0 )
02186 {
02187 tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->fmt.i_extra );
02188 memcpy( tracks[i_track]->fmt.p_extra, &p_bih[1], tracks[i_track]->fmt.i_extra );
02189 }
02190 }
02191 }
02192 else if( !strcmp( tracks[i_track]->psz_codec, "V_MPEG1" ) ||
02193 !strcmp( tracks[i_track]->psz_codec, "V_MPEG2" ) )
02194 {
02195 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
02196 }
02197 else if( !strncmp( tracks[i_track]->psz_codec, "V_MPEG4", 7 ) )
02198 {
02199 if( !strcmp( tracks[i_track]->psz_codec, "V_MPEG4/MS/V3" ) )
02200 {
02201 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'D', 'I', 'V', '3' );
02202 }
02203 else if( !strcmp( tracks[i_track]->psz_codec, "V_MPEG4/ISO/AVC" ) )
02204 {
02205 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'a', 'v', 'c', '1' );
02206 tracks[i_track]->fmt.i_extra = tracks[i_track]->i_extra_data;
02207 tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->i_extra_data );
02208 memcpy( tracks[i_track]->fmt.p_extra,tracks[i_track]->p_extra_data, tracks[i_track]->i_extra_data );
02209 }
02210 else
02211 {
02212 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
02213 }
02214 }
02215 else if( !strcmp( tracks[i_track]->psz_codec, "V_QUICKTIME" ) )
02216 {
02217 MP4_Box_t *p_box = (MP4_Box_t*)malloc( sizeof( MP4_Box_t ) );
02218 stream_t *p_mp4_stream = stream_MemoryNew( VLC_OBJECT(&sys.demuxer),
02219 tracks[i_track]->p_extra_data,
02220 tracks[i_track]->i_extra_data,
02221 VLC_FALSE );
02222 MP4_ReadBoxCommon( p_mp4_stream, p_box );
02223 MP4_ReadBox_sample_vide( p_mp4_stream, p_box );
02224 tracks[i_track]->fmt.i_codec = p_box->i_type;
02225 tracks[i_track]->fmt.video.i_width = p_box->data.p_sample_vide->i_width;
02226 tracks[i_track]->fmt.video.i_height = p_box->data.p_sample_vide->i_height;
02227 tracks[i_track]->fmt.i_extra = p_box->data.p_sample_vide->i_qt_image_description;
02228 tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->fmt.i_extra );
02229 memcpy( tracks[i_track]->fmt.p_extra, p_box->data.p_sample_vide->p_qt_image_description, tracks[i_track]->fmt.i_extra );
02230 MP4_FreeBox_sample_vide( p_box );
02231 stream_Delete( p_mp4_stream );
02232 }
02233 else if( !strcmp( tracks[i_track]->psz_codec, "A_MS/ACM" ) )
02234 {
02235 if( tracks[i_track]->i_extra_data < (int)sizeof( WAVEFORMATEX ) )
02236 {
02237 msg_Err( &sys.demuxer, "missing/invalid WAVEFORMATEX" );
02238 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
02239 }
02240 else
02241 {
02242 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)tracks[i_track]->p_extra_data;
02243
02244 wf_tag_to_fourcc( GetWLE( &p_wf->wFormatTag ), &tracks[i_track]->fmt.i_codec, NULL );
02245
02246 tracks[i_track]->fmt.audio.i_channels = GetWLE( &p_wf->nChannels );
02247 tracks[i_track]->fmt.audio.i_rate = GetDWLE( &p_wf->nSamplesPerSec );
02248 tracks[i_track]->fmt.i_bitrate = GetDWLE( &p_wf->nAvgBytesPerSec ) * 8;
02249 tracks[i_track]->fmt.audio.i_blockalign = GetWLE( &p_wf->nBlockAlign );;
02250 tracks[i_track]->fmt.audio.i_bitspersample = GetWLE( &p_wf->wBitsPerSample );
02251
02252 tracks[i_track]->fmt.i_extra = GetWLE( &p_wf->cbSize );
02253 if( tracks[i_track]->fmt.i_extra > 0 )
02254 {
02255 tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->fmt.i_extra );
02256 memcpy( tracks[i_track]->fmt.p_extra, &p_wf[1], tracks[i_track]->fmt.i_extra );
02257 }
02258 }
02259 }
02260 else if( !strcmp( tracks[i_track]->psz_codec, "A_MPEG/L3" ) ||
02261 !strcmp( tracks[i_track]->psz_codec, "A_MPEG/L2" ) ||
02262 !strcmp( tracks[i_track]->psz_codec, "A_MPEG/L1" ) )
02263 {
02264 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
02265 }
02266 else if( !strcmp( tracks[i_track]->psz_codec, "A_AC3" ) )
02267 {
02268 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
02269 }
02270 else if( !strcmp( tracks[i_track]->psz_codec, "A_DTS" ) )
02271 {
02272 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'd', 't', 's', ' ' );
02273 }
02274 else if( !strcmp( tracks[i_track]->psz_codec, "A_FLAC" ) )
02275 {
02276 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'f', 'l', 'a', 'c' );
02277 tracks[i_track]->fmt.i_extra = tracks[i_track]->i_extra_data;
02278 tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->i_extra_data );
02279 memcpy( tracks[i_track]->fmt.p_extra,tracks[i_track]->p_extra_data, tracks[i_track]->i_extra_data );
02280 }
02281 else if( !strcmp( tracks[i_track]->psz_codec, "A_VORBIS" ) )
02282 {
02283 int i, i_offset = 1, i_size[3], i_extra;
02284 uint8_t *p_extra;
02285
02286 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'v', 'o', 'r', 'b' );
02287
02288
02289 if( tracks[i_track]->p_extra_data[0] != 0x02 )
02290 msg_Err( &sys.demuxer, "invalid vorbis header" );
02291
02292 for( i = 0; i < 2; i++ )
02293 {
02294 i_size[i] = 0;
02295 while( i_offset < tracks[i_track]->i_extra_data )
02296 {
02297 i_size[i] += tracks[i_track]->p_extra_data[i_offset];
02298 if( tracks[i_track]->p_extra_data[i_offset++] != 0xff ) break;
02299 }
02300 }
02301
02302 i_size[0] = __MIN(i_size[0], tracks[i_track]->i_extra_data - i_offset);
02303 i_size[1] = __MIN(i_size[1], tracks[i_track]->i_extra_data -i_offset -i_size[0]);
02304 i_size[2] = tracks[i_track]->i_extra_data - i_offset - i_size[0] - i_size[1];
02305
02306 tracks[i_track]->fmt.i_extra = 3 * 2 + i_size[0] + i_size[1] + i_size[2];
02307 tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->fmt.i_extra );
02308 p_extra = (uint8_t *)tracks[i_track]->fmt.p_extra; i_extra = 0;
02309 for( i = 0; i < 3; i++ )
02310 {
02311 *(p_extra++) = i_size[i] >> 8;
02312 *(p_extra++) = i_size[i] & 0xFF;
02313 memcpy( p_extra, tracks[i_track]->p_extra_data + i_offset + i_extra,
02314 i_size[i] );
02315 p_extra += i_size[i];
02316 i_extra += i_size[i];
02317 }
02318 }
02319 else if( !strncmp( tracks[i_track]->psz_codec, "A_AAC/MPEG2/", strlen( "A_AAC/MPEG2/" ) ) ||
02320 !strncmp( tracks[i_track]->psz_codec, "A_AAC/MPEG4/", strlen( "A_AAC/MPEG4/" ) ) )
02321 {
02322 int i_profile, i_srate, sbr = 0;
02323 static unsigned int i_sample_rates[] =
02324 {
02325 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
02326 16000, 12000, 11025, 8000, 7350, 0, 0, 0
02327 };
02328
02329 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
02330
02331
02332 if( !strcmp( &tracks[i_track]->psz_codec[12], "MAIN" ) )
02333 {
02334 i_profile = 0;
02335 }
02336 else if( !strcmp( &tracks[i_track]->psz_codec[12], "LC" ) )
02337 {
02338 i_profile = 1;
02339 }
02340 else if( !strcmp( &tracks[i_track]->psz_codec[12], "SSR" ) )
02341 {
02342 i_profile = 2;
02343 }
02344 else if( !strcmp( &tracks[i_track]->psz_codec[12], "LC/SBR" ) )
02345 {
02346 i_profile = 1;
02347 sbr = 1;
02348 }
02349 else
02350 {
02351 i_profile = 3;
02352 }
02353
02354 for( i_srate = 0; i_srate < 13; i_srate++ )
02355 {
02356 if( i_sample_rates[i_srate] == tracks[i_track]->i_original_rate )
02357 {
02358 break;
02359 }
02360 }
02361 msg_Dbg( &sys.demuxer, "profile=%d srate=%d", i_profile, i_srate );
02362
02363 tracks[i_track]->fmt.i_extra = sbr ? 5 : 2;
02364 tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->fmt.i_extra );
02365 ((uint8_t*)tracks[i_track]->fmt.p_extra)[0] = ((i_profile + 1) << 3) | ((i_srate&0xe) >> 1);
02366 ((uint8_t*)tracks[i_track]->fmt.p_extra)[1] = ((i_srate & 0x1) << 7) | (tracks[i_track]->fmt.audio.i_channels << 3);
02367 if (sbr != 0)
02368 {
02369 int syncExtensionType = 0x2B7;
02370 int iDSRI;
02371 for (iDSRI=0; iDSRI<13; iDSRI++)
02372 if( i_sample_rates[iDSRI] == tracks[i_track]->fmt.audio.i_rate )
02373 break;
02374 ((uint8_t*)tracks[i_track]->fmt.p_extra)[2] = (syncExtensionType >> 3) & 0xFF;
02375 ((uint8_t*)tracks[i_track]->fmt.p_extra)[3] = ((syncExtensionType & 0x7) << 5) | 5;
02376 ((uint8_t*)tracks[i_track]->fmt.p_extra)[4] = ((1 & 0x1) << 7) | (iDSRI << 3);
02377 }
02378 }
02379 else if( !strcmp( tracks[i_track]->psz_codec, "A_AAC" ) )
02380 {
02381 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
02382 tracks[i_track]->fmt.i_extra = tracks[i_track]->i_extra_data;
02383 tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->i_extra_data );
02384 memcpy( tracks[i_track]->fmt.p_extra, tracks[i_track]->p_extra_data, tracks[i_track]->i_extra_data );
02385 }
02386 else if( !strcmp( tracks[i_track]->psz_codec, "A_PCM/INT/BIG" ) ||
02387 !strcmp( tracks[i_track]->psz_codec, "A_PCM/INT/LIT" ) ||
02388 !strcmp( tracks[i_track]->psz_codec, "A_PCM/FLOAT/IEEE" ) )
02389 {
02390 if( !strcmp( tracks[i_track]->psz_codec, "A_PCM/INT/BIG" ) )
02391 {
02392 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
02393 }
02394 else
02395 {
02396 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
02397 }
02398 tracks[i_track]->fmt.audio.i_blockalign = ( tracks[i_track]->fmt.audio.i_bitspersample + 7 ) / 8 * tracks[i_track]->fmt.audio.i_channels;
02399 }
02400 else if( !strcmp( tracks[i_track]->psz_codec, "A_TTA1" ) )
02401 {
02402
02403 msg_Err( &sys.demuxer, "TTA not supported yet[%d, n=%d]", (int)i_track, tracks[i_track]->i_number );
02404 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
02405 }
02406 else if( !strcmp( tracks[i_track]->psz_codec, "A_WAVPACK4" ) )
02407 {
02408
02409 msg_Err( &sys.demuxer, "Wavpack not supported yet[%d, n=%d]", (int)i_track, tracks[i_track]->i_number );
02410 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
02411 }
02412 else if( !strcmp( tracks[i_track]->psz_codec, "S_TEXT/UTF8" ) )
02413 {
02414 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
02415 tracks[i_track]->fmt.subs.psz_encoding = strdup( "UTF-8" );
02416 }
02417 else if( !strcmp( tracks[i_track]->psz_codec, "S_TEXT/SSA" ) ||
02418 !strcmp( tracks[i_track]->psz_codec, "S_TEXT/ASS" ) ||
02419 !strcmp( tracks[i_track]->psz_codec, "S_SSA" ) ||
02420 !strcmp( tracks[i_track]->psz_codec, "S_ASS" ))
02421 {
02422 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 's', 's', 'a', ' ' );
02423 tracks[i_track]->fmt.subs.psz_encoding = strdup( "UTF-8" );
02424 }
02425 else if( !strcmp( tracks[i_track]->psz_codec, "S_VOBSUB" ) )
02426 {
02427 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 's','p','u',' ' );
02428 if( tracks[i_track]->i_extra_data )
02429 {
02430 char *p_start;
02431 char *p_buf = (char *)malloc( tracks[i_track]->i_extra_data + 1);
02432 memcpy( p_buf, tracks[i_track]->p_extra_data , tracks[i_track]->i_extra_data );
02433 p_buf[tracks[i_track]->i_extra_data] = '\0';
02434
02435 p_start = strstr( p_buf, "size:" );
02436 if( sscanf( p_start, "size: %dx%d",
02437 &tracks[i_track]->fmt.subs.spu.i_original_frame_width, &tracks[i_track]->fmt.subs.spu.i_original_frame_height ) == 2 )
02438 {
02439 msg_Dbg( &sys.demuxer, "original frame size vobsubs: %dx%d", tracks[i_track]->fmt.subs.spu.i_original_frame_width, tracks[i_track]->fmt.subs.spu.i_original_frame_height );
02440 }
02441 else
02442 {
02443 msg_Warn( &sys.demuxer, "reading original frame size for vobsub failed" );
02444 }
02445 free( p_buf );
02446 }
02447 }
02448 else if( !strcmp( tracks[i_track]->psz_codec, "B_VOBBTN" ) )
02449 {
02450 tracks[i_track]->fmt.i_cat = NAV_ES;
02451 continue;
02452 }
02453 else
02454 {
02455 msg_Err( &sys.demuxer, "unknow codec id=`%s'", tracks[i_track]->psz_codec );
02456 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
02457 }
02458 if( tracks[i_track]->b_default )
02459 {
02460 tracks[i_track]->fmt.i_priority = 1000;
02461 }
02462
02463 tracks[i_track]->p_es = es_out_Add( sys.demuxer.out, &tracks[i_track]->fmt );
02464
02465 es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, tracks[i_track]->p_es, i_start_time );
02466 }
02467
02468 sys.i_start_pts = i_start_time;
02469
02470 es.I_O().setFilePointer( i_start_pos );
02471
02472 delete ep;
02473 ep = new EbmlParser( &es, segment, &sys.demuxer );
02474
02475 return true;
02476 }
02477
02478 void demux_sys_t::StartUiThread()
02479 {
02480 if ( !b_ui_hooked )
02481 {
02482 msg_Dbg( &demuxer, "Starting the UI Hook" );
02483 b_ui_hooked = true;
02484
02485
02486 p_input = (input_thread_t *) vlc_object_find( &demuxer, VLC_OBJECT_INPUT, FIND_PARENT );
02487 var_Create( p_input, "x-start", VLC_VAR_INTEGER );
02488 var_Create( p_input, "y-start", VLC_VAR_INTEGER );
02489 var_Create( p_input, "x-end", VLC_VAR_INTEGER );
02490 var_Create( p_input, "y-end", VLC_VAR_INTEGER );
02491 var_Create( p_input, "color", VLC_VAR_ADDRESS );
02492 var_Create( p_input, "menu-palette", VLC_VAR_ADDRESS );
02493 var_Create( p_input, "highlight", VLC_VAR_BOOL );
02494 var_Create( p_input, "highlight-mutex", VLC_VAR_MUTEX );
02495
02496
02497 p_ev = (event_thread_t *) vlc_object_create( &demuxer, sizeof( event_thread_t ) );
02498 p_ev->p_demux = &demuxer;
02499 p_ev->b_die = VLC_FALSE;
02500 vlc_mutex_init( p_ev, &p_ev->lock );
02501 vlc_thread_create( p_ev, "mkv event thread handler", EventThread,
02502 VLC_THREAD_PRIORITY_LOW, VLC_FALSE );
02503 }
02504 }
02505
02506 void demux_sys_t::StopUiThread()
02507 {
02508 if ( b_ui_hooked )
02509 {
02510 p_ev->b_die = VLC_TRUE;
02511
02512 vlc_thread_join( p_ev );
02513 vlc_object_destroy( p_ev );
02514
02515 p_ev = NULL;
02516
02517 var_Destroy( p_input, "highlight-mutex" );
02518 var_Destroy( p_input, "highlight" );
02519 var_Destroy( p_input, "x-start" );
02520 var_Destroy( p_input, "x-end" );
02521 var_Destroy( p_input, "y-start" );
02522 var_Destroy( p_input, "y-end" );
02523 var_Destroy( p_input, "color" );
02524 var_Destroy( p_input, "menu-palette" );
02525
02526 vlc_object_release( p_input );
02527
02528 msg_Dbg( &demuxer, "Stopping the UI Hook" );
02529 }
02530 b_ui_hooked = false;
02531 }
02532
02533 int demux_sys_t::EventMouse( vlc_object_t *p_this, char const *psz_var,
02534 vlc_value_t oldval, vlc_value_t newval, void *p_data )
02535 {
02536 event_thread_t *p_ev = (event_thread_t *) p_data;
02537 vlc_mutex_lock( &p_ev->lock );
02538 if( psz_var[6] == 'c' )
02539 {
02540 p_ev->b_clicked = VLC_TRUE;
02541 msg_Dbg( p_this, "Event Mouse: clicked");
02542 }
02543 else if( psz_var[6] == 'm' )
02544 p_ev->b_moved = VLC_TRUE;
02545 vlc_mutex_unlock( &p_ev->lock );
02546
02547 return VLC_SUCCESS;
02548 }
02549
02550 int demux_sys_t::EventKey( vlc_object_t *p_this, char const *psz_var,
02551 vlc_value_t oldval, vlc_value_t newval, void *p_data )
02552 {
02553 event_thread_t *p_ev = (event_thread_t *) p_data;
02554 vlc_mutex_lock( &p_ev->lock );
02555 p_ev->b_key = VLC_TRUE;
02556 vlc_mutex_unlock( &p_ev->lock );
02557 msg_Dbg( p_this, "Event Key");
02558
02559 return VLC_SUCCESS;
02560 }
02561
02562 int demux_sys_t::EventThread( vlc_object_t *p_this )
02563 {
02564 event_thread_t *p_ev = (event_thread_t*)p_this;
02565 demux_sys_t *p_sys = p_ev->p_demux->p_sys;
02566 vlc_object_t *p_vout = NULL;
02567
02568 p_ev->b_moved = VLC_FALSE;
02569 p_ev->b_clicked = VLC_FALSE;
02570 p_ev->b_key = VLC_FALSE;
02571
02572
02573 var_AddCallback( p_ev->p_vlc, "key-pressed", EventKey, p_ev );
02574
02575
02576 while( !p_ev->b_die )
02577 {
02578 if ( !p_sys->b_pci_packet_set )
02579 {
02580
02581 msleep( 100000 );
02582 continue;
02583 }
02584
02585 vlc_bool_t b_activated = VLC_FALSE;
02586
02587
02588 if( p_ev->b_key )
02589 {
02590 vlc_value_t valk;
02591 struct vlc_t::hotkey *p_hotkeys = p_ev->p_vlc->p_hotkeys;
02592 int i, i_action = -1;
02593
02594 msg_Dbg( p_ev->p_demux, "Handle Key Event");
02595
02596 vlc_mutex_lock( &p_ev->lock );
02597
02598 pci_t *pci = (pci_t *) &p_sys->pci_packet;
02599
02600 var_Get( p_ev->p_vlc, "key-pressed", &valk );
02601 for( i = 0; p_hotkeys[i].psz_action != NULL; i++ )
02602 {
02603 if( p_hotkeys[i].i_key == valk.i_int )
02604 {
02605 i_action = p_hotkeys[i].i_action;
02606 }
02607 }
02608
02609 uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );
02610
02611 switch( i_action )
02612 {
02613 case ACTIONID_NAV_LEFT:
02614 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
02615 {
02616 btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
02617 if ( p_button_ptr->left > 0 && p_button_ptr->left <= pci->hli.hl_gi.btn_ns )
02618 {
02619 i_curr_button = p_button_ptr->left;
02620 p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
02621 btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
02622 if ( button_ptr.auto_action_mode )
02623 {
02624 vlc_mutex_unlock( &p_ev->lock );
02625 vlc_mutex_lock( &p_sys->lock_demuxer );
02626
02627
02628 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
02629
02630 vlc_mutex_unlock( &p_sys->lock_demuxer );
02631 vlc_mutex_lock( &p_ev->lock );
02632 }
02633 }
02634 }
02635 break;
02636 case ACTIONID_NAV_RIGHT:
02637 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
02638 {
02639 btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
02640 if ( p_button_ptr->right > 0 && p_button_ptr->right <= pci->hli.hl_gi.btn_ns )
02641 {
02642 i_curr_button = p_button_ptr->right;
02643 p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
02644 btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
02645 if ( button_ptr.auto_action_mode )
02646 {
02647 vlc_mutex_unlock( &p_ev->lock );
02648 vlc_mutex_lock( &p_sys->lock_demuxer );
02649
02650
02651 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
02652
02653 vlc_mutex_unlock( &p_sys->lock_demuxer );
02654 vlc_mutex_lock( &p_ev->lock );
02655 }
02656 }
02657 }
02658 break;
02659 case ACTIONID_NAV_UP:
02660 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
02661 {
02662 btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
02663 if ( p_button_ptr->up > 0 && p_button_ptr->up <= pci->hli.hl_gi.btn_ns )
02664 {
02665 i_curr_button = p_button_ptr->up;
02666 p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
02667 btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
02668 if ( button_ptr.auto_action_mode )
02669 {
02670 vlc_mutex_unlock( &p_ev->lock );
02671 vlc_mutex_lock( &p_sys->lock_demuxer );
02672
02673
02674 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
02675
02676 vlc_mutex_unlock( &p_sys->lock_demuxer );
02677 vlc_mutex_lock( &p_ev->lock );
02678 }
02679 }
02680 }
02681 break;
02682 case ACTIONID_NAV_DOWN:
02683 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
02684 {
02685 btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
02686 if ( p_button_ptr->down > 0 && p_button_ptr->down <= pci->hli.hl_gi.btn_ns )
02687 {
02688 i_curr_button = p_button_ptr->down;
02689 p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
02690 btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
02691 if ( button_ptr.auto_action_mode )
02692 {
02693 vlc_mutex_unlock( &p_ev->lock );
02694 vlc_mutex_lock( &p_sys->lock_demuxer );
02695
02696
02697 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
02698
02699 vlc_mutex_unlock( &p_sys->lock_demuxer );
02700 vlc_mutex_lock( &p_ev->lock );
02701 }
02702 }
02703 }
02704 break;
02705 case ACTIONID_NAV_ACTIVATE:
02706 b_activated = VLC_TRUE;
02707
02708 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
02709 {
02710 btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
02711
02712 vlc_mutex_unlock( &p_ev->lock );
02713 vlc_mutex_lock( &p_sys->lock_demuxer );
02714
02715
02716 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
02717
02718 vlc_mutex_unlock( &p_sys->lock_demuxer );
02719 vlc_mutex_lock( &p_ev->lock );
02720 }
02721 break;
02722 default:
02723 break;
02724 }
02725 p_ev->b_key = VLC_FALSE;
02726 vlc_mutex_unlock( &p_ev->lock );
02727 }
02728
02729
02730 if( p_vout && ( p_ev->b_moved || p_ev->b_clicked ) )
02731 {
02732 vlc_value_t valx, valy;
02733
02734 vlc_mutex_lock( &p_ev->lock );
02735 pci_t *pci = (pci_t *) &p_sys->pci_packet;
02736 var_Get( p_vout, "mouse-x", &valx );
02737 var_Get( p_vout, "mouse-y", &valy );
02738
02739 if( p_ev->b_clicked )
02740 {
02741 int32_t button;
02742 int32_t best,dist,d;
02743 int32_t mx,my,dx,dy;
02744
02745 msg_Dbg( p_ev->p_demux, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", (unsigned)valx.i_int, (unsigned)valy.i_int);
02746
02747 b_activated = VLC_TRUE;
02748
02749 best = 0;
02750 dist = 0x08000000;
02751 for(button = 1; button <= pci->hli.hl_gi.btn_ns; button++)
02752 {
02753 btni_t *button_ptr = &(pci->hli.btnit[button-1]);
02754
02755 if(((unsigned)valx.i_int >= button_ptr->x_start)
02756 && ((unsigned)valx.i_int <= button_ptr->x_end)
02757 && ((unsigned)valy.i_int >= button_ptr->y_start)
02758 && ((unsigned)valy.i_int <= button_ptr->y_end))
02759 {
02760 mx = (button_ptr->x_start + button_ptr->x_end)/2;
02761 my = (button_ptr->y_start + button_ptr->y_end)/2;
02762 dx = mx - valx.i_int;
02763 dy = my - valy.i_int;
02764 d = (dx*dx) + (dy*dy);
02765
02766
02767 if(d < dist) {
02768 dist = d;
02769 best = button;
02770 }
02771 }
02772 }
02773
02774 if ( best != 0)
02775 {
02776 btni_t button_ptr = pci->hli.btnit[best-1];
02777 uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );
02778
02779 msg_Dbg( &p_sys->demuxer, "Clicked button %d", best );
02780 vlc_mutex_unlock( &p_ev->lock );
02781 vlc_mutex_lock( &p_sys->lock_demuxer );
02782
02783
02784 p_sys->dvd_interpretor.SetSPRM( 0x88, best );
02785 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
02786
02787 msg_Dbg( &p_sys->demuxer, "Processed button %d", best );
02788
02789
02790 if ( best != i_curr_button )
02791 {
02792 vlc_value_t val;
02793
02794 if( var_Get( p_sys->p_input, "highlight-mutex", &val ) == VLC_SUCCESS )
02795 {
02796 vlc_mutex_t *p_mutex = (vlc_mutex_t *) val.p_address;
02797 uint32_t i_palette;
02798
02799 if(button_ptr.btn_coln != 0) {
02800 i_palette = pci->hli.btn_colit.btn_coli[button_ptr.btn_coln-1][1];
02801 } else {
02802 i_palette = 0;
02803 }
02804
02805 for( int i = 0; i < 4; i++ )
02806 {
02807 uint32_t i_yuv = 0xFF;
02808 uint8_t i_alpha = (i_palette>>(i*4))&0x0f;
02809 i_alpha = i_alpha == 0xf ? 0xff : i_alpha << 4;
02810
02811 p_sys->palette[i][0] = (i_yuv >> 16) & 0xff;
02812 p_sys->palette[i][1] = (i_yuv >> 0) & 0xff;
02813 p_sys->palette[i][2] = (i_yuv >> 8) & 0xff;
02814 p_sys->palette[i][3] = i_alpha;
02815 }
02816
02817 vlc_mutex_lock( p_mutex );
02818 val.i_int = button_ptr.x_start; var_Set( p_sys->p_input, "x-start", val );
02819 val.i_int = button_ptr.x_end; var_Set( p_sys->p_input, "x-end", val );
02820 val.i_int = button_ptr.y_start; var_Set( p_sys->p_input, "y-start", val );
02821 val.i_int = button_ptr.y_end; var_Set( p_sys->p_input, "y-end", val );
02822
02823 val.p_address = (void *)p_sys->palette;
02824 var_Set( p_sys->p_input, "menu-palette", val );
02825
02826 val.b_bool = VLC_TRUE; var_Set( p_sys->p_input, "highlight", val );
02827 vlc_mutex_unlock( p_mutex );
02828 }
02829 }
02830 vlc_mutex_unlock( &p_sys->lock_demuxer );
02831 vlc_mutex_lock( &p_ev->lock );
02832 }
02833 }
02834 else if( p_ev->b_moved )
02835 {
02836
02837 }
02838
02839 p_ev->b_moved = VLC_FALSE;
02840 p_ev->b_clicked = VLC_FALSE;
02841 vlc_mutex_unlock( &p_ev->lock );
02842 }
02843
02844
02845 if( p_vout && p_vout->b_die )
02846 {
02847 var_DelCallback( p_vout, "mouse-moved", EventMouse, p_ev );
02848 var_DelCallback( p_vout, "mouse-clicked", EventMouse, p_ev );
02849 vlc_object_release( p_vout );
02850 p_vout = NULL;
02851 }
02852
02853 else if( p_vout == NULL )
02854 {
02855 p_vout = (vlc_object_t*) vlc_object_find( p_sys->p_input, VLC_OBJECT_VOUT,
02856 FIND_CHILD );
02857 if( p_vout)
02858 {
02859 var_AddCallback( p_vout, "mouse-moved", EventMouse, p_ev );
02860 var_AddCallback( p_vout, "mouse-clicked", EventMouse, p_ev );
02861 }
02862 }
02863
02864
02865 msleep( 10000 );
02866 }
02867
02868
02869 if( p_vout )
02870 {
02871 var_DelCallback( p_vout, "mouse-moved", EventMouse, p_ev );
02872 var_DelCallback( p_vout, "mouse-clicked", EventMouse, p_ev );
02873 vlc_object_release( p_vout );
02874 }
02875 var_DelCallback( p_ev->p_vlc, "key-pressed", EventKey, p_ev );
02876
02877 vlc_mutex_destroy( &p_ev->lock );
02878
02879 return VLC_SUCCESS;
02880 }
02881
02882 void matroska_segment_c::UnSelect( )
02883 {
02884 size_t i_track;
02885
02886 for( i_track = 0; i_track < tracks.size(); i_track++ )
02887 {
02888 if ( tracks[i_track]->p_es != NULL )
02889 {
02890
02891 es_out_Del( sys.demuxer.out, tracks[i_track]->p_es );
02892 tracks[i_track]->p_es = NULL;
02893 }
02894 }
02895 delete ep;
02896 ep = NULL;
02897 }
02898
02899 void virtual_segment_c::PrepareChapters( )
02900 {
02901 if ( linked_segments.size() == 0 )
02902 return;
02903
02904
02905 matroska_segment_c *p_segment;
02906 size_t i, j;
02907
02908
02909 p_segment = linked_segments[0];
02910 p_editions = &p_segment->stored_editions;
02911
02912 for ( i=1 ; i<linked_segments.size(); i++ )
02913 {
02914 p_segment = linked_segments[i];
02915
02916 for (j=0; j<p_segment->stored_editions.size(); j++)
02917 (*p_editions)[j]->Append( *p_segment->stored_editions[j] );
02918 }
02919 }
02920
02921 std::string chapter_edition_c::GetMainName() const
02922 {
02923 if ( sub_chapters.size() )
02924 {
02925 return sub_chapters[0]->GetCodecName( true );
02926 }
02927 return "";
02928 }
02929
02930 int chapter_item_c::PublishChapters( input_title_t & title, int & i_user_chapters, int i_level )
02931 {
02932
02933 if ( !b_display_seekpoint || psz_name == "" )
02934 {
02935 psz_name = GetCodecName();
02936 if ( psz_name != "" )
02937 b_display_seekpoint = true;
02938 }
02939
02940 if (b_display_seekpoint)
02941 {
02942 seekpoint_t *sk = vlc_seekpoint_New();
02943
02944 sk->i_level = i_level;
02945 sk->i_time_offset = i_start_time;
02946 sk->psz_name = strdup( psz_name.c_str() );
02947
02948
02949 title.i_seekpoint++;
02950 title.seekpoint = (seekpoint_t**)realloc( title.seekpoint, title.i_seekpoint * sizeof( seekpoint_t* ) );
02951 title.seekpoint[title.i_seekpoint-1] = sk;
02952
02953 if ( b_user_display )
02954 i_user_chapters++;
02955 }
02956
02957 for ( size_t i=0; i<sub_chapters.size() ; i++)
02958 {
02959 sub_chapters[i]->PublishChapters( title, i_user_chapters, i_level+1 );
02960 }
02961
02962 i_seekpoint_num = i_user_chapters;
02963
02964 return i_user_chapters;
02965 }
02966
02967 bool virtual_segment_c::UpdateCurrentToChapter( demux_t & demux )
02968 {
02969 demux_sys_t & sys = *demux.p_sys;
02970 chapter_item_c *psz_curr_chapter;
02971 bool b_has_seeked = false;
02972
02973
02974 if ( p_editions->size() )
02975 {
02976
02977 psz_curr_chapter = (*p_editions)[i_current_edition]->FindTimecode( sys.i_pts, psz_current_chapter );
02978
02979
02980 if (psz_curr_chapter != NULL && psz_current_chapter != psz_curr_chapter)
02981 {
02982 if ( (*p_editions)[i_current_edition]->b_ordered )
02983 {
02984
02985 b_has_seeked = psz_curr_chapter->EnterAndLeave( psz_current_chapter );
02986 if ( !b_has_seeked )
02987 {
02988
02989 if ( psz_current_chapter == NULL || (psz_current_chapter->i_end_time != psz_curr_chapter->i_start_time) )
02990 Seek( demux, sys.i_pts, 0, psz_curr_chapter );
02991 }
02992 }
02993
02994 if ( !b_has_seeked )
02995 {
02996 psz_current_chapter = psz_curr_chapter;
02997 if ( psz_curr_chapter->i_seekpoint_num > 0 )
02998 {
02999 demux.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
03000 demux.info.i_title = sys.i_current_title = i_sys_title;
03001 demux.info.i_seekpoint = psz_curr_chapter->i_seekpoint_num - 1;
03002 }
03003 }
03004
03005 return true;
03006 }
03007 else if (psz_curr_chapter == NULL)
03008 {
03009
03010 if ( (*p_editions)[i_current_edition]->b_ordered && psz_current_chapter != NULL )
03011 {
03012 if ( !(*p_editions)[i_current_edition]->EnterAndLeave( psz_current_chapter, false ) )
03013 psz_current_chapter = NULL;
03014 else
03015 return true;
03016 }
03017 }
03018 }
03019 return false;
03020 }
03021
03022 chapter_item_c *virtual_segment_c::BrowseCodecPrivate( unsigned int codec_id,
03023 bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
03024 const void *p_cookie,
03025 size_t i_cookie_size )
03026 {
03027
03028 std::vector<chapter_edition_c*>::iterator index = p_editions->begin();
03029 if ( index != p_editions->end() )
03030 {
03031 chapter_item_c *p_result = (*index)->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
03032 if ( p_result != NULL )
03033 return p_result;
03034 }
03035 return NULL;
03036 }
03037
03038 chapter_item_c *virtual_segment_c::FindChapter( int64_t i_find_uid )
03039 {
03040
03041 std::vector<chapter_edition_c*>::iterator index = p_editions->begin();
03042 if ( index != p_editions->end() )
03043 {
03044 chapter_item_c *p_result = (*index)->FindChapter( i_find_uid );
03045 if ( p_result != NULL )
03046 return p_result;
03047 }
03048 return NULL;
03049 }
03050
03051 chapter_item_c *chapter_item_c::BrowseCodecPrivate( unsigned int codec_id,
03052 bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
03053 const void *p_cookie,
03054 size_t i_cookie_size )
03055 {
03056
03057 std::vector<chapter_codec_cmds_c*>::const_iterator index = codecs.begin();
03058 while ( index != codecs.end() )
03059 {
03060 if ( match( **index ,p_cookie, i_cookie_size ) )
03061 return this;
03062 index++;
03063 }
03064
03065
03066 chapter_item_c *p_result = NULL;
03067 std::vector<chapter_item_c*>::const_iterator index2 = sub_chapters.begin();
03068 while ( index2 != sub_chapters.end() )
03069 {
03070 p_result = (*index2)->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
03071 if ( p_result != NULL )
03072 return p_result;
03073 index2++;
03074 }
03075
03076 return p_result;
03077 }
03078
03079 void chapter_item_c::Append( const chapter_item_c & chapter )
03080 {
03081
03082 size_t i;
03083 chapter_item_c *p_chapter;
03084
03085 for ( i=0; i<chapter.sub_chapters.size(); i++ )
03086 {
03087 p_chapter = FindChapter( chapter.sub_chapters[i]->i_uid );
03088 if ( p_chapter != NULL )
03089 {
03090 p_chapter->Append( *chapter.sub_chapters[i] );
03091 }
03092 else
03093 {
03094 sub_chapters.push_back( chapter.sub_chapters[i] );
03095 }
03096 }
03097
03098 i_user_start_time = min( i_user_start_time, chapter.i_user_start_time );
03099 i_user_end_time = max( i_user_end_time, chapter.i_user_end_time );
03100 }
03101
03102 chapter_item_c * chapter_item_c::FindChapter( int64_t i_find_uid )
03103 {
03104 size_t i;
03105 chapter_item_c *p_result = NULL;
03106
03107 if ( i_uid == i_find_uid )
03108 return this;
03109
03110 for ( i=0; i<sub_chapters.size(); i++)
03111 {
03112 p_result = sub_chapters[i]->FindChapter( i_find_uid );
03113 if ( p_result != NULL )
03114 break;
03115 }
03116 return p_result;
03117 }
03118
03119 std::string chapter_item_c::GetCodecName( bool f_for_title ) const
03120 {
03121 std::string result;
03122
03123 std::vector<chapter_codec_cmds_c*>::const_iterator index = codecs.begin();
03124 while ( index != codecs.end() )
03125 {
03126 result = (*index)->GetCodecName( f_for_title );
03127 if ( result != "" )
03128 break;
03129 index++;
03130 }
03131
03132 return result;
03133 }
03134
03135 std::string dvd_chapter_codec_c::GetCodecName( bool f_for_title ) const
03136 {
03137 std::string result;
03138 if ( p_private_data->GetSize() >= 3)
03139 {
03140 const binary* p_data = p_private_data->GetBuffer();
03141
03142
03143
03144
03145
03146
03147
03148
03149 if ( p_data[0] == MATROSKA_DVD_LEVEL_LU )
03150 {
03151 char psz_str[11];
03152 sprintf( psz_str, " (%c%c) ---", p_data[1], p_data[2] );
03153 result = N_("--- DVD Menu");
03154 result += psz_str;
03155 }
03156 else if ( p_data[0] == MATROSKA_DVD_LEVEL_SS && f_for_title )
03157 {
03158 if ( p_data[1] == 0x00 )
03159 result = N_("First Played");
03160 else if ( p_data[1] == 0xC0 )
03161 result = N_("Video Manager");
03162 else if ( p_data[1] == 0x80 )
03163 {
03164 uint16_t i_title = (p_data[2] << 8) + p_data[3];
03165 char psz_str[20];
03166 sprintf( psz_str, " %d -----", i_title );
03167 result = N_("----- Title");
03168 result += psz_str;
03169 }
03170 }
03171 }
03172
03173 return result;
03174 }
03175
03176 int16 chapter_item_c::GetTitleNumber( ) const
03177 {
03178 int result = -1;
03179
03180 std::vector<chapter_codec_cmds_c*>::const_iterator index = codecs.begin();
03181 while ( index != codecs.end() )
03182 {
03183 result = (*index)->GetTitleNumber( );
03184 if ( result >= 0 )
03185 break;
03186 index++;
03187 }
03188
03189 return result;
03190 }
03191
03192 int16 dvd_chapter_codec_c::GetTitleNumber()
03193 {
03194 if ( p_private_data->GetSize() >= 3)
03195 {
03196 const binary* p_data = p_private_data->GetBuffer();
03197 if ( p_data[0] == MATROSKA_DVD_LEVEL_SS )
03198 {
03199 return int16( (p_data[2] << 8) + p_data[3] );
03200 }
03201 }
03202 return -1;
03203 }
03204
03205 static void Seek( demux_t *p_demux, mtime_t i_date, double f_percent, chapter_item_c *psz_chapter )
03206 {
03207 demux_sys_t *p_sys = p_demux->p_sys;
03208 virtual_segment_c *p_vsegment = p_sys->p_current_segment;
03209 matroska_segment_c *p_segment = p_vsegment->Segment();
03210 mtime_t i_time_offset = 0;
03211
03212 int i_index;
03213
03214 msg_Dbg( p_demux, "seek request to "I64Fd" (%f%%)", i_date, f_percent );
03215 if( i_date < 0 && f_percent < 0 )
03216 {
03217 msg_Warn( p_demux, "cannot seek nowhere !" );
03218 return;
03219 }
03220 if( f_percent > 1.0 )
03221 {
03222 msg_Warn( p_demux, "cannot seek so far !" );
03223 return;
03224 }
03225
03226
03227 if( f_percent >= 0 && (config_GetInt( p_demux, "mkv-seek-percent" ) || !p_segment->b_cues || i_date < 0 ))
03228 {
03229 if (p_sys->f_duration >= 0)
03230 {
03231 i_date = int64_t( f_percent * p_sys->f_duration * 1000.0 );
03232 }
03233 else
03234 {
03235 int64_t i_pos = int64_t( f_percent * stream_Size( p_demux->s ) );
03236
03237 msg_Dbg( p_demux, "inacurate way of seeking" );
03238 for( i_index = 0; i_index < p_segment->i_index; i_index++ )
03239 {
03240 if( p_segment->p_indexes[i_index].i_position >= i_pos)
03241 {
03242 break;
03243 }
03244 }
03245 if( i_index == p_segment->i_index )
03246 {
03247 i_index--;
03248 }
03249
03250 i_date = p_segment->p_indexes[i_index].i_time;
03251
03252 #if 0
03253 if( p_segment->p_indexes[i_index].i_position < i_pos )
03254 {
03255 EbmlElement *el;
03256
03257 msg_Warn( p_demux, "searching for cluster, could take some time" );
03258
03259
03260 while( ( el = p_sys->ep->Get() ) != NULL )
03261 {
03262 if( MKV_IS_ID( el, KaxCluster ) )
03263 {
03264 KaxCluster *cluster = (KaxCluster*)el;
03265
03266
03267 p_segment->IndexAppendCluster( cluster );
03268
03269 if( (int64_t)cluster->GetElementPosition() >= i_pos )
03270 {
03271 p_sys->cluster = cluster;
03272 p_sys->ep->Down();
03273 break;
03274 }
03275 }
03276 }
03277 }
03278 #endif
03279 }
03280 }
03281
03282 p_vsegment->Seek( *p_demux, i_date, i_time_offset, psz_chapter );
03283 }
03284
03285
03286
03287
03288
03289
03290 static int Demux( demux_t *p_demux)
03291 {
03292 demux_sys_t *p_sys = p_demux->p_sys;
03293
03294 vlc_mutex_lock( &p_sys->lock_demuxer );
03295
03296 virtual_segment_c *p_vsegment = p_sys->p_current_segment;
03297 matroska_segment_c *p_segment = p_vsegment->Segment();
03298 if ( p_segment == NULL ) return 0;
03299 int i_block_count = 0;
03300 int i_return = 0;
03301
03302 for( ;; )
03303 {
03304 if ( p_sys->demuxer.b_die )
03305 break;
03306
03307 if( p_sys->i_pts >= p_sys->i_start_pts )
03308 if ( p_vsegment->UpdateCurrentToChapter( *p_demux ) )
03309 {
03310 i_return = 1;
03311 break;
03312 }
03313
03314 if ( p_vsegment->Edition() && p_vsegment->Edition()->b_ordered && p_vsegment->CurrentChapter() == NULL )
03315 {
03316
03317 if ( !p_vsegment->SelectNext() )
03318 break;
03319 p_segment->UnSelect( );
03320
03321 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
03322
03323
03324 p_segment = p_vsegment->Segment();
03325 if ( !p_segment->Select( 0 ) )
03326 {
03327 msg_Err( p_demux, "Failed to select new segment" );
03328 break;
03329 }
03330 continue;
03331 }
03332
03333 KaxBlock *block;
03334 int64_t i_block_duration = 0;
03335 int64_t i_block_ref1;
03336 int64_t i_block_ref2;
03337
03338 #if LIBMATROSKA_VERSION >= 0x000800
03339 KaxSimpleBlock *simpleblock;
03340
03341 if( p_segment->BlockGet( block, simpleblock, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
03342 #else
03343 if( p_segment->BlockGet( block, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
03344 #endif
03345 {
03346 if ( p_vsegment->Edition() && p_vsegment->Edition()->b_ordered )
03347 {
03348 const chapter_item_c *p_chap = p_vsegment->CurrentChapter();
03349
03350 if ( p_chap != NULL )
03351 {
03352
03353
03354
03355
03356 p_sys->i_pts = p_chap->i_user_end_time;
03357 p_sys->i_pts++;
03358
03359 i_return = 1;
03360 }
03361
03362 break;
03363 }
03364 else
03365 {
03366 msg_Warn( p_demux, "cannot get block EOF?" );
03367 p_segment->UnSelect( );
03368
03369 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
03370
03371
03372 if ( !p_vsegment->SelectNext() )
03373
03374 break;
03375 p_segment = p_vsegment->Segment();
03376 if ( !p_segment->Select( 0 ) )
03377 {
03378 msg_Err( p_demux, "Failed to select new segment" );
03379 break;
03380 }
03381
03382 continue;
03383 }
03384 }
03385
03386 #if LIBMATROSKA_VERSION >= 0x000800
03387 if ( simpleblock != NULL )
03388 p_sys->i_pts = (p_sys->i_chapter_time + simpleblock->GlobalTimecode()) / (mtime_t) 1000;
03389 else
03390 #endif
03391 p_sys->i_pts = (p_sys->i_chapter_time + block->GlobalTimecode()) / (mtime_t) 1000;
03392
03393 if( p_sys->i_pts >= p_sys->i_start_pts )
03394 {
03395 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pts );
03396
03397 if ( p_vsegment->UpdateCurrentToChapter( *p_demux ) )
03398 {
03399 i_return = 1;
03400 delete block;
03401 break;
03402 }
03403 }
03404
03405 if ( p_vsegment->Edition() && p_vsegment->Edition()->b_ordered && p_vsegment->CurrentChapter() == NULL )
03406 {
03407
03408 if ( !p_vsegment->SelectNext() )
03409 {
03410 delete block;
03411 break;
03412 }
03413 p_segment->UnSelect( );
03414
03415 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
03416
03417
03418 p_segment = p_vsegment->Segment();
03419 if ( !p_segment->Select( 0 ) )
03420 {
03421 msg_Err( p_demux, "Failed to select new segment" );
03422 delete block;
03423 break;
03424 }
03425 delete block;
03426 continue;
03427 }
03428
03429 #if LIBMATROSKA_VERSION >= 0x000800
03430 BlockDecode( p_demux, block, simpleblock, p_sys->i_pts, i_block_duration, i_block_ref1 >= 0 || i_block_ref2 > 0 );
03431 #else
03432 BlockDecode( p_demux, block, p_sys->i_pts, i_block_duration, i_block_ref1 >= 0 || i_block_ref2 > 0 );
03433 #endif
03434
03435 delete block;
03436 i_block_count++;
03437
03438
03439 if( i_block_count > 5 )
03440 {
03441 i_return = 1;
03442 break;
03443 }
03444 }
03445
03446 vlc_mutex_unlock( &p_sys->lock_demuxer );
03447
03448 return i_return;
03449 }
03450
03451
03452
03453
03454
03455
03456 vlc_stream_io_callback::vlc_stream_io_callback( stream_t *s_, vlc_bool_t b_owner_ )
03457 {
03458 s = s_;
03459 b_owner = b_owner_;
03460 mb_eof = VLC_FALSE;
03461 }
03462
03463 uint32 vlc_stream_io_callback::read( void *p_buffer, size_t i_size )
03464 {
03465 if( i_size <= 0 || mb_eof )
03466 {
03467 return 0;
03468 }
03469
03470 return stream_Read( s, p_buffer, i_size );
03471 }
03472 void vlc_stream_io_callback::setFilePointer(int64_t i_offset, seek_mode mode )
03473 {
03474 int64_t i_pos;
03475
03476 switch( mode )
03477 {
03478 case seek_beginning:
03479 i_pos = i_offset;
03480 break;
03481 case seek_end:
03482 i_pos = stream_Size( s ) - i_offset;
03483 break;
03484 default:
03485 i_pos= stream_Tell( s ) + i_offset;
03486 break;
03487 }
03488
03489 if( i_pos < 0 || i_pos >= stream_Size( s ) )
03490 {
03491 mb_eof = VLC_TRUE;
03492 return;
03493 }
03494
03495 mb_eof = VLC_FALSE;
03496 if( stream_Seek( s, i_pos ) )
03497 {
03498 mb_eof = VLC_TRUE;
03499 }
03500 return;
03501 }
03502 size_t vlc_stream_io_callback::write( const void *p_buffer, size_t i_size )
03503 {
03504 return 0;
03505 }
03506 uint64 vlc_stream_io_callback::getFilePointer( void )
03507 {
03508 if ( s == NULL )
03509 return 0;
03510 return stream_Tell( s );
03511 }
03512 void vlc_stream_io_callback::close( void )
03513 {
03514 return;
03515 }
03516
03517
03518
03519
03520
03521 EbmlParser::EbmlParser( EbmlStream *es, EbmlElement *el_start, demux_t *p_demux )
03522 {
03523 int i;
03524
03525 m_es = es;
03526 m_got = NULL;
03527 m_el[0] = el_start;
03528 mi_remain_size[0] = el_start->GetSize();
03529
03530 for( i = 1; i < 6; i++ )
03531 {
03532 m_el[i] = NULL;
03533 }
03534 mi_level = 1;
03535 mi_user_level = 1;
03536 mb_keep = VLC_FALSE;
03537 mb_dummy = config_GetInt( p_demux, "mkv-use-dummy" );
03538 }
03539
03540 EbmlParser::~EbmlParser( void )
03541 {
03542 int i;
03543
03544 for( i = 1; i < mi_level; i++ )
03545 {
03546 if( !mb_keep )
03547 {
03548 delete m_el[i];
03549 }
03550 mb_keep = VLC_FALSE;
03551 }
03552 }
03553
03554 EbmlElement* EbmlParser::UnGet( uint64 i_block_pos, uint64 i_cluster_pos )
03555 {
03556 if ( mi_user_level > mi_level )
03557 {
03558 while ( mi_user_level != mi_level )
03559 {
03560 delete m_el[mi_user_level];
03561 m_el[mi_user_level] = NULL;
03562 mi_user_level--;
03563 }
03564 }
03565 m_got = NULL;
03566 mb_keep = VLC_FALSE;
03567 if ( m_el[1]->GetElementPosition() == i_cluster_pos )
03568 {
03569 m_es->I_O().setFilePointer( i_block_pos, seek_beginning );
03570 return (EbmlMaster*) m_el[1];
03571 }
03572 else
03573 {
03574
03575 m_es->I_O().setFilePointer( i_cluster_pos, seek_beginning );
03576 mi_level--;
03577 mi_user_level--;
03578 delete m_el[mi_level];
03579 m_el[mi_level] = NULL;
03580 return NULL;
03581 }
03582 }
03583
03584 void EbmlParser::Up( void )
03585 {
03586 if( mi_user_level == mi_level )
03587 {
03588 fprintf( stderr," arrrrrrrrrrrrrg Up cannot escape itself\n" );
03589 }
03590
03591 mi_user_level--;
03592 }
03593
03594 void EbmlParser::Down( void )
03595 {
03596 mi_user_level++;
03597 mi_level++;
03598 }
03599
03600 void EbmlParser::Keep( void )
03601 {
03602 mb_keep = VLC_TRUE;
03603 }
03604
03605 int EbmlParser::GetLevel( void )
03606 {
03607 return mi_user_level;
03608 }
03609
03610 void EbmlParser::Reset( demux_t *p_demux )
03611 {
03612 while ( mi_level > 0)
03613 {
03614 delete m_el[mi_level];
03615 m_el[mi_level] = NULL;
03616 mi_level--;
03617 }
03618 mi_user_level = mi_level = 1;
03619 #if LIBEBML_VERSION >= 0x000704
03620
03621 m_es->I_O().setFilePointer( static_cast<KaxSegment*>(m_el[0])->GetGlobalPosition(0) );
03622 #else
03623 m_es->I_O().setFilePointer( m_el[0]->GetElementPosition() + m_el[0]->ElementSize(true) - m_el[0]->GetSize() );
03624 #endif
03625 mb_dummy = config_GetInt( p_demux, "mkv-use-dummy" );
03626 }
03627
03628 EbmlElement *EbmlParser::Get( void )
03629 {
03630 int i_ulev = 0;
03631
03632 if( mi_user_level != mi_level )
03633 {
03634 return NULL;
03635 }
03636 if( m_got )
03637 {
03638 EbmlElement *ret = m_got;
03639 m_got = NULL;
03640
03641 return ret;
03642 }
03643
03644 if( m_el[mi_level] )
03645 {
03646 m_el[mi_level]->SkipData( *m_es, m_el[mi_level]->Generic().Context );
03647 if( !mb_keep )
03648 {
03649 delete m_el[mi_level];
03650 }
03651 mb_keep = VLC_FALSE;
03652 }
03653
03654 m_el[mi_level] = m_es->FindNextElement( m_el[mi_level - 1]->Generic().Context, i_ulev, 0xFFFFFFFFL, mb_dummy != 0, 1 );
03655
03656 if( i_ulev > 0 )
03657 {
03658 while( i_ulev > 0 )
03659 {
03660 if( mi_level == 1 )
03661 {
03662 mi_level = 0;
03663 return NULL;
03664 }
03665
03666 delete m_el[mi_level - 1];
03667 m_got = m_el[mi_level -1] = m_el[mi_level];
03668 m_el[mi_level] = NULL;
03669
03670 mi_level--;
03671 i_ulev--;
03672 }
03673 return NULL;
03674 }
03675 else if( m_el[mi_level] == NULL )
03676 {
03677 fprintf( stderr," m_el[mi_level] == NULL\n" );
03678 }
03679
03680 return m_el[mi_level];
03681 }
03682
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693 void matroska_segment_c::LoadCues( )
03694 {
03695 int64_t i_sav_position = es.I_O().getFilePointer();
03696 EbmlParser *ep;
03697 EbmlElement *el, *cues;
03698
03699
03700 if( i_cues_position < 0 )
03701 {
03702 msg_Warn( &sys.demuxer, "no cues/empty cues found->seek won't be precise" );
03703
03704
03705 }
03706
03707 vlc_bool_t b_seekable;
03708
03709 stream_Control( sys.demuxer.s, STREAM_CAN_FASTSEEK, &b_seekable );
03710 if( !b_seekable )
03711 return;
03712
03713 msg_Dbg( &sys.demuxer, "loading cues" );
03714 es.I_O().setFilePointer( i_cues_position, seek_beginning );
03715 cues = es.FindNextID( KaxCues::ClassInfos, 0xFFFFFFFFL);
03716
03717 if( cues == NULL )
03718 {
03719 msg_Err( &sys.demuxer, "cannot load cues (broken seekhead or file)" );
03720 es.I_O().setFilePointer( i_sav_position, seek_beginning );
03721 return;
03722 }
03723
03724 ep = new EbmlParser( &es, cues, &sys.demuxer );
03725 while( ( el = ep->Get() ) != NULL )
03726 {
03727 if( MKV_IS_ID( el, KaxCuePoint ) )
03728 {
03729 #define idx p_indexes[i_index]
03730
03731 idx.i_track = -1;
03732 idx.i_block_number= -1;
03733 idx.i_position = -1;
03734 idx.i_time = 0;
03735 idx.b_key = VLC_TRUE;
03736
03737 ep->Down();
03738 while( ( el = ep->Get() ) != NULL )
03739 {
03740 if( MKV_IS_ID( el, KaxCueTime ) )
03741 {
03742 KaxCueTime &ctime = *(KaxCueTime*)el;
03743
03744 ctime.ReadData( es.I_O() );
03745
03746 idx.i_time = uint64( ctime ) * i_timescale / (mtime_t)1000;
03747 }
03748 else if( MKV_IS_ID( el, KaxCueTrackPositions ) )
03749 {
03750 ep->Down();
03751 while( ( el = ep->Get() ) != NULL )
03752 {
03753 if( MKV_IS_ID( el, KaxCueTrack ) )
03754 {
03755 KaxCueTrack &ctrack = *(KaxCueTrack*)el;
03756
03757 ctrack.ReadData( es.I_O() );
03758 idx.i_track = uint16( ctrack );
03759 }
03760 else if( MKV_IS_ID( el, KaxCueClusterPosition ) )
03761 {
03762 KaxCueClusterPosition &ccpos = *(KaxCueClusterPosition*)el;
03763
03764 ccpos.ReadData( es.I_O() );
03765 idx.i_position = segment->GetGlobalPosition( uint64( ccpos ) );
03766 }
03767 else if( MKV_IS_ID( el, KaxCueBlockNumber ) )
03768 {
03769 KaxCueBlockNumber &cbnum = *(KaxCueBlockNumber*)el;
03770
03771 cbnum.ReadData( es.I_O() );
03772 idx.i_block_number = uint32( cbnum );
03773 }
03774 else
03775 {
03776 msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() );
03777 }
03778 }
03779 ep->Up();
03780 }
03781 else
03782 {
03783 msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() );
03784 }
03785 }
03786 ep->Up();
03787
03788 #if 0
03789 msg_Dbg( &sys.demuxer, " * added time="I64Fd" pos="I64Fd
03790 " track=%d bnum=%d", idx.i_time, idx.i_position,
03791 idx.i_track, idx.i_block_number );
03792 #endif
03793
03794 i_index++;
03795 if( i_index >= i_index_max )
03796 {
03797 i_index_max += 1024;
03798 p_indexes = (mkv_index_t*)realloc( p_indexes, sizeof( mkv_index_t ) * i_index_max );
03799 }
03800 #undef idx
03801 }
03802 else
03803 {
03804 msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() );
03805 }
03806 }
03807 delete ep;
03808 delete cues;
03809
03810 b_cues = VLC_TRUE;
03811
03812 msg_Dbg( &sys.demuxer, "loading cues done." );
03813 es.I_O().setFilePointer( i_sav_position, seek_beginning );
03814 }
03815
03816 void matroska_segment_c::LoadTags( )
03817 {
03818 int64_t i_sav_position = es.I_O().getFilePointer();
03819 EbmlParser *ep;
03820 EbmlElement *el, *tags;
03821
03822 msg_Dbg( &sys.demuxer, "loading tags" );
03823 es.I_O().setFilePointer( i_tags_position, seek_beginning );
03824 tags = es.FindNextID( KaxTags::ClassInfos, 0xFFFFFFFFL);
03825
03826 if( tags == NULL )
03827 {
03828 msg_Err( &sys.demuxer, "cannot load tags (broken seekhead or file)" );
03829 es.I_O().setFilePointer( i_sav_position, seek_beginning );
03830 return;
03831 }
03832
03833 msg_Dbg( &sys.demuxer, "Tags" );
03834 ep = new EbmlParser( &es, tags, &sys.demuxer );
03835 while( ( el = ep->Get() ) != NULL )
03836 {
03837 if( MKV_IS_ID( el, KaxTag ) )
03838 {
03839 msg_Dbg( &sys.demuxer, "+ Tag" );
03840 ep->Down();
03841 while( ( el = ep->Get() ) != NULL )
03842 {
03843 if( MKV_IS_ID( el, KaxTagTargets ) )
03844 {
03845 msg_Dbg( &sys.demuxer, "| + Targets" );
03846 ep->Down();
03847 while( ( el = ep->Get() ) != NULL )
03848 {
03849 msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid( *el ).name() );
03850 }
03851 ep->Up();
03852 }
03853 else if( MKV_IS_ID( el, KaxTagGeneral ) )
03854 {
03855 msg_Dbg( &sys.demuxer, "| + General" );
03856 ep->Down();
03857 while( ( el = ep->Get() ) != NULL )
03858 {
03859 msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid( *el ).name() );
03860 }
03861 ep->Up();
03862 }
03863 else if( MKV_IS_ID( el, KaxTagGenres ) )
03864 {
03865 msg_Dbg( &sys.demuxer, "| + Genres" );
03866 ep->Down();
03867 while( ( el = ep->Get() ) != NULL )
03868 {
03869 msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid( *el ).name() );
03870 }
03871 ep->Up();
03872 }
03873 else if( MKV_IS_ID( el, KaxTagAudioSpecific ) )
03874 {
03875 msg_Dbg( &sys.demuxer, "| + Audio Specific" );
03876 ep->Down();
03877 while( ( el = ep->Get() ) != NULL )
03878 {
03879 msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid( *el ).name() );
03880 }
03881 ep->Up();
03882 }
03883 else if( MKV_IS_ID( el, KaxTagImageSpecific ) )
03884 {
03885 msg_Dbg( &sys.demuxer, "| + Images Specific" );
03886 ep->Down();
03887 while( ( el = ep->Get() ) != NULL )
03888 {
03889 msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid( *el ).name() );
03890 }
03891 ep->Up();
03892 }
03893 else if( MKV_IS_ID( el, KaxTagMultiComment ) )
03894 {
03895 msg_Dbg( &sys.demuxer, "| + Multi Comment" );
03896 }
03897 else if( MKV_IS_ID( el, KaxTagMultiCommercial ) )
03898 {
03899 msg_Dbg( &sys.demuxer, "| + Multi Commercial" );
03900 }
03901 else if( MKV_IS_ID( el, KaxTagMultiDate ) )
03902 {
03903 msg_Dbg( &sys.demuxer, "| + Multi Date" );
03904 }
03905 else if( MKV_IS_ID( el, KaxTagMultiEntity ) )
03906 {
03907 msg_Dbg( &sys.demuxer, "| + Multi Entity" );
03908 }
03909 else if( MKV_IS_ID( el, KaxTagMultiIdentifier ) )
03910 {
03911 msg_Dbg( &sys.demuxer, "| + Multi Identifier" );
03912 }
03913 else if( MKV_IS_ID( el, KaxTagMultiLegal ) )
03914 {
03915 msg_Dbg( &sys.demuxer, "| + Multi Legal" );
03916 }
03917 else if( MKV_IS_ID( el, KaxTagMultiTitle ) )
03918 {
03919 msg_Dbg( &sys.demuxer, "| + Multi Title" );
03920 }
03921 else
03922 {
03923 msg_Dbg( &sys.demuxer, "| + Unknown (%s)", typeid( *el ).name() );
03924 }
03925 }
03926 ep->Up();
03927 }
03928 else
03929 {
03930 msg_Dbg( &sys.demuxer, "+ Unknown (%s)", typeid( *el ).name() );
03931 }
03932 }
03933 delete ep;
03934 delete tags;
03935
03936 msg_Dbg( &sys.demuxer, "loading tags done." );
03937 es.I_O().setFilePointer( i_sav_position, seek_beginning );
03938 }
03939
03940
03941
03942
03943 void matroska_segment_c::ParseSeekHead( KaxSeekHead *seekhead )
03944 {
03945 EbmlElement *el;
03946 size_t i, j;
03947 int i_upper_level = 0;
03948
03949 msg_Dbg( &sys.demuxer, "| + Seek head" );
03950
03951
03952 seekhead->Read( es, seekhead->Generic().Context, i_upper_level, el, true );
03953
03954 for( i = 0; i < seekhead->ListSize(); i++ )
03955 {
03956 EbmlElement *l = (*seekhead)[i];
03957
03958 if( MKV_IS_ID( l, KaxSeek ) )
03959 {
03960 EbmlMaster *sk = static_cast<EbmlMaster *>(l);
03961 EbmlId id = EbmlVoid::ClassInfos.GlobalId;
03962 int64_t i_pos = -1;
03963
03964 for( j = 0; j < sk->ListSize(); j++ )
03965 {
03966 EbmlElement *l = (*sk)[j];
03967
03968 if( MKV_IS_ID( l, KaxSeekID ) )
03969 {
03970 KaxSeekID &sid = *(KaxSeekID*)l;
03971 id = EbmlId( sid.GetBuffer(), sid.GetSize() );
03972 }
03973 else if( MKV_IS_ID( l, KaxSeekPosition ) )
03974 {
03975 KaxSeekPosition &spos = *(KaxSeekPosition*)l;
03976 i_pos = uint64( spos );
03977 }
03978 else
03979 {
03980 msg_Dbg( &sys.demuxer, "| | | + Unknown (%s)", typeid(*l).name() );
03981 }
03982 }
03983
03984 if( i_pos >= 0 )
03985 {
03986 if( id == KaxCues::ClassInfos.GlobalId )
03987 {
03988 msg_Dbg( &sys.demuxer, "| | | = cues at "I64Fd, i_pos );
03989 i_cues_position = segment->GetGlobalPosition( i_pos );
03990 }
03991 else if( id == KaxChapters::ClassInfos.GlobalId )
03992 {
03993 msg_Dbg( &sys.demuxer, "| | | = chapters at "I64Fd, i_pos );
03994 i_chapters_position = segment->GetGlobalPosition( i_pos );
03995 }
03996 else if( id == KaxTags::ClassInfos.GlobalId )
03997 {
03998 msg_Dbg( &sys.demuxer, "| | | = tags at "I64Fd, i_pos );
03999 i_tags_position = segment->GetGlobalPosition( i_pos );
04000 }
04001 }
04002 }
04003 else
04004 {
04005 msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid(*l).name() );
04006 }
04007 }
04008 }
04009
04010
04011
04012
04013 void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
04014 {
04015 size_t i, j, k, n;
04016 bool bSupported = true;
04017
04018 mkv_track_t *tk;
04019
04020 msg_Dbg( &sys.demuxer, "| | + Track Entry" );
04021
04022 tk = new mkv_track_t();
04023
04024
04025 memset( tk, 0, sizeof( mkv_track_t ) );
04026
04027 es_format_Init( &tk->fmt, UNKNOWN_ES, 0 );
04028 tk->fmt.psz_language = strdup("English");
04029 tk->fmt.psz_description = NULL;
04030
04031 tk->b_default = VLC_TRUE;
04032 tk->b_enabled = VLC_TRUE;
04033 tk->b_silent = VLC_FALSE;
04034 tk->i_number = tracks.size() - 1;
04035 tk->i_extra_data = 0;
04036 tk->p_extra_data = NULL;
04037 tk->psz_codec = NULL;
04038 tk->i_default_duration = 0;
04039 tk->f_timecodescale = 1.0;
04040
04041 tk->b_inited = VLC_FALSE;
04042 tk->i_data_init = 0;
04043 tk->p_data_init = NULL;
04044
04045 tk->psz_codec_name = NULL;
04046 tk->psz_codec_settings = NULL;
04047 tk->psz_codec_info_url = NULL;
04048 tk->psz_codec_download_url = NULL;
04049
04050 tk->i_compression_type = MATROSKA_COMPRESSION_NONE;
04051 tk->p_compression_data = NULL;
04052
04053 for( i = 0; i < m->ListSize(); i++ )
04054 {
04055 EbmlElement *l = (*m)[i];
04056
04057 if( MKV_IS_ID( l, KaxTrackNumber ) )
04058 {
04059 KaxTrackNumber &tnum = *(KaxTrackNumber*)l;
04060
04061 tk->i_number = uint32( tnum );
04062 msg_Dbg( &sys.demuxer, "| | | + Track Number=%u", uint32( tnum ) );
04063 }
04064 else if( MKV_IS_ID( l, KaxTrackUID ) )
04065 {
04066 KaxTrackUID &tuid = *(KaxTrackUID*)l;
04067
04068 msg_Dbg( &sys.demuxer, "| | | + Track UID=%u", uint32( tuid ) );
04069 }
04070 else if( MKV_IS_ID( l, KaxTrackType ) )
04071 {
04072 char *psz_type;
04073 KaxTrackType &ttype = *(KaxTrackType*)l;
04074
04075 switch( uint8(ttype) )
04076 {
04077 case track_audio:
04078 psz_type = "audio";
04079 tk->fmt.i_cat = AUDIO_ES;
04080 break;
04081 case track_video:
04082 psz_type = "video";
04083 tk->fmt.i_cat = VIDEO_ES;
04084 break;
04085 case track_subtitle:
04086 psz_type = "subtitle";
04087 tk->fmt.i_cat = SPU_ES;
04088 break;
04089 case track_buttons:
04090 psz_type = "buttons";
04091 tk->fmt.i_cat = SPU_ES;
04092 break;
04093 default:
04094 psz_type = "unknown";
04095 tk->fmt.i_cat = UNKNOWN_ES;
04096 break;
04097 }
04098
04099 msg_Dbg( &sys.demuxer, "| | | + Track Type=%s", psz_type );
04100 }
04101
04102
04103
04104
04105
04106
04107
04108
04109 else if( MKV_IS_ID( l, KaxTrackFlagDefault ) )
04110 {
04111 KaxTrackFlagDefault &fdef = *(KaxTrackFlagDefault*)l;
04112
04113 tk->b_default = uint32( fdef );
04114 msg_Dbg( &sys.demuxer, "| | | + Track Default=%u", uint32( fdef ) );
04115 }
04116 else if( MKV_IS_ID( l, KaxTrackFlagLacing ) )
04117 {
04118 KaxTrackFlagLacing &lac = *(KaxTrackFlagLacing*)l;
04119
04120 msg_Dbg( &sys.demuxer, "| | | + Track Lacing=%d", uint32( lac ) );
04121 }
04122 else if( MKV_IS_ID( l, KaxTrackMinCache ) )
04123 {
04124 KaxTrackMinCache &cmin = *(KaxTrackMinCache*)l;
04125
04126 msg_Dbg( &sys.demuxer, "| | | + Track MinCache=%d", uint32( cmin ) );
04127 }
04128 else if( MKV_IS_ID( l, KaxTrackMaxCache ) )
04129 {
04130 KaxTrackMaxCache &cmax = *(KaxTrackMaxCache*)l;
04131
04132 msg_Dbg( &sys.demuxer, "| | | + Track MaxCache=%d", uint32( cmax ) );
04133 }
04134 else if( MKV_IS_ID( l, KaxTrackDefaultDuration ) )
04135 {
04136 KaxTrackDefaultDuration &defd = *(KaxTrackDefaultDuration*)l;
04137
04138 tk->i_default_duration = uint64(defd);
04139 msg_Dbg( &sys.demuxer, "| | | + Track Default Duration="I64Fd, uint64(defd) );
04140 }
04141 else if( MKV_IS_ID( l, KaxTrackTimecodeScale ) )
04142 {
04143 KaxTrackTimecodeScale &ttcs = *(KaxTrackTimecodeScale*)l;
04144
04145 tk->f_timecodescale = float( ttcs );
04146 msg_Dbg( &sys.demuxer, "| | | + Track TimeCodeScale=%f", tk->f_timecodescale );
04147 }
04148 else if( MKV_IS_ID( l, KaxTrackName ) )
04149 {
04150 KaxTrackName &tname = *(KaxTrackName*)l;
04151
04152 tk->fmt.psz_description = ToUTF8( UTFstring( tname ) );
04153 msg_Dbg( &sys.demuxer, "| | | + Track Name=%s", tk->fmt.psz_description );
04154 }
04155 else if( MKV_IS_ID( l, KaxTrackLanguage ) )
04156 {
04157 KaxTrackLanguage &lang = *(KaxTrackLanguage*)l;
04158
04159 if ( tk->fmt.psz_language != NULL )
04160 free( tk->fmt.psz_language );
04161 tk->fmt.psz_language = strdup( string( lang ).c_str() );
04162 msg_Dbg( &sys.demuxer,
04163 "| | | + Track Language=`%s'", tk->fmt.psz_language );
04164 }
04165 else if( MKV_IS_ID( l, KaxCodecID ) )
04166 {
04167 KaxCodecID &codecid = *(KaxCodecID*)l;
04168
04169 tk->psz_codec = strdup( string( codecid ).c_str() );
04170 msg_Dbg( &sys.demuxer, "| | | + Track CodecId=%s", string( codecid ).c_str() );
04171 }
04172 else if( MKV_IS_ID( l, KaxCodecPrivate ) )
04173 {
04174 KaxCodecPrivate &cpriv = *(KaxCodecPrivate*)l;
04175
04176 tk->i_extra_data = cpriv.GetSize();
04177 if( tk->i_extra_data > 0 )
04178 {
04179 tk->p_extra_data = (uint8_t*)malloc( tk->i_extra_data );
04180 memcpy( tk->p_extra_data, cpriv.GetBuffer(), tk->i_extra_data );
04181 }
04182 msg_Dbg( &sys.demuxer, "| | | + Track CodecPrivate size="I64Fd, cpriv.GetSize() );
04183 }
04184 else if( MKV_IS_ID( l, KaxCodecName ) )
04185 {
04186 KaxCodecName &cname = *(KaxCodecName*)l;
04187
04188 tk->psz_codec_name = ToUTF8( UTFstring( cname ) );
04189 msg_Dbg( &sys.demuxer, "| | | + Track Codec Name=%s", tk->psz_codec_name );
04190 }
04191 else if( MKV_IS_ID( l, KaxContentEncodings ) )
04192 {
04193 EbmlMaster *cencs = static_cast<EbmlMaster*>(l);
04194 MkvTree( sys.demuxer, 3, "Content Encodings" );
04195 if ( cencs->ListSize() > 1 )
04196 {
04197 msg_Err( &sys.demuxer, "Multiple Compression method not supported" );
04198 bSupported = false;
04199 }
04200 for( j = 0; j < cencs->ListSize(); j++ )
04201 {
04202 EbmlElement *l2 = (*cencs)[j];
04203 if( MKV_IS_ID( l2, KaxContentEncoding ) )
04204 {
04205 MkvTree( sys.demuxer, 4, "Content Encoding" );
04206 EbmlMaster *cenc = static_cast<EbmlMaster*>(l2);
04207 for( k = 0; k < cenc->ListSize(); k++ )
04208 {
04209 EbmlElement *l3 = (*cenc)[k];
04210 if( MKV_IS_ID( l3, KaxContentEncodingOrder ) )
04211 {
04212 KaxContentEncodingOrder &encord = *(KaxContentEncodingOrder*)l3;
04213 MkvTree( sys.demuxer, 5, "Order: %i", uint32( encord ) );
04214 }
04215 else if( MKV_IS_ID( l3, KaxContentEncodingScope ) )
04216 {
04217 KaxContentEncodingScope &encscope = *(KaxContentEncodingScope*)l3;
04218 MkvTree( sys.demuxer, 5, "Scope: %i", uint32( encscope ) );
04219 }
04220 else if( MKV_IS_ID( l3, KaxContentEncodingType ) )
04221 {
04222 KaxContentEncodingType &enctype = *(KaxContentEncodingType*)l3;
04223 MkvTree( sys.demuxer, 5, "Type: %i", uint32( enctype ) );
04224 }
04225 else if( MKV_IS_ID( l3, KaxContentCompression ) )
04226 {
04227 EbmlMaster *compr = static_cast<EbmlMaster*>(l3);
04228 MkvTree( sys.demuxer, 5, "Content Compression" );
04229 for( n = 0; n < compr->ListSize(); n++ )
04230 {
04231 EbmlElement *l4 = (*compr)[n];
04232 if( MKV_IS_ID( l4, KaxContentCompAlgo ) )
04233 {
04234 KaxContentCompAlgo &compalg = *(KaxContentCompAlgo*)l4;
04235 MkvTree( sys.demuxer, 6, "Compression Algorithm: %i", uint32(compalg) );
04236 tk->i_compression_type = uint32( compalg );
04237 if ( ( tk->i_compression_type != MATROSKA_COMPRESSION_ZLIB ) &&
04238 ( tk->i_compression_type != MATROSKA_COMPRESSION_HEADER ) )
04239 {
04240 msg_Err( &sys.demuxer, "Track Compression method %d not supported", tk->i_compression_type );
04241 bSupported = false;
04242 }
04243 }
04244 else if( MKV_IS_ID( l4, KaxContentCompSettings ) )
04245 {
04246 tk->p_compression_data = new KaxContentCompSettings( *(KaxContentCompSettings*)l4 );
04247 }
04248 else
04249 {
04250 MkvTree( sys.demuxer, 6, "Unknown (%s)", typeid(*l4).name() );
04251 }
04252 }
04253 }
04254
04255 else
04256 {
04257 MkvTree( sys.demuxer, 5, "Unknown (%s)", typeid(*l3).name() );
04258 }
04259 }
04260
04261 }
04262 else
04263 {
04264 MkvTree( sys.demuxer, 4, "Unknown (%s)", typeid(*l2).name() );
04265 }
04266 }
04267
04268 }
04269
04270
04271
04272
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302 else if( MKV_IS_ID( l, KaxTrackVideo ) )
04303 {
04304 EbmlMaster *tkv = static_cast<EbmlMaster*>(l);
04305 unsigned int j;
04306
04307 msg_Dbg( &sys.demuxer, "| | | + Track Video" );
04308 tk->f_fps = 0.0;
04309
04310 tk->fmt.video.i_frame_rate_base = (unsigned int)(tk->i_default_duration / 1000);
04311 tk->fmt.video.i_frame_rate = 1000000;
04312
04313 for( j = 0; j < tkv->ListSize(); j++ )
04314 {
04315 EbmlElement *l = (*tkv)[j];
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329 if( MKV_IS_ID( l, KaxVideoPixelWidth ) )
04330 {
04331 KaxVideoPixelWidth &vwidth = *(KaxVideoPixelWidth*)l;
04332
04333 tk->fmt.video.i_width += uint16( vwidth );
04334 msg_Dbg( &sys.demuxer, "| | | | + width=%d", uint16( vwidth ) );
04335 }
04336 else if( MKV_IS_ID( l, KaxVideoPixelHeight ) )
04337 {
04338 KaxVideoPixelWidth &vheight = *(KaxVideoPixelWidth*)l;
04339
04340 tk->fmt.video.i_height += uint16( vheight );
04341 msg_Dbg( &sys.demuxer, "| | | | + height=%d", uint16( vheight ) );
04342 }
04343 else if( MKV_IS_ID( l, KaxVideoDisplayWidth ) )
04344 {
04345 KaxVideoDisplayWidth &vwidth = *(KaxVideoDisplayWidth*)l;
04346
04347 tk->fmt.video.i_visible_width = uint16( vwidth );
04348 msg_Dbg( &sys.demuxer, "| | | | + display width=%d", uint16( vwidth ) );
04349 }
04350 else if( MKV_IS_ID( l, KaxVideoDisplayHeight ) )
04351 {
04352 KaxVideoDisplayWidth &vheight = *(KaxVideoDisplayWidth*)l;
04353
04354 tk->fmt.video.i_visible_height = uint16( vheight );
04355 msg_Dbg( &sys.demuxer, "| | | | + display height=%d", uint16( vheight ) );
04356 }
04357 else if( MKV_IS_ID( l, KaxVideoPixelCropBottom ) )
04358 {
04359 KaxVideoPixelCropBottom &cropval = *(KaxVideoPixelCropBottom*)l;
04360
04361 tk->fmt.video.i_height -= uint16( cropval );
04362 msg_Dbg( &sys.demuxer, "| | | | + crop pixel bottom=%d", uint16( cropval ) );
04363 }
04364 else if( MKV_IS_ID( l, KaxVideoPixelCropTop ) )
04365 {
04366 KaxVideoPixelCropTop &cropval = *(KaxVideoPixelCropTop*)l;
04367
04368 tk->fmt.video.i_height -= uint16( cropval );
04369 tk->fmt.video.i_y_offset += uint16( cropval );
04370 msg_Dbg( &sys.demuxer, "| | | | + crop pixel top=%d", uint16( cropval ) );
04371 }
04372 else if( MKV_IS_ID( l, KaxVideoPixelCropRight ) )
04373 {
04374 KaxVideoPixelCropRight &cropval = *(KaxVideoPixelCropRight*)l;
04375
04376 tk->fmt.video.i_width -= uint16( cropval );
04377 msg_Dbg( &sys.demuxer, "| | | | + crop pixel right=%d", uint16( cropval ) );
04378 }
04379 else if( MKV_IS_ID( l, KaxVideoPixelCropLeft ) )
04380 {
04381 KaxVideoPixelCropLeft &cropval = *(KaxVideoPixelCropLeft*)l;
04382
04383 tk->fmt.video.i_width -= uint16( cropval );
04384 tk->fmt.video.i_x_offset += uint16( cropval );
04385 msg_Dbg( &sys.demuxer, "| | | | + crop pixel left=%d", uint16( cropval ) );
04386 }
04387 else if( MKV_IS_ID( l, KaxVideoFrameRate ) )
04388 {
04389 KaxVideoFrameRate &vfps = *(KaxVideoFrameRate*)l;
04390
04391 tk->f_fps = float( vfps );
04392 msg_Dbg( &sys.demuxer, " | | | + fps=%f", float( vfps ) );
04393 }
04394
04395
04396
04397
04398
04399
04400
04401
04402
04403
04404
04405
04406
04407
04408
04409
04410
04411
04412
04413 else
04414 {
04415 msg_Dbg( &sys.demuxer, "| | | | + Unknown (%s)", typeid(*l).name() );
04416 }
04417 }
04418 if ( tk->fmt.video.i_visible_height && tk->fmt.video.i_visible_width )
04419 tk->fmt.video.i_aspect = VOUT_ASPECT_FACTOR * tk->fmt.video.i_visible_width / tk->fmt.video.i_visible_height;
04420 }
04421 else if( MKV_IS_ID( l, KaxTrackAudio ) )
04422 {
04423 EbmlMaster *tka = static_cast<EbmlMaster*>(l);
04424 unsigned int j;
04425
04426 msg_Dbg( &sys.demuxer, "| | | + Track Audio" );
04427
04428 for( j = 0; j < tka->ListSize(); j++ )
04429 {
04430 EbmlElement *l = (*tka)[j];
04431
04432 if( MKV_IS_ID( l, KaxAudioSamplingFreq ) )
04433 {
04434 KaxAudioSamplingFreq &afreq = *(KaxAudioSamplingFreq*)l;
04435
04436 tk->i_original_rate = tk->fmt.audio.i_rate = (int)float( afreq );
04437 msg_Dbg( &sys.demuxer, "| | | | + afreq=%d", tk->fmt.audio.i_rate );
04438 }
04439 else if( MKV_IS_ID( l, KaxAudioOutputSamplingFreq ) )
04440 {
04441 KaxAudioOutputSamplingFreq &afreq = *(KaxAudioOutputSamplingFreq*)l;
04442
04443 tk->fmt.audio.i_rate = (int)float( afreq );
04444 msg_Dbg( &sys.demuxer, "| | | | + aoutfreq=%d", tk->fmt.audio.i_rate );
04445 }
04446 else if( MKV_IS_ID( l, KaxAudioChannels ) )
04447 {
04448 KaxAudioChannels &achan = *(KaxAudioChannels*)l;
04449
04450 tk->fmt.audio.i_channels = uint8( achan );
04451 msg_Dbg( &sys.demuxer, "| | | | + achan=%u", uint8( achan ) );
04452 }
04453 else if( MKV_IS_ID( l, KaxAudioBitDepth ) )
04454 {
04455 KaxAudioBitDepth &abits = *(KaxAudioBitDepth*)l;
04456
04457 tk->fmt.audio.i_bitspersample = uint8( abits );
04458 msg_Dbg( &sys.demuxer, "| | | | + abits=%u", uint8( abits ) );
04459 }
04460 else
04461 {
04462 msg_Dbg( &sys.demuxer, "| | | | + Unknown (%s)", typeid(*l).name() );
04463 }
04464 }
04465 }
04466 else
04467 {
04468 msg_Dbg( &sys.demuxer, "| | | + Unknown (%s)",
04469 typeid(*l).name() );
04470 }
04471 }
04472
04473 if ( bSupported )
04474 {
04475 tracks.push_back( tk );
04476 }
04477 else
04478 {
04479 msg_Err( &sys.demuxer, "Track Entry %d not supported", tk->i_number );
04480 delete tk;
04481 }
04482 }
04483
04484
04485
04486
04487 void matroska_segment_c::ParseTracks( KaxTracks *tracks )
04488 {
04489 EbmlElement *el;
04490 unsigned int i;
04491 int i_upper_level = 0;
04492
04493 msg_Dbg( &sys.demuxer, "| + Tracks" );
04494
04495
04496 tracks->Read( es, tracks->Generic().Context, i_upper_level, el, true );
04497
04498 for( i = 0; i < tracks->ListSize(); i++ )
04499 {
04500 EbmlElement *l = (*tracks)[i];
04501
04502 if( MKV_IS_ID( l, KaxTrackEntry ) )
04503 {
04504 ParseTrackEntry( static_cast<KaxTrackEntry *>(l) );
04505 }
04506 else
04507 {
04508 msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid(*l).name() );
04509 }
04510 }
04511 }
04512
04513
04514
04515
04516 void matroska_segment_c::ParseInfo( KaxInfo *info )
04517 {
04518 EbmlElement *el;
04519 EbmlMaster *m;
04520 size_t i, j;
04521 int i_upper_level = 0;
04522
04523 msg_Dbg( &sys.demuxer, "| + Information" );
04524
04525
04526 m = static_cast<EbmlMaster *>(info);
04527 m->Read( es, info->Generic().Context, i_upper_level, el, true );
04528
04529 for( i = 0; i < m->ListSize(); i++ )
04530 {
04531 EbmlElement *l = (*m)[i];
04532
04533 if( MKV_IS_ID( l, KaxSegmentUID ) )
04534 {
04535 if ( p_segment_uid == NULL )
04536 p_segment_uid = new KaxSegmentUID(*static_cast<KaxSegmentUID*>(l));
04537
04538 msg_Dbg( &sys.demuxer, "| | + UID=%d", *(uint32*)p_segment_uid->GetBuffer() );
04539 }
04540 else if( MKV_IS_ID( l, KaxPrevUID ) )
04541 {
04542 if ( p_prev_segment_uid == NULL )
04543 p_prev_segment_uid = new KaxPrevUID(*static_cast<KaxPrevUID*>(l));
04544
04545 msg_Dbg( &sys.demuxer, "| | + PrevUID=%d", *(uint32*)p_prev_segment_uid->GetBuffer() );
04546 }
04547 else if( MKV_IS_ID( l, KaxNextUID ) )
04548 {
04549 if ( p_next_segment_uid == NULL )
04550 p_next_segment_uid = new KaxNextUID(*static_cast<KaxNextUID*>(l));
04551
04552 msg_Dbg( &sys.demuxer, "| | + NextUID=%d", *(uint32*)p_next_segment_uid->GetBuffer() );
04553 }
04554 else if( MKV_IS_ID( l, KaxTimecodeScale ) )
04555 {
04556 KaxTimecodeScale &tcs = *(KaxTimecodeScale*)l;
04557
04558 i_timescale = uint64(tcs);
04559
04560 msg_Dbg( &sys.demuxer, "| | + TimecodeScale="I64Fd,
04561 i_timescale );
04562 }
04563 else if( MKV_IS_ID( l, KaxDuration ) )
04564 {
04565 KaxDuration &dur = *(KaxDuration*)l;
04566
04567 i_duration = mtime_t( double( dur ) );
04568
04569 msg_Dbg( &sys.demuxer, "| | + Duration="I64Fd,
04570 i_duration );
04571 }
04572 else if( MKV_IS_ID( l, KaxMuxingApp ) )
04573 {
04574 KaxMuxingApp &mapp = *(KaxMuxingApp*)l;
04575
04576 psz_muxing_application = ToUTF8( UTFstring( mapp ) );
04577
04578 msg_Dbg( &sys.demuxer, "| | + Muxing Application=%s",
04579 psz_muxing_application );
04580 }
04581 else if( MKV_IS_ID( l, KaxWritingApp ) )
04582 {
04583 KaxWritingApp &wapp = *(KaxWritingApp*)l;
04584
04585 psz_writing_application = ToUTF8( UTFstring( wapp ) );
04586
04587 msg_Dbg( &sys.demuxer, "| | + Writing Application=%s",
04588 psz_writing_application );
04589 }
04590 else if( MKV_IS_ID( l, KaxSegmentFilename ) )
04591 {
04592 KaxSegmentFilename &sfn = *(KaxSegmentFilename*)l;
04593
04594 psz_segment_filename = ToUTF8( UTFstring( sfn ) );
04595
04596 msg_Dbg( &sys.demuxer, "| | + Segment Filename=%s",
04597 psz_segment_filename );
04598 }
04599 else if( MKV_IS_ID( l, KaxTitle ) )
04600 {
04601 KaxTitle &title = *(KaxTitle*)l;
04602
04603 psz_title = ToUTF8( UTFstring( title ) );
04604
04605 msg_Dbg( &sys.demuxer, "| | + Title=%s", psz_title );
04606 }
04607 else if( MKV_IS_ID( l, KaxSegmentFamily ) )
04608 {
04609 KaxSegmentFamily *uid = static_cast<KaxSegmentFamily*>(l);
04610
04611 families.push_back( new KaxSegmentFamily(*uid) );
04612
04613 msg_Dbg( &sys.demuxer, "| | + family=%d", *(uint32*)uid->GetBuffer() );
04614 }
04615 #if defined( HAVE_GMTIME_R ) && !defined( SYS_DARWIN )
04616 else if( MKV_IS_ID( l, KaxDateUTC ) )
04617 {
04618 KaxDateUTC &date = *(KaxDateUTC*)l;
04619 time_t i_date;
04620 struct tm tmres;
04621 char buffer[256];
04622
04623 i_date = date.GetEpochDate();
04624 memset( buffer, 0, 256 );
04625 if( gmtime_r( &i_date, &tmres ) &&
04626 asctime_r( &tmres, buffer ) )
04627 {
04628 buffer[strlen( buffer)-1]= '\0';
04629 psz_date_utc = strdup( buffer );
04630 msg_Dbg( &sys.demuxer, "| | + Date=%s", psz_date_utc );
04631 }
04632 }
04633 #endif
04634 #if LIBMATROSKA_VERSION >= 0x000704
04635 else if( MKV_IS_ID( l, KaxChapterTranslate ) )
04636 {
04637 KaxChapterTranslate *p_trans = static_cast<KaxChapterTranslate*>( l );
04638 chapter_translation_c *p_translate = new chapter_translation_c();
04639
04640 p_trans->Read( es, p_trans->Generic().Context, i_upper_level, el, true );
04641 for( j = 0; j < p_trans->ListSize(); j++ )
04642 {
04643 EbmlElement *l = (*p_trans)[j];
04644
04645 if( MKV_IS_ID( l, KaxChapterTranslateEditionUID ) )
04646 {
04647 p_translate->editions.push_back( uint64( *static_cast<KaxChapterTranslateEditionUID*>( l ) ) );
04648 }
04649 else if( MKV_IS_ID( l, KaxChapterTranslateCodec ) )
04650 {
04651 p_translate->codec_id = uint32( *static_cast<KaxChapterTranslateCodec*>( l ) );
04652 }
04653 else if( MKV_IS_ID( l, KaxChapterTranslateID ) )
04654 {
04655 p_translate->p_translated = new KaxChapterTranslateID( *static_cast<KaxChapterTranslateID*>( l ) );
04656 }
04657 }
04658
04659 translations.push_back( p_translate );
04660 }
04661 #endif
04662 else
04663 {
04664 msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid(*l).name() );
04665 }
04666 }
04667
04668 double f_dur = double(i_duration) * double(i_timescale) / 1000000.0;
04669 i_duration = mtime_t(f_dur);
04670 }
04671
04672
04673
04674
04675
04676 void matroska_segment_c::ParseChapterAtom( int i_level, KaxChapterAtom *ca, chapter_item_c & chapters )
04677 {
04678 size_t i, j;
04679
04680 msg_Dbg( &sys.demuxer, "| | | + ChapterAtom (level=%d)", i_level );
04681 for( i = 0; i < ca->ListSize(); i++ )
04682 {
04683 EbmlElement *l = (*ca)[i];
04684
04685 if( MKV_IS_ID( l, KaxChapterUID ) )
04686 {
04687 chapters.i_uid = uint64_t(*(KaxChapterUID*)l);
04688 msg_Dbg( &sys.demuxer, "| | | | + ChapterUID: %lld", chapters.i_uid );
04689 }
04690 else if( MKV_IS_ID( l, KaxChapterFlagHidden ) )
04691 {
04692 KaxChapterFlagHidden &flag =*(KaxChapterFlagHidden*)l;
04693 chapters.b_display_seekpoint = uint8( flag ) == 0;
04694
04695 msg_Dbg( &sys.demuxer, "| | | | + ChapterFlagHidden: %s", chapters.b_display_seekpoint ? "no":"yes" );
04696 }
04697 else if( MKV_IS_ID( l, KaxChapterTimeStart ) )
04698 {
04699 KaxChapterTimeStart &start =*(KaxChapterTimeStart*)l;
04700 chapters.i_start_time = uint64( start ) / I64C(1000);
04701
04702 msg_Dbg( &sys.demuxer, "| | | | + ChapterTimeStart: %lld", chapters.i_start_time );
04703 }
04704 else if( MKV_IS_ID( l, KaxChapterTimeEnd ) )
04705 {
04706 KaxChapterTimeEnd &end =*(KaxChapterTimeEnd*)l;
04707 chapters.i_end_time = uint64( end ) / I64C(1000);
04708
04709 msg_Dbg( &sys.demuxer, "| | | | + ChapterTimeEnd: %lld", chapters.i_end_time );
04710 }
04711 else if( MKV_IS_ID( l, KaxChapterDisplay ) )
04712 {
04713 EbmlMaster *cd = static_cast<EbmlMaster *>(l);
04714
04715 msg_Dbg( &sys.demuxer, "| | | | + ChapterDisplay" );
04716 for( j = 0; j < cd->ListSize(); j++ )
04717 {
04718 EbmlElement *l= (*cd)[j];
04719
04720 if( MKV_IS_ID( l, KaxChapterString ) )
04721 {
04722 int k;
04723
04724 KaxChapterString &name =*(KaxChapterString*)l;
04725 for (k = 0; k < i_level; k++)
04726 chapters.psz_name += '+';
04727 chapters.psz_name += ' ';
04728 char *psz_tmp_utf8 = ToUTF8( UTFstring( name ) );
04729 chapters.psz_name += psz_tmp_utf8;
04730 chapters.b_user_display = true;
04731
04732 msg_Dbg( &sys.demuxer, "| | | | | + ChapterString '%s'", psz_tmp_utf8 );
04733 free( psz_tmp_utf8 );
04734 }
04735 else if( MKV_IS_ID( l, KaxChapterLanguage ) )
04736 {
04737 KaxChapterLanguage &lang =*(KaxChapterLanguage*)l;
04738 const char *psz = string( lang ).c_str();
04739
04740 msg_Dbg( &sys.demuxer, "| | | | | + ChapterLanguage '%s'", psz );
04741 }
04742 else if( MKV_IS_ID( l, KaxChapterCountry ) )
04743 {
04744 KaxChapterCountry &ct =*(KaxChapterCountry*)l;
04745 const char *psz = string( ct ).c_str();
04746
04747 msg_Dbg( &sys.demuxer, "| | | | | + ChapterCountry '%s'", psz );
04748 }
04749 }
04750 }
04751 else if( MKV_IS_ID( l, KaxChapterProcess ) )
04752 {
04753 msg_Dbg( &sys.demuxer, "| | | | + ChapterProcess" );
04754
04755 KaxChapterProcess *cp = static_cast<KaxChapterProcess *>(l);
04756 chapter_codec_cmds_c *p_ccodec = NULL;
04757
04758 for( j = 0; j < cp->ListSize(); j++ )
04759 {
04760 EbmlElement *k= (*cp)[j];
04761
04762 if( MKV_IS_ID( k, KaxChapterProcessCodecID ) )
04763 {
04764 KaxChapterProcessCodecID *p_codec_id = static_cast<KaxChapterProcessCodecID*>( k );
04765 if ( uint32(*p_codec_id) == 0 )
04766 p_ccodec = new matroska_script_codec_c( sys );
04767 else if ( uint32(*p_codec_id) == 1 )
04768 p_ccodec = new dvd_chapter_codec_c( sys );
04769 break;
04770 }
04771 }
04772
04773 if ( p_ccodec != NULL )
04774 {
04775 for( j = 0; j < cp->ListSize(); j++ )
04776 {
04777 EbmlElement *k= (*cp)[j];
04778
04779 if( MKV_IS_ID( k, KaxChapterProcessPrivate ) )
04780 {
04781 KaxChapterProcessPrivate * p_private = static_cast<KaxChapterProcessPrivate*>( k );
04782 p_ccodec->SetPrivate( *p_private );
04783 }
04784 else if( MKV_IS_ID( k, KaxChapterProcessCommand ) )
04785 {
04786 p_ccodec->AddCommand( *static_cast<KaxChapterProcessCommand*>( k ) );
04787 }
04788 }
04789 chapters.codecs.push_back( p_ccodec );
04790 }
04791 }
04792 else if( MKV_IS_ID( l, KaxChapterAtom ) )
04793 {
04794 chapter_item_c *new_sub_chapter = new chapter_item_c();
04795 ParseChapterAtom( i_level+1, static_cast<KaxChapterAtom *>(l), *new_sub_chapter );
04796 new_sub_chapter->psz_parent = &chapters;
04797 chapters.sub_chapters.push_back( new_sub_chapter );
04798 }
04799 }
04800 }
04801
04802
04803
04804
04805 void matroska_segment_c::ParseChapters( KaxChapters *chapters )
04806 {
04807 EbmlElement *el;
04808 size_t i;
04809 int i_upper_level = 0;
04810 mtime_t i_dur;
04811
04812
04813 chapters->Read( es, chapters->Generic().Context, i_upper_level, el, true );
04814
04815 for( i = 0; i < chapters->ListSize(); i++ )
04816 {
04817 EbmlElement *l = (*chapters)[i];
04818
04819 if( MKV_IS_ID( l, KaxEditionEntry ) )
04820 {
04821 chapter_edition_c *p_edition = new chapter_edition_c();
04822
04823 EbmlMaster *E = static_cast<EbmlMaster *>(l );
04824 size_t j;
04825 msg_Dbg( &sys.demuxer, "| | + EditionEntry" );
04826 for( j = 0; j < E->ListSize(); j++ )
04827 {
04828 EbmlElement *l = (*E)[j];
04829
04830 if( MKV_IS_ID( l, KaxChapterAtom ) )
04831 {
04832 chapter_item_c *new_sub_chapter = new chapter_item_c();
04833 ParseChapterAtom( 0, static_cast<KaxChapterAtom *>(l), *new_sub_chapter );
04834 p_edition->sub_chapters.push_back( new_sub_chapter );
04835 }
04836 else if( MKV_IS_ID( l, KaxEditionUID ) )
04837 {
04838 p_edition->i_uid = uint64(*static_cast<KaxEditionUID *>( l ));
04839 }
04840 else if( MKV_IS_ID( l, KaxEditionFlagOrdered ) )
04841 {
04842 p_edition->b_ordered = config_GetInt( &sys.demuxer, "mkv-use-ordered-chapters" ) ? (uint8(*static_cast<KaxEditionFlagOrdered *>( l )) != 0) : 0;
04843 }
04844 else if( MKV_IS_ID( l, KaxEditionFlagDefault ) )
04845 {
04846 if (uint8(*static_cast<KaxEditionFlagDefault *>( l )) != 0)
04847 i_default_edition = stored_editions.size();
04848 }
04849 else
04850 {
04851 msg_Dbg( &sys.demuxer, "| | | + Unknown (%s)", typeid(*l).name() );
04852 }
04853 }
04854 stored_editions.push_back( p_edition );
04855 }
04856 else
04857 {
04858 msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid(*l).name() );
04859 }
04860 }
04861
04862 for( i = 0; i < stored_editions.size(); i++ )
04863 {
04864 stored_editions[i]->RefreshChapters( );
04865 }
04866
04867 if ( stored_editions.size() != 0 && stored_editions[i_default_edition]->b_ordered )
04868 {
04869
04870 i_dur = stored_editions[i_default_edition]->Duration() / I64C(1000);
04871 if (i_dur > 0)
04872 i_duration = i_dur;
04873 }
04874 }
04875
04876 void matroska_segment_c::ParseCluster( )
04877 {
04878 EbmlElement *el;
04879 EbmlMaster *m;
04880 unsigned int i;
04881 int i_upper_level = 0;
04882
04883
04884 m = static_cast<EbmlMaster *>( cluster );
04885 m->Read( es, cluster->Generic().Context, i_upper_level, el, true );
04886
04887 for( i = 0; i < m->ListSize(); i++ )
04888 {
04889 EbmlElement *l = (*m)[i];
04890
04891 if( MKV_IS_ID( l, KaxClusterTimecode ) )
04892 {
04893 KaxClusterTimecode &ctc = *(KaxClusterTimecode*)l;
04894
04895 cluster->InitTimecode( uint64( ctc ), i_timescale );
04896 break;
04897 }
04898 }
04899
04900 i_start_time = cluster->GlobalTimecode() / 1000;
04901 }
04902
04903
04904
04905
04906 void matroska_segment_c::InformationCreate( )
04907 {
04908 size_t i_track;
04909
04910 sys.meta = vlc_meta_New();
04911
04912 if( psz_title )
04913 {
04914 vlc_meta_Add( sys.meta, VLC_META_TITLE, psz_title );
04915 }
04916 if( psz_date_utc )
04917 {
04918 vlc_meta_Add( sys.meta, VLC_META_DATE, psz_date_utc );
04919 }
04920 if( psz_segment_filename )
04921 {
04922 vlc_meta_Add( sys.meta, _("Segment filename"), psz_segment_filename );
04923 }
04924 if( psz_muxing_application )
04925 {
04926 vlc_meta_Add( sys.meta, _("Muxing application"), psz_muxing_application );
04927 }
04928 if( psz_writing_application )
04929 {
04930 vlc_meta_Add( sys.meta, _("Writing application"), psz_writing_application );
04931 }
04932
04933 for( i_track = 0; i_track < tracks.size(); i_track++ )
04934 {
04935 mkv_track_t *tk = tracks[i_track];
04936 vlc_meta_t *mtk = vlc_meta_New();
04937
04938 sys.meta->track = (vlc_meta_t**)realloc( sys.meta->track,
04939 sizeof( vlc_meta_t * ) * ( sys.meta->i_track + 1 ) );
04940 sys.meta->track[sys.meta->i_track++] = mtk;
04941
04942 if( tk->fmt.psz_description )
04943 {
04944 vlc_meta_Add( sys.meta, VLC_META_DESCRIPTION, tk->fmt.psz_description );
04945 }
04946 if( tk->psz_codec_name )
04947 {
04948 vlc_meta_Add( sys.meta, VLC_META_CODEC_NAME, tk->psz_codec_name );
04949 }
04950 if( tk->psz_codec_settings )
04951 {
04952 vlc_meta_Add( sys.meta, VLC_META_SETTING, tk->psz_codec_settings );
04953 }
04954 if( tk->psz_codec_info_url )
04955 {
04956 vlc_meta_Add( sys.meta, VLC_META_CODEC_DESCRIPTION, tk->psz_codec_info_url );
04957 }
04958 if( tk->psz_codec_download_url )
04959 {
04960 vlc_meta_Add( sys.meta, VLC_META_URL, tk->psz_codec_download_url );
04961 }
04962 }
04963
04964 if( i_tags_position >= 0 )
04965 {
04966 vlc_bool_t b_seekable;
04967
04968 stream_Control( sys.demuxer.s, STREAM_CAN_FASTSEEK, &b_seekable );
04969 if( b_seekable )
04970 {
04971 LoadTags( );
04972 }
04973 }
04974 }
04975
04976
04977
04978
04979
04980
04981 void matroska_segment_c::IndexAppendCluster( KaxCluster *cluster )
04982 {
04983 #define idx p_indexes[i_index]
04984 idx.i_track = -1;
04985 idx.i_block_number= -1;
04986 idx.i_position = cluster->GetElementPosition();
04987 idx.i_time = -1;
04988 idx.b_key = VLC_TRUE;
04989
04990 i_index++;
04991 if( i_index >= i_index_max )
04992 {
04993 i_index_max += 1024;
04994 p_indexes = (mkv_index_t*)realloc( p_indexes, sizeof( mkv_index_t ) * i_index_max );
04995 }
04996 #undef idx
04997 }
04998
04999 void chapter_edition_c::RefreshChapters( )
05000 {
05001 chapter_item_c::RefreshChapters( b_ordered, -1 );
05002 b_display_seekpoint = false;
05003 }
05004
05005 int64_t chapter_item_c::RefreshChapters( bool b_ordered, int64_t i_prev_user_time )
05006 {
05007 int64_t i_user_time = i_prev_user_time;
05008
05009
05010 std::vector<chapter_item_c*>::iterator index = sub_chapters.begin();
05011 while ( index != sub_chapters.end() )
05012 {
05013 i_user_time = (*index)->RefreshChapters( b_ordered, i_user_time );
05014 index++;
05015 }
05016
05017 if ( b_ordered )
05018 {
05019
05020 if ( i_prev_user_time == -1 )
05021 {
05022 if ( i_user_time == -1 )
05023 i_user_time = 0;
05024 i_prev_user_time = 0;
05025 }
05026
05027 i_user_start_time = i_prev_user_time;
05028 if ( i_end_time != -1 && i_user_time == i_prev_user_time )
05029 {
05030 i_user_end_time = i_user_start_time - i_start_time + i_end_time;
05031 }
05032 else
05033 {
05034 i_user_end_time = i_user_time;
05035 }
05036 }
05037 else
05038 {
05039 if ( sub_chapters.begin() != sub_chapters.end() )
05040 std::sort( sub_chapters.begin(), sub_chapters.end(), chapter_item_c::CompareTimecode );
05041 i_user_start_time = i_start_time;
05042 if ( i_end_time != -1 )
05043 i_user_end_time = i_end_time;
05044 else if ( i_user_time != -1 )
05045 i_user_end_time = i_user_time;
05046 else
05047 i_user_end_time = i_user_start_time;
05048 }
05049
05050 return i_user_end_time;
05051 }
05052
05053 mtime_t chapter_edition_c::Duration() const
05054 {
05055 mtime_t i_result = 0;
05056
05057 if ( sub_chapters.size() )
05058 {
05059 std::vector<chapter_item_c*>::const_iterator index = sub_chapters.end();
05060 index--;
05061 i_result = (*index)->i_user_end_time;
05062 }
05063
05064 return i_result;
05065 }
05066
05067 chapter_item_c * chapter_edition_c::FindTimecode( mtime_t i_timecode, const chapter_item_c * p_current )
05068 {
05069 if ( !b_ordered )
05070 p_current = NULL;
05071 bool b_found_current = false;
05072 return chapter_item_c::FindTimecode( i_timecode, p_current, b_found_current );
05073 }
05074
05075 chapter_item_c *chapter_item_c::FindTimecode( mtime_t i_user_timecode, const chapter_item_c * p_current, bool & b_found )
05076 {
05077 chapter_item_c *psz_result = NULL;
05078
05079 if ( p_current == this )
05080 b_found = true;
05081
05082 if ( i_user_timecode >= i_user_start_time &&
05083 ( i_user_timecode < i_user_end_time ||
05084 ( i_user_start_time == i_user_end_time && i_user_timecode == i_user_end_time )))
05085 {
05086 std::vector<chapter_item_c*>::iterator index = sub_chapters.begin();
05087 while ( index != sub_chapters.end() && ((p_current == NULL && psz_result == NULL) || (p_current != NULL && (!b_found || psz_result == NULL))))
05088 {
05089 psz_result = (*index)->FindTimecode( i_user_timecode, p_current, b_found );
05090 index++;
05091 }
05092
05093 if ( psz_result == NULL )
05094 psz_result = this;
05095 }
05096
05097 return psz_result;
05098 }
05099
05100 bool chapter_item_c::ParentOf( const chapter_item_c & item ) const
05101 {
05102 if ( &item == this )
05103 return true;
05104
05105 std::vector<chapter_item_c*>::const_iterator index = sub_chapters.begin();
05106 while ( index != sub_chapters.end() )
05107 {
05108 if ( (*index)->ParentOf( item ) )
05109 return true;
05110 index++;
05111 }
05112
05113 return false;
05114 }
05115
05116 void demux_sys_t::PreloadFamily( const matroska_segment_c & of_segment )
05117 {
05118 for (size_t i=0; i<opened_segments.size(); i++)
05119 {
05120 opened_segments[i]->PreloadFamily( of_segment );
05121 }
05122 }
05123 bool matroska_segment_c::PreloadFamily( const matroska_segment_c & of_segment )
05124 {
05125 if ( b_preloaded )
05126 return false;
05127
05128 for (size_t i=0; i<families.size(); i++)
05129 {
05130 for (size_t j=0; j<of_segment.families.size(); j++)
05131 {
05132 if ( *(families[i]) == *(of_segment.families[j]) )
05133 return Preload( );
05134 }
05135 }
05136
05137 return false;
05138 }
05139
05140
05141 void demux_sys_t::PreloadLinked( matroska_segment_c *p_segment )
05142 {
05143 size_t i_preloaded, i, j;
05144 virtual_segment_c *p_seg;
05145
05146 p_current_segment = VirtualFromSegments( p_segment );
05147
05148 used_segments.push_back( p_current_segment );
05149
05150
05151 do {
05152 i_preloaded = 0;
05153 for ( i=0; i< opened_segments.size(); i++ )
05154 {
05155 if ( opened_segments[i]->b_preloaded && !IsUsedSegment( *opened_segments[i] ) )
05156 {
05157 p_seg = VirtualFromSegments( opened_segments[i] );
05158 used_segments.push_back( p_seg );
05159 i_preloaded++;
05160 }
05161 }
05162 } while ( i_preloaded );
05163
05164
05165 for ( i=0; i< used_segments.size(); i++ )
05166 {
05167 p_seg = used_segments[i];
05168 if ( p_seg->p_editions != NULL )
05169 {
05170 std::string sz_name;
05171 input_title_t *p_title = vlc_input_title_New();
05172 p_seg->i_sys_title = i;
05173 int i_chapters;
05174
05175
05176 for ( j=0; j<p_seg->p_editions->size(); j++ )
05177 {
05178 if ( p_title->psz_name == NULL )
05179 {
05180 sz_name = (*p_seg->p_editions)[j]->GetMainName();
05181 if ( sz_name != "" )
05182 p_title->psz_name = strdup( sz_name.c_str() );
05183 }
05184
05185 chapter_edition_c *p_edition = (*p_seg->p_editions)[j];
05186
05187 i_chapters = 0;
05188 p_edition->PublishChapters( *p_title, i_chapters, 0 );
05189 }
05190
05191
05192 if ( p_title->psz_name == NULL )
05193 {
05194 sz_name = N_("Segment ");
05195 char psz_str[6];
05196 sprintf( psz_str, "%d", (int)i );
05197 sz_name += psz_str;
05198 p_title->psz_name = strdup( sz_name.c_str() );
05199 }
05200
05201 titles.push_back( p_title );
05202 }
05203 }
05204
05205
05206 }
05207
05208 bool demux_sys_t::IsUsedSegment( matroska_segment_c &segment ) const
05209 {
05210 for ( size_t i=0; i< used_segments.size(); i++ )
05211 {
05212 if ( used_segments[i]->FindUID( *segment.p_segment_uid ) )
05213 return true;
05214 }
05215 return false;
05216 }
05217
05218 virtual_segment_c *demux_sys_t::VirtualFromSegments( matroska_segment_c *p_segment ) const
05219 {
05220 size_t i_preloaded, i;
05221
05222 virtual_segment_c *p_result = new virtual_segment_c( p_segment );
05223
05224
05225 do {
05226 i_preloaded = 0;
05227 for ( i=0; i< opened_segments.size(); i++ )
05228 {
05229 i_preloaded += p_result->AddSegment( opened_segments[i] );
05230 }
05231 } while ( i_preloaded );
05232
05233 p_result->Sort( );
05234
05235 p_result->PreloadLinked( );
05236
05237 p_result->PrepareChapters( );
05238
05239 return p_result;
05240 }
05241
05242 bool demux_sys_t::PreparePlayback( virtual_segment_c *p_new_segment )
05243 {
05244 if ( p_new_segment != NULL && p_new_segment != p_current_segment )
05245 {
05246 if ( p_current_segment != NULL && p_current_segment->Segment() != NULL )
05247 p_current_segment->Segment()->UnSelect();
05248
05249 p_current_segment = p_new_segment;
05250 i_current_title = p_new_segment->i_sys_title;
05251 }
05252
05253 p_current_segment->LoadCues();
05254 f_duration = p_current_segment->Duration();
05255
05256
05257 p_current_segment->Segment()->InformationCreate( );
05258
05259 p_current_segment->Segment()->Select( 0 );
05260
05261 return true;
05262 }
05263
05264 void demux_sys_t::JumpTo( virtual_segment_c & vsegment, chapter_item_c * p_chapter )
05265 {
05266
05267 if ( &vsegment != p_current_segment )
05268 {
05269 PreparePlayback( &vsegment );
05270 }
05271
05272 if ( p_chapter != NULL )
05273 {
05274 if ( !p_chapter->Enter( true ) )
05275 {
05276
05277 vsegment.Seek( demuxer, p_chapter->i_user_start_time, -1, p_chapter );
05278 }
05279 }
05280
05281 }
05282
05283 bool matroska_segment_c::CompareSegmentUIDs( const matroska_segment_c * p_item_a, const matroska_segment_c * p_item_b )
05284 {
05285 if ( p_item_a == NULL || p_item_b == NULL )
05286 return false;
05287
05288 EbmlBinary * p_itema = (EbmlBinary *)(p_item_a->p_segment_uid);
05289 if ( p_item_b->p_prev_segment_uid != NULL && *p_itema == *p_item_b->p_prev_segment_uid )
05290 return true;
05291
05292 p_itema = (EbmlBinary *)(&p_item_a->p_next_segment_uid);
05293 if ( p_item_b->p_segment_uid != NULL && *p_itema == *p_item_b->p_segment_uid )
05294 return true;
05295
05296 if ( p_item_b->p_prev_segment_uid != NULL && *p_itema == *p_item_b->p_prev_segment_uid )
05297 return true;
05298
05299 return false;
05300 }
05301
05302 bool matroska_segment_c::Preload( )
05303 {
05304 if ( b_preloaded )
05305 return false;
05306
05307 EbmlElement *el = NULL;
05308
05309 ep->Reset( &sys.demuxer );
05310
05311 while( ( el = ep->Get() ) != NULL )
05312 {
05313 if( MKV_IS_ID( el, KaxInfo ) )
05314 {
05315 ParseInfo( static_cast<KaxInfo*>( el ) );
05316 }
05317 else if( MKV_IS_ID( el, KaxTracks ) )
05318 {
05319 ParseTracks( static_cast<KaxTracks*>( el ) );
05320 if ( tracks.size() == 0 )
05321 {
05322 msg_Err( &sys.demuxer, "No tracks supported" );
05323 return false;
05324 }
05325 }
05326 else if( MKV_IS_ID( el, KaxSeekHead ) )
05327 {
05328 ParseSeekHead( static_cast<KaxSeekHead*>( el ) );
05329 }
05330 else if( MKV_IS_ID( el, KaxCues ) )
05331 {
05332 msg_Dbg( &sys.demuxer, "| + Cues" );
05333 }
05334 else if( MKV_IS_ID( el, KaxCluster ) )
05335 {
05336 msg_Dbg( &sys.demuxer, "| + Cluster" );
05337
05338 cluster = (KaxCluster*)el;
05339
05340 i_cluster_pos = i_start_pos = cluster->GetElementPosition();
05341 ParseCluster( );
05342
05343 ep->Down();
05344
05345 break;
05346 }
05347 else if( MKV_IS_ID( el, KaxAttachments ) )
05348 {
05349 msg_Dbg( &sys.demuxer, "| + Attachments FIXME (but probably never supported)" );
05350 }
05351 else if( MKV_IS_ID( el, KaxChapters ) )
05352 {
05353 msg_Dbg( &sys.demuxer, "| + Chapters" );
05354 ParseChapters( static_cast<KaxChapters*>( el ) );
05355 }
05356 else if( MKV_IS_ID( el, KaxTag ) )
05357 {
05358 msg_Dbg( &sys.demuxer, "| + Tags FIXME TODO" );
05359 }
05360 else
05361 {
05362 msg_Dbg( &sys.demuxer, "| + Unknown (%s)", typeid(*el).name() );
05363 }
05364 }
05365
05366 b_preloaded = true;
05367
05368 return true;
05369 }
05370
05371 matroska_segment_c *demux_sys_t::FindSegment( const EbmlBinary & uid ) const
05372 {
05373 for (size_t i=0; i<opened_segments.size(); i++)
05374 {
05375 if ( *opened_segments[i]->p_segment_uid == uid )
05376 return opened_segments[i];
05377 }
05378 return NULL;
05379 }
05380
05381 chapter_item_c *demux_sys_t::BrowseCodecPrivate( unsigned int codec_id,
05382 bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
05383 const void *p_cookie,
05384 size_t i_cookie_size,
05385 virtual_segment_c * &p_segment_found )
05386 {
05387 chapter_item_c *p_result = NULL;
05388 for (size_t i=0; i<used_segments.size(); i++)
05389 {
05390 p_result = used_segments[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
05391 if ( p_result != NULL )
05392 {
05393 p_segment_found = used_segments[i];
05394 break;
05395 }
05396 }
05397 return p_result;
05398 }
05399
05400 chapter_item_c *demux_sys_t::FindChapter( int64_t i_find_uid, virtual_segment_c * & p_segment_found )
05401 {
05402 chapter_item_c *p_result = NULL;
05403 for (size_t i=0; i<used_segments.size(); i++)
05404 {
05405 p_result = used_segments[i]->FindChapter( i_find_uid );
05406 if ( p_result != NULL )
05407 {
05408 p_segment_found = used_segments[i];
05409 break;
05410 }
05411 }
05412 return p_result;
05413 }
05414
05415 void virtual_segment_c::Sort()
05416 {
05417
05418 matroska_segment_c *p_segment = linked_segments[i_current_segment];
05419
05420 std::sort( linked_segments.begin(), linked_segments.end(), matroska_segment_c::CompareSegmentUIDs );
05421
05422 for ( i_current_segment=0; i_current_segment<linked_segments.size(); i_current_segment++)
05423 if ( linked_segments[i_current_segment] == p_segment )
05424 break;
05425 }
05426
05427 size_t virtual_segment_c::AddSegment( matroska_segment_c *p_segment )
05428 {
05429 size_t i;
05430
05431 for ( i=0; i<linked_segments.size(); i++ )
05432 {
05433 if ( linked_segments[i]->p_segment_uid != NULL
05434 && p_segment->p_segment_uid != NULL
05435 && *p_segment->p_segment_uid == *linked_segments[i]->p_segment_uid )
05436 return 0;
05437 }
05438
05439
05440 for ( i=0; i<linked_uids.size(); i++ )
05441 {
05442 if ( (p_segment->p_segment_uid != NULL && *p_segment->p_segment_uid == linked_uids[i])
05443 || (p_segment->p_prev_segment_uid != NULL && *p_segment->p_prev_segment_uid == linked_uids[i])
05444 || (p_segment->p_next_segment_uid !=NULL && *p_segment->p_next_segment_uid == linked_uids[i]) )
05445 {
05446 linked_segments.push_back( p_segment );
05447
05448 AppendUID( p_segment->p_prev_segment_uid );
05449 AppendUID( p_segment->p_next_segment_uid );
05450
05451 return 1;
05452 }
05453 }
05454 return 0;
05455 }
05456
05457 void virtual_segment_c::PreloadLinked( )
05458 {
05459 for ( size_t i=0; i<linked_segments.size(); i++ )
05460 {
05461 linked_segments[i]->Preload( );
05462 }
05463 i_current_edition = linked_segments[0]->i_default_edition;
05464 }
05465
05466 mtime_t virtual_segment_c::Duration() const
05467 {
05468 mtime_t i_duration;
05469 if ( linked_segments.size() == 0 )
05470 i_duration = 0;
05471 else {
05472 matroska_segment_c *p_last_segment = linked_segments[linked_segments.size()-1];
05473
05474
05475 i_duration = p_last_segment->i_start_time / 1000 + p_last_segment->i_duration;
05476 }
05477 return i_duration;
05478 }
05479
05480 void virtual_segment_c::LoadCues( )
05481 {
05482 for ( size_t i=0; i<linked_segments.size(); i++ )
05483 {
05484 linked_segments[i]->LoadCues();
05485 }
05486 }
05487
05488 void virtual_segment_c::AppendUID( const EbmlBinary * p_UID )
05489 {
05490 if ( p_UID == NULL )
05491 return;
05492 if ( p_UID->GetBuffer() == NULL )
05493 return;
05494
05495 for (size_t i=0; i<linked_uids.size(); i++)
05496 {
05497 if ( *p_UID == linked_uids[i] )
05498 return;
05499 }
05500 linked_uids.push_back( *(KaxSegmentUID*)(p_UID) );
05501 }
05502
05503 void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset )
05504 {
05505 KaxBlock *block;
05506 #if LIBMATROSKA_VERSION >= 0x000800
05507 KaxSimpleBlock *simpleblock;
05508 #endif
05509 int i_track_skipping;
05510 int64_t i_block_duration;
05511 int64_t i_block_ref1;
05512 int64_t i_block_ref2;
05513 size_t i_track;
05514 int64_t i_seek_position = i_start_pos;
05515 int64_t i_seek_time = i_start_time;
05516
05517 if ( i_index > 0 )
05518 {
05519 int i_idx = 0;
05520
05521 for( ; i_idx < i_index; i_idx++ )
05522 {
05523 if( p_indexes[i_idx].i_time + i_time_offset > i_date )
05524 {
05525 break;
05526 }
05527 }
05528
05529 if( i_idx > 0 )
05530 {
05531 i_idx--;
05532 }
05533
05534 i_seek_position = p_indexes[i_idx].i_position;
05535 i_seek_time = p_indexes[i_idx].i_time;
05536 }
05537
05538 msg_Dbg( &sys.demuxer, "seek got "I64Fd" (%d%%)",
05539 i_seek_time, (int)( 100 * i_seek_position / stream_Size( sys.demuxer.s ) ) );
05540
05541 es.I_O().setFilePointer( i_seek_position, seek_beginning );
05542
05543 delete ep;
05544 ep = new EbmlParser( &es, segment, &sys.demuxer );
05545 cluster = NULL;
05546
05547 sys.i_start_pts = i_date;
05548
05549 es_out_Control( sys.demuxer.out, ES_OUT_RESET_PCR );
05550
05551
05552 i_track_skipping = 0;
05553 for( i_track = 0; i_track < tracks.size(); i_track++ )
05554 {
05555 if( tracks[i_track]->fmt.i_cat == VIDEO_ES )
05556 {
05557 tracks[i_track]->b_search_keyframe = VLC_TRUE;
05558 i_track_skipping++;
05559 }
05560 es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, tracks[i_track]->p_es, i_date );
05561 }
05562
05563
05564 while( i_track_skipping > 0 )
05565 {
05566 #if LIBMATROSKA_VERSION >= 0x000800
05567 if( BlockGet( block, simpleblock, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
05568 #else
05569 if( BlockGet( block, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
05570 #endif
05571 {
05572 msg_Warn( &sys.demuxer, "cannot get block EOF?" );
05573
05574 return;
05575 }
05576 ep->Down();
05577
05578 for( i_track = 0; i_track < tracks.size(); i_track++ )
05579 {
05580 if( tracks[i_track]->i_number == block->TrackNum() )
05581 {
05582 break;
05583 }
05584 }
05585
05586 sys.i_pts = (sys.i_chapter_time + block->GlobalTimecode()) / (mtime_t) 1000;
05587
05588 if( i_track < tracks.size() )
05589 {
05590 if( sys.i_pts >= sys.i_start_pts )
05591 {
05592 cluster = static_cast<KaxCluster*>(ep->UnGet( i_block_pos, i_cluster_pos ));
05593 i_track_skipping = 0;
05594 }
05595 else if( tracks[i_track]->fmt.i_cat == VIDEO_ES )
05596 {
05597 if( i_block_ref1 == 0 && tracks[i_track]->b_search_keyframe )
05598 {
05599 tracks[i_track]->b_search_keyframe = VLC_FALSE;
05600 i_track_skipping--;
05601 }
05602 if( !tracks[i_track]->b_search_keyframe )
05603 {
05604 #if LIBMATROSKA_VERSION >= 0x000800
05605 BlockDecode( &sys.demuxer, block, simpleblock, sys.i_pts, 0, i_block_ref1 >= 0 || i_block_ref2 > 0 );
05606 #else
05607 BlockDecode( &sys.demuxer, block, sys.i_pts, 0, i_block_ref1 >= 0 || i_block_ref2 > 0 );
05608 #endif
05609 }
05610 }
05611 }
05612
05613 delete block;
05614 }
05615 }
05616
05617 void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset, chapter_item_c *psz_chapter )
05618 {
05619 demux_sys_t *p_sys = demuxer.p_sys;
05620 size_t i;
05621
05622
05623 if ( psz_chapter == NULL )
05624 {
05625 if ( Edition() && Edition()->b_ordered )
05626 {
05627
05628 psz_chapter = (*p_editions)[i_current_edition]->FindTimecode( i_date, psz_current_chapter );
05629 }
05630 }
05631
05632 if ( psz_chapter != NULL )
05633 {
05634 psz_current_chapter = psz_chapter;
05635 p_sys->i_chapter_time = i_time_offset = psz_chapter->i_user_start_time - psz_chapter->i_start_time;
05636 if ( psz_chapter->i_seekpoint_num > 0 )
05637 {
05638 demuxer.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
05639 demuxer.info.i_title = p_sys->i_current_title = i_sys_title;
05640 demuxer.info.i_seekpoint = psz_chapter->i_seekpoint_num - 1;
05641 }
05642 }
05643
05644
05645 for ( i=0; i<linked_segments.size(); i++ )
05646 {
05647 if ( i_date < linked_segments[i]->i_start_time )
05648 break;
05649 }
05650
05651 if ( i > 0 )
05652 i--;
05653
05654 if ( i_current_segment != i )
05655 {
05656 linked_segments[i_current_segment]->UnSelect();
05657 linked_segments[i]->Select( i_date );
05658 i_current_segment = i;
05659 }
05660
05661 linked_segments[i]->Seek( i_date, i_time_offset );
05662 }
05663
05664 void chapter_codec_cmds_c::AddCommand( const KaxChapterProcessCommand & command )
05665 {
05666 size_t i;
05667
05668 uint32 codec_time = uint32(-1);
05669 for( i = 0; i < command.ListSize(); i++ )
05670 {
05671 const EbmlElement *k = command[i];
05672
05673 if( MKV_IS_ID( k, KaxChapterProcessTime ) )
05674 {
05675 codec_time = uint32( *static_cast<const KaxChapterProcessTime*>( k ) );
05676 break;
05677 }
05678 }
05679
05680 for( i = 0; i < command.ListSize(); i++ )
05681 {
05682 const EbmlElement *k = command[i];
05683
05684 if( MKV_IS_ID( k, KaxChapterProcessData ) )
05685 {
05686 KaxChapterProcessData *p_data = new KaxChapterProcessData( *static_cast<const KaxChapterProcessData*>( k ) );
05687 switch ( codec_time )
05688 {
05689 case 0:
05690 during_cmds.push_back( p_data );
05691 break;
05692 case 1:
05693 enter_cmds.push_back( p_data );
05694 break;
05695 case 2:
05696 leave_cmds.push_back( p_data );
05697 break;
05698 default:
05699 delete p_data;
05700 }
05701 }
05702 }
05703 }
05704
05705 bool chapter_item_c::Enter( bool b_do_subs )
05706 {
05707 bool f_result = false;
05708 std::vector<chapter_codec_cmds_c*>::iterator index = codecs.begin();
05709 while ( index != codecs.end() )
05710 {
05711 f_result |= (*index)->Enter();
05712 index++;
05713 }
05714
05715 if ( b_do_subs )
05716 {
05717
05718 std::vector<chapter_item_c*>::iterator index_ = sub_chapters.begin();
05719 while ( index_ != sub_chapters.end() )
05720 {
05721 f_result |= (*index_)->Enter( true );
05722 index_++;
05723 }
05724 }
05725 return f_result;
05726 }
05727
05728 bool chapter_item_c::Leave( bool b_do_subs )
05729 {
05730 bool f_result = false;
05731 b_is_leaving = true;
05732 std::vector<chapter_codec_cmds_c*>::iterator index = codecs.begin();
05733 while ( index != codecs.end() )
05734 {
05735 f_result |= (*index)->Leave();
05736 index++;
05737 }
05738
05739 if ( b_do_subs )
05740 {
05741
05742 std::vector<chapter_item_c*>::iterator index_ = sub_chapters.begin();
05743 while ( index_ != sub_chapters.end() )
05744 {
05745 f_result |= (*index_)->Leave( true );
05746 index_++;
05747 }
05748 }
05749 b_is_leaving = false;
05750 return f_result;
05751 }
05752
05753 bool chapter_item_c::EnterAndLeave( chapter_item_c *p_item, bool b_final_enter )
05754 {
05755 chapter_item_c *p_common_parent = p_item;
05756
05757
05758 while ( p_common_parent != NULL && !p_common_parent->ParentOf( *this ) )
05759 {
05760 if ( !p_common_parent->b_is_leaving && p_common_parent->Leave( false ) )
05761 return true;
05762 p_common_parent = p_common_parent->psz_parent;
05763 }
05764
05765
05766 if ( p_common_parent != NULL )
05767 {
05768 do
05769 {
05770 if ( p_common_parent == this )
05771 return Enter( true );
05772
05773 for ( size_t i = 0; i<p_common_parent->sub_chapters.size(); i++ )
05774 {
05775 if ( p_common_parent->sub_chapters[i]->ParentOf( *this ) )
05776 {
05777 p_common_parent = p_common_parent->sub_chapters[i];
05778 if ( p_common_parent != this )
05779 if ( p_common_parent->Enter( false ) )
05780 return true;
05781
05782 break;
05783 }
05784 }
05785 } while ( 1 );
05786 }
05787
05788 if ( b_final_enter )
05789 return Enter( true );
05790 else
05791 return false;
05792 }
05793
05794 bool dvd_chapter_codec_c::Enter()
05795 {
05796 bool f_result = false;
05797 std::vector<KaxChapterProcessData*>::iterator index = enter_cmds.begin();
05798 while ( index != enter_cmds.end() )
05799 {
05800 if ( (*index)->GetSize() )
05801 {
05802 binary *p_data = (*index)->GetBuffer();
05803 size_t i_size = *p_data++;
05804
05805 i_size = min( i_size, ((*index)->GetSize() - 1) >> 3 );
05806 for ( ; i_size > 0; i_size--, p_data += 8 )
05807 {
05808 msg_Dbg( &sys.demuxer, "Matroska DVD enter command" );
05809 f_result |= sys.dvd_interpretor.Interpret( p_data );
05810 }
05811 }
05812 index++;
05813 }
05814 return f_result;
05815 }
05816
05817 bool dvd_chapter_codec_c::Leave()
05818 {
05819 bool f_result = false;
05820 std::vector<KaxChapterProcessData*>::iterator index = leave_cmds.begin();
05821 while ( index != leave_cmds.end() )
05822 {
05823 if ( (*index)->GetSize() )
05824 {
05825 binary *p_data = (*index)->GetBuffer();
05826 size_t i_size = *p_data++;
05827
05828 i_size = min( i_size, ((*index)->GetSize() - 1) >> 3 );
05829 for ( ; i_size > 0; i_size--, p_data += 8 )
05830 {
05831 msg_Dbg( &sys.demuxer, "Matroska DVD leave command" );
05832 f_result |= sys.dvd_interpretor.Interpret( p_data );
05833 }
05834 }
05835 index++;
05836 }
05837 return f_result;
05838 }
05839
05840
05841 bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_size )
05842 {
05843 if ( i_size != 8 )
05844 return false;
05845
05846 virtual_segment_c *p_segment = NULL;
05847 chapter_item_c *p_chapter = NULL;
05848 bool f_result = false;
05849 uint16 i_command = ( p_command[0] << 8 ) + p_command[1];
05850
05851
05852 if ( (i_command & 0xF0) != 0 )
05853 {
05854 bool b_test_positive = true;
05855 bool b_test_value = (i_command & CMD_DVD_TEST_VALUE) != 0;
05856 uint8 i_test = i_command & 0x70;
05857 uint16 i_value;
05858
05859
05860 uint8 i_cr1;
05861 uint16 i_cr2;
05862 switch ( i_command >> 12 )
05863 {
05864 default:
05865 i_cr1 = p_command[3];
05866 i_cr2 = (p_command[4] << 8) + p_command[5];
05867 break;
05868 case 3:
05869 case 4:
05870 case 5:
05871 i_cr1 = p_command[6];
05872 i_cr2 = p_command[7];
05873 b_test_value = false;
05874 break;
05875 case 6:
05876 case 7:
05877 if ( ((p_command[1] >> 4) & 0x7) == 0)
05878 {
05879 i_cr1 = p_command[2];
05880 i_cr2 = (p_command[6] << 8) + p_command[7];
05881 }
05882 else
05883 {
05884 i_cr1 = p_command[2];
05885 i_cr2 = (p_command[6] << 8) + p_command[7];
05886 }
05887 break;
05888 }
05889
05890 if ( b_test_value )
05891 i_value = i_cr2;
05892 else
05893 i_value = GetPRM( i_cr2 );
05894
05895 switch ( i_test )
05896 {
05897 case CMD_DVD_IF_GPREG_EQUAL:
05898
05899 msg_Dbg( &sys.demuxer, "IF %s EQUALS %s", GetRegTypeName( false, i_cr1 ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
05900 if (!( GetPRM( i_cr1 ) == i_value ))
05901 {
05902 b_test_positive = false;
05903 }
05904 break;
05905 case CMD_DVD_IF_GPREG_NOT_EQUAL:
05906
05907 msg_Dbg( &sys.demuxer, "IF %s NOT EQUALS %s", GetRegTypeName( false, i_cr1 ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
05908 if (!( GetPRM( i_cr1 ) != i_value ))
05909 {
05910 b_test_positive = false;
05911 }
05912 break;
05913 case CMD_DVD_IF_GPREG_INF:
05914
05915 msg_Dbg( &sys.demuxer, "IF %s < %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
05916 if (!( GetPRM( i_cr1 ) < i_value ))
05917 {
05918 b_test_positive = false;
05919 }
05920 break;
05921 case CMD_DVD_IF_GPREG_INF_EQUAL:
05922
05923 msg_Dbg( &sys.demuxer, "IF %s < %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
05924 if (!( GetPRM( i_cr1 ) <= i_value ))
05925 {
05926 b_test_positive = false;
05927 }
05928 break;
05929 case CMD_DVD_IF_GPREG_AND:
05930
05931 msg_Dbg( &sys.demuxer, "IF %s & %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
05932 if (!( GetPRM( i_cr1 ) & i_value ))
05933 {
05934 b_test_positive = false;
05935 }
05936 break;
05937 case CMD_DVD_IF_GPREG_SUP:
05938
05939 msg_Dbg( &sys.demuxer, "IF %s >= %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
05940 if (!( GetPRM( i_cr1 ) > i_value ))
05941 {
05942 b_test_positive = false;
05943 }
05944 break;
05945 case CMD_DVD_IF_GPREG_SUP_EQUAL:
05946
05947 msg_Dbg( &sys.demuxer, "IF %s >= %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
05948 if (!( GetPRM( i_cr1 ) >= i_value ))
05949 {
05950 b_test_positive = false;
05951 }
05952 break;
05953 }
05954
05955 if ( !b_test_positive )
05956 return false;
05957 }
05958
05959
05960 i_command &= 0xFF0F;
05961
05962 switch ( i_command )
05963 {
05964 case CMD_DVD_NOP:
05965 case CMD_DVD_NOP2:
05966 {
05967 msg_Dbg( &sys.demuxer, "NOP" );
05968 break;
05969 }
05970 case CMD_DVD_BREAK:
05971 {
05972 msg_Dbg( &sys.demuxer, "Break" );
05973
05974 break;
05975 }
05976 case CMD_DVD_JUMP_TT:
05977 {
05978 uint8 i_title = p_command[5];
05979 msg_Dbg( &sys.demuxer, "JumpTT %d", i_title );
05980
05981
05982 p_chapter = sys.BrowseCodecPrivate( 1, MatchTitleNumber, &i_title, sizeof(i_title), p_segment );
05983 if ( p_segment != NULL )
05984 {
05985 sys.JumpTo( *p_segment, p_chapter );
05986 f_result = true;
05987 }
05988
05989 break;
05990 }
05991 case CMD_DVD_CALLSS_VTSM1:
05992 {
05993 msg_Dbg( &sys.demuxer, "CallSS" );
05994 binary p_type;
05995 switch( (p_command[6] & 0xC0) >> 6 ) {
05996 case 0:
05997 p_type = p_command[5] & 0x0F;
05998 switch ( p_type )
05999 {
06000 case 0x00:
06001 msg_Dbg( &sys.demuxer, "CallSS PGC (rsm_cell %x)", p_command[4]);
06002 break;
06003 case 0x02:
06004 msg_Dbg( &sys.demuxer, "CallSS Title Entry (rsm_cell %x)", p_command[4]);
06005 break;
06006 case 0x03:
06007 msg_Dbg( &sys.demuxer, "CallSS Root Menu (rsm_cell %x)", p_command[4]);
06008 break;
06009 case 0x04:
06010 msg_Dbg( &sys.demuxer, "CallSS Subpicture Menu (rsm_cell %x)", p_command[4]);
06011 break;
06012 case 0x05:
06013 msg_Dbg( &sys.demuxer, "CallSS Audio Menu (rsm_cell %x)", p_command[4]);
06014 break;
06015 case 0x06:
06016 msg_Dbg( &sys.demuxer, "CallSS Angle Menu (rsm_cell %x)", p_command[4]);
06017 break;
06018 case 0x07:
06019 msg_Dbg( &sys.demuxer, "CallSS Chapter Menu (rsm_cell %x)", p_command[4]);
06020 break;
06021 default:
06022 msg_Dbg( &sys.demuxer, "CallSS <unknown> (rsm_cell %x)", p_command[4]);
06023 break;
06024 }
06025 p_chapter = sys.BrowseCodecPrivate( 1, MatchPgcType, &p_type, 1, p_segment );
06026 if ( p_segment != NULL )
06027 {
06028 sys.JumpTo( *p_segment, p_chapter );
06029 f_result = true;
06030 }
06031 break;
06032 case 1:
06033 msg_Dbg( &sys.demuxer, "CallSS VMGM (menu %d, rsm_cell %x)", p_command[5] & 0x0F, p_command[4]);
06034 break;
06035 case 2:
06036 msg_Dbg( &sys.demuxer, "CallSS VTSM (menu %d, rsm_cell %x)", p_command[5] & 0x0F, p_command[4]);
06037 break;
06038 case 3:
06039 msg_Dbg( &sys.demuxer, "CallSS VMGM (pgc %d, rsm_cell %x)", (p_command[2] << 8) + p_command[3], p_command[4]);
06040 break;
06041 }
06042 break;
06043 }
06044 case CMD_DVD_JUMP_SS:
06045 {
06046 msg_Dbg( &sys.demuxer, "JumpSS");
06047 binary p_type;
06048 switch( (p_command[5] & 0xC0) >> 6 ) {
06049 case 0:
06050 msg_Dbg( &sys.demuxer, "JumpSS FP");
06051 break;
06052 case 1:
06053 p_type = p_command[5] & 0x0F;
06054 switch ( p_type )
06055 {
06056 case 0x02:
06057 msg_Dbg( &sys.demuxer, "JumpSS VMGM Title Entry");
06058 break;
06059 case 0x03:
06060 msg_Dbg( &sys.demuxer, "JumpSS VMGM Root Menu");
06061 break;
06062 case 0x04:
06063 msg_Dbg( &sys.demuxer, "JumpSS VMGM Subpicture Menu");
06064 break;
06065 case 0x05:
06066 msg_Dbg( &sys.demuxer, "JumpSS VMGM Audio Menu");
06067 break;
06068 case 0x06:
06069 msg_Dbg( &sys.demuxer, "JumpSS VMGM Angle Menu");
06070 break;
06071 case 0x07:
06072 msg_Dbg( &sys.demuxer, "JumpSS VMGM Chapter Menu");
06073 break;
06074 default:
06075 msg_Dbg( &sys.demuxer, "JumpSS <unknown>");
06076 break;
06077 }
06078
06079 p_chapter = sys.BrowseCodecPrivate( 1, MatchIsVMG, NULL, 0, p_segment );
06080 if ( p_segment != NULL )
06081 {
06082 p_chapter = p_segment->BrowseCodecPrivate( 1, MatchPgcType, &p_type, 1 );
06083 if ( p_chapter != NULL )
06084 {
06085 sys.JumpTo( *p_segment, p_chapter );
06086 f_result = true;
06087 }
06088 }
06089 break;
06090 case 2:
06091 p_type = p_command[5] & 0x0F;
06092 switch ( p_type )
06093 {
06094 case 0x02:
06095 msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Title Entry", p_command[4], p_command[3]);
06096 break;
06097 case 0x03:
06098 msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Root Menu", p_command[4], p_command[3]);
06099 break;
06100 case 0x04:
06101 msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Subpicture Menu", p_command[4], p_command[3]);
06102 break;
06103 case 0x05:
06104 msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Audio Menu", p_command[4], p_command[3]);
06105 break;
06106 case 0x06:
06107 msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Angle Menu", p_command[4], p_command[3]);
06108 break;
06109 case 0x07:
06110 msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Chapter Menu", p_command[4], p_command[3]);
06111 break;
06112 default:
06113 msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) <unknown>", p_command[4], p_command[3]);
06114 break;
06115 }
06116
06117 p_chapter = sys.BrowseCodecPrivate( 1, MatchVTSMNumber, &p_command[4], 1, p_segment );
06118
06119 if ( p_segment != NULL && p_chapter != NULL )
06120 {
06121
06122 p_chapter = p_chapter->BrowseCodecPrivate( 1, MatchTitleNumber, &p_command[3], 1 );
06123 if ( p_chapter != NULL )
06124 {
06125
06126 p_chapter = p_segment->BrowseCodecPrivate( 1, MatchPgcType, &p_type, 1 );
06127 if ( p_chapter != NULL )
06128 {
06129 sys.JumpTo( *p_segment, p_chapter );
06130 f_result = true;
06131 }
06132 }
06133 else
06134 msg_Dbg( &sys.demuxer, "Title (%d) does not exist in this VTS", p_command[3] );
06135 }
06136 else
06137 msg_Dbg( &sys.demuxer, "DVD Domain VTS (%d) not found", p_command[4] );
06138 break;
06139 case 3:
06140 msg_Dbg( &sys.demuxer, "JumpSS VMGM (pgc %d)", (p_command[2] << 8) + p_command[3]);
06141 break;
06142 }
06143 break;
06144 }
06145 case CMD_DVD_JUMPVTS_PTT:
06146 {
06147 uint8 i_title = p_command[5];
06148 uint8 i_ptt = p_command[3];
06149
06150 msg_Dbg( &sys.demuxer, "JumpVTS Title (%d) PTT (%d)", i_title, i_ptt);
06151
06152
06153 p_chapter = sys.p_current_segment->BrowseCodecPrivate( 1, MatchIsDomain, NULL, 0 );
06154 if ( p_chapter != NULL )
06155 {
06156 int16 i_curr_title = p_chapter->GetTitleNumber( );
06157 if ( i_curr_title > 0 )
06158 {
06159 p_chapter = sys.BrowseCodecPrivate( 1, MatchVTSNumber, &i_curr_title, sizeof(i_curr_title), p_segment );
06160
06161 if ( p_segment != NULL && p_chapter != NULL )
06162 {
06163
06164 p_chapter = p_chapter->BrowseCodecPrivate( 1, MatchTitleNumber, &i_title, sizeof(i_title) );
06165 if ( p_chapter != NULL )
06166 {
06167
06168 p_chapter = p_chapter->BrowseCodecPrivate( 1, MatchChapterNumber, &i_ptt, sizeof(i_ptt) );
06169 if ( p_chapter != NULL )
06170 {
06171 sys.JumpTo( *p_segment, p_chapter );
06172 f_result = true;
06173 }
06174 }
06175 else
06176 msg_Dbg( &sys.demuxer, "Title (%d) does not exist in this VTS", i_title );
06177 }
06178 else
06179 msg_Dbg( &sys.demuxer, "DVD Domain VTS (%d) not found", i_curr_title );
06180 }
06181 else
06182 msg_Dbg( &sys.demuxer, "JumpVTS_PTT command found but not in a VTS(M)");
06183 }
06184 else
06185 msg_Dbg( &sys.demuxer, "JumpVTS_PTT command but the DVD domain wasn't found");
06186 break;
06187 }
06188 case CMD_DVD_SET_GPRMMD:
06189 {
06190 msg_Dbg( &sys.demuxer, "Set GPRMMD [%d]=%d", (p_command[4] << 8) + p_command[5], (p_command[2] << 8) + p_command[3]);
06191
06192 if ( !SetGPRM( (p_command[4] << 8) + p_command[5], (p_command[2] << 8) + p_command[3] ) )
06193 msg_Dbg( &sys.demuxer, "Set GPRMMD failed" );
06194 break;
06195 }
06196 case CMD_DVD_LINKPGCN:
06197 {
06198 uint16 i_pgcn = (p_command[6] << 8) + p_command[7];
06199
06200 msg_Dbg( &sys.demuxer, "Link PGCN(%d)", i_pgcn );
06201 p_chapter = sys.p_current_segment->BrowseCodecPrivate( 1, MatchPgcNumber, &i_pgcn, 2 );
06202 if ( p_chapter != NULL )
06203 {
06204 if ( !p_chapter->Enter( true ) )
06205
06206 sys.p_current_segment->Seek( sys.demuxer, p_chapter->i_user_start_time, -1, p_chapter );
06207
06208 f_result = true;
06209 }
06210 break;
06211 }
06212 case CMD_DVD_LINKCN:
06213 {
06214 uint8 i_cn = p_command[7];
06215
06216 p_chapter = sys.p_current_segment->CurrentChapter();
06217
06218 msg_Dbg( &sys.demuxer, "LinkCN (cell %d)", i_cn );
06219 p_chapter = p_chapter->BrowseCodecPrivate( 1, MatchCellNumber, &i_cn, 1 );
06220 if ( p_chapter != NULL )
06221 {
06222 if ( !p_chapter->Enter( true ) )
06223
06224 sys.p_current_segment->Seek( sys.demuxer, p_chapter->i_user_start_time, -1, p_chapter );
06225
06226 f_result = true;
06227 }
06228 break;
06229 }
06230 case CMD_DVD_GOTO_LINE:
06231 {
06232 msg_Dbg( &sys.demuxer, "GotoLine (%d)", (p_command[6] << 8) + p_command[7] );
06233
06234 break;
06235 }
06236 case CMD_DVD_SET_HL_BTNN1:
06237 {
06238 msg_Dbg( &sys.demuxer, "SetHL_BTN (%d)", p_command[4] );
06239 SetSPRM( 0x88, p_command[4] );
06240 break;
06241 }
06242 default:
06243 {
06244 msg_Dbg( &sys.demuxer, "unsupported command : %02X %02X %02X %02X %02X %02X %02X %02X"
06245 ,p_command[0]
06246 ,p_command[1]
06247 ,p_command[2]
06248 ,p_command[3]
06249 ,p_command[4]
06250 ,p_command[5]
06251 ,p_command[6]
06252 ,p_command[7]);
06253 break;
06254 }
06255 }
06256
06257 return f_result;
06258 }
06259
06260 bool dvd_command_interpretor_c::MatchIsDomain( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
06261 {
06262 return ( data.p_private_data != NULL && data.p_private_data->GetBuffer()[0] == MATROSKA_DVD_LEVEL_SS );
06263 }
06264
06265 bool dvd_command_interpretor_c::MatchIsVMG( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
06266 {
06267 if ( data.p_private_data == NULL || data.p_private_data->GetSize() < 2 )
06268 return false;
06269
06270 return ( data.p_private_data->GetBuffer()[0] == MATROSKA_DVD_LEVEL_SS && data.p_private_data->GetBuffer()[1] == 0xC0);
06271 }
06272
06273 bool dvd_command_interpretor_c::MatchVTSNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
06274 {
06275 if ( i_cookie_size != 2 || data.p_private_data == NULL || data.p_private_data->GetSize() < 4 )
06276 return false;
06277
06278 if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_SS || data.p_private_data->GetBuffer()[1] != 0x80 )
06279 return false;
06280
06281 uint16 i_gtitle = (data.p_private_data->GetBuffer()[2] << 8 ) + data.p_private_data->GetBuffer()[3];
06282 uint16 i_title = *(uint16*)p_cookie;
06283
06284 return (i_gtitle == i_title);
06285 }
06286
06287 bool dvd_command_interpretor_c::MatchVTSMNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
06288 {
06289 if ( i_cookie_size != 1 || data.p_private_data == NULL || data.p_private_data->GetSize() < 4 )
06290 return false;
06291
06292 if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_SS || data.p_private_data->GetBuffer()[1] != 0x40 )
06293 return false;
06294
06295 uint8 i_gtitle = data.p_private_data->GetBuffer()[3];
06296 uint8 i_title = *(uint8*)p_cookie;
06297
06298 return (i_gtitle == i_title);
06299 }
06300
06301 bool dvd_command_interpretor_c::MatchTitleNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
06302 {
06303 if ( i_cookie_size != 1 || data.p_private_data == NULL || data.p_private_data->GetSize() < 4 )
06304 return false;
06305
06306 if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_TT )
06307 return false;
06308
06309 uint16 i_gtitle = (data.p_private_data->GetBuffer()[1] << 8 ) + data.p_private_data->GetBuffer()[2];
06310 uint8 i_title = *(uint8*)p_cookie;
06311
06312 return (i_gtitle == i_title);
06313 }
06314
06315 bool dvd_command_interpretor_c::MatchPgcType( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
06316 {
06317 if ( i_cookie_size != 1 || data.p_private_data == NULL || data.p_private_data->GetSize() < 8 )
06318 return false;
06319
06320 if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_PGC )
06321 return false;
06322
06323 uint8 i_pgc_type = data.p_private_data->GetBuffer()[3] & 0x0F;
06324 uint8 i_pgc = *(uint8*)p_cookie;
06325
06326 return (i_pgc_type == i_pgc);
06327 }
06328
06329 bool dvd_command_interpretor_c::MatchPgcNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
06330 {
06331 if ( i_cookie_size != 2 || data.p_private_data == NULL || data.p_private_data->GetSize() < 8 )
06332 return false;
06333
06334 if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_PGC )
06335 return false;
06336
06337 uint16 *i_pgc_n = (uint16 *)p_cookie;
06338 uint16 i_pgc_num = (data.p_private_data->GetBuffer()[1] << 8) + data.p_private_data->GetBuffer()[2];
06339
06340 return (i_pgc_num == *i_pgc_n);
06341 }
06342
06343 bool dvd_command_interpretor_c::MatchChapterNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
06344 {
06345 if ( i_cookie_size != 1 || data.p_private_data == NULL || data.p_private_data->GetSize() < 2 )
06346 return false;
06347
06348 if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_PTT )
06349 return false;
06350
06351 uint8 i_chapter = data.p_private_data->GetBuffer()[1];
06352 uint8 i_ptt = *(uint8*)p_cookie;
06353
06354 return (i_chapter == i_ptt);
06355 }
06356
06357 bool dvd_command_interpretor_c::MatchCellNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
06358 {
06359 if ( i_cookie_size != 1 || data.p_private_data == NULL || data.p_private_data->GetSize() < 5 )
06360 return false;
06361
06362 if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_CN )
06363 return false;
06364
06365 uint8 *i_cell_n = (uint8 *)p_cookie;
06366 uint8 i_cell_num = data.p_private_data->GetBuffer()[3];
06367
06368 return (i_cell_num == *i_cell_n);
06369 }
06370
06371 bool matroska_script_codec_c::Enter()
06372 {
06373 bool f_result = false;
06374 std::vector<KaxChapterProcessData*>::iterator index = enter_cmds.begin();
06375 while ( index != enter_cmds.end() )
06376 {
06377 if ( (*index)->GetSize() )
06378 {
06379 msg_Dbg( &sys.demuxer, "Matroska Script enter command" );
06380 f_result |= interpretor.Interpret( (*index)->GetBuffer(), (*index)->GetSize() );
06381 }
06382 index++;
06383 }
06384 return f_result;
06385 }
06386
06387 bool matroska_script_codec_c::Leave()
06388 {
06389 bool f_result = false;
06390 std::vector<KaxChapterProcessData*>::iterator index = leave_cmds.begin();
06391 while ( index != leave_cmds.end() )
06392 {
06393 if ( (*index)->GetSize() )
06394 {
06395 msg_Dbg( &sys.demuxer, "Matroska Script leave command" );
06396 f_result |= interpretor.Interpret( (*index)->GetBuffer(), (*index)->GetSize() );
06397 }
06398 index++;
06399 }
06400 return f_result;
06401 }
06402
06403
06404
06405 bool matroska_script_interpretor_c::Interpret( const binary * p_command, size_t i_size )
06406 {
06407 bool b_result = false;
06408
06409 char *psz_str = (char*) malloc( i_size + 1 );
06410 memcpy( psz_str, p_command, i_size );
06411 psz_str[ i_size ] = '\0';
06412
06413 std::string sz_command = psz_str;
06414 free( psz_str );
06415
06416 msg_Dbg( &sys.demuxer, "command : %s", sz_command.c_str() );
06417
06418 #if defined(__GNUC__) && (__GNUC__ < 3)
06419 if ( sz_command.compare( CMD_MS_GOTO_AND_PLAY, 0, CMD_MS_GOTO_AND_PLAY.size() ) == 0 )
06420 #else
06421 if ( sz_command.compare( 0, CMD_MS_GOTO_AND_PLAY.size(), CMD_MS_GOTO_AND_PLAY ) == 0 )
06422 #endif
06423 {
06424 size_t i,j;
06425
06426
06427 for ( i=CMD_MS_GOTO_AND_PLAY.size(); i<sz_command.size(); i++)
06428 {
06429 if ( sz_command[i] == '(' )
06430 {
06431 i++;
06432 break;
06433 }
06434 }
06435
06436 for ( j=i; j<sz_command.size(); j++)
06437 {
06438 if ( sz_command[j] == ')' )
06439 {
06440 i--;
06441 break;
06442 }
06443 }
06444
06445 std::string st = sz_command.substr( i+1, j-i-1 );
06446 int64_t i_chapter_uid = atoi( st.c_str() );
06447
06448 virtual_segment_c *p_segment;
06449 chapter_item_c *p_chapter = sys.FindChapter( i_chapter_uid, p_segment );
06450
06451 if ( p_chapter == NULL )
06452 msg_Dbg( &sys.demuxer, "Chapter "I64Fd" not found", i_chapter_uid);
06453 else
06454 {
06455 if ( !p_chapter->EnterAndLeave( sys.p_current_segment->CurrentChapter() ) )
06456 p_segment->Seek( sys.demuxer, p_chapter->i_user_start_time, -1, p_chapter );
06457 b_result = true;
06458 }
06459 }
06460
06461 return b_result;
06462 }
06463
06464 void demux_sys_t::SwapButtons()
06465 {
06466 #ifndef WORDS_BIGENDIAN
06467 uint8_t button, i, j;
06468
06469 for( button = 1; button <= pci_packet.hli.hl_gi.btn_ns; button++) {
06470 btni_t *button_ptr = &(pci_packet.hli.btnit[button-1]);
06471 binary *p_data = (binary*) button_ptr;
06472
06473 uint16 i_x_start = ((p_data[0] & 0x3F) << 4 ) + ( p_data[1] >> 4 );
06474 uint16 i_x_end = ((p_data[1] & 0x03) << 8 ) + p_data[2];
06475 uint16 i_y_start = ((p_data[3] & 0x3F) << 4 ) + ( p_data[4] >> 4 );
06476 uint16 i_y_end = ((p_data[4] & 0x03) << 8 ) + p_data[5];
06477 button_ptr->x_start = i_x_start;
06478 button_ptr->x_end = i_x_end;
06479 button_ptr->y_start = i_y_start;
06480 button_ptr->y_end = i_y_end;
06481
06482 }
06483 for ( i = 0; i<3; i++ )
06484 {
06485 for ( j = 0; j<2; j++ )
06486 {
06487 pci_packet.hli.btn_colit.btn_coli[i][j] = U32_AT( &pci_packet.hli.btn_colit.btn_coli[i][j] );
06488 }
06489 }
06490 #endif
06491 }