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