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