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