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