]> git.sesse.net Git - vlc/blob - modules/demux/mkv.cpp
Add secstotimestr and msecstotimestr to convert (milli)seconds to a
[vlc] / modules / demux / mkv.cpp
1 /*****************************************************************************
2  * mkv.cpp : matroska demuxer
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: mkv.cpp,v 1.48 2003/12/02 01:54:30 rocky 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() );
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 if( EbmlId( *el4 ) == KaxVideoPixelWidth::ClassInfos.GlobalId )
716                                 {
717                                     KaxVideoPixelWidth &vwidth = *(KaxVideoPixelWidth*)el4;
718                                     vwidth.ReadData( p_sys->es->I_O() );
719
720                                     tk.fmt.video.i_width = uint16( vwidth );
721                                     msg_Dbg( p_input, "|   |   |   |   + width=%d", uint16( vwidth ) );
722                                 }
723                                 else if( EbmlId( *el4 ) == KaxVideoPixelHeight::ClassInfos.GlobalId )
724                                 {
725                                     KaxVideoPixelWidth &vheight = *(KaxVideoPixelWidth*)el4;
726                                     vheight.ReadData( p_sys->es->I_O() );
727
728                                     tk.fmt.video.i_height = uint16( vheight );
729                                     msg_Dbg( p_input, "|   |   |   |   + height=%d", uint16( vheight ) );
730                                 }
731                                 else if( EbmlId( *el4 ) == KaxVideoDisplayWidth::ClassInfos.GlobalId )
732                                 {
733                                     KaxVideoDisplayWidth &vwidth = *(KaxVideoDisplayWidth*)el4;
734                                     vwidth.ReadData( p_sys->es->I_O() );
735
736                                     tk.fmt.video.i_visible_width = uint16( vwidth );
737                                     msg_Dbg( p_input, "|   |   |   |   + display width=%d", uint16( vwidth ) );
738                                 }
739                                 else if( EbmlId( *el4 ) == KaxVideoDisplayHeight::ClassInfos.GlobalId )
740                                 {
741                                     KaxVideoDisplayWidth &vheight = *(KaxVideoDisplayWidth*)el4;
742                                     vheight.ReadData( p_sys->es->I_O() );
743
744                                     tk.fmt.video.i_visible_height = uint16( vheight );
745                                     msg_Dbg( p_input, "|   |   |   |   + display height=%d", uint16( vheight ) );
746                                 }
747                                 else if( EbmlId( *el4 ) == KaxVideoFrameRate::ClassInfos.GlobalId )
748                                 {
749                                     KaxVideoFrameRate &vfps = *(KaxVideoFrameRate*)el4;
750                                     vfps.ReadData( p_sys->es->I_O() );
751
752                                     tk.f_fps = float( vfps );
753                                     msg_Dbg( p_input, "   |   |   |   + fps=%f", float( vfps ) );
754                                 }
755                                 else if( EbmlId( *el4 ) == KaxVideoDisplayUnit::ClassInfos.GlobalId )
756                                 {
757                                      KaxVideoDisplayUnit &vdmode = *(KaxVideoDisplayUnit*)el4;
758                                     vdmode.ReadData( p_sys->es->I_O() );
759
760                                     msg_Dbg( p_input, "|   |   |   |   + Track Video Display Unit=%s",
761                                              uint8( vdmode ) == 0 ? "pixels" : ( uint8( vdmode ) == 1 ? "centimeters": "inches" ) );
762                                 }
763                                 else if( EbmlId( *el4 ) == KaxVideoAspectRatio::ClassInfos.GlobalId )
764                                 {
765                                     KaxVideoAspectRatio &ratio = *(KaxVideoAspectRatio*)el4;
766                                     ratio.ReadData( p_sys->es->I_O() );
767
768                                     msg_Dbg( p_input, "   |   |   |   + Track Video Aspect Ratio Type=%u", uint8( ratio ) );
769                                 }
770                                 else if( EbmlId( *el4 ) == KaxVideoGamma::ClassInfos.GlobalId )
771                                 {
772                                     KaxVideoGamma &gamma = *(KaxVideoGamma*)el4;
773                                     gamma.ReadData( p_sys->es->I_O() );
774
775                                     msg_Dbg( p_input, "   |   |   |   + fps=%f", float( gamma ) );
776                                 }
777                                 else
778                                 {
779                                     msg_Dbg( p_input, "|   |   |   |   + Unknown (%s)", typeid(*el4).name() );
780                                 }
781                             }
782                             p_sys->ep->Up();
783                         }
784                         else  if( EbmlId( *el3 ) == KaxTrackAudio::ClassInfos.GlobalId )
785                         {
786                             msg_Dbg( p_input, "|   |   |   + Track Audio" );
787
788                             p_sys->ep->Down();
789
790                             while( ( el4 = p_sys->ep->Get() ) != NULL )
791                             {
792                                 if( EbmlId( *el4 ) == KaxAudioSamplingFreq::ClassInfos.GlobalId )
793                                 {
794                                     KaxAudioSamplingFreq &afreq = *(KaxAudioSamplingFreq*)el4;
795                                     afreq.ReadData( p_sys->es->I_O() );
796
797                                     tk.fmt.audio.i_rate = (int)float( afreq );
798                                     msg_Dbg( p_input, "|   |   |   |   + afreq=%d", tk.fmt.audio.i_rate );
799                                 }
800                                 else if( EbmlId( *el4 ) == KaxAudioChannels::ClassInfos.GlobalId )
801                                 {
802                                     KaxAudioChannels &achan = *(KaxAudioChannels*)el4;
803                                     achan.ReadData( p_sys->es->I_O() );
804
805                                     tk.fmt.audio.i_channels = uint8( achan );
806                                     msg_Dbg( p_input, "|   |   |   |   + achan=%u", uint8( achan ) );
807                                 }
808                                 else if( EbmlId( *el4 ) == KaxAudioBitDepth::ClassInfos.GlobalId )
809                                 {
810                                     KaxAudioBitDepth &abits = *(KaxAudioBitDepth*)el4;
811                                     abits.ReadData( p_sys->es->I_O() );
812
813                                     tk.fmt.audio.i_bitspersample = uint8( abits );
814                                     msg_Dbg( p_input, "|   |   |   |   + abits=%u", uint8( abits ) );
815                                 }
816                                 else
817                                 {
818                                     msg_Dbg( p_input, "|   |   |   |   + Unknown (%s)", typeid(*el4).name() );
819                                 }
820                             }
821                             p_sys->ep->Up();
822                         }
823                         else
824                         {
825                             msg_Dbg( p_input, "|   |   |   + Unknown (%s)",
826                                      typeid(*el3).name() );
827                         }
828                     }
829                     p_sys->ep->Up();
830                 }
831                 else
832                 {
833                     msg_Dbg( p_input, "|   |   + Unknown (%s)",
834                              typeid(*el2).name() );
835                 }
836 #undef tk
837             }
838             p_sys->ep->Up();
839         }
840         else if( EbmlId( *el1 ) == KaxSeekHead::ClassInfos.GlobalId )
841         {
842             msg_Dbg( p_input, "|   + Seek head" );
843             p_sys->ep->Down();
844             while( ( el = p_sys->ep->Get() ) != NULL )
845             {
846                 if( EbmlId( *el ) == KaxSeek::ClassInfos.GlobalId )
847                 {
848                     EbmlId id = EbmlVoid::ClassInfos.GlobalId;
849                     int64_t i_pos = -1;
850
851                     //msg_Dbg( p_input, "|   |   + Seek" );
852                     p_sys->ep->Down();
853                     while( ( el = p_sys->ep->Get() ) != NULL )
854                     {
855                         if( EbmlId( *el ) == KaxSeekID::ClassInfos.GlobalId )
856                         {
857                             KaxSeekID &sid = *(KaxSeekID*)el;
858
859                             sid.ReadData( p_sys->es->I_O() );
860
861                             id = EbmlId( sid.GetBuffer(), sid.GetSize() );
862                         }
863                         else  if( EbmlId( *el ) == KaxSeekPosition::ClassInfos.GlobalId )
864                         {
865                             KaxSeekPosition &spos = *(KaxSeekPosition*)el;
866
867                             spos.ReadData( p_sys->es->I_O() );
868
869                             i_pos = uint64( spos );
870                         }
871                         else
872                         {
873                             msg_Dbg( p_input, "|   |   |   + Unknown (%s)",
874                                      typeid(*el).name() );
875                         }
876                     }
877                     p_sys->ep->Up();
878
879                     if( i_pos >= 0 )
880                     {
881                         if( id == KaxCues::ClassInfos.GlobalId )
882                         {
883                             msg_Dbg( p_input, "|   |   |   = cues at "I64Fd,
884                                      i_pos );
885                             p_sys->i_cues_position = p_sys->segment->GetGlobalPosition( i_pos );
886                         }
887                         else if( id == KaxChapters::ClassInfos.GlobalId )
888                         {
889                             msg_Dbg( p_input, "|   |   |   = chapters at "I64Fd,
890                                      i_pos );
891                             p_sys->i_chapters_position = p_sys->segment->GetGlobalPosition( i_pos );
892                         }
893                         else if( id == KaxTags::ClassInfos.GlobalId )
894                         {
895                             msg_Dbg( p_input, "|   |   |   = tags at "I64Fd,
896                                      i_pos );
897                             p_sys->i_tags_position = p_sys->segment->GetGlobalPosition( i_pos );
898                         }
899
900                     }
901                 }
902                 else
903                 {
904                     msg_Dbg( p_input, "|   |   + Unknown (%s)",
905                              typeid(*el).name() );
906                 }
907             }
908             p_sys->ep->Up();
909         }
910         else if( EbmlId( *el1 ) == KaxCues::ClassInfos.GlobalId )
911         {
912             msg_Dbg( p_input, "|   + Cues" );
913         }
914         else if( EbmlId( *el1 ) == KaxCluster::ClassInfos.GlobalId )
915         {
916             msg_Dbg( p_input, "|   + Cluster" );
917
918             p_sys->cluster = (KaxCluster*)el1;
919
920             p_sys->ep->Down();
921             /* stop parsing the stream */
922             break;
923         }
924 #ifdef HAVE_MATROSKA_KAXATTACHMENTS_H
925         else if( EbmlId( *el1 ) == KaxAttachments::ClassInfos.GlobalId )
926 #else
927         else if( EbmlId( *el1 ) == KaxAttachements::ClassInfos.GlobalId )
928 #endif
929         {
930             msg_Dbg( p_input, "|   + Attachments FIXME TODO (but probably never supported)" );
931         }
932         else if( EbmlId( *el1 ) == KaxChapters::ClassInfos.GlobalId )
933         {
934             msg_Dbg( p_input, "|   + Chapters FIXME TODO" );
935         }
936         else if( EbmlId( *el1 ) == KaxTag::ClassInfos.GlobalId )
937         {
938             msg_Dbg( p_input, "|   + Tags FIXME TODO" );
939         }
940         else
941         {
942             msg_Dbg( p_input, "|   + Unknown (%s)", typeid(*el1).name() );
943         }
944     }
945
946     if( p_sys->cluster == NULL )
947     {
948         msg_Err( p_input, "cannot find any cluster, damaged file ?" );
949         goto error;
950     }
951
952     if( p_sys->i_chapters_position >= 0 )
953     {
954         msg_Warn( p_input, "chapters unsupported" );
955     }
956
957     /* *** Load the cue if found *** */
958     if( p_sys->i_cues_position >= 0 )
959     {
960         vlc_bool_t b_seekable;
961
962         stream_Control( p_input->s, STREAM_CAN_FASTSEEK, &b_seekable );
963         if( b_seekable )
964         {
965             LoadCues( p_input );
966         }
967     }
968
969     if( !p_sys->b_cues || p_sys->i_index <= 0 )
970     {
971         msg_Warn( p_input, "no cues/empty cues found->seek won't be precise" );
972
973         IndexAppendCluster( p_input, p_sys->cluster );
974
975         p_sys->b_cues = VLC_FALSE;
976     }
977
978     /* Create one program */
979     vlc_mutex_lock( &p_input->stream.stream_lock );
980     if( input_InitStream( p_input, 0 ) == -1)
981     {
982         vlc_mutex_unlock( &p_input->stream.stream_lock );
983         msg_Err( p_input, "cannot init stream" );
984         goto error;
985     }
986     p_input->stream.i_mux_rate = 0;
987     vlc_mutex_unlock( &p_input->stream.stream_lock );
988
989     if( p_sys->f_duration > 1001.0 )
990     {
991         mtime_t i_duration = (mtime_t)( p_sys->f_duration / 1000.0 );
992         p_input->stream.i_mux_rate = stream_Size( p_input->s )/50 / i_duration;
993     }
994
995     /* add all es */
996     msg_Dbg( p_input, "found %d es", p_sys->i_track );
997     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
998     {
999 #define tk  p_sys->track[i_track]
1000         if( tk.fmt.i_cat == UNKNOWN_ES )
1001         {
1002             msg_Warn( p_input, "invalid track[%d, n=%d]", i_track, tk.i_number );
1003             tk.p_es = NULL;
1004             continue;
1005         }
1006
1007         if( tk.fmt.i_cat == SPU_ES )
1008         {
1009             vlc_value_t val;
1010             val.psz_string = "UTF-8";
1011 #if defined(HAVE_ICONV)
1012             var_Create( p_input, "subsdec-encoding", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
1013             var_Set( p_input, "subsdec-encoding", val );
1014 #endif
1015         }
1016         if( !strcmp( tk.psz_codec, "V_MS/VFW/FOURCC" ) )
1017         {
1018             if( tk.i_extra_data < (int)sizeof( BITMAPINFOHEADER ) )
1019             {
1020                 msg_Err( p_input, "missing/invalid BITMAPINFOHEADER" );
1021                 tk.fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1022             }
1023             else
1024             {
1025                 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)tk.p_extra_data;
1026
1027                 tk.fmt.video.i_width = GetDWLE( &p_bih->biWidth );
1028                 tk.fmt.video.i_height= GetDWLE( &p_bih->biHeight );
1029                 tk.fmt.i_codec       = GetFOURCC( &p_bih->biCompression );
1030
1031                 tk.fmt.i_extra       = GetDWLE( &p_bih->biSize ) - sizeof( BITMAPINFOHEADER );
1032                 if( tk.fmt.i_extra > 0 )
1033                 {
1034                     tk.fmt.p_extra = malloc( tk.fmt.i_extra );
1035                     memcpy( tk.fmt.p_extra, &p_bih[1], tk.fmt.i_extra );
1036                 }
1037             }
1038         }
1039         else if( !strcmp( tk.psz_codec, "V_MPEG1" ) ||
1040                  !strcmp( tk.psz_codec, "V_MPEG2" ) )
1041         {
1042             tk.fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
1043         }
1044         else if( !strncmp( tk.psz_codec, "V_MPEG4", 7 ) )
1045         {
1046             if( !strcmp( tk.psz_codec, "V_MPEG4/MS/V3" ) )
1047             {
1048                 tk.fmt.i_codec = VLC_FOURCC( 'D', 'I', 'V', '3' );
1049             }
1050             else
1051             {
1052                 tk.fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
1053             }
1054         }
1055         else if( !strcmp( tk.psz_codec, "A_MS/ACM" ) )
1056         {
1057             if( tk.i_extra_data < (int)sizeof( WAVEFORMATEX ) )
1058             {
1059                 msg_Err( p_input, "missing/invalid WAVEFORMATEX" );
1060                 tk.fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1061             }
1062             else
1063             {
1064                 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)tk.p_extra_data;
1065
1066                 wf_tag_to_fourcc( GetWLE( &p_wf->wFormatTag ), &tk.fmt.i_codec, NULL );
1067
1068                 tk.fmt.audio.i_channels   = GetWLE( &p_wf->nChannels );
1069                 tk.fmt.audio.i_rate = GetDWLE( &p_wf->nSamplesPerSec );
1070                 tk.fmt.i_bitrate    = GetDWLE( &p_wf->nAvgBytesPerSec ) * 8;
1071                 tk.fmt.audio.i_blockalign = GetWLE( &p_wf->nBlockAlign );;
1072                 tk.fmt.audio.i_bitspersample = GetWLE( &p_wf->wBitsPerSample );
1073
1074                 tk.fmt.i_extra            = GetWLE( &p_wf->cbSize );
1075                 if( tk.fmt.i_extra > 0 )
1076                 {
1077                     tk.fmt.p_extra = malloc( tk.fmt.i_extra );
1078                     memcpy( tk.fmt.p_extra, &p_wf[1], tk.fmt.i_extra );
1079                 }
1080             }
1081         }
1082         else if( !strcmp( tk.psz_codec, "A_MPEG/L3" ) ||
1083                  !strcmp( tk.psz_codec, "A_MPEG/L2" ) ||
1084                  !strcmp( tk.psz_codec, "A_MPEG/L1" ) )
1085         {
1086             tk.fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
1087         }
1088         else if( !strcmp( tk.psz_codec, "A_AC3" ) )
1089         {
1090             tk.fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
1091         }
1092         else if( !strcmp( tk.psz_codec, "A_DTS" ) )
1093         {
1094             tk.fmt.i_codec = VLC_FOURCC( 'd', 't', 's', ' ' );
1095         }
1096         else if( !strcmp( tk.psz_codec, "A_VORBIS" ) )
1097         {
1098             tk.fmt.i_codec = VLC_FOURCC( 'v', 'o', 'r', 'b' );
1099             tk.i_data_init = tk.i_extra_data;
1100             tk.p_data_init = tk.p_extra_data;
1101         }
1102         else if( !strncmp( tk.psz_codec, "A_AAC/MPEG2/", strlen( "A_AAC/MPEG2/" ) ) ||
1103                  !strncmp( tk.psz_codec, "A_AAC/MPEG4/", strlen( "A_AAC/MPEG4/" ) ) )
1104         {
1105             int i_profile, i_srate;
1106             static unsigned int i_sample_rates[] =
1107             {
1108                     96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1109                         16000, 12000, 11025, 8000,  7350,  0,     0,     0
1110             };
1111
1112             tk.fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
1113             /* create data for faad (MP4DecSpecificDescrTag)*/
1114
1115             if( !strcmp( &tk.psz_codec[12], "MAIN" ) )
1116             {
1117                 i_profile = 0;
1118             }
1119             else if( !strcmp( &tk.psz_codec[12], "LC" ) )
1120             {
1121                 i_profile = 1;
1122             }
1123             else if( !strcmp( &tk.psz_codec[12], "SSR" ) )
1124             {
1125                 i_profile = 2;
1126             }
1127             else
1128             {
1129                 i_profile = 3;
1130             }
1131
1132             for( i_srate = 0; i_srate < 13; i_srate++ )
1133             {
1134                 if( i_sample_rates[i_srate] == tk.fmt.audio.i_rate )
1135                 {
1136                     break;
1137                 }
1138             }
1139             msg_Dbg( p_input, "profile=%d srate=%d", i_profile, i_srate );
1140
1141             tk.fmt.i_extra = 2;
1142             tk.fmt.p_extra = malloc( tk.fmt.i_extra );
1143             ((uint8_t*)tk.fmt.p_extra)[0] = ((i_profile + 1) << 3) | ((i_srate&0xe) >> 1);
1144             ((uint8_t*)tk.fmt.p_extra)[1] = ((i_srate & 0x1) << 7) | (tk.fmt.audio.i_channels << 3);
1145         }
1146         else if( !strcmp( tk.psz_codec, "A_PCM/INT/BIG" ) ||
1147                  !strcmp( tk.psz_codec, "A_PCM/INT/LIT" ) ||
1148                  !strcmp( tk.psz_codec, "A_PCM/FLOAT/IEEE" ) )
1149         {
1150             if( !strcmp( tk.psz_codec, "A_PCM/INT/BIG" ) )
1151             {
1152                 tk.fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
1153             }
1154             else
1155             {
1156                 tk.fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
1157             }
1158             tk.fmt.audio.i_blockalign = ( tk.fmt.audio.i_bitspersample + 7 ) / 8 * tk.fmt.audio.i_channels;
1159         }
1160         else if( !strcmp( tk.psz_codec, "S_TEXT/UTF8" ) )
1161         {
1162             tk.fmt.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
1163         }
1164         else if( !strcmp( tk.psz_codec, "S_TEXT/SSA" ) ||
1165                  !strcmp( tk.psz_codec, "S_SSA" ) ||
1166                  !strcmp( tk.psz_codec, "S_ASS" ))
1167         {
1168             tk.fmt.i_codec = VLC_FOURCC( 's', 's', 'a', ' ' );
1169 #if 0
1170             /* FIXME */
1171             tk.fmt.i_extra = sizeof( subtitle_data_t );
1172             tk.fmt.p_extra = malloc( tk.fmt.i_extra );
1173             ((es_sys_t*)tk->fmt.p_extra)->psz_header = strdup( (char *)tk.p_extra_data );
1174 #endif
1175         }
1176         else if( !strcmp( tk.psz_codec, "S_VOBSUB" ) )
1177         {
1178             tk.fmt.i_codec = VLC_FOURCC( 's','p','u',' ' );
1179         }
1180         else
1181         {
1182             msg_Err( p_input, "unknow codec id=`%s'", tk.psz_codec );
1183             tk.fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1184         }
1185
1186         tk.p_es = es_out_Add( p_input->p_es_out, &tk.fmt );
1187 #undef tk
1188     }
1189
1190     /* add informations */
1191     InformationsCreate( p_input );
1192
1193     return VLC_SUCCESS;
1194
1195 error:
1196     delete p_sys->es;
1197     delete p_sys->in;
1198     free( p_sys );
1199     return VLC_EGENERIC;
1200 }
1201
1202 /*****************************************************************************
1203  * Close: frees unused data
1204  *****************************************************************************/
1205 static void Close( vlc_object_t *p_this )
1206 {
1207     input_thread_t *p_input = (input_thread_t *)p_this;
1208     demux_sys_t    *p_sys   = p_input->p_demux_data;
1209
1210     int             i_track;
1211
1212     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1213     {
1214 #define tk  p_sys->track[i_track]
1215         if( tk.fmt.psz_description )
1216         {
1217             free( tk.fmt.psz_language );
1218         }
1219         if( tk.psz_codec )
1220         {
1221             free( tk.psz_codec );
1222         }
1223         if( tk.fmt.psz_language )
1224         {
1225             free( tk.fmt.psz_language );
1226         }
1227 #undef tk
1228     }
1229     free( p_sys->track );
1230
1231     if( p_sys->psz_writing_application  )
1232     {
1233         free( p_sys->psz_writing_application );
1234     }
1235     if( p_sys->psz_muxing_application  )
1236     {
1237         free( p_sys->psz_muxing_application );
1238     }
1239
1240     delete p_sys->segment;
1241
1242     delete p_sys->ep;
1243     delete p_sys->es;
1244     delete p_sys->in;
1245
1246     free( p_sys );
1247 }
1248
1249 static int BlockGet( input_thread_t *p_input, KaxBlock **pp_block, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration )
1250 {
1251     demux_sys_t    *p_sys   = p_input->p_demux_data;
1252
1253     *pp_block = NULL;
1254     *pi_ref1  = -1;
1255     *pi_ref2  = -1;
1256
1257     for( ;; )
1258     {
1259         EbmlElement *el;
1260         int         i_level;
1261
1262         if( p_input->b_die )
1263         {
1264             return VLC_EGENERIC;
1265         }
1266
1267         el = p_sys->ep->Get();
1268         i_level = p_sys->ep->GetLevel();
1269
1270         if( el == NULL && *pp_block != NULL )
1271         {
1272             /* update the index */
1273 #define idx p_sys->index[p_sys->i_index - 1]
1274             if( p_sys->i_index > 0 && idx.i_time == -1 )
1275             {
1276                 idx.i_time        = (*pp_block)->GlobalTimecode() * (mtime_t) 1000 / p_sys->i_timescale;
1277                 idx.b_key         = *pi_ref1 == -1 ? VLC_TRUE : VLC_FALSE;
1278             }
1279 #undef idx
1280             return VLC_SUCCESS;
1281         }
1282
1283         if( el == NULL )
1284         {
1285             if( p_sys->ep->GetLevel() > 1 )
1286             {
1287                 p_sys->ep->Up();
1288                 continue;
1289             }
1290             msg_Warn( p_input, "EOF" );
1291             return VLC_EGENERIC;
1292         }
1293
1294         /* do parsing */
1295         if( i_level == 1 )
1296         {
1297             if( EbmlId( *el ) == KaxCluster::ClassInfos.GlobalId )
1298             {
1299                 p_sys->cluster = (KaxCluster*)el;
1300
1301                 /* add it to the index */
1302                 if( p_sys->i_index == 0 ||
1303                     ( p_sys->i_index > 0 && p_sys->index[p_sys->i_index - 1].i_position < (int64_t)p_sys->cluster->GetElementPosition() ) )
1304                 {
1305                     IndexAppendCluster( p_input, p_sys->cluster );
1306                 }
1307
1308                 p_sys->ep->Down();
1309             }
1310             else if( EbmlId( *el ) == KaxCues::ClassInfos.GlobalId )
1311             {
1312                 msg_Warn( p_input, "find KaxCues FIXME" );
1313                 return VLC_EGENERIC;
1314             }
1315             else
1316             {
1317                 msg_Dbg( p_input, "unknown (%s)", typeid( el ).name() );
1318             }
1319         }
1320         else if( i_level == 2 )
1321         {
1322             if( EbmlId( *el ) == KaxClusterTimecode::ClassInfos.GlobalId )
1323             {
1324                 KaxClusterTimecode &ctc = *(KaxClusterTimecode*)el;
1325
1326                 ctc.ReadData( p_sys->es->I_O() );
1327                 p_sys->cluster->InitTimecode( uint64( ctc ), p_sys->i_timescale );
1328             }
1329             else if( EbmlId( *el ) == KaxBlockGroup::ClassInfos.GlobalId )
1330             {
1331                 p_sys->ep->Down();
1332             }
1333         }
1334         else if( i_level == 3 )
1335         {
1336             if( EbmlId( *el ) == KaxBlock::ClassInfos.GlobalId )
1337             {
1338                 *pp_block = (KaxBlock*)el;
1339
1340                 (*pp_block)->ReadData( p_sys->es->I_O() );
1341                 (*pp_block)->SetParent( *p_sys->cluster );
1342
1343                 p_sys->ep->Keep();
1344             }
1345             else if( EbmlId( *el ) == KaxBlockDuration::ClassInfos.GlobalId )
1346             {
1347                 KaxBlockDuration &dur = *(KaxBlockDuration*)el;
1348
1349                 dur.ReadData( p_sys->es->I_O() );
1350                 *pi_duration = uint64( dur );
1351             }
1352             else if( EbmlId( *el ) == KaxReferenceBlock::ClassInfos.GlobalId )
1353             {
1354                 KaxReferenceBlock &ref = *(KaxReferenceBlock*)el;
1355
1356                 ref.ReadData( p_sys->es->I_O() );
1357                 if( *pi_ref1 == -1 )
1358                 {
1359                     *pi_ref1 = int64( ref );
1360                 }
1361                 else
1362                 {
1363                     *pi_ref2 = int64( ref );
1364                 }
1365             }
1366         }
1367         else
1368         {
1369             msg_Err( p_input, "invalid level = %d", i_level );
1370             return VLC_EGENERIC;
1371         }
1372     }
1373 }
1374
1375 static block_t *MemToBlock( input_thread_t *p_input, uint8_t *p_mem, int i_mem)
1376 {
1377     block_t *p_block;
1378     if( !(p_block = block_New( p_input, i_mem ) ) ) return NULL;
1379     memcpy( p_block->p_buffer, p_mem, i_mem );
1380     //p_block->i_rate = p_input->stream.control.i_rate;
1381     return p_block;
1382 }
1383
1384 static void BlockDecode( input_thread_t *p_input, KaxBlock *block, mtime_t i_pts, mtime_t i_duration )
1385 {
1386     demux_sys_t    *p_sys   = p_input->p_demux_data;
1387
1388     int             i_track;
1389     unsigned int    i;
1390     vlc_bool_t      b;
1391
1392 #define tk  p_sys->track[i_track]
1393     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1394     {
1395         if( tk.i_number == block->TrackNum() )
1396         {
1397             break;
1398         }
1399     }
1400
1401     if( i_track >= p_sys->i_track )
1402     {
1403         msg_Err( p_input, "invalid track number=%d", block->TrackNum() );
1404         return;
1405     }
1406
1407     es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk.p_es, &b );
1408     if( !b )
1409     {
1410         tk.b_inited = VLC_FALSE;
1411         return;
1412     }
1413
1414     if( tk.fmt.i_cat == AUDIO_ES && p_input->stream.control.b_mute )
1415     {
1416         return;
1417     }
1418
1419     /* First send init data */
1420     if( !tk.b_inited && tk.i_data_init > 0 )
1421     {
1422         block_t *p_init;
1423
1424         msg_Dbg( p_input, "sending header (%d bytes)", tk.i_data_init );
1425
1426         if( tk.fmt.i_codec == VLC_FOURCC( 'v', 'o', 'r', 'b' ) )
1427         {
1428             int i;
1429             int i_offset = 1;
1430             int i_size[3];
1431
1432             /* XXX hack split the 3 headers */
1433             if( tk.p_data_init[0] != 0x02 )
1434             {
1435                 msg_Err( p_input, "invalid vorbis header" );
1436             }
1437
1438             for( i = 0; i < 2; i++ )
1439             {
1440                 i_size[i] = 0;
1441                 while( i_offset < tk.i_data_init )
1442                 {
1443                     i_size[i] += tk.p_data_init[i_offset];
1444                     if( tk.p_data_init[i_offset++] != 0xff )
1445                     {
1446                         break;
1447                     }
1448                 }
1449             }
1450             i_size[0] = __MIN( i_size[0], tk.i_data_init - i_offset );
1451             i_size[1] = __MIN( i_size[1], tk.i_data_init - i_offset - i_size[0] );
1452             i_size[2] = tk.i_data_init - i_offset - i_size[0] - i_size[1];
1453
1454             p_init = MemToBlock( p_input, &tk.p_data_init[i_offset], i_size[0] );
1455             if( p_init )
1456             {
1457                 es_out_Send( p_input->p_es_out, tk.p_es, p_init );
1458             }
1459             p_init = MemToBlock( p_input, &tk.p_data_init[i_offset+i_size[0]], i_size[1] );
1460             if( p_init )
1461             {
1462                 es_out_Send( p_input->p_es_out, tk.p_es, p_init );
1463             }
1464             p_init = MemToBlock( p_input, &tk.p_data_init[i_offset+i_size[0]+i_size[1]], i_size[2] );
1465             if( p_init )
1466             {
1467                 es_out_Send( p_input->p_es_out, tk.p_es, p_init );
1468             }
1469         }
1470         else
1471         {
1472             p_init = MemToBlock( p_input, tk.p_data_init, tk.i_data_init );
1473             if( p_init )
1474             {
1475                 es_out_Send( p_input->p_es_out, tk.p_es, p_init );
1476             }
1477         }
1478     }
1479     tk.b_inited = VLC_TRUE;
1480
1481
1482     for( i = 0; i < block->NumberFrames(); i++ )
1483     {
1484         block_t *p_block;
1485         DataBuffer &data = block->GetBuffer(i);
1486
1487         p_block = MemToBlock( p_input, data.Buffer(), data.Size() );
1488         if( p_block == NULL )
1489         {
1490             break;
1491         }
1492
1493         if( tk.fmt.i_cat != VIDEO_ES )
1494             p_block->i_dts = p_block->i_pts = i_pts;
1495         else
1496         {
1497             p_block->i_dts = i_pts;
1498             p_block->i_pts = 0;
1499         }
1500
1501         if( tk.fmt.i_cat == SPU_ES && strcmp( tk.psz_codec, "S_VOBSUB" ) )
1502         {
1503             if( i_duration > 0 )
1504             {
1505                 p_block->i_dts += i_duration * 1000;
1506             }
1507             else
1508             {
1509                 p_block->i_dts = 0;
1510             }
1511         }
1512         es_out_Send( p_input->p_es_out, tk.p_es, p_block );
1513
1514         /* use time stamp only for first block */
1515         i_pts = 0;
1516     }
1517
1518 #undef tk
1519 }
1520
1521 static void Seek( input_thread_t *p_input, mtime_t i_date, int i_percent)
1522 {
1523     demux_sys_t    *p_sys   = p_input->p_demux_data;
1524
1525     KaxBlock    *block;
1526     int64_t     i_block_duration;
1527     int64_t     i_block_ref1;
1528     int64_t     i_block_ref2;
1529
1530     int         i_index;
1531     int         i_track_skipping;
1532     int         i_track;
1533
1534     msg_Dbg( p_input, "seek request to "I64Fd" (%d%%)", i_date, i_percent );
1535     if( i_date < 0 && i_percent < 0 )
1536     {
1537         return;
1538     }
1539
1540     delete p_sys->ep;
1541     p_sys->ep = new EbmlParser( p_sys->es, p_sys->segment );
1542     p_sys->cluster = NULL;
1543
1544     /* seek without index or without date */
1545     if( config_GetInt( p_input, "mkv-seek-percent" ) || !p_sys->b_cues || i_date < 0 )
1546     {
1547         int64_t i_pos = i_percent * stream_Size( p_input->s ) / 100;
1548
1549         msg_Dbg( p_input, "imprecise way of seeking" );
1550         for( i_index = 0; i_index < p_sys->i_index; i_index++ )
1551         {
1552             if( p_sys->index[i_index].i_position >= i_pos)
1553             {
1554                 break;
1555             }
1556         }
1557         if( i_index == p_sys->i_index )
1558         {
1559             i_index--;
1560         }
1561
1562         p_sys->in->setFilePointer( p_sys->index[i_index].i_position,
1563                                    seek_beginning );
1564
1565         if( p_sys->index[i_index].i_position < i_pos )
1566         {
1567             EbmlElement *el;
1568
1569             msg_Warn( p_input, "searching for cluster, could take some time" );
1570
1571             /* search a cluster */
1572             while( ( el = p_sys->ep->Get() ) != NULL )
1573             {
1574                 if( EbmlId( *el ) == KaxCluster::ClassInfos.GlobalId )
1575                 {
1576                     KaxCluster *cluster = (KaxCluster*)el;
1577
1578                     /* add it to the index */
1579                     IndexAppendCluster( p_input, cluster );
1580
1581                     if( (int64_t)cluster->GetElementPosition() >= i_pos )
1582                     {
1583                         p_sys->cluster = cluster;
1584                         p_sys->ep->Down();
1585                         break;
1586                     }
1587                 }
1588             }
1589         }
1590     }
1591     else
1592     {
1593         for( i_index = 0; i_index < p_sys->i_index; i_index++ )
1594         {
1595             if( p_sys->index[i_index].i_time >= i_date )
1596             {
1597                 break;
1598             }
1599         }
1600
1601         if( i_index > 0 )
1602         {
1603             i_index--;
1604         }
1605
1606         msg_Dbg( p_input, "seek got "I64Fd" (%d%%)",
1607                  p_sys->index[i_index].i_time,
1608                  (int)( 100 * p_sys->index[i_index].i_position /
1609                         stream_Size( p_input->s ) ) );
1610
1611         p_sys->in->setFilePointer( p_sys->index[i_index].i_position,
1612                                    seek_beginning );
1613     }
1614
1615     /* now parse until key frame */
1616 #define tk  p_sys->track[i_track]
1617     i_track_skipping = 0;
1618     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1619     {
1620         if( tk.fmt.i_cat == VIDEO_ES )
1621         {
1622             tk.b_search_keyframe = VLC_TRUE;
1623             i_track_skipping++;
1624         }
1625     }
1626
1627     while( i_track_skipping > 0 )
1628     {
1629         if( BlockGet( p_input, &block, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
1630         {
1631             msg_Warn( p_input, "cannot get block EOF?" );
1632
1633             return;
1634         }
1635
1636         p_sys->i_pts = block->GlobalTimecode() * (mtime_t) 1000 / p_sys->i_timescale;
1637
1638         for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1639         {
1640             if( tk.i_number == block->TrackNum() )
1641             {
1642                 break;
1643             }
1644         }
1645
1646         if( i_track < p_sys->i_track )
1647         {
1648             if( tk.fmt.i_cat == VIDEO_ES && i_block_ref1 == -1 && tk.b_search_keyframe )
1649             {
1650                 tk.b_search_keyframe = VLC_FALSE;
1651                 i_track_skipping--;
1652             }
1653             if( tk.fmt.i_cat == VIDEO_ES && !tk.b_search_keyframe )
1654             {
1655                 BlockDecode( p_input, block, 0, 0 );
1656             }
1657         }
1658
1659         delete block;
1660     }
1661 #undef tk
1662 }
1663
1664 /*****************************************************************************
1665  * Demux: reads and demuxes data packets
1666  *****************************************************************************
1667  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1668  *****************************************************************************/
1669 static int Demux( input_thread_t * p_input )
1670 {
1671     demux_sys_t    *p_sys   = p_input->p_demux_data;
1672     mtime_t        i_start_pts;
1673     int            i_block_count = 0;
1674
1675     KaxBlock *block;
1676     int64_t i_block_duration;
1677     int64_t i_block_ref1;
1678     int64_t i_block_ref2;
1679
1680     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1681     {
1682         mtime_t i_duration = (mtime_t)( p_sys->f_duration / 1000 );
1683         mtime_t i_date = -1;
1684         int i_percent  = -1;
1685
1686         if( i_duration > 0 )
1687         {
1688             i_date = (mtime_t)1000000 *
1689                      (mtime_t)i_duration*
1690                      (mtime_t)p_sys->in->getFilePointer() /
1691                      (mtime_t)stream_Size( p_input->s );
1692         }
1693         if( stream_Size( p_input->s ) > 0 )
1694         {
1695             i_percent = 100 * p_sys->in->getFilePointer() /
1696                         stream_Size( p_input->s );
1697         }
1698
1699         Seek( p_input, i_date, i_percent);
1700     }
1701
1702     i_start_pts = -1;
1703
1704     for( ;; )
1705     {
1706         mtime_t i_pts;
1707
1708         if( BlockGet( p_input, &block, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
1709         {
1710             msg_Warn( p_input, "cannot get block EOF?" );
1711
1712             return 0;
1713         }
1714
1715         p_sys->i_pts = block->GlobalTimecode() * (mtime_t) 1000 / p_sys->i_timescale;
1716
1717         if( p_sys->i_pts > 0 )
1718         {
1719             input_ClockManageRef( p_input,
1720                                   p_input->stream.p_selected_program,
1721                                   p_sys->i_pts * 9 / 100 );
1722         }
1723
1724         i_pts = input_ClockGetTS( p_input,
1725                                   p_input->stream.p_selected_program,
1726                                   p_sys->i_pts * 9 / 100 );
1727
1728
1729
1730         BlockDecode( p_input, block, i_pts, i_block_duration );
1731
1732         delete block;
1733         i_block_count++;
1734
1735         if( i_start_pts == -1 )
1736         {
1737             i_start_pts = p_sys->i_pts;
1738         }
1739         else if( p_sys->i_pts > i_start_pts + (mtime_t)100000 || i_block_count > 5 )
1740         {
1741             return 1;
1742         }
1743     }
1744 }
1745
1746
1747
1748 /*****************************************************************************
1749  * Stream managment
1750  *****************************************************************************/
1751 vlc_stream_io_callback::vlc_stream_io_callback( stream_t *s_ )
1752 {
1753     s = s_;
1754     mb_eof = VLC_FALSE;
1755 }
1756
1757 uint32_t vlc_stream_io_callback::read( void *p_buffer, size_t i_size )
1758 {
1759     if( i_size <= 0 || mb_eof )
1760     {
1761         return 0;
1762     }
1763
1764     return stream_Read( s, p_buffer, i_size );
1765 }
1766 void vlc_stream_io_callback::setFilePointer(int64_t i_offset, seek_mode mode )
1767 {
1768     int64_t i_pos;
1769
1770     switch( mode )
1771     {
1772         case seek_beginning:
1773             i_pos = i_offset;
1774             break;
1775         case seek_end:
1776             i_pos = stream_Size( s ) - i_offset;
1777             break;
1778         default:
1779             i_pos= stream_Tell( s ) + i_offset;
1780             break;
1781     }
1782
1783     if( i_pos < 0 || i_pos >= stream_Size( s ) )
1784     {
1785         mb_eof = VLC_TRUE;
1786         return;
1787     }
1788
1789     mb_eof = VLC_FALSE;
1790     if( stream_Seek( s, i_pos ) )
1791     {
1792         mb_eof = VLC_TRUE;
1793     }
1794     return;
1795 }
1796 size_t vlc_stream_io_callback::write( const void *p_buffer, size_t i_size )
1797 {
1798     return 0;
1799 }
1800 uint64_t vlc_stream_io_callback::getFilePointer( void )
1801 {
1802     return stream_Tell( s );
1803 }
1804 void vlc_stream_io_callback::close( void )
1805 {
1806     return;
1807 }
1808
1809
1810 /*****************************************************************************
1811  * Ebml Stream parser
1812  *****************************************************************************/
1813 EbmlParser::EbmlParser( EbmlStream *es, EbmlElement *el_start )
1814 {
1815     int i;
1816
1817     m_es = es;
1818     m_got = NULL;
1819     m_el[0] = el_start;
1820
1821     for( i = 1; i < 6; i++ )
1822     {
1823         m_el[i] = NULL;
1824     }
1825     mi_level = 1;
1826     mi_user_level = 1;
1827     mb_keep = VLC_FALSE;
1828 }
1829
1830 EbmlParser::~EbmlParser( void )
1831 {
1832     int i;
1833
1834     for( i = 1; i < mi_level; i++ )
1835     {
1836         if( !mb_keep )
1837         {
1838             delete m_el[i];
1839         }
1840         mb_keep = VLC_FALSE;
1841     }
1842 }
1843
1844 void EbmlParser::Up( void )
1845 {
1846     if( mi_user_level == mi_level )
1847     {
1848         fprintf( stderr," arrrrrrrrrrrrrg Up cannot escape itself\n" );
1849     }
1850
1851     mi_user_level--;
1852 }
1853
1854 void EbmlParser::Down( void )
1855 {
1856     mi_user_level++;
1857     mi_level++;
1858 }
1859
1860 void EbmlParser::Keep( void )
1861 {
1862     mb_keep = VLC_TRUE;
1863 }
1864
1865 int EbmlParser::GetLevel( void )
1866 {
1867     return mi_user_level;
1868 }
1869
1870 EbmlElement *EbmlParser::Get( void )
1871 {
1872     int i_ulev = 0;
1873
1874     if( mi_user_level != mi_level )
1875     {
1876         return NULL;
1877     }
1878     if( m_got )
1879     {
1880         EbmlElement *ret = m_got;
1881         m_got = NULL;
1882
1883         return ret;
1884     }
1885
1886     if( m_el[mi_level] )
1887     {
1888         m_el[mi_level]->SkipData( *m_es, m_el[mi_level]->Generic().Context );
1889         if( !mb_keep )
1890         {
1891             delete m_el[mi_level];
1892         }
1893         mb_keep = VLC_FALSE;
1894     }
1895
1896     m_el[mi_level] = m_es->FindNextElement( m_el[mi_level - 1]->Generic().Context, i_ulev, 0xFFFFFFFFL, true, 1 );
1897     if( i_ulev > 0 )
1898     {
1899         while( i_ulev > 0 )
1900         {
1901             if( mi_level == 1 )
1902             {
1903                 mi_level = 0;
1904                 return NULL;
1905             }
1906
1907             delete m_el[mi_level - 1];
1908             m_got = m_el[mi_level -1] = m_el[mi_level];
1909             m_el[mi_level] = NULL;
1910
1911             mi_level--;
1912             i_ulev--;
1913         }
1914         return NULL;
1915     }
1916     else if( m_el[mi_level] == NULL )
1917     {
1918         fprintf( stderr," m_el[mi_level] == NULL\n" );
1919     }
1920
1921     return m_el[mi_level];
1922 }
1923
1924
1925 /*****************************************************************************
1926  * Tools
1927  *  * LoadCues : load the cues element and update index
1928  *
1929  *  * LoadTags : load ... the tags element
1930  *
1931  *  * InformationsCreate : create all informations, load tags if present
1932  *
1933  *****************************************************************************/
1934 static void LoadCues( input_thread_t *p_input )
1935 {
1936     demux_sys_t *p_sys = p_input->p_demux_data;
1937     int64_t     i_sav_position = p_sys->in->getFilePointer();
1938     EbmlParser  *ep;
1939     EbmlElement *el, *cues;
1940
1941     msg_Dbg( p_input, "loading cues" );
1942     p_sys->in->setFilePointer( p_sys->i_cues_position, seek_beginning );
1943     cues = p_sys->es->FindNextID( KaxCues::ClassInfos, 0xFFFFFFFFL);
1944
1945     if( cues == NULL )
1946     {
1947         msg_Err( p_input, "cannot load cues (broken seekhead or file)" );
1948         return;
1949     }
1950
1951     ep = new EbmlParser( p_sys->es, cues );
1952     while( ( el = ep->Get() ) != NULL )
1953     {
1954         if( EbmlId( *el ) == KaxCuePoint::ClassInfos.GlobalId )
1955         {
1956 #define idx p_sys->index[p_sys->i_index]
1957
1958             idx.i_track       = -1;
1959             idx.i_block_number= -1;
1960             idx.i_position    = -1;
1961             idx.i_time        = -1;
1962             idx.b_key         = VLC_TRUE;
1963
1964             ep->Down();
1965             while( ( el = ep->Get() ) != NULL )
1966             {
1967                 if( EbmlId( *el ) == KaxCueTime::ClassInfos.GlobalId )
1968                 {
1969                     KaxCueTime &ctime = *(KaxCueTime*)el;
1970
1971                     ctime.ReadData( p_sys->es->I_O() );
1972
1973                     idx.i_time = uint64( ctime ) * (mtime_t)1000000000 / p_sys->i_timescale;
1974                 }
1975                 else if( EbmlId( *el ) == KaxCueTrackPositions::ClassInfos.GlobalId )
1976                 {
1977                     ep->Down();
1978                     while( ( el = ep->Get() ) != NULL )
1979                     {
1980                         if( EbmlId( *el ) == KaxCueTrack::ClassInfos.GlobalId )
1981                         {
1982                             KaxCueTrack &ctrack = *(KaxCueTrack*)el;
1983
1984                             ctrack.ReadData( p_sys->es->I_O() );
1985                             idx.i_track = uint16( ctrack );
1986                         }
1987                         else if( EbmlId( *el ) == KaxCueClusterPosition::ClassInfos.GlobalId )
1988                         {
1989                             KaxCueClusterPosition &ccpos = *(KaxCueClusterPosition*)el;
1990
1991                             ccpos.ReadData( p_sys->es->I_O() );
1992                             idx.i_position = p_sys->segment->GetGlobalPosition( uint64( ccpos ) );
1993                         }
1994                         else if( EbmlId( *el ) == KaxCueBlockNumber::ClassInfos.GlobalId )
1995                         {
1996                             KaxCueBlockNumber &cbnum = *(KaxCueBlockNumber*)el;
1997
1998                             cbnum.ReadData( p_sys->es->I_O() );
1999                             idx.i_block_number = uint32( cbnum );
2000                         }
2001                         else
2002                         {
2003                             msg_Dbg( p_input, "         * Unknown (%s)", typeid(*el).name() );
2004                         }
2005                     }
2006                     ep->Up();
2007                 }
2008                 else
2009                 {
2010                     msg_Dbg( p_input, "     * Unknown (%s)", typeid(*el).name() );
2011                 }
2012             }
2013             ep->Up();
2014
2015             msg_Dbg( p_input, " * added time="I64Fd" pos="I64Fd
2016                      " track=%d bnum=%d", idx.i_time, idx.i_position,
2017                      idx.i_track, idx.i_block_number );
2018
2019             p_sys->i_index++;
2020             if( p_sys->i_index >= p_sys->i_index_max )
2021             {
2022                 p_sys->i_index_max += 1024;
2023                 p_sys->index = (mkv_index_t*)realloc( p_sys->index, sizeof( mkv_index_t ) * p_sys->i_index_max );
2024             }
2025 #undef idx
2026         }
2027         else
2028         {
2029             msg_Dbg( p_input, " * Unknown (%s)", typeid(*el).name() );
2030         }
2031     }
2032     delete ep;
2033     delete cues;
2034
2035     p_sys->b_cues = VLC_TRUE;
2036
2037     msg_Dbg( p_input, "loading cues done." );
2038     p_sys->in->setFilePointer( i_sav_position, seek_beginning );
2039 }
2040
2041 static void LoadTags( input_thread_t *p_input )
2042 {
2043     demux_sys_t *p_sys = p_input->p_demux_data;
2044     int64_t     i_sav_position = p_sys->in->getFilePointer();
2045     EbmlParser  *ep;
2046     EbmlElement *el, *tags;
2047
2048     msg_Dbg( p_input, "loading tags" );
2049     p_sys->in->setFilePointer( p_sys->i_tags_position, seek_beginning );
2050     tags = p_sys->es->FindNextID( KaxTags::ClassInfos, 0xFFFFFFFFL);
2051
2052     if( tags == NULL )
2053     {
2054         msg_Err( p_input, "cannot load tags (broken seekhead or file)" );
2055         return;
2056     }
2057
2058     msg_Dbg( p_input, "Tags" );
2059     ep = new EbmlParser( p_sys->es, tags );
2060     while( ( el = ep->Get() ) != NULL )
2061     {
2062         if( EbmlId( *el ) == KaxTag::ClassInfos.GlobalId )
2063         {
2064             msg_Dbg( p_input, "+ Tag" );
2065             ep->Down();
2066             while( ( el = ep->Get() ) != NULL )
2067             {
2068                 if( EbmlId( *el ) == KaxTagTargets::ClassInfos.GlobalId )
2069                 {
2070                     msg_Dbg( p_input, "|   + Targets" );
2071                     ep->Down();
2072                     while( ( el = ep->Get() ) != NULL )
2073                     {
2074                         msg_Dbg( p_input, "|   |   + Unknown (%s)", typeid( *el ).name() );
2075                     }
2076                     ep->Up();
2077                 }
2078                 else if( EbmlId( *el ) == KaxTagGeneral::ClassInfos.GlobalId )
2079                 {
2080                     msg_Dbg( p_input, "|   + General" );
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 ) == KaxTagGenres::ClassInfos.GlobalId )
2089                 {
2090                     msg_Dbg( p_input, "|   + Genres" );
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 ) == KaxTagAudioSpecific::ClassInfos.GlobalId )
2099                 {
2100                     msg_Dbg( p_input, "|   + Audio Specific" );
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 ) == KaxTagImageSpecific::ClassInfos.GlobalId )
2109                 {
2110                     msg_Dbg( p_input, "|   + Images 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 ) == KaxTagMultiComment::ClassInfos.GlobalId )
2119                 {
2120                     msg_Dbg( p_input, "|   + Multi Comment" );
2121                 }
2122                 else if( EbmlId( *el ) == KaxTagMultiCommercial::ClassInfos.GlobalId )
2123                 {
2124                     msg_Dbg( p_input, "|   + Multi Commercial" );
2125                 }
2126                 else if( EbmlId( *el ) == KaxTagMultiDate::ClassInfos.GlobalId )
2127                 {
2128                     msg_Dbg( p_input, "|   + Multi Date" );
2129                 }
2130                 else if( EbmlId( *el ) == KaxTagMultiEntity::ClassInfos.GlobalId )
2131                 {
2132                     msg_Dbg( p_input, "|   + Multi Entity" );
2133                 }
2134                 else if( EbmlId( *el ) == KaxTagMultiIdentifier::ClassInfos.GlobalId )
2135                 {
2136                     msg_Dbg( p_input, "|   + Multi Identifier" );
2137                 }
2138                 else if( EbmlId( *el ) == KaxTagMultiLegal::ClassInfos.GlobalId )
2139                 {
2140                     msg_Dbg( p_input, "|   + Multi Legal" );
2141                 }
2142                 else if( EbmlId( *el ) == KaxTagMultiTitle::ClassInfos.GlobalId )
2143                 {
2144                     msg_Dbg( p_input, "|   + Multi Title" );
2145                 }
2146                 else
2147                 {
2148                     msg_Dbg( p_input, "|   + Unknown (%s)", typeid( *el ).name() );
2149                 }
2150             }
2151             ep->Up();
2152         }
2153         else
2154         {
2155             msg_Dbg( p_input, "+ Unknown (%s)", typeid( *el ).name() );
2156         }
2157     }
2158     delete ep;
2159     delete tags;
2160
2161     msg_Dbg( p_input, "loading tags done." );
2162     p_sys->in->setFilePointer( i_sav_position, seek_beginning );
2163 }
2164
2165 static void InformationsCreate( input_thread_t *p_input )
2166 {
2167     demux_sys_t           *p_sys = p_input->p_demux_data;
2168     input_info_category_t *p_cat;
2169     int                   i_track;
2170
2171     p_cat = input_InfoCategory( p_input, "Matroska" );
2172     if( p_sys->f_duration > 1000.1 )
2173     {
2174         char psz_buffer[MSTRTIME_MAX_SIZE];
2175         input_AddInfo( p_cat, _("Duration"), 
2176                        msecstotimestr( psz_buffer, p_sys->f_duration ) );
2177     }
2178
2179     if( p_sys->psz_title )
2180     {
2181         input_AddInfo( p_cat, _("Title"), "%s" ,p_sys->psz_title );
2182     }
2183     if( p_sys->psz_date_utc )
2184     {
2185         input_AddInfo( p_cat, _("Date UTC"), "%s" ,p_sys->psz_date_utc );
2186     }
2187     if( p_sys->psz_segment_filename )
2188     {
2189         input_AddInfo( p_cat, _("Segment Filename"), "%s" ,p_sys->psz_segment_filename );
2190     }
2191     if( p_sys->psz_muxing_application )
2192     {
2193         input_AddInfo( p_cat, _("Muxing Application"), "%s" ,p_sys->psz_muxing_application );
2194     }
2195     if( p_sys->psz_writing_application )
2196     {
2197         input_AddInfo( p_cat, _("Writing Application"), "%s" ,p_sys->psz_writing_application );
2198     }
2199     input_AddInfo( p_cat, _("Number of streams"), "%d" , p_sys->i_track );
2200
2201     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
2202     {
2203         char psz_cat[strlen( "Stream " ) + 10];
2204 #define tk  p_sys->track[i_track]
2205
2206         sprintf( psz_cat, "Stream %d", i_track );
2207         p_cat = input_InfoCategory( p_input, psz_cat);
2208         if( tk.fmt.psz_description )
2209         {
2210             input_AddInfo( p_cat, _("Name"), "%s", tk.fmt.psz_description );
2211         }
2212         if( tk.fmt.psz_language )
2213         {
2214             input_AddInfo( p_cat, _("Language"), "%s", tk.fmt.psz_language );
2215         }
2216         if( tk.psz_codec_name )
2217         {
2218             input_AddInfo( p_cat, _("Codec Name"), "%s", tk.psz_codec_name );
2219         }
2220         if( tk.psz_codec_settings )
2221         {
2222             input_AddInfo( p_cat, _("Codec Setting"), "%s", tk.psz_codec_settings );
2223         }
2224         if( tk.psz_codec_info_url )
2225         {
2226             input_AddInfo( p_cat, _("Codec Info"), "%s", tk.psz_codec_info_url );
2227         }
2228         if( tk.psz_codec_download_url )
2229         {
2230             input_AddInfo( p_cat, _("Codec Download"), "%s", tk.psz_codec_download_url );
2231         }
2232 #undef  tk
2233     }
2234
2235     if( p_sys->i_tags_position >= 0 )
2236     {
2237         vlc_bool_t b_seekable;
2238
2239         stream_Control( p_input->s, STREAM_CAN_FASTSEEK, &b_seekable );
2240         if( b_seekable )
2241         {
2242             LoadTags( p_input );
2243         }
2244     }
2245 }
2246
2247
2248 /*****************************************************************************
2249  * Divers
2250  *****************************************************************************/
2251
2252 static void IndexAppendCluster( input_thread_t *p_input, KaxCluster *cluster )
2253 {
2254     demux_sys_t    *p_sys   = p_input->p_demux_data;
2255
2256 #define idx p_sys->index[p_sys->i_index]
2257     idx.i_track       = -1;
2258     idx.i_block_number= -1;
2259     idx.i_position    = cluster->GetElementPosition();
2260     idx.i_time        = -1;
2261     idx.b_key         = VLC_TRUE;
2262
2263     p_sys->i_index++;
2264     if( p_sys->i_index >= p_sys->i_index_max )
2265     {
2266         p_sys->i_index_max += 1024;
2267         p_sys->index = (mkv_index_t*)realloc( p_sys->index, sizeof( mkv_index_t ) * p_sys->i_index_max );
2268     }
2269 #undef idx
2270 }
2271
2272 static char * UTF8ToStr( const UTFstring &u )
2273 {
2274     int     i_src;
2275     const wchar_t *src;
2276     char *dst, *p;
2277
2278     i_src = u.length();
2279     src   = u.c_str();
2280
2281     p = dst = (char*)malloc( i_src + 1);
2282     while( i_src > 0 )
2283     {
2284         if( *src < 255 )
2285         {
2286             *p++ = (char)*src;
2287         }
2288         else
2289         {
2290             *p++ = '?';
2291         }
2292         src++;
2293         i_src--;
2294     }
2295     *p++= '\0';
2296
2297     return dst;
2298 }
2299
2300 static char *LanguageGetName    ( const char *psz_code )
2301 {
2302     const iso639_lang_t *pl;
2303
2304     if( strlen( psz_code ) == 2 )
2305     {
2306         pl = GetLang_1( psz_code );
2307     }
2308     else if( strlen( psz_code ) == 3 )
2309     {
2310         pl = GetLang_2B( psz_code );
2311         if( !strcmp( pl->psz_iso639_1, "??" ) )
2312         {
2313             pl = GetLang_2T( psz_code );
2314         }
2315     }
2316     else
2317     {
2318         return strdup( psz_code );
2319     }
2320
2321     if( !strcmp( pl->psz_iso639_1, "??" ) )
2322     {
2323        return strdup( psz_code );
2324     }
2325     else
2326     {
2327         if( *pl->psz_native_name )
2328         {
2329             return strdup( pl->psz_native_name );
2330         }
2331         return strdup( pl->psz_eng_name );
2332     }
2333 }
2334