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