]> git.sesse.net Git - vlc/blob - modules/demux/mkv.cpp
a8b22663d92df65d409772273c995ca878c16ec7
[vlc] / modules / demux / mkv.cpp
1 /*****************************************************************************
2  * mkv.cpp : matroska demuxer
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: mkv.cpp,v 1.54 2004/01/22 20:48:07 sigmunau Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28
29 #include <vlc/vlc.h>
30
31 #ifdef HAVE_TIME_H
32 #   include <time.h>                                               /* time() */
33 #endif
34
35 #include <vlc/input.h>
36
37 #include <codecs.h>                        /* BITMAPINFOHEADER, WAVEFORMATEX */
38 #include "iso_lang.h"
39
40 #include <iostream>
41 #include <cassert>
42 #include <typeinfo>
43
44 #ifdef HAVE_WCHAR_H
45 #   include <wchar.h>
46 #endif
47
48 /* libebml and matroska */
49 #include "ebml/EbmlHead.h"
50 #include "ebml/EbmlSubHead.h"
51 #include "ebml/EbmlStream.h"
52 #include "ebml/EbmlContexts.h"
53 #include "ebml/EbmlVersion.h"
54 #include "ebml/EbmlVoid.h"
55
56 #include "matroska/FileKax.h"
57 #ifdef HAVE_MATROSKA_KAXATTACHMENTS_H
58 #include "matroska/KaxAttachments.h"
59 #else
60 #include "matroska/KaxAttachements.h"
61 #endif
62 #include "matroska/KaxBlock.h"
63 #include "matroska/KaxBlockData.h"
64 #include "matroska/KaxChapters.h"
65 #include "matroska/KaxCluster.h"
66 #include "matroska/KaxClusterData.h"
67 #include "matroska/KaxContexts.h"
68 #include "matroska/KaxCues.h"
69 #include "matroska/KaxCuesData.h"
70 #include "matroska/KaxInfo.h"
71 #include "matroska/KaxInfoData.h"
72 #include "matroska/KaxSeekHead.h"
73 #include "matroska/KaxSegment.h"
74 #include "matroska/KaxTag.h"
75 #include "matroska/KaxTags.h"
76 #include "matroska/KaxTagMulti.h"
77 #include "matroska/KaxTracks.h"
78 #include "matroska/KaxTrackAudio.h"
79 #include "matroska/KaxTrackVideo.h"
80 #include "matroska/KaxTrackEntryData.h"
81
82 #include "ebml/StdIOCallback.h"
83
84 using namespace LIBMATROSKA_NAMESPACE;
85 using namespace std;
86
87 /*****************************************************************************
88  * Module descriptor
89  *****************************************************************************/
90 static int  Open ( vlc_object_t * );
91 static void Close( vlc_object_t * );
92
93 vlc_module_begin();
94     add_category_hint( N_("mkv demuxer"), NULL, VLC_TRUE );
95         add_bool( "mkv-seek-percent", 1, NULL,
96                   N_("Seek based on percent not time"),
97                   N_("Seek based on percent not time"), VLC_TRUE );
98
99     set_description( _("mka/mkv stream demuxer" ) );
100     set_capability( "demux", 50 );
101     set_callbacks( Open, Close );
102     add_shortcut( "mka" );
103     add_shortcut( "mkv" );
104 vlc_module_end();
105
106 /*****************************************************************************
107  * Local prototypes
108  *****************************************************************************/
109 static int  Demux   ( input_thread_t * );
110 static void Seek    ( input_thread_t *, mtime_t i_date, int i_percent );
111
112
113 /*****************************************************************************
114  * Stream managment
115  *****************************************************************************/
116 class vlc_stream_io_callback: public IOCallback
117 {
118   private:
119     stream_t       *s;
120     vlc_bool_t     mb_eof;
121
122   public:
123     vlc_stream_io_callback( stream_t * );
124
125     virtual uint32_t read            ( void *p_buffer, size_t i_size);
126     virtual void     setFilePointer  ( int64_t i_offset, seek_mode mode = seek_beginning );
127     virtual size_t   write           ( const void *p_buffer, size_t i_size);
128     virtual uint64_t getFilePointer  ( void );
129     virtual void     close           ( void );
130 };
131
132 /*****************************************************************************
133  * Ebml Stream parser
134  *****************************************************************************/
135 class EbmlParser
136 {
137   public:
138     EbmlParser( EbmlStream *es, EbmlElement *el_start );
139     ~EbmlParser( void );
140
141     void Up( void );
142     void Down( void );
143     EbmlElement *Get( void );
144     void        Keep( void );
145
146     int GetLevel( void );
147
148   private:
149     EbmlStream  *m_es;
150     int         mi_level;
151     EbmlElement *m_el[6];
152
153     EbmlElement *m_got;
154
155     int         mi_user_level;
156     vlc_bool_t  mb_keep;
157 };
158
159
160 /*****************************************************************************
161  * Some functions to manipulate memory
162  *****************************************************************************/
163 #define GetFOURCC( p )  __GetFOURCC( (uint8_t*)p )
164 static vlc_fourcc_t __GetFOURCC( uint8_t *p )
165 {
166     return VLC_FOURCC( p[0], p[1], p[2], p[3] );
167 }
168
169 /*****************************************************************************
170  * definitions of structures and functions used by this plugins
171  *****************************************************************************/
172 typedef struct
173 {
174     vlc_bool_t  b_default;
175     vlc_bool_t  b_enabled;
176     int         i_number;
177
178     int         i_extra_data;
179     uint8_t     *p_extra_data;
180
181     char         *psz_codec;
182
183     uint64_t     i_default_duration;
184     float        f_timecodescale;
185
186     /* video */
187     es_format_t fmt;
188     float       f_fps;
189     es_out_id_t *p_es;
190
191     vlc_bool_t      b_inited;
192     /* data to be send first */
193     int             i_data_init;
194     uint8_t         *p_data_init;
195
196     /* hack : it's for seek */
197     vlc_bool_t      b_search_keyframe;
198
199     /* informative */
200     char         *psz_codec_name;
201     char         *psz_codec_settings;
202     char         *psz_codec_info_url;
203     char         *psz_codec_download_url;
204
205 } mkv_track_t;
206
207 typedef struct
208 {
209     int     i_track;
210     int     i_block_number;
211
212     int64_t i_position;
213     int64_t i_time;
214
215     vlc_bool_t b_key;
216 } mkv_index_t;
217
218 struct demux_sys_t
219 {
220     vlc_stream_io_callback  *in;
221     EbmlStream              *es;
222     EbmlParser              *ep;
223
224     /* time scale */
225     uint64_t                i_timescale;
226
227     /* duration of the segment */
228     float                   f_duration;
229
230     /* all tracks */
231     int                     i_track;
232     mkv_track_t             *track;
233
234     /* from seekhead */
235     int64_t                 i_cues_position;
236     int64_t                 i_chapters_position;
237     int64_t                 i_tags_position;
238
239     /* current data */
240     KaxSegment              *segment;
241     KaxCluster              *cluster;
242
243     mtime_t                 i_pts;
244
245     vlc_bool_t              b_cues;
246     int                     i_index;
247     int                     i_index_max;
248     mkv_index_t             *index;
249
250     /* info */
251     char                    *psz_muxing_application;
252     char                    *psz_writing_application;
253     char                    *psz_segment_filename;
254     char                    *psz_title;
255     char                    *psz_date_utc;
256 };
257
258 #define MKVD_TIMECODESCALE 1000000
259
260 static void IndexAppendCluster  ( input_thread_t *p_input, KaxCluster *cluster );
261 static char *UTF8ToStr          ( const UTFstring &u );
262 static void LoadCues            ( input_thread_t *);
263 static void InformationsCreate  ( input_thread_t *p_input );
264
265 static char *LanguageGetName    ( const char *psz_code );
266
267 /*****************************************************************************
268  * Open: initializes matroska demux structures
269  *****************************************************************************/
270 static int Open( vlc_object_t * p_this )
271 {
272     input_thread_t *p_input = (input_thread_t *)p_this;
273     demux_sys_t    *p_sys;
274     uint8_t        *p_peek;
275
276     int             i_track;
277
278     EbmlElement     *el = NULL, *el1 = NULL, *el2 = NULL, *el3 = NULL, *el4 = NULL;
279
280     /* Set the demux function */
281     p_input->pf_demux = Demux;
282     p_input->pf_demux_control = demux_vaControlDefault;
283
284     /* peek the begining */
285     if( input_Peek( p_input, &p_peek, 4 ) < 4 )
286     {
287         msg_Warn( p_input, "cannot peek" );
288         return VLC_EGENERIC;
289     }
290
291     /* is a valid file */
292     if( p_peek[0] != 0x1a || p_peek[1] != 0x45 ||
293         p_peek[2] != 0xdf || p_peek[3] != 0xa3 )
294     {
295         msg_Warn( p_input, "matroska module discarded "
296                            "(invalid header 0x%.2x%.2x%.2x%.2x)",
297                            p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
298         return VLC_EGENERIC;
299     }
300
301     p_input->p_demux_data = p_sys = (demux_sys_t*)malloc(sizeof( demux_sys_t ));
302     memset( p_sys, 0, sizeof( demux_sys_t ) );
303
304     p_sys->in = new vlc_stream_io_callback( p_input->s );
305     p_sys->es = new EbmlStream( *p_sys->in );
306     p_sys->f_duration   = -1;
307     p_sys->i_timescale     = MKVD_TIMECODESCALE;
308     p_sys->i_track      = 0;
309     p_sys->track        = (mkv_track_t*)malloc( sizeof( mkv_track_t ) );
310     p_sys->i_pts   = 0;
311     p_sys->i_cues_position = -1;
312     p_sys->i_chapters_position = -1;
313     p_sys->i_tags_position = -1;
314
315     p_sys->b_cues       = VLC_FALSE;
316     p_sys->i_index      = 0;
317     p_sys->i_index_max  = 1024;
318     p_sys->index        = (mkv_index_t*)malloc( sizeof( mkv_index_t ) *
319                                                 p_sys->i_index_max );
320
321     p_sys->psz_muxing_application = NULL;
322     p_sys->psz_writing_application = NULL;
323     p_sys->psz_segment_filename = NULL;
324     p_sys->psz_title = NULL;
325     p_sys->psz_date_utc = NULL;;
326
327     if( p_sys->es == NULL )
328     {
329         msg_Err( p_input, "failed to create EbmlStream" );
330         delete p_sys->in;
331         free( p_sys );
332         return VLC_EGENERIC;
333     }
334     /* Find the EbmlHead element */
335     el = p_sys->es->FindNextID(EbmlHead::ClassInfos, 0xFFFFFFFFL);
336     if( el == NULL )
337     {
338         msg_Err( p_input, "cannot find EbmlHead" );
339         goto error;
340     }
341     msg_Dbg( p_input, "EbmlHead" );
342     /* skip it */
343     el->SkipData( *p_sys->es, el->Generic().Context );
344     delete el;
345
346     /* Find a segment */
347     el = p_sys->es->FindNextID( KaxSegment::ClassInfos, 0xFFFFFFFFL);
348     if( el == NULL )
349     {
350         msg_Err( p_input, "cannot find KaxSegment" );
351         goto error;
352     }
353     msg_Dbg( p_input, "+ Segment" );
354     p_sys->segment = (KaxSegment*)el;
355     p_sys->cluster = NULL;
356
357     p_sys->ep = new EbmlParser( p_sys->es, el );
358
359     while( ( el1 = p_sys->ep->Get() ) != NULL )
360     {
361         if( EbmlId( *el1 ) == KaxInfo::ClassInfos.GlobalId )
362         {
363             msg_Dbg( p_input, "|   + Informations" );
364
365             p_sys->ep->Down();
366             while( ( el2 = p_sys->ep->Get() ) != NULL )
367             {
368                 if( EbmlId( *el2 ) == KaxTimecodeScale::ClassInfos.GlobalId )
369                 {
370                     KaxTimecodeScale &tcs = *(KaxTimecodeScale*)el2;
371
372                     tcs.ReadData( p_sys->es->I_O() );
373                     p_sys->i_timescale = uint64(tcs);
374
375                     msg_Dbg( p_input, "|   |   + TimecodeScale="I64Fd,
376                              p_sys->i_timescale );
377                 }
378                 else if( EbmlId( *el2 ) == KaxDuration::ClassInfos.GlobalId )
379                 {
380                     KaxDuration &dur = *(KaxDuration*)el2;
381
382                     dur.ReadData( p_sys->es->I_O() );
383                     p_sys->f_duration = float(dur);
384
385                     msg_Dbg( p_input, "|   |   + Duration=%f",
386                              p_sys->f_duration );
387                 }
388                 else if( EbmlId( *el2 ) == KaxMuxingApp::ClassInfos.GlobalId )
389                 {
390                     KaxMuxingApp &mapp = *(KaxMuxingApp*)el2;
391
392                     mapp.ReadData( p_sys->es->I_O() );
393
394                     p_sys->psz_muxing_application = UTF8ToStr( UTFstring( mapp ) );
395
396                     msg_Dbg( p_input, "|   |   + Muxing Application=%s",
397                              p_sys->psz_muxing_application );
398                 }
399                 else if( EbmlId( *el2 ) == KaxWritingApp::ClassInfos.GlobalId )
400                 {
401                     KaxWritingApp &wapp = *(KaxWritingApp*)el2;
402
403                     wapp.ReadData( p_sys->es->I_O() );
404
405                     p_sys->psz_writing_application = UTF8ToStr( UTFstring( wapp ) );
406
407                     msg_Dbg( p_input, "|   |   + Wrinting Application=%s",
408                              p_sys->psz_writing_application );
409                 }
410                 else if( EbmlId( *el2 ) == KaxSegmentFilename::ClassInfos.GlobalId )
411                 {
412                     KaxSegmentFilename &sfn = *(KaxSegmentFilename*)el2;
413
414                     sfn.ReadData( p_sys->es->I_O() );
415
416                     p_sys->psz_segment_filename = UTF8ToStr( UTFstring( sfn ) );
417
418                     msg_Dbg( p_input, "|   |   + Segment Filename=%s",
419                              p_sys->psz_segment_filename );
420                 }
421                 else if( EbmlId( *el2 ) == KaxTitle::ClassInfos.GlobalId )
422                 {
423                     KaxTitle &title = *(KaxTitle*)el2;
424
425                     title.ReadData( p_sys->es->I_O() );
426
427                     p_sys->psz_title = UTF8ToStr( UTFstring( title ) );
428
429                     msg_Dbg( p_input, "|   |   + Title=%s", p_sys->psz_title );
430                 }
431 #ifdef HAVE_GMTIME_R
432                 else if( EbmlId( *el2 ) == KaxDateUTC::ClassInfos.GlobalId )
433                 {
434                     KaxDateUTC &date = *(KaxDateUTC*)el2;
435                     time_t i_date;
436                     struct tm tmres;
437                     char   buffer[256];
438
439                     date.ReadData( p_sys->es->I_O() );
440
441                     i_date = date.GetEpochDate();
442                     memset( buffer, 0, 256 );
443                     if( gmtime_r( &i_date, &tmres ) &&
444                         asctime_r( &tmres, buffer ) )
445                     {
446                         buffer[strlen( buffer)-1]= '\0';
447                         p_sys->psz_date_utc = strdup( buffer );
448                         msg_Dbg( p_input, "|   |   + Date=%s", p_sys->psz_date_utc );
449                     }
450                 }
451 #endif
452                 else
453                 {
454                     msg_Dbg( p_input, "|   |   + Unknown (%s)", typeid(*el2).name() );
455                 }
456             }
457             p_sys->ep->Up();
458         }
459         else if( EbmlId( *el1 ) == KaxTracks::ClassInfos.GlobalId )
460         {
461             msg_Dbg( p_input, "|   + Tracks" );
462
463             p_sys->ep->Down();
464             while( ( el2 = p_sys->ep->Get() ) != NULL )
465             {
466                 if( EbmlId( *el2 ) == KaxTrackEntry::ClassInfos.GlobalId )
467                 {
468                     msg_Dbg( p_input, "|   |   + Track Entry" );
469
470                     p_sys->i_track++;
471                     p_sys->track = (mkv_track_t*)realloc( p_sys->track, sizeof( mkv_track_t ) * (p_sys->i_track + 1 ) );
472 #define tk  p_sys->track[p_sys->i_track - 1]
473                     memset( &tk, 0, sizeof( mkv_track_t ) );
474
475                     es_format_Init( &tk.fmt, UNKNOWN_ES, 0 );
476                     tk.fmt.psz_language = strdup("English");
477                     tk.fmt.psz_description = NULL;
478
479                     tk.b_default = VLC_TRUE;
480                     tk.b_enabled = VLC_TRUE;
481                     tk.i_number = p_sys->i_track - 1;
482                     tk.i_extra_data = 0;
483                     tk.p_extra_data = NULL;
484                     tk.psz_codec = NULL;
485                     tk.i_default_duration = 0;
486                     tk.f_timecodescale = 1.0;
487
488                     tk.b_inited = VLC_FALSE;
489                     tk.i_data_init = 0;
490                     tk.p_data_init = NULL;
491
492                     tk.psz_codec_name = NULL;
493                     tk.psz_codec_settings = NULL;
494                     tk.psz_codec_info_url = NULL;
495                     tk.psz_codec_download_url = NULL;
496
497                     p_sys->ep->Down();
498
499                     while( ( el3 = p_sys->ep->Get() ) != NULL )
500                     {
501                         if( EbmlId( *el3 ) == KaxTrackNumber::ClassInfos.GlobalId )
502                         {
503                             KaxTrackNumber &tnum = *(KaxTrackNumber*)el3;
504                             tnum.ReadData( p_sys->es->I_O() );
505
506                             tk.i_number = uint32( tnum );
507                             msg_Dbg( p_input, "|   |   |   + Track Number=%u",
508                                      uint32( tnum ) );
509                         }
510                         else  if( EbmlId( *el3 ) == KaxTrackUID::ClassInfos.GlobalId )
511                         {
512                             KaxTrackUID &tuid = *(KaxTrackUID*)el3;
513                             tuid.ReadData( p_sys->es->I_O() );
514
515                             msg_Dbg( p_input, "|   |   |   + Track UID=%u",
516                                      uint32( tuid ) );
517                         }
518                         else  if( EbmlId( *el3 ) == KaxTrackType::ClassInfos.GlobalId )
519                         {
520                             char *psz_type;
521                             KaxTrackType &ttype = *(KaxTrackType*)el3;
522                             ttype.ReadData( p_sys->es->I_O() );
523                             switch( uint8(ttype) )
524                             {
525                                 case track_audio:
526                                     psz_type = "audio";
527                                     tk.fmt.i_cat = AUDIO_ES;
528                                     break;
529                                 case track_video:
530                                     psz_type = "video";
531                                     tk.fmt.i_cat = VIDEO_ES;
532                                     break;
533                                 case track_subtitle:
534                                     psz_type = "subtitle";
535                                     tk.fmt.i_cat = SPU_ES;
536                                     break;
537                                 default:
538                                     psz_type = "unknown";
539                                     tk.fmt.i_cat = UNKNOWN_ES;
540                                     break;
541                             }
542
543                             msg_Dbg( p_input, "|   |   |   + Track Type=%s",
544                                      psz_type );
545                         }
546 //                         else  if( EbmlId( *el3 ) == KaxTrackFlagEnabled::ClassInfos.GlobalId )
547 //                         {
548 //                             KaxTrackFlagEnabled &fenb = *(KaxTrackFlagEnabled*)el3;
549 //                             fenb.ReadData( p_sys->es->I_O() );
550
551 //                             tk.b_enabled = uint32( fenb );
552 //                             msg_Dbg( p_input, "|   |   |   + Track Enabled=%u",
553 //                                      uint32( fenb )  );
554 //                         }
555                         else  if( EbmlId( *el3 ) == KaxTrackFlagDefault::ClassInfos.GlobalId )
556                         {
557                             KaxTrackFlagDefault &fdef = *(KaxTrackFlagDefault*)el3;
558                             fdef.ReadData( p_sys->es->I_O() );
559
560                             tk.b_default = uint32( fdef );
561                             msg_Dbg( p_input, "|   |   |   + Track Default=%u",
562                                      uint32( fdef )  );
563                         }
564                         else  if( EbmlId( *el3 ) == KaxTrackFlagLacing::ClassInfos.GlobalId )
565                         {
566                             KaxTrackFlagLacing &lac = *(KaxTrackFlagLacing*)el3;
567                             lac.ReadData( p_sys->es->I_O() );
568
569                             msg_Dbg( p_input, "|   |   |   + Track Lacing=%d",
570                                      uint32( lac ) );
571                         }
572                         else  if( EbmlId( *el3 ) == KaxTrackMinCache::ClassInfos.GlobalId )
573                         {
574                             KaxTrackMinCache &cmin = *(KaxTrackMinCache*)el3;
575                             cmin.ReadData( p_sys->es->I_O() );
576
577                             msg_Dbg( p_input, "|   |   |   + Track MinCache=%d",
578                                      uint32( cmin ) );
579                         }
580                         else  if( EbmlId( *el3 ) == KaxTrackMaxCache::ClassInfos.GlobalId )
581                         {
582                             KaxTrackMaxCache &cmax = *(KaxTrackMaxCache*)el3;
583                             cmax.ReadData( p_sys->es->I_O() );
584
585                             msg_Dbg( p_input, "|   |   |   + Track MaxCache=%d",
586                                      uint32( cmax ) );
587                         }
588                         else  if( EbmlId( *el3 ) == KaxTrackDefaultDuration::ClassInfos.GlobalId )
589                         {
590                             KaxTrackDefaultDuration &defd = *(KaxTrackDefaultDuration*)el3;
591                             defd.ReadData( p_sys->es->I_O() );
592
593                             tk.i_default_duration = uint64(defd);
594                             msg_Dbg( p_input, "|   |   |   + Track Default Duration="I64Fd, uint64(defd) );
595                         }
596                         else  if( EbmlId( *el3 ) == KaxTrackTimecodeScale::ClassInfos.GlobalId )
597                         {
598                             KaxTrackTimecodeScale &ttcs = *(KaxTrackTimecodeScale*)el3;
599                             ttcs.ReadData( p_sys->es->I_O() );
600
601                             tk.f_timecodescale = float( ttcs );
602                             msg_Dbg( p_input, "|   |   |   + Track TimeCodeScale=%f", tk.f_timecodescale );
603                         }
604                         else if( EbmlId( *el3 ) == KaxTrackName::ClassInfos.GlobalId )
605                         {
606                             KaxTrackName &tname = *(KaxTrackName*)el3;
607                             tname.ReadData( p_sys->es->I_O() );
608
609                             tk.fmt.psz_description = UTF8ToStr( UTFstring( tname ) );
610                             msg_Dbg( p_input, "|   |   |   + Track Name=%s",
611                                      tk.fmt.psz_description );
612                         }
613                         else  if( EbmlId( *el3 ) == KaxTrackLanguage::ClassInfos.GlobalId )
614                         {
615                             KaxTrackLanguage &lang = *(KaxTrackLanguage*)el3;
616                             lang.ReadData( p_sys->es->I_O() );
617
618                             tk.fmt.psz_language =
619                                 LanguageGetName( string( lang ).c_str() );
620                             msg_Dbg( p_input,
621                                      "|   |   |   + Track Language=`%s'(%s) ",
622                                      tk.fmt.psz_language, string( lang ).c_str() );
623                         }
624                         else  if( EbmlId( *el3 ) == KaxCodecID::ClassInfos.GlobalId )
625                         {
626                             KaxCodecID &codecid = *(KaxCodecID*)el3;
627                             codecid.ReadData( p_sys->es->I_O() );
628
629                             tk.psz_codec = strdup( string( codecid ).c_str() );
630                             msg_Dbg( p_input, "|   |   |   + Track CodecId=%s",
631                                      string( codecid ).c_str() );
632                         }
633                         else  if( EbmlId( *el3 ) == KaxCodecPrivate::ClassInfos.GlobalId )
634                         {
635                             KaxCodecPrivate &cpriv = *(KaxCodecPrivate*)el3;
636                             cpriv.ReadData( p_sys->es->I_O(), SCOPE_ALL_DATA );
637
638                             tk.i_extra_data = cpriv.GetSize();
639                             if( tk.i_extra_data > 0 )
640                             {
641                                 tk.p_extra_data = (uint8_t*)malloc( tk.i_extra_data );
642                                 memcpy( tk.p_extra_data, cpriv.GetBuffer(), tk.i_extra_data );
643                             }
644                             msg_Dbg( p_input, "|   |   |   + Track CodecPrivate size="I64Fd, cpriv.GetSize() );
645                         }
646                         else if( EbmlId( *el3 ) == KaxCodecName::ClassInfos.GlobalId )
647                         {
648                             KaxCodecName &cname = *(KaxCodecName*)el3;
649                             cname.ReadData( p_sys->es->I_O() );
650
651                             tk.psz_codec_name = UTF8ToStr( UTFstring( cname ) );
652                             msg_Dbg( p_input, "|   |   |   + Track Codec Name=%s", tk.psz_codec_name );
653                         }
654 //                         else if( EbmlId( *el3 ) == KaxCodecSettings::ClassInfos.GlobalId )
655 //                         {
656 //                             KaxCodecSettings &cset = *(KaxCodecSettings*)el3;
657 //                             cset.ReadData( p_sys->es->I_O() );
658
659 //                             tk.psz_codec_settings = UTF8ToStr( UTFstring( cset ) );
660 //                             msg_Dbg( p_input, "|   |   |   + Track Codec Settings=%s", tk.psz_codec_settings );
661 //                         }
662 //                         else if( EbmlId( *el3 ) == KaxCodecInfoURL::ClassInfos.GlobalId )
663 //                         {
664 //                             KaxCodecInfoURL &ciurl = *(KaxCodecInfoURL*)el3;
665 //                             ciurl.ReadData( p_sys->es->I_O() );
666
667 //                             tk.psz_codec_info_url = strdup( string( ciurl ).c_str() );
668 //                             msg_Dbg( p_input, "|   |   |   + Track Codec Info URL=%s", tk.psz_codec_info_url );
669 //                         }
670 //                         else if( EbmlId( *el3 ) == KaxCodecDownloadURL::ClassInfos.GlobalId )
671 //                         {
672 //                             KaxCodecDownloadURL &cdurl = *(KaxCodecDownloadURL*)el3;
673 //                             cdurl.ReadData( p_sys->es->I_O() );
674
675 //                             tk.psz_codec_download_url = strdup( string( cdurl ).c_str() );
676 //                             msg_Dbg( p_input, "|   |   |   + Track Codec Info URL=%s", tk.psz_codec_download_url );
677 //                         }
678 //                         else if( EbmlId( *el3 ) == KaxCodecDecodeAll::ClassInfos.GlobalId )
679 //                         {
680 //                             KaxCodecDecodeAll &cdall = *(KaxCodecDecodeAll*)el3;
681 //                             cdall.ReadData( p_sys->es->I_O() );
682
683 //                             msg_Dbg( p_input, "|   |   |   + Track Codec Decode All=%u <== UNUSED", uint8( cdall ) );
684 //                         }
685 //                         else if( EbmlId( *el3 ) == KaxTrackOverlay::ClassInfos.GlobalId )
686 //                         {
687 //                             KaxTrackOverlay &tovr = *(KaxTrackOverlay*)el3;
688 //                             tovr.ReadData( p_sys->es->I_O() );
689
690 //                             msg_Dbg( p_input, "|   |   |   + Track Overlay=%u <== UNUSED", uint32( tovr ) );
691 //                         }
692                         else  if( EbmlId( *el3 ) == KaxTrackVideo::ClassInfos.GlobalId )
693                         {
694                             msg_Dbg( p_input, "|   |   |   + Track Video" );
695                             tk.f_fps = 0.0;
696
697                             p_sys->ep->Down();
698
699                             while( ( el4 = p_sys->ep->Get() ) != NULL )
700                             {
701 //                                 if( EbmlId( *el4 ) == KaxVideoFlagInterlaced::ClassInfos.GlobalId )
702 //                                 {
703 //                                     KaxVideoFlagInterlaced &fint = *(KaxVideoFlagInterlaced*)el4;
704 //                                     fint.ReadData( p_sys->es->I_O() );
705
706 //                                     msg_Dbg( p_input, "|   |   |   |   + Track Video Interlaced=%u", uint8( fint ) );
707 //                                 }
708 //                                 else if( EbmlId( *el4 ) == KaxVideoStereoMode::ClassInfos.GlobalId )
709 //                                 {
710 //                                     KaxVideoStereoMode &stereo = *(KaxVideoStereoMode*)el4;
711 //                                     stereo.ReadData( p_sys->es->I_O() );
712
713 //                                     msg_Dbg( p_input, "|   |   |   |   + Track Video Stereo Mode=%u", uint8( stereo ) );
714 //                                 }
715 //                                 else 
716                               if( EbmlId( *el4 ) == KaxVideoPixelWidth::ClassInfos.GlobalId )
717                                 {
718                                     KaxVideoPixelWidth &vwidth = *(KaxVideoPixelWidth*)el4;
719                                     vwidth.ReadData( p_sys->es->I_O() );
720
721                                     tk.fmt.video.i_width = uint16( vwidth );
722                                     msg_Dbg( p_input, "|   |   |   |   + width=%d", uint16( vwidth ) );
723                                 }
724                                 else if( EbmlId( *el4 ) == KaxVideoPixelHeight::ClassInfos.GlobalId )
725                                 {
726                                     KaxVideoPixelWidth &vheight = *(KaxVideoPixelWidth*)el4;
727                                     vheight.ReadData( p_sys->es->I_O() );
728
729                                     tk.fmt.video.i_height = uint16( vheight );
730                                     msg_Dbg( p_input, "|   |   |   |   + height=%d", uint16( vheight ) );
731                                 }
732                                 else if( EbmlId( *el4 ) == KaxVideoDisplayWidth::ClassInfos.GlobalId )
733                                 {
734                                     KaxVideoDisplayWidth &vwidth = *(KaxVideoDisplayWidth*)el4;
735                                     vwidth.ReadData( p_sys->es->I_O() );
736
737                                     tk.fmt.video.i_visible_width = uint16( vwidth );
738                                     msg_Dbg( p_input, "|   |   |   |   + display width=%d", uint16( vwidth ) );
739                                 }
740                                 else if( EbmlId( *el4 ) == KaxVideoDisplayHeight::ClassInfos.GlobalId )
741                                 {
742                                     KaxVideoDisplayWidth &vheight = *(KaxVideoDisplayWidth*)el4;
743                                     vheight.ReadData( p_sys->es->I_O() );
744
745                                     tk.fmt.video.i_visible_height = uint16( vheight );
746                                     msg_Dbg( p_input, "|   |   |   |   + display height=%d", uint16( vheight ) );
747                                 }
748                                 else if( EbmlId( *el4 ) == KaxVideoFrameRate::ClassInfos.GlobalId )
749                                 {
750                                     KaxVideoFrameRate &vfps = *(KaxVideoFrameRate*)el4;
751                                     vfps.ReadData( p_sys->es->I_O() );
752
753                                     tk.f_fps = float( vfps );
754                                     msg_Dbg( p_input, "   |   |   |   + fps=%f", float( vfps ) );
755                                 }
756 //                                 else if( EbmlId( *el4 ) == KaxVideoDisplayUnit::ClassInfos.GlobalId )
757 //                                 {
758 //                                      KaxVideoDisplayUnit &vdmode = *(KaxVideoDisplayUnit*)el4;
759 //                                     vdmode.ReadData( p_sys->es->I_O() );
760
761 //                                     msg_Dbg( p_input, "|   |   |   |   + Track Video Display Unit=%s",
762 //                                              uint8( vdmode ) == 0 ? "pixels" : ( uint8( vdmode ) == 1 ? "centimeters": "inches" ) );
763 //                                 }
764 //                                 else if( EbmlId( *el4 ) == KaxVideoAspectRatio::ClassInfos.GlobalId )
765 //                                 {
766 //                                     KaxVideoAspectRatio &ratio = *(KaxVideoAspectRatio*)el4;
767 //                                     ratio.ReadData( p_sys->es->I_O() );
768
769 //                                     msg_Dbg( p_input, "   |   |   |   + Track Video Aspect Ratio Type=%u", uint8( ratio ) );
770 //                                 }
771 //                                 else if( EbmlId( *el4 ) == KaxVideoGamma::ClassInfos.GlobalId )
772 //                                 {
773 //                                     KaxVideoGamma &gamma = *(KaxVideoGamma*)el4;
774 //                                     gamma.ReadData( p_sys->es->I_O() );
775
776 //                                     msg_Dbg( p_input, "   |   |   |   + fps=%f", float( gamma ) );
777 //                                 }
778                                 else
779                                 {
780                                     msg_Dbg( p_input, "|   |   |   |   + Unknown (%s)", typeid(*el4).name() );
781                                 }
782                             }
783                             p_sys->ep->Up();
784                         }
785                         else  if( EbmlId( *el3 ) == KaxTrackAudio::ClassInfos.GlobalId )
786                         {
787                             msg_Dbg( p_input, "|   |   |   + Track Audio" );
788
789                             p_sys->ep->Down();
790
791                             while( ( el4 = p_sys->ep->Get() ) != NULL )
792                             {
793                                 if( EbmlId( *el4 ) == KaxAudioSamplingFreq::ClassInfos.GlobalId )
794                                 {
795                                     KaxAudioSamplingFreq &afreq = *(KaxAudioSamplingFreq*)el4;
796                                     afreq.ReadData( p_sys->es->I_O() );
797
798                                     tk.fmt.audio.i_rate = (int)float( afreq );
799                                     msg_Dbg( p_input, "|   |   |   |   + afreq=%d", tk.fmt.audio.i_rate );
800                                 }
801                                 else if( EbmlId( *el4 ) == KaxAudioChannels::ClassInfos.GlobalId )
802                                 {
803                                     KaxAudioChannels &achan = *(KaxAudioChannels*)el4;
804                                     achan.ReadData( p_sys->es->I_O() );
805
806                                     tk.fmt.audio.i_channels = uint8( achan );
807                                     msg_Dbg( p_input, "|   |   |   |   + achan=%u", uint8( achan ) );
808                                 }
809                                 else if( EbmlId( *el4 ) == KaxAudioBitDepth::ClassInfos.GlobalId )
810                                 {
811                                     KaxAudioBitDepth &abits = *(KaxAudioBitDepth*)el4;
812                                     abits.ReadData( p_sys->es->I_O() );
813
814                                     tk.fmt.audio.i_bitspersample = uint8( abits );
815                                     msg_Dbg( p_input, "|   |   |   |   + abits=%u", uint8( abits ) );
816                                 }
817                                 else
818                                 {
819                                     msg_Dbg( p_input, "|   |   |   |   + Unknown (%s)", typeid(*el4).name() );
820                                 }
821                             }
822                             p_sys->ep->Up();
823                         }
824                         else
825                         {
826                             msg_Dbg( p_input, "|   |   |   + Unknown (%s)",
827                                      typeid(*el3).name() );
828                         }
829                     }
830                     p_sys->ep->Up();
831                 }
832                 else
833                 {
834                     msg_Dbg( p_input, "|   |   + Unknown (%s)",
835                              typeid(*el2).name() );
836                 }
837 #undef tk
838             }
839             p_sys->ep->Up();
840         }
841         else if( EbmlId( *el1 ) == KaxSeekHead::ClassInfos.GlobalId )
842         {
843             msg_Dbg( p_input, "|   + Seek head" );
844             p_sys->ep->Down();
845             while( ( el = p_sys->ep->Get() ) != NULL )
846             {
847                 if( EbmlId( *el ) == KaxSeek::ClassInfos.GlobalId )
848                 {
849                     EbmlId id = EbmlVoid::ClassInfos.GlobalId;
850                     int64_t i_pos = -1;
851
852                     //msg_Dbg( p_input, "|   |   + Seek" );
853                     p_sys->ep->Down();
854                     while( ( el = p_sys->ep->Get() ) != NULL )
855                     {
856                         if( EbmlId( *el ) == KaxSeekID::ClassInfos.GlobalId )
857                         {
858                             KaxSeekID &sid = *(KaxSeekID*)el;
859
860                             sid.ReadData( p_sys->es->I_O(), SCOPE_ALL_DATA );
861
862                             id = EbmlId( sid.GetBuffer(), sid.GetSize() );
863                         }
864                         else  if( EbmlId( *el ) == KaxSeekPosition::ClassInfos.GlobalId )
865                         {
866                             KaxSeekPosition &spos = *(KaxSeekPosition*)el;
867
868                             spos.ReadData( p_sys->es->I_O(), SCOPE_ALL_DATA );
869
870                             i_pos = uint64( spos );
871                         }
872                         else
873                         {
874                             msg_Dbg( p_input, "|   |   |   + Unknown (%s)",
875                                      typeid(*el).name() );
876                         }
877                     }
878                     p_sys->ep->Up();
879
880                     if( i_pos >= 0 )
881                     {
882                         if( id == KaxCues::ClassInfos.GlobalId )
883                         {
884                             msg_Dbg( p_input, "|   |   |   = cues at "I64Fd,
885                                      i_pos );
886                             p_sys->i_cues_position = p_sys->segment->GetGlobalPosition( i_pos );
887                         }
888                         else if( id == KaxChapters::ClassInfos.GlobalId )
889                         {
890                             msg_Dbg( p_input, "|   |   |   = chapters at "I64Fd,
891                                      i_pos );
892                             p_sys->i_chapters_position = p_sys->segment->GetGlobalPosition( i_pos );
893                         }
894                         else if( id == KaxTags::ClassInfos.GlobalId )
895                         {
896                             msg_Dbg( p_input, "|   |   |   = tags at "I64Fd,
897                                      i_pos );
898                             p_sys->i_tags_position = p_sys->segment->GetGlobalPosition( i_pos );
899                         }
900
901                     }
902                 }
903                 else
904                 {
905                     msg_Dbg( p_input, "|   |   + Unknown (%s)",
906                              typeid(*el).name() );
907                 }
908             }
909             p_sys->ep->Up();
910         }
911         else if( EbmlId( *el1 ) == KaxCues::ClassInfos.GlobalId )
912         {
913             msg_Dbg( p_input, "|   + Cues" );
914         }
915         else if( EbmlId( *el1 ) == KaxCluster::ClassInfos.GlobalId )
916         {
917             msg_Dbg( p_input, "|   + Cluster" );
918
919             p_sys->cluster = (KaxCluster*)el1;
920
921             p_sys->ep->Down();
922             /* stop parsing the stream */
923             break;
924         }
925 #ifdef HAVE_MATROSKA_KAXATTACHMENTS_H
926         else if( EbmlId( *el1 ) == KaxAttachments::ClassInfos.GlobalId )
927 #else
928         else if( EbmlId( *el1 ) == KaxAttachements::ClassInfos.GlobalId )
929 #endif
930         {
931             msg_Dbg( p_input, "|   + Attachments FIXME TODO (but probably never supported)" );
932         }
933         else if( EbmlId( *el1 ) == KaxChapters::ClassInfos.GlobalId )
934         {
935             msg_Dbg( p_input, "|   + Chapters FIXME TODO" );
936         }
937         else if( EbmlId( *el1 ) == KaxTag::ClassInfos.GlobalId )
938         {
939             msg_Dbg( p_input, "|   + Tags FIXME TODO" );
940         }
941         else
942         {
943             msg_Dbg( p_input, "|   + Unknown (%s)", typeid(*el1).name() );
944         }
945     }
946
947     if( p_sys->cluster == NULL )
948     {
949         msg_Err( p_input, "cannot find any cluster, damaged file ?" );
950         goto error;
951     }
952
953     if( p_sys->i_chapters_position >= 0 )
954     {
955         msg_Warn( p_input, "chapters unsupported" );
956     }
957
958     /* *** Load the cue if found *** */
959     if( p_sys->i_cues_position >= 0 )
960     {
961         vlc_bool_t b_seekable;
962
963         stream_Control( p_input->s, STREAM_CAN_FASTSEEK, &b_seekable );
964         if( b_seekable )
965         {
966             LoadCues( p_input );
967         }
968     }
969
970     if( !p_sys->b_cues || p_sys->i_index <= 0 )
971     {
972         msg_Warn( p_input, "no cues/empty cues found->seek won't be precise" );
973
974         IndexAppendCluster( p_input, p_sys->cluster );
975
976         p_sys->b_cues = VLC_FALSE;
977     }
978
979     /* Create one program */
980     vlc_mutex_lock( &p_input->stream.stream_lock );
981     if( input_InitStream( p_input, 0 ) == -1)
982     {
983         vlc_mutex_unlock( &p_input->stream.stream_lock );
984         msg_Err( p_input, "cannot init stream" );
985         goto error;
986     }
987     p_input->stream.i_mux_rate = 0;
988     vlc_mutex_unlock( &p_input->stream.stream_lock );
989
990     if( p_sys->f_duration > 1001.0 )
991     {
992         mtime_t i_duration = (mtime_t)( p_sys->f_duration / 1000.0 );
993         p_input->stream.i_mux_rate = stream_Size( p_input->s )/50 / i_duration;
994     }
995
996     /* add all es */
997     msg_Dbg( p_input, "found %d es", p_sys->i_track );
998     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
999     {
1000 #define tk  p_sys->track[i_track]
1001         if( tk.fmt.i_cat == UNKNOWN_ES )
1002         {
1003             msg_Warn( p_input, "invalid track[%d, n=%d]", i_track, tk.i_number );
1004             tk.p_es = NULL;
1005             continue;
1006         }
1007
1008         if( tk.fmt.i_cat == SPU_ES )
1009         {
1010             vlc_value_t val;
1011             val.psz_string = "UTF-8";
1012 #if defined(HAVE_ICONV)
1013             var_Create( p_input, "subsdec-encoding", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
1014             var_Set( p_input, "subsdec-encoding", val );
1015 #endif
1016         }
1017         if( !strcmp( tk.psz_codec, "V_MS/VFW/FOURCC" ) )
1018         {
1019             if( tk.i_extra_data < (int)sizeof( BITMAPINFOHEADER ) )
1020             {
1021                 msg_Err( p_input, "missing/invalid BITMAPINFOHEADER" );
1022                 tk.fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1023             }
1024             else
1025             {
1026                 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)tk.p_extra_data;
1027
1028                 tk.fmt.video.i_width = GetDWLE( &p_bih->biWidth );
1029                 tk.fmt.video.i_height= GetDWLE( &p_bih->biHeight );
1030                 tk.fmt.i_codec       = GetFOURCC( &p_bih->biCompression );
1031
1032                 tk.fmt.i_extra       = GetDWLE( &p_bih->biSize ) - sizeof( BITMAPINFOHEADER );
1033                 if( tk.fmt.i_extra > 0 )
1034                 {
1035                     tk.fmt.p_extra = malloc( tk.fmt.i_extra );
1036                     memcpy( tk.fmt.p_extra, &p_bih[1], tk.fmt.i_extra );
1037                 }
1038             }
1039         }
1040         else if( !strcmp( tk.psz_codec, "V_MPEG1" ) ||
1041                  !strcmp( tk.psz_codec, "V_MPEG2" ) )
1042         {
1043             tk.fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
1044         }
1045         else if( !strncmp( tk.psz_codec, "V_MPEG4", 7 ) )
1046         {
1047             if( !strcmp( tk.psz_codec, "V_MPEG4/MS/V3" ) )
1048             {
1049                 tk.fmt.i_codec = VLC_FOURCC( 'D', 'I', 'V', '3' );
1050             }
1051             else
1052             {
1053                 tk.fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
1054             }
1055         }
1056         else if( !strcmp( tk.psz_codec, "A_MS/ACM" ) )
1057         {
1058             if( tk.i_extra_data < (int)sizeof( WAVEFORMATEX ) )
1059             {
1060                 msg_Err( p_input, "missing/invalid WAVEFORMATEX" );
1061                 tk.fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1062             }
1063             else
1064             {
1065                 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)tk.p_extra_data;
1066
1067                 wf_tag_to_fourcc( GetWLE( &p_wf->wFormatTag ), &tk.fmt.i_codec, NULL );
1068
1069                 tk.fmt.audio.i_channels   = GetWLE( &p_wf->nChannels );
1070                 tk.fmt.audio.i_rate = GetDWLE( &p_wf->nSamplesPerSec );
1071                 tk.fmt.i_bitrate    = GetDWLE( &p_wf->nAvgBytesPerSec ) * 8;
1072                 tk.fmt.audio.i_blockalign = GetWLE( &p_wf->nBlockAlign );;
1073                 tk.fmt.audio.i_bitspersample = GetWLE( &p_wf->wBitsPerSample );
1074
1075                 tk.fmt.i_extra            = GetWLE( &p_wf->cbSize );
1076                 if( tk.fmt.i_extra > 0 )
1077                 {
1078                     tk.fmt.p_extra = malloc( tk.fmt.i_extra );
1079                     memcpy( tk.fmt.p_extra, &p_wf[1], tk.fmt.i_extra );
1080                 }
1081             }
1082         }
1083         else if( !strcmp( tk.psz_codec, "A_MPEG/L3" ) ||
1084                  !strcmp( tk.psz_codec, "A_MPEG/L2" ) ||
1085                  !strcmp( tk.psz_codec, "A_MPEG/L1" ) )
1086         {
1087             tk.fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
1088         }
1089         else if( !strcmp( tk.psz_codec, "A_AC3" ) )
1090         {
1091             tk.fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
1092         }
1093         else if( !strcmp( tk.psz_codec, "A_DTS" ) )
1094         {
1095             tk.fmt.i_codec = VLC_FOURCC( 'd', 't', 's', ' ' );
1096         }
1097         else if( !strcmp( tk.psz_codec, "A_FLAC" ) )
1098         {
1099             tk.fmt.i_codec = VLC_FOURCC( 'f', 'l', 'a', 'c' );
1100             tk.fmt.i_extra = tk.i_extra_data;
1101             tk.fmt.p_extra = malloc( tk.i_extra_data );
1102             memcpy( tk.fmt.p_extra,tk.p_extra_data, tk.i_extra_data );
1103         }
1104         else if( !strcmp( tk.psz_codec, "A_VORBIS" ) )
1105         {
1106             tk.fmt.i_codec = VLC_FOURCC( 'v', 'o', 'r', 'b' );
1107             tk.i_data_init = tk.i_extra_data;
1108             tk.p_data_init = tk.p_extra_data;
1109         }
1110         else if( !strncmp( tk.psz_codec, "A_AAC/MPEG2/", strlen( "A_AAC/MPEG2/" ) ) ||
1111                  !strncmp( tk.psz_codec, "A_AAC/MPEG4/", strlen( "A_AAC/MPEG4/" ) ) )
1112         {
1113             int i_profile, i_srate;
1114             static unsigned int i_sample_rates[] =
1115             {
1116                     96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1117                         16000, 12000, 11025, 8000,  7350,  0,     0,     0
1118             };
1119
1120             tk.fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
1121             /* create data for faad (MP4DecSpecificDescrTag)*/
1122
1123             if( !strcmp( &tk.psz_codec[12], "MAIN" ) )
1124             {
1125                 i_profile = 0;
1126             }
1127             else if( !strcmp( &tk.psz_codec[12], "LC" ) )
1128             {
1129                 i_profile = 1;
1130             }
1131             else if( !strcmp( &tk.psz_codec[12], "SSR" ) )
1132             {
1133                 i_profile = 2;
1134             }
1135             else
1136             {
1137                 i_profile = 3;
1138             }
1139
1140             for( i_srate = 0; i_srate < 13; i_srate++ )
1141             {
1142                 if( i_sample_rates[i_srate] == tk.fmt.audio.i_rate )
1143                 {
1144                     break;
1145                 }
1146             }
1147             msg_Dbg( p_input, "profile=%d srate=%d", i_profile, i_srate );
1148
1149             tk.fmt.i_extra = 2;
1150             tk.fmt.p_extra = malloc( tk.fmt.i_extra );
1151             ((uint8_t*)tk.fmt.p_extra)[0] = ((i_profile + 1) << 3) | ((i_srate&0xe) >> 1);
1152             ((uint8_t*)tk.fmt.p_extra)[1] = ((i_srate & 0x1) << 7) | (tk.fmt.audio.i_channels << 3);
1153         }
1154         else if( !strcmp( tk.psz_codec, "A_PCM/INT/BIG" ) ||
1155                  !strcmp( tk.psz_codec, "A_PCM/INT/LIT" ) ||
1156                  !strcmp( tk.psz_codec, "A_PCM/FLOAT/IEEE" ) )
1157         {
1158             if( !strcmp( tk.psz_codec, "A_PCM/INT/BIG" ) )
1159             {
1160                 tk.fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
1161             }
1162             else
1163             {
1164                 tk.fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
1165             }
1166             tk.fmt.audio.i_blockalign = ( tk.fmt.audio.i_bitspersample + 7 ) / 8 * tk.fmt.audio.i_channels;
1167         }
1168         else if( !strcmp( tk.psz_codec, "S_TEXT/UTF8" ) )
1169         {
1170             tk.fmt.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
1171         }
1172         else if( !strcmp( tk.psz_codec, "S_TEXT/SSA" ) ||
1173                  !strcmp( tk.psz_codec, "S_SSA" ) ||
1174                  !strcmp( tk.psz_codec, "S_ASS" ))
1175         {
1176             tk.fmt.i_codec = VLC_FOURCC( 's', 's', 'a', ' ' );
1177 #if 0
1178             /* FIXME */
1179             tk.fmt.i_extra = sizeof( subtitle_data_t );
1180             tk.fmt.p_extra = malloc( tk.fmt.i_extra );
1181             ((es_sys_t*)tk->fmt.p_extra)->psz_header = strdup( (char *)tk.p_extra_data );
1182 #endif
1183         }
1184         else if( !strcmp( tk.psz_codec, "S_VOBSUB" ) )
1185         {
1186             tk.fmt.i_codec = VLC_FOURCC( 's','p','u',' ' );
1187         }
1188         else
1189         {
1190             msg_Err( p_input, "unknow codec id=`%s'", tk.psz_codec );
1191             tk.fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1192         }
1193
1194         tk.p_es = es_out_Add( p_input->p_es_out, &tk.fmt );
1195 #undef tk
1196     }
1197
1198     /* add informations */
1199     InformationsCreate( p_input );
1200
1201     return VLC_SUCCESS;
1202
1203 error:
1204     delete p_sys->es;
1205     delete p_sys->in;
1206     free( p_sys );
1207     return VLC_EGENERIC;
1208 }
1209
1210 /*****************************************************************************
1211  * Close: frees unused data
1212  *****************************************************************************/
1213 static void Close( vlc_object_t *p_this )
1214 {
1215     input_thread_t *p_input = (input_thread_t *)p_this;
1216     demux_sys_t    *p_sys   = p_input->p_demux_data;
1217
1218     int             i_track;
1219
1220     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1221     {
1222 #define tk  p_sys->track[i_track]
1223         if( tk.fmt.psz_description )
1224         {
1225             free( tk.fmt.psz_language );
1226         }
1227         if( tk.psz_codec )
1228         {
1229             free( tk.psz_codec );
1230         }
1231         if( tk.fmt.psz_language )
1232         {
1233             free( tk.fmt.psz_language );
1234         }
1235 #undef tk
1236     }
1237     free( p_sys->track );
1238
1239     if( p_sys->psz_writing_application  )
1240     {
1241         free( p_sys->psz_writing_application );
1242     }
1243     if( p_sys->psz_muxing_application  )
1244     {
1245         free( p_sys->psz_muxing_application );
1246     }
1247
1248     delete p_sys->segment;
1249
1250     delete p_sys->ep;
1251     delete p_sys->es;
1252     delete p_sys->in;
1253
1254     free( p_sys );
1255 }
1256
1257 static int BlockGet( input_thread_t *p_input, KaxBlock **pp_block, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration )
1258 {
1259     demux_sys_t    *p_sys   = p_input->p_demux_data;
1260
1261     *pp_block = NULL;
1262     *pi_ref1  = -1;
1263     *pi_ref2  = -1;
1264
1265     for( ;; )
1266     {
1267         EbmlElement *el;
1268         int         i_level;
1269
1270         if( p_input->b_die )
1271         {
1272             return VLC_EGENERIC;
1273         }
1274
1275         el = p_sys->ep->Get();
1276         i_level = p_sys->ep->GetLevel();
1277
1278         if( el == NULL && *pp_block != NULL )
1279         {
1280             /* update the index */
1281 #define idx p_sys->index[p_sys->i_index - 1]
1282             if( p_sys->i_index > 0 && idx.i_time == -1 )
1283             {
1284                 idx.i_time        = (*pp_block)->GlobalTimecode() * (mtime_t) 1000 / p_sys->i_timescale;
1285                 idx.b_key         = *pi_ref1 == -1 ? VLC_TRUE : VLC_FALSE;
1286             }
1287 #undef idx
1288             return VLC_SUCCESS;
1289         }
1290
1291         if( el == NULL )
1292         {
1293             if( p_sys->ep->GetLevel() > 1 )
1294             {
1295                 p_sys->ep->Up();
1296                 continue;
1297             }
1298             msg_Warn( p_input, "EOF" );
1299             return VLC_EGENERIC;
1300         }
1301
1302         /* do parsing */
1303         if( i_level == 1 )
1304         {
1305             if( EbmlId( *el ) == KaxCluster::ClassInfos.GlobalId )
1306             {
1307                 p_sys->cluster = (KaxCluster*)el;
1308
1309                 /* add it to the index */
1310                 if( p_sys->i_index == 0 ||
1311                     ( p_sys->i_index > 0 && p_sys->index[p_sys->i_index - 1].i_position < (int64_t)p_sys->cluster->GetElementPosition() ) )
1312                 {
1313                     IndexAppendCluster( p_input, p_sys->cluster );
1314                 }
1315
1316                 p_sys->ep->Down();
1317             }
1318             else if( EbmlId( *el ) == KaxCues::ClassInfos.GlobalId )
1319             {
1320                 msg_Warn( p_input, "find KaxCues FIXME" );
1321                 return VLC_EGENERIC;
1322             }
1323             else
1324             {
1325                 msg_Dbg( p_input, "unknown (%s)", typeid( el ).name() );
1326             }
1327         }
1328         else if( i_level == 2 )
1329         {
1330             if( EbmlId( *el ) == KaxClusterTimecode::ClassInfos.GlobalId )
1331             {
1332                 KaxClusterTimecode &ctc = *(KaxClusterTimecode*)el;
1333
1334                 ctc.ReadData( p_sys->es->I_O(), SCOPE_ALL_DATA );
1335                 p_sys->cluster->InitTimecode( uint64( ctc ), p_sys->i_timescale );
1336             }
1337             else if( EbmlId( *el ) == KaxBlockGroup::ClassInfos.GlobalId )
1338             {
1339                 p_sys->ep->Down();
1340             }
1341         }
1342         else if( i_level == 3 )
1343         {
1344             if( EbmlId( *el ) == KaxBlock::ClassInfos.GlobalId )
1345             {
1346                 *pp_block = (KaxBlock*)el;
1347
1348                 (*pp_block)->ReadData( p_sys->es->I_O() );
1349                 (*pp_block)->SetParent( *p_sys->cluster );
1350
1351                 p_sys->ep->Keep();
1352             }
1353             else if( EbmlId( *el ) == KaxBlockDuration::ClassInfos.GlobalId )
1354             {
1355                 KaxBlockDuration &dur = *(KaxBlockDuration*)el;
1356
1357                 dur.ReadData( p_sys->es->I_O() );
1358                 *pi_duration = uint64( dur );
1359             }
1360             else if( EbmlId( *el ) == KaxReferenceBlock::ClassInfos.GlobalId )
1361             {
1362                 KaxReferenceBlock &ref = *(KaxReferenceBlock*)el;
1363
1364                 ref.ReadData( p_sys->es->I_O() );
1365                 if( *pi_ref1 == -1 )
1366                 {
1367                     *pi_ref1 = int64( ref );
1368                 }
1369                 else
1370                 {
1371                     *pi_ref2 = int64( ref );
1372                 }
1373             }
1374         }
1375         else
1376         {
1377             msg_Err( p_input, "invalid level = %d", i_level );
1378             return VLC_EGENERIC;
1379         }
1380     }
1381 }
1382
1383 static block_t *MemToBlock( input_thread_t *p_input, uint8_t *p_mem, int i_mem)
1384 {
1385     block_t *p_block;
1386     if( !(p_block = block_New( p_input, i_mem ) ) ) return NULL;
1387     memcpy( p_block->p_buffer, p_mem, i_mem );
1388     //p_block->i_rate = p_input->stream.control.i_rate;
1389     return p_block;
1390 }
1391
1392 static void BlockDecode( input_thread_t *p_input, KaxBlock *block, mtime_t i_pts, mtime_t i_duration )
1393 {
1394     demux_sys_t    *p_sys   = p_input->p_demux_data;
1395
1396     int             i_track;
1397     unsigned int    i;
1398     vlc_bool_t      b;
1399
1400 #define tk  p_sys->track[i_track]
1401     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1402     {
1403         if( tk.i_number == block->TrackNum() )
1404         {
1405             break;
1406         }
1407     }
1408
1409     if( i_track >= p_sys->i_track )
1410     {
1411         msg_Err( p_input, "invalid track number=%d", block->TrackNum() );
1412         return;
1413     }
1414
1415     es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk.p_es, &b );
1416     if( !b )
1417     {
1418         tk.b_inited = VLC_FALSE;
1419         return;
1420     }
1421
1422     if( tk.fmt.i_cat == AUDIO_ES && p_input->stream.control.b_mute )
1423     {
1424         return;
1425     }
1426
1427     /* First send init data */
1428     if( !tk.b_inited && tk.i_data_init > 0 )
1429     {
1430         block_t *p_init;
1431
1432         msg_Dbg( p_input, "sending header (%d bytes)", tk.i_data_init );
1433
1434         if( tk.fmt.i_codec == VLC_FOURCC( 'v', 'o', 'r', 'b' ) )
1435         {
1436             int i;
1437             int i_offset = 1;
1438             int i_size[3];
1439
1440             /* XXX hack split the 3 headers */
1441             if( tk.p_data_init[0] != 0x02 )
1442             {
1443                 msg_Err( p_input, "invalid vorbis header" );
1444             }
1445
1446             for( i = 0; i < 2; i++ )
1447             {
1448                 i_size[i] = 0;
1449                 while( i_offset < tk.i_data_init )
1450                 {
1451                     i_size[i] += tk.p_data_init[i_offset];
1452                     if( tk.p_data_init[i_offset++] != 0xff )
1453                     {
1454                         break;
1455                     }
1456                 }
1457             }
1458             i_size[0] = __MIN( i_size[0], tk.i_data_init - i_offset );
1459             i_size[1] = __MIN( i_size[1], tk.i_data_init - i_offset - i_size[0] );
1460             i_size[2] = tk.i_data_init - i_offset - i_size[0] - i_size[1];
1461
1462             p_init = MemToBlock( p_input, &tk.p_data_init[i_offset], i_size[0] );
1463             if( p_init )
1464             {
1465                 es_out_Send( p_input->p_es_out, tk.p_es, p_init );
1466             }
1467             p_init = MemToBlock( p_input, &tk.p_data_init[i_offset+i_size[0]], i_size[1] );
1468             if( p_init )
1469             {
1470                 es_out_Send( p_input->p_es_out, tk.p_es, p_init );
1471             }
1472             p_init = MemToBlock( p_input, &tk.p_data_init[i_offset+i_size[0]+i_size[1]], i_size[2] );
1473             if( p_init )
1474             {
1475                 es_out_Send( p_input->p_es_out, tk.p_es, p_init );
1476             }
1477         }
1478         else
1479         {
1480             p_init = MemToBlock( p_input, tk.p_data_init, tk.i_data_init );
1481             if( p_init )
1482             {
1483                 es_out_Send( p_input->p_es_out, tk.p_es, p_init );
1484             }
1485         }
1486     }
1487     tk.b_inited = VLC_TRUE;
1488
1489
1490     for( i = 0; i < block->NumberFrames(); i++ )
1491     {
1492         block_t *p_block;
1493         DataBuffer &data = block->GetBuffer(i);
1494
1495         p_block = MemToBlock( p_input, data.Buffer(), data.Size() );
1496         if( p_block == NULL )
1497         {
1498             break;
1499         }
1500
1501         if( tk.fmt.i_cat != VIDEO_ES )
1502             p_block->i_dts = p_block->i_pts = i_pts;
1503         else
1504         {
1505             p_block->i_dts = i_pts;
1506             p_block->i_pts = 0;
1507         }
1508
1509         if( tk.fmt.i_cat == SPU_ES && strcmp( tk.psz_codec, "S_VOBSUB" ) )
1510         {
1511             if( i_duration > 0 )
1512             {
1513                 p_block->i_dts += i_duration * 1000;
1514             }
1515             else
1516             {
1517                 p_block->i_dts = 0;
1518             }
1519         }
1520         es_out_Send( p_input->p_es_out, tk.p_es, p_block );
1521
1522         /* use time stamp only for first block */
1523         i_pts = 0;
1524     }
1525
1526 #undef tk
1527 }
1528
1529 static void Seek( input_thread_t *p_input, mtime_t i_date, int i_percent)
1530 {
1531     demux_sys_t    *p_sys   = p_input->p_demux_data;
1532
1533     KaxBlock    *block;
1534     int64_t     i_block_duration;
1535     int64_t     i_block_ref1;
1536     int64_t     i_block_ref2;
1537
1538     int         i_index;
1539     int         i_track_skipping;
1540     int         i_track;
1541
1542     msg_Dbg( p_input, "seek request to "I64Fd" (%d%%)", i_date, i_percent );
1543     if( i_date < 0 && i_percent < 0 )
1544     {
1545         return;
1546     }
1547
1548     delete p_sys->ep;
1549     p_sys->ep = new EbmlParser( p_sys->es, p_sys->segment );
1550     p_sys->cluster = NULL;
1551
1552     /* seek without index or without date */
1553     if( config_GetInt( p_input, "mkv-seek-percent" ) || !p_sys->b_cues || i_date < 0 )
1554     {
1555         int64_t i_pos = i_percent * stream_Size( p_input->s ) / 100;
1556
1557         msg_Dbg( p_input, "imprecise way of seeking" );
1558         for( i_index = 0; i_index < p_sys->i_index; i_index++ )
1559         {
1560             if( p_sys->index[i_index].i_position >= i_pos)
1561             {
1562                 break;
1563             }
1564         }
1565         if( i_index == p_sys->i_index )
1566         {
1567             i_index--;
1568         }
1569
1570         p_sys->in->setFilePointer( p_sys->index[i_index].i_position,
1571                                    seek_beginning );
1572
1573         if( p_sys->index[i_index].i_position < i_pos )
1574         {
1575             EbmlElement *el;
1576
1577             msg_Warn( p_input, "searching for cluster, could take some time" );
1578
1579             /* search a cluster */
1580             while( ( el = p_sys->ep->Get() ) != NULL )
1581             {
1582                 if( EbmlId( *el ) == KaxCluster::ClassInfos.GlobalId )
1583                 {
1584                     KaxCluster *cluster = (KaxCluster*)el;
1585
1586                     /* add it to the index */
1587                     IndexAppendCluster( p_input, cluster );
1588
1589                     if( (int64_t)cluster->GetElementPosition() >= i_pos )
1590                     {
1591                         p_sys->cluster = cluster;
1592                         p_sys->ep->Down();
1593                         break;
1594                     }
1595                 }
1596             }
1597         }
1598     }
1599     else
1600     {
1601         for( i_index = 0; i_index < p_sys->i_index; i_index++ )
1602         {
1603             if( p_sys->index[i_index].i_time >= i_date )
1604             {
1605                 break;
1606             }
1607         }
1608
1609         if( i_index > 0 )
1610         {
1611             i_index--;
1612         }
1613
1614         msg_Dbg( p_input, "seek got "I64Fd" (%d%%)",
1615                  p_sys->index[i_index].i_time,
1616                  (int)( 100 * p_sys->index[i_index].i_position /
1617                         stream_Size( p_input->s ) ) );
1618
1619         p_sys->in->setFilePointer( p_sys->index[i_index].i_position,
1620                                    seek_beginning );
1621     }
1622
1623     /* now parse until key frame */
1624 #define tk  p_sys->track[i_track]
1625     i_track_skipping = 0;
1626     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1627     {
1628         if( tk.fmt.i_cat == VIDEO_ES )
1629         {
1630             tk.b_search_keyframe = VLC_TRUE;
1631             i_track_skipping++;
1632         }
1633     }
1634
1635     while( i_track_skipping > 0 )
1636     {
1637         if( BlockGet( p_input, &block, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
1638         {
1639             msg_Warn( p_input, "cannot get block EOF?" );
1640
1641             return;
1642         }
1643
1644         p_sys->i_pts = block->GlobalTimecode() * (mtime_t) 1000 / p_sys->i_timescale;
1645
1646         for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1647         {
1648             if( tk.i_number == block->TrackNum() )
1649             {
1650                 break;
1651             }
1652         }
1653
1654         if( i_track < p_sys->i_track )
1655         {
1656             if( tk.fmt.i_cat == VIDEO_ES && i_block_ref1 == -1 && tk.b_search_keyframe )
1657             {
1658                 tk.b_search_keyframe = VLC_FALSE;
1659                 i_track_skipping--;
1660             }
1661             if( tk.fmt.i_cat == VIDEO_ES && !tk.b_search_keyframe )
1662             {
1663                 BlockDecode( p_input, block, 0, 0 );
1664             }
1665         }
1666
1667         delete block;
1668     }
1669 #undef tk
1670 }
1671
1672 /*****************************************************************************
1673  * Demux: reads and demuxes data packets
1674  *****************************************************************************
1675  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1676  *****************************************************************************/
1677 static int Demux( input_thread_t * p_input )
1678 {
1679     demux_sys_t    *p_sys   = p_input->p_demux_data;
1680     mtime_t        i_start_pts;
1681     int            i_block_count = 0;
1682
1683     KaxBlock *block;
1684     int64_t i_block_duration;
1685     int64_t i_block_ref1;
1686     int64_t i_block_ref2;
1687
1688     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1689     {
1690         mtime_t i_duration = (mtime_t)( p_sys->f_duration / 1000 );
1691         mtime_t i_date = -1;
1692         int i_percent  = -1;
1693
1694         if( i_duration > 0 )
1695         {
1696             i_date = (mtime_t)1000000 *
1697                      (mtime_t)i_duration*
1698                      (mtime_t)p_sys->in->getFilePointer() /
1699                      (mtime_t)stream_Size( p_input->s );
1700         }
1701         if( stream_Size( p_input->s ) > 0 )
1702         {
1703             i_percent = 100 * p_sys->in->getFilePointer() /
1704                         stream_Size( p_input->s );
1705         }
1706
1707         Seek( p_input, i_date, i_percent);
1708     }
1709
1710     i_start_pts = -1;
1711
1712     for( ;; )
1713     {
1714         mtime_t i_pts;
1715
1716         if( BlockGet( p_input, &block, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
1717         {
1718             msg_Warn( p_input, "cannot get block EOF?" );
1719
1720             return 0;
1721         }
1722
1723         p_sys->i_pts = block->GlobalTimecode() * (mtime_t) 1000 / p_sys->i_timescale;
1724
1725         if( p_sys->i_pts > 0 )
1726         {
1727             input_ClockManageRef( p_input,
1728                                   p_input->stream.p_selected_program,
1729                                   p_sys->i_pts * 9 / 100 );
1730         }
1731
1732         i_pts = input_ClockGetTS( p_input,
1733                                   p_input->stream.p_selected_program,
1734                                   p_sys->i_pts * 9 / 100 );
1735
1736
1737
1738         BlockDecode( p_input, block, i_pts, i_block_duration );
1739
1740         delete block;
1741         i_block_count++;
1742
1743         if( i_start_pts == -1 )
1744         {
1745             i_start_pts = p_sys->i_pts;
1746         }
1747         else if( p_sys->i_pts > i_start_pts + (mtime_t)100000 || i_block_count > 5 )
1748         {
1749             return 1;
1750         }
1751     }
1752 }
1753
1754
1755
1756 /*****************************************************************************
1757  * Stream managment
1758  *****************************************************************************/
1759 vlc_stream_io_callback::vlc_stream_io_callback( stream_t *s_ )
1760 {
1761     s = s_;
1762     mb_eof = VLC_FALSE;
1763 }
1764
1765 uint32_t vlc_stream_io_callback::read( void *p_buffer, size_t i_size )
1766 {
1767     if( i_size <= 0 || mb_eof )
1768     {
1769         return 0;
1770     }
1771
1772     return stream_Read( s, p_buffer, i_size );
1773 }
1774 void vlc_stream_io_callback::setFilePointer(int64_t i_offset, seek_mode mode )
1775 {
1776     int64_t i_pos;
1777
1778     switch( mode )
1779     {
1780         case seek_beginning:
1781             i_pos = i_offset;
1782             break;
1783         case seek_end:
1784             i_pos = stream_Size( s ) - i_offset;
1785             break;
1786         default:
1787             i_pos= stream_Tell( s ) + i_offset;
1788             break;
1789     }
1790
1791     if( i_pos < 0 || i_pos >= stream_Size( s ) )
1792     {
1793         mb_eof = VLC_TRUE;
1794         return;
1795     }
1796
1797     mb_eof = VLC_FALSE;
1798     if( stream_Seek( s, i_pos ) )
1799     {
1800         mb_eof = VLC_TRUE;
1801     }
1802     return;
1803 }
1804 size_t vlc_stream_io_callback::write( const void *p_buffer, size_t i_size )
1805 {
1806     return 0;
1807 }
1808 uint64_t vlc_stream_io_callback::getFilePointer( void )
1809 {
1810     return stream_Tell( s );
1811 }
1812 void vlc_stream_io_callback::close( void )
1813 {
1814     return;
1815 }
1816
1817
1818 /*****************************************************************************
1819  * Ebml Stream parser
1820  *****************************************************************************/
1821 EbmlParser::EbmlParser( EbmlStream *es, EbmlElement *el_start )
1822 {
1823     int i;
1824
1825     m_es = es;
1826     m_got = NULL;
1827     m_el[0] = el_start;
1828
1829     for( i = 1; i < 6; i++ )
1830     {
1831         m_el[i] = NULL;
1832     }
1833     mi_level = 1;
1834     mi_user_level = 1;
1835     mb_keep = VLC_FALSE;
1836 }
1837
1838 EbmlParser::~EbmlParser( void )
1839 {
1840     int i;
1841
1842     for( i = 1; i < mi_level; i++ )
1843     {
1844         if( !mb_keep )
1845         {
1846             delete m_el[i];
1847         }
1848         mb_keep = VLC_FALSE;
1849     }
1850 }
1851
1852 void EbmlParser::Up( void )
1853 {
1854     if( mi_user_level == mi_level )
1855     {
1856         fprintf( stderr," arrrrrrrrrrrrrg Up cannot escape itself\n" );
1857     }
1858
1859     mi_user_level--;
1860 }
1861
1862 void EbmlParser::Down( void )
1863 {
1864     mi_user_level++;
1865     mi_level++;
1866 }
1867
1868 void EbmlParser::Keep( void )
1869 {
1870     mb_keep = VLC_TRUE;
1871 }
1872
1873 int EbmlParser::GetLevel( void )
1874 {
1875     return mi_user_level;
1876 }
1877
1878 EbmlElement *EbmlParser::Get( void )
1879 {
1880     int i_ulev = 0;
1881
1882     if( mi_user_level != mi_level )
1883     {
1884         return NULL;
1885     }
1886     if( m_got )
1887     {
1888         EbmlElement *ret = m_got;
1889         m_got = NULL;
1890
1891         return ret;
1892     }
1893
1894     if( m_el[mi_level] )
1895     {
1896         m_el[mi_level]->SkipData( *m_es, m_el[mi_level]->Generic().Context );
1897         if( !mb_keep )
1898         {
1899             delete m_el[mi_level];
1900         }
1901         mb_keep = VLC_FALSE;
1902     }
1903
1904     m_el[mi_level] = m_es->FindNextElement( m_el[mi_level - 1]->Generic().Context, i_ulev, 0xFFFFFFFFL, true, 1 );
1905     if( i_ulev > 0 )
1906     {
1907         while( i_ulev > 0 )
1908         {
1909             if( mi_level == 1 )
1910             {
1911                 mi_level = 0;
1912                 return NULL;
1913             }
1914
1915             delete m_el[mi_level - 1];
1916             m_got = m_el[mi_level -1] = m_el[mi_level];
1917             m_el[mi_level] = NULL;
1918
1919             mi_level--;
1920             i_ulev--;
1921         }
1922         return NULL;
1923     }
1924     else if( m_el[mi_level] == NULL )
1925     {
1926         fprintf( stderr," m_el[mi_level] == NULL\n" );
1927     }
1928
1929     return m_el[mi_level];
1930 }
1931
1932
1933 /*****************************************************************************
1934  * Tools
1935  *  * LoadCues : load the cues element and update index
1936  *
1937  *  * LoadTags : load ... the tags element
1938  *
1939  *  * InformationsCreate : create all informations, load tags if present
1940  *
1941  *****************************************************************************/
1942 static void LoadCues( input_thread_t *p_input )
1943 {
1944     demux_sys_t *p_sys = p_input->p_demux_data;
1945     int64_t     i_sav_position = p_sys->in->getFilePointer();
1946     EbmlParser  *ep;
1947     EbmlElement *el, *cues;
1948
1949     msg_Dbg( p_input, "loading cues" );
1950     p_sys->in->setFilePointer( p_sys->i_cues_position, seek_beginning );
1951     cues = p_sys->es->FindNextID( KaxCues::ClassInfos, 0xFFFFFFFFL);
1952
1953     if( cues == NULL )
1954     {
1955         msg_Err( p_input, "cannot load cues (broken seekhead or file)" );
1956         return;
1957     }
1958
1959     ep = new EbmlParser( p_sys->es, cues );
1960     while( ( el = ep->Get() ) != NULL )
1961     {
1962         if( EbmlId( *el ) == KaxCuePoint::ClassInfos.GlobalId )
1963         {
1964 #define idx p_sys->index[p_sys->i_index]
1965
1966             idx.i_track       = -1;
1967             idx.i_block_number= -1;
1968             idx.i_position    = -1;
1969             idx.i_time        = -1;
1970             idx.b_key         = VLC_TRUE;
1971
1972             ep->Down();
1973             while( ( el = ep->Get() ) != NULL )
1974             {
1975                 if( EbmlId( *el ) == KaxCueTime::ClassInfos.GlobalId )
1976                 {
1977                     KaxCueTime &ctime = *(KaxCueTime*)el;
1978
1979                     ctime.ReadData( p_sys->es->I_O() );
1980
1981                     idx.i_time = uint64( ctime ) * (mtime_t)1000000000 / p_sys->i_timescale;
1982                 }
1983                 else if( EbmlId( *el ) == KaxCueTrackPositions::ClassInfos.GlobalId )
1984                 {
1985                     ep->Down();
1986                     while( ( el = ep->Get() ) != NULL )
1987                     {
1988                         if( EbmlId( *el ) == KaxCueTrack::ClassInfos.GlobalId )
1989                         {
1990                             KaxCueTrack &ctrack = *(KaxCueTrack*)el;
1991
1992                             ctrack.ReadData( p_sys->es->I_O() );
1993                             idx.i_track = uint16( ctrack );
1994                         }
1995                         else if( EbmlId( *el ) == KaxCueClusterPosition::ClassInfos.GlobalId )
1996                         {
1997                             KaxCueClusterPosition &ccpos = *(KaxCueClusterPosition*)el;
1998
1999                             ccpos.ReadData( p_sys->es->I_O() );
2000                             idx.i_position = p_sys->segment->GetGlobalPosition( uint64( ccpos ) );
2001                         }
2002                         else if( EbmlId( *el ) == KaxCueBlockNumber::ClassInfos.GlobalId )
2003                         {
2004                             KaxCueBlockNumber &cbnum = *(KaxCueBlockNumber*)el;
2005
2006                             cbnum.ReadData( p_sys->es->I_O() );
2007                             idx.i_block_number = uint32( cbnum );
2008                         }
2009                         else
2010                         {
2011                             msg_Dbg( p_input, "         * Unknown (%s)", typeid(*el).name() );
2012                         }
2013                     }
2014                     ep->Up();
2015                 }
2016                 else
2017                 {
2018                     msg_Dbg( p_input, "     * Unknown (%s)", typeid(*el).name() );
2019                 }
2020             }
2021             ep->Up();
2022
2023 #if 0
2024             msg_Dbg( p_input, " * added time="I64Fd" pos="I64Fd
2025                      " track=%d bnum=%d", idx.i_time, idx.i_position,
2026                      idx.i_track, idx.i_block_number );
2027 #endif
2028
2029             p_sys->i_index++;
2030             if( p_sys->i_index >= p_sys->i_index_max )
2031             {
2032                 p_sys->i_index_max += 1024;
2033                 p_sys->index = (mkv_index_t*)realloc( p_sys->index, sizeof( mkv_index_t ) * p_sys->i_index_max );
2034             }
2035 #undef idx
2036         }
2037         else
2038         {
2039             msg_Dbg( p_input, " * Unknown (%s)", typeid(*el).name() );
2040         }
2041     }
2042     delete ep;
2043     delete cues;
2044
2045     p_sys->b_cues = VLC_TRUE;
2046
2047     msg_Dbg( p_input, "loading cues done." );
2048     p_sys->in->setFilePointer( i_sav_position, seek_beginning );
2049 }
2050
2051 static void LoadTags( input_thread_t *p_input )
2052 {
2053     demux_sys_t *p_sys = p_input->p_demux_data;
2054     int64_t     i_sav_position = p_sys->in->getFilePointer();
2055     EbmlParser  *ep;
2056     EbmlElement *el, *tags;
2057
2058     msg_Dbg( p_input, "loading tags" );
2059     p_sys->in->setFilePointer( p_sys->i_tags_position, seek_beginning );
2060     tags = p_sys->es->FindNextID( KaxTags::ClassInfos, 0xFFFFFFFFL);
2061
2062     if( tags == NULL )
2063     {
2064         msg_Err( p_input, "cannot load tags (broken seekhead or file)" );
2065         return;
2066     }
2067
2068     msg_Dbg( p_input, "Tags" );
2069     ep = new EbmlParser( p_sys->es, tags );
2070     while( ( el = ep->Get() ) != NULL )
2071     {
2072         if( EbmlId( *el ) == KaxTag::ClassInfos.GlobalId )
2073         {
2074             msg_Dbg( p_input, "+ Tag" );
2075             ep->Down();
2076             while( ( el = ep->Get() ) != NULL )
2077             {
2078                 if( EbmlId( *el ) == KaxTagTargets::ClassInfos.GlobalId )
2079                 {
2080                     msg_Dbg( p_input, "|   + Targets" );
2081                     ep->Down();
2082                     while( ( el = ep->Get() ) != NULL )
2083                     {
2084                         msg_Dbg( p_input, "|   |   + Unknown (%s)", typeid( *el ).name() );
2085                     }
2086                     ep->Up();
2087                 }
2088                 else if( EbmlId( *el ) == KaxTagGeneral::ClassInfos.GlobalId )
2089                 {
2090                     msg_Dbg( p_input, "|   + General" );
2091                     ep->Down();
2092                     while( ( el = ep->Get() ) != NULL )
2093                     {
2094                         msg_Dbg( p_input, "|   |   + Unknown (%s)", typeid( *el ).name() );
2095                     }
2096                     ep->Up();
2097                 }
2098                 else if( EbmlId( *el ) == KaxTagGenres::ClassInfos.GlobalId )
2099                 {
2100                     msg_Dbg( p_input, "|   + Genres" );
2101                     ep->Down();
2102                     while( ( el = ep->Get() ) != NULL )
2103                     {
2104                         msg_Dbg( p_input, "|   |   + Unknown (%s)", typeid( *el ).name() );
2105                     }
2106                     ep->Up();
2107                 }
2108                 else if( EbmlId( *el ) == KaxTagAudioSpecific::ClassInfos.GlobalId )
2109                 {
2110                     msg_Dbg( p_input, "|   + Audio Specific" );
2111                     ep->Down();
2112                     while( ( el = ep->Get() ) != NULL )
2113                     {
2114                         msg_Dbg( p_input, "|   |   + Unknown (%s)", typeid( *el ).name() );
2115                     }
2116                     ep->Up();
2117                 }
2118                 else if( EbmlId( *el ) == KaxTagImageSpecific::ClassInfos.GlobalId )
2119                 {
2120                     msg_Dbg( p_input, "|   + Images Specific" );
2121                     ep->Down();
2122                     while( ( el = ep->Get() ) != NULL )
2123                     {
2124                         msg_Dbg( p_input, "|   |   + Unknown (%s)", typeid( *el ).name() );
2125                     }
2126                     ep->Up();
2127                 }
2128                 else if( EbmlId( *el ) == KaxTagMultiComment::ClassInfos.GlobalId )
2129                 {
2130                     msg_Dbg( p_input, "|   + Multi Comment" );
2131                 }
2132                 else if( EbmlId( *el ) == KaxTagMultiCommercial::ClassInfos.GlobalId )
2133                 {
2134                     msg_Dbg( p_input, "|   + Multi Commercial" );
2135                 }
2136                 else if( EbmlId( *el ) == KaxTagMultiDate::ClassInfos.GlobalId )
2137                 {
2138                     msg_Dbg( p_input, "|   + Multi Date" );
2139                 }
2140                 else if( EbmlId( *el ) == KaxTagMultiEntity::ClassInfos.GlobalId )
2141                 {
2142                     msg_Dbg( p_input, "|   + Multi Entity" );
2143                 }
2144                 else if( EbmlId( *el ) == KaxTagMultiIdentifier::ClassInfos.GlobalId )
2145                 {
2146                     msg_Dbg( p_input, "|   + Multi Identifier" );
2147                 }
2148                 else if( EbmlId( *el ) == KaxTagMultiLegal::ClassInfos.GlobalId )
2149                 {
2150                     msg_Dbg( p_input, "|   + Multi Legal" );
2151                 }
2152                 else if( EbmlId( *el ) == KaxTagMultiTitle::ClassInfos.GlobalId )
2153                 {
2154                     msg_Dbg( p_input, "|   + Multi Title" );
2155                 }
2156                 else
2157                 {
2158                     msg_Dbg( p_input, "|   + Unknown (%s)", typeid( *el ).name() );
2159                 }
2160             }
2161             ep->Up();
2162         }
2163         else
2164         {
2165             msg_Dbg( p_input, "+ Unknown (%s)", typeid( *el ).name() );
2166         }
2167     }
2168     delete ep;
2169     delete tags;
2170
2171     msg_Dbg( p_input, "loading tags done." );
2172     p_sys->in->setFilePointer( i_sav_position, seek_beginning );
2173 }
2174
2175 static void InformationsCreate( input_thread_t *p_input )
2176 {
2177     demux_sys_t           *p_sys = p_input->p_demux_data;
2178     input_info_category_t *p_cat;
2179     playlist_t            *p_playlist;
2180     int                   i_track;
2181
2182     p_cat = input_InfoCategory( p_input, "Matroska" );
2183     if( p_sys->f_duration > 1000.1 )
2184     {
2185         char psz_buffer[MSTRTIME_MAX_SIZE];
2186         input_AddInfo( p_cat, _("Duration"),
2187                        msecstotimestr( psz_buffer, (int)p_sys->f_duration ) );
2188     }
2189
2190     if( p_sys->psz_title )
2191     {
2192         input_AddInfo( p_cat, _("Title"), "%s" ,p_sys->psz_title );
2193     }
2194     if( p_sys->psz_date_utc )
2195     {
2196         input_AddInfo( p_cat, _("UTC date"), "%s" ,p_sys->psz_date_utc );
2197     }
2198     if( p_sys->psz_segment_filename )
2199     {
2200         input_AddInfo( p_cat, _("Segment filename"), "%s" ,p_sys->psz_segment_filename );
2201     }
2202     if( p_sys->psz_muxing_application )
2203     {
2204         input_AddInfo( p_cat, _("Muxing application"), "%s" ,p_sys->psz_muxing_application );
2205     }
2206     if( p_sys->psz_writing_application )
2207     {
2208         input_AddInfo( p_cat, _("Writing application"), "%s" ,p_sys->psz_writing_application );
2209     }
2210     input_AddInfo( p_cat, _("Number of streams"), "%d" , p_sys->i_track );
2211
2212     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
2213     {
2214         char psz_cat[strlen( "Stream " ) + 10];
2215 #define tk  p_sys->track[i_track]
2216
2217         sprintf( psz_cat, "Stream %d", i_track );
2218         p_cat = input_InfoCategory( p_input, psz_cat);
2219         if( tk.fmt.psz_description )
2220         {
2221             input_AddInfo( p_cat, _("Name"), "%s", tk.fmt.psz_description );
2222         }
2223         if( tk.fmt.psz_language )
2224         {
2225             input_AddInfo( p_cat, _("Language"), "%s", tk.fmt.psz_language );
2226         }
2227         if( tk.psz_codec_name )
2228         {
2229             input_AddInfo( p_cat, _("Codec name"), "%s", tk.psz_codec_name );
2230         }
2231         if( tk.psz_codec_settings )
2232         {
2233             input_AddInfo( p_cat, _("Codec setting"), "%s", tk.psz_codec_settings );
2234         }
2235         if( tk.psz_codec_info_url )
2236         {
2237             input_AddInfo( p_cat, _("Codec info"), "%s", tk.psz_codec_info_url );
2238         }
2239         if( tk.psz_codec_download_url )
2240         {
2241             input_AddInfo( p_cat, _("Codec download"), "%s", tk.psz_codec_download_url );
2242         }
2243 #undef  tk
2244     }
2245
2246     if( p_sys->i_tags_position >= 0 )
2247     {
2248         vlc_bool_t b_seekable;
2249
2250         stream_Control( p_input->s, STREAM_CAN_FASTSEEK, &b_seekable );
2251         if( b_seekable )
2252         {
2253             LoadTags( p_input );
2254         }
2255     }
2256 }
2257
2258
2259 /*****************************************************************************
2260  * Divers
2261  *****************************************************************************/
2262
2263 static void IndexAppendCluster( input_thread_t *p_input, KaxCluster *cluster )
2264 {
2265     demux_sys_t    *p_sys   = p_input->p_demux_data;
2266
2267 #define idx p_sys->index[p_sys->i_index]
2268     idx.i_track       = -1;
2269     idx.i_block_number= -1;
2270     idx.i_position    = cluster->GetElementPosition();
2271     idx.i_time        = -1;
2272     idx.b_key         = VLC_TRUE;
2273
2274     p_sys->i_index++;
2275     if( p_sys->i_index >= p_sys->i_index_max )
2276     {
2277         p_sys->i_index_max += 1024;
2278         p_sys->index = (mkv_index_t*)realloc( p_sys->index, sizeof( mkv_index_t ) * p_sys->i_index_max );
2279     }
2280 #undef idx
2281 }
2282
2283 static char * UTF8ToStr( const UTFstring &u )
2284 {
2285     int     i_src;
2286     const wchar_t *src;
2287     char *dst, *p;
2288
2289     i_src = u.length();
2290     src   = u.c_str();
2291
2292     p = dst = (char*)malloc( i_src + 1);
2293     while( i_src > 0 )
2294     {
2295         if( *src < 255 )
2296         {
2297             *p++ = (char)*src;
2298         }
2299         else
2300         {
2301             *p++ = '?';
2302         }
2303         src++;
2304         i_src--;
2305     }
2306     *p++= '\0';
2307
2308     return dst;
2309 }
2310
2311 static char *LanguageGetName    ( const char *psz_code )
2312 {
2313     const iso639_lang_t *pl;
2314
2315     if( strlen( psz_code ) == 2 )
2316     {
2317         pl = GetLang_1( psz_code );
2318     }
2319     else if( strlen( psz_code ) == 3 )
2320     {
2321         pl = GetLang_2B( psz_code );
2322         if( !strcmp( pl->psz_iso639_1, "??" ) )
2323         {
2324             pl = GetLang_2T( psz_code );
2325         }
2326     }
2327     else
2328     {
2329         return strdup( psz_code );
2330     }
2331
2332     if( !strcmp( pl->psz_iso639_1, "??" ) )
2333     {
2334        return strdup( psz_code );
2335     }
2336     else
2337     {
2338         if( *pl->psz_native_name )
2339         {
2340             return strdup( pl->psz_native_name );
2341         }
2342         return strdup( pl->psz_eng_name );
2343     }
2344 }
2345