* mkv: fix a double delete.
[vlc.git] / modules / demux / mkv.cpp
1 /*****************************************************************************
2  * mkv.cpp : matroska demuxer
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: mkv.cpp,v 1.4 2003/06/22 16:27:11 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 #include <vlc/input.h>
32
33 #include <codecs.h>                        /* BITMAPINFOHEADER, WAVEFORMATEX */
34
35 #include <iostream>
36 #include <cassert>
37 #include <typeinfo>
38
39 /* libebml and matroska */
40 #include "ebml/EbmlHead.h"
41 #include "ebml/EbmlSubHead.h"
42 #include "ebml/EbmlStream.h"
43 #include "ebml/EbmlContexts.h"
44 #include "ebml/EbmlVersion.h"
45 #include "ebml/EbmlVoid.h"
46
47 #include "matroska/FileKax.h"
48 #include "matroska/KaxAttachements.h"
49 #include "matroska/KaxBlock.h"
50 #include "matroska/KaxBlockData.h"
51 #include "matroska/KaxChapters.h"
52 #include "matroska/KaxCluster.h"
53 #include "matroska/KaxClusterData.h"
54 #include "matroska/KaxContexts.h"
55 #include "matroska/KaxCues.h"
56 #include "matroska/KaxCuesData.h"
57 #include "matroska/KaxInfo.h"
58 #include "matroska/KaxInfoData.h"
59 #include "matroska/KaxSeekHead.h"
60 #include "matroska/KaxSegment.h"
61 #include "matroska/KaxTag.h"
62 #include "matroska/KaxTracks.h"
63 #include "matroska/KaxTrackAudio.h"
64 #include "matroska/KaxTrackVideo.h"
65
66 #include "ebml/StdIOCallback.h"
67
68 using namespace LIBMATROSKA_NAMESPACE;
69 using namespace std;
70
71
72 /*****************************************************************************
73  * Local prototypes
74  *****************************************************************************/
75 static int  Activate  ( vlc_object_t * );
76 static void Deactivate( vlc_object_t * );
77 static int  Demux     ( input_thread_t * );
78
79 /*****************************************************************************
80  * Module descriptor
81  *****************************************************************************/
82 vlc_module_begin();
83     add_category_hint( N_("mkv-demuxer"), NULL, VLC_TRUE );
84         add_bool( "mkv-index", 0, NULL,
85                   N_("Create index if no cues found"),
86                   N_("Create index if no cues found"), VLC_TRUE );
87     set_description( _("mka/mkv stream demuxer" ) );
88     set_capability( "demux", 50 );
89     set_callbacks( Activate, Deactivate );
90     add_shortcut( "mka" );
91     add_shortcut( "mkv" );
92 vlc_module_end();
93
94
95 /*****************************************************************************
96  * Stream managment
97  *****************************************************************************/
98 class vlc_stream_io_callback: public IOCallback
99 {
100   private:
101     input_thread_t *p_input;
102
103   public:
104     vlc_stream_io_callback( input_thread_t * );
105
106     virtual uint32_t read            ( void *p_buffer, size_t i_size);
107     virtual void     setFilePointer  ( int64_t i_offset, seek_mode mode = seek_beginning );
108     virtual size_t   write           ( const void *p_buffer, size_t i_size);
109     virtual uint64_t getFilePointer  ( void );
110     virtual void     close           ( void );
111 };
112
113
114 vlc_stream_io_callback::vlc_stream_io_callback( input_thread_t *p_input_ )
115 {
116     p_input = p_input_;
117 }
118
119 uint32_t vlc_stream_io_callback::read( void *p_buffer, size_t i_size )
120 {
121     data_packet_t *p_data;
122
123     int i_count;
124     int i_read = 0;
125
126
127     if( !i_size )
128     {
129         return 0;
130     }
131
132     do
133     {
134         i_count = input_SplitBuffer(p_input, &p_data, __MIN( i_size, 10240 ) );
135         if( i_count <= 0 )
136         {
137             return i_read;
138         }
139         memcpy( p_buffer, p_data->p_payload_start, i_count );
140         input_DeletePacket( p_input->p_method_data, p_data );
141
142         (uint8_t*)p_buffer += i_count;
143         i_size            -= i_count;
144         i_read            += i_count;
145
146     } while( i_size );
147
148     return i_read;
149 }
150
151
152 void vlc_stream_io_callback::setFilePointer(int64_t i_offset, seek_mode mode )
153 {
154     int64_t i_pos;
155
156     vlc_mutex_lock( &p_input->stream.stream_lock );
157     switch( mode )
158     {
159         case seek_beginning:
160             i_pos = i_offset;
161             break;
162         case seek_end:
163             i_pos = p_input->stream.p_selected_area->i_size - i_offset;
164             break;
165         default:
166             i_pos= p_input->stream.p_selected_area->i_tell + i_offset;
167             break;
168     }
169     if( i_pos < 0 || i_pos > p_input->stream.p_selected_area->i_size )
170     {
171         msg_Err( p_input, "seeking to wrong place (i_pos=%lld)", i_pos );
172         vlc_mutex_unlock( &p_input->stream.stream_lock );
173         return;
174     }
175     vlc_mutex_unlock( &p_input->stream.stream_lock );
176
177     input_AccessReinit( p_input );
178     p_input->pf_seek( p_input, i_pos );
179 }
180
181 size_t vlc_stream_io_callback::write( const void *p_buffer, size_t i_size )
182 {
183     return 0;
184 }
185
186 uint64_t vlc_stream_io_callback::getFilePointer( void )
187 {
188     uint64_t i_pos;
189
190     vlc_mutex_lock( &p_input->stream.stream_lock );
191     i_pos= p_input->stream.p_selected_area->i_tell;
192     vlc_mutex_unlock( &p_input->stream.stream_lock );
193
194     return i_pos;
195 }
196
197 void vlc_stream_io_callback::close( void )
198 {
199     return;
200 }
201
202 /*****************************************************************************
203  * Ebml Stream parser
204  *****************************************************************************/
205 class EbmlParser
206 {
207     public:
208         EbmlParser( EbmlStream *es, EbmlElement *el_start );
209         ~EbmlParser( void );
210         void Up( void );
211         void Down( void );
212         EbmlElement *Get( void );
213         void        Keep( void );
214
215         int GetLevel( void );
216
217     private:
218
219     EbmlStream  *m_es;
220     int         mi_level;
221     EbmlElement *m_el[6];
222
223     EbmlElement *m_got;
224
225     int         mi_user_level;
226     vlc_bool_t  mb_keep;
227
228 };
229
230 EbmlParser::EbmlParser( EbmlStream *es, EbmlElement *el_start )
231 {
232     int i;
233
234     m_es = es;
235     m_got = NULL;
236     m_el[0] = el_start;
237
238     for( i = 1; i < 6; i++ )
239     {
240         m_el[i] = NULL;
241     }
242     mi_level = 1;
243     mi_user_level = 1;
244     mb_keep = VLC_FALSE;
245 }
246
247 EbmlParser::~EbmlParser( void )
248 {
249     int i;
250
251     for( i = 1; i < mi_level; i++ )
252     {
253         if( !mb_keep )
254         {
255             delete m_el[i];
256         }
257         mb_keep = VLC_FALSE;
258     }
259 }
260
261 void EbmlParser::Up( void )
262 {
263     if( mi_user_level == mi_level )
264     {
265         fprintf( stderr," arrrrrrrrrrrrrg Up cannot escape itself\n" );
266     }
267
268     mi_user_level--;
269 }
270
271 void EbmlParser::Down( void )
272 {
273     mi_user_level++;
274     mi_level++;
275 }
276
277 void EbmlParser::Keep( void )
278 {
279     mb_keep = VLC_TRUE;
280 }
281
282 int EbmlParser::GetLevel( void )
283 {
284     return mi_user_level;
285 }
286
287 EbmlElement *EbmlParser::Get( void )
288 {
289     int i_ulev = 0;
290
291     if( mi_user_level != mi_level )
292     {
293         return NULL;
294     }
295     if( m_got )
296     {
297         EbmlElement *ret = m_got;
298         m_got = NULL;
299
300         return ret;
301     }
302
303     if( m_el[mi_level] )
304     {
305         m_el[mi_level]->SkipData( *m_es, m_el[mi_level]->Generic().Context );
306         if( !mb_keep )
307         {
308             delete m_el[mi_level];
309         }
310         mb_keep = VLC_FALSE;
311     }
312
313     m_el[mi_level] = m_es->FindNextElement( m_el[mi_level - 1]->Generic().Context, i_ulev, 0xFFFFFFFFL, true, 1 );
314     if( i_ulev > 0 )
315     {
316         while( i_ulev > 0 )
317         {
318             if( mi_level == 1 )
319             {
320                 mi_level = 0;
321                 return NULL;
322             }
323
324             delete m_el[mi_level - 1];
325             m_got = m_el[mi_level -1] = m_el[mi_level];
326             m_el[mi_level] = NULL;
327
328             mi_level--;
329             i_ulev--;
330         }
331         return NULL;
332     }
333     else if( m_el[mi_level] == NULL )
334     {
335         fprintf( stderr," m_el[mi_level] == NULL\n" );
336     }
337
338     return m_el[mi_level];
339 }
340
341 /*****************************************************************************
342  * Some functions to manipulate memory
343  *****************************************************************************/
344 #define GetWLE( p )     __GetWLE( (uint8_t*)p )
345 #define GetDWLE( p )    __GetDWLE( (uint8_t*)p )
346 #define GetFOURCC( p )  __GetFOURCC( (uint8_t*)p )
347 static uint16_t __GetWLE( uint8_t *p )
348 {
349     return (uint16_t)p[0] | ( ((uint16_t)p[1]) << 8 );
350 }
351 static uint32_t __GetDWLE( uint8_t *p )
352 {
353     return (uint32_t)p[0] | ( ((uint32_t)p[1]) << 8 ) |
354             ( ((uint32_t)p[2]) << 16 ) | ( ((uint32_t)p[3]) << 24 );
355 }
356 static vlc_fourcc_t __GetFOURCC( uint8_t *p )
357 {
358     return VLC_FOURCC( p[0], p[1], p[2], p[3] );
359 }
360
361
362 /*****************************************************************************
363  * definitions of structures and functions used by this plugins
364  *****************************************************************************/
365 typedef struct
366 {
367     int         i_cat;
368     vlc_bool_t  b_default;
369     int         i_number;
370
371     int         i_extra_data;
372     uint8_t     *p_extra_data;
373
374     char         *psz_language;
375
376     char         *psz_codec;
377     vlc_fourcc_t i_codec;
378
379     uint64_t     i_default_duration;
380     /* video */
381     int         i_width;
382     int         i_height;
383     int         i_display_width;
384     int         i_display_height;
385     float       f_fps;
386
387
388     /* audio */
389     int         i_channels;
390     int         i_samplerate;
391     int         i_bitspersample;
392
393     es_descriptor_t *p_es;
394
395
396
397     vlc_bool_t      b_inited;
398     /* data to be send first */
399     int             i_data_init;
400     uint8_t         *p_data_init;
401
402     /* hack : it's for seek */
403     vlc_bool_t      b_search_keyframe;
404 } mkv_track_t;
405
406 typedef struct
407 {
408     int     i_track;
409     int     i_block_number;
410
411     int64_t i_position;
412     int64_t i_time;
413
414     vlc_bool_t b_key;
415 } mkv_index_t;
416
417 struct demux_sys_t
418 {
419     vlc_stream_io_callback  *in;
420     EbmlStream              *es;
421     EbmlParser              *ep;
422
423     /* time scale */
424     uint64_t                i_timescale;
425
426     /* duration of the segment */
427     float                   f_duration;
428
429     /* all tracks */
430     int                     i_track;
431     mkv_track_t             *track;
432
433     /* from seekhead */
434     int64_t                 i_cues_position;
435     int64_t                 i_chapters_position;
436
437     /* current data */
438     KaxSegment              *segment;
439     KaxCluster              *cluster;
440
441     mtime_t                 i_pts;
442
443     int                     i_index;
444     int                     i_index_max;
445     mkv_index_t             *index;
446 };
447
448 #define MKVD_TIMECODESCALE 1000000
449
450 /*****************************************************************************
451  * Activate: initializes matroska demux structures
452  *****************************************************************************/
453 static int Activate( vlc_object_t * p_this )
454 {
455     input_thread_t *p_input = (input_thread_t *)p_this;
456     demux_sys_t    *p_sys;
457     uint8_t        *p_peek;
458
459     int             i_track;
460     vlc_bool_t      b_audio_selected;
461     int             i_spu_channel, i_audio_channel;
462
463     EbmlElement     *el = NULL, *el1 = NULL, *el2 = NULL, *el3 = NULL, *el4 = NULL;
464
465     /* Initialize access plug-in structures. */
466     if( p_input->i_mtu == 0 )
467     {
468         /* Improve speed. */
469         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
470     }
471
472     /* Set the demux function */
473     p_input->pf_demux = Demux;
474
475     /* peek the begining */
476     if( input_Peek( p_input, &p_peek, 4 ) < 4 )
477     {
478         msg_Warn( p_input, "cannot peek" );
479         return VLC_EGENERIC;
480     }
481
482     /* is a valid file */
483     if( p_peek[0] != 0x1a || p_peek[1] != 0x45 || p_peek[2] != 0xdf || p_peek[3] != 0xa3 )
484     {
485         msg_Warn( p_input, "matroska module discarded (invalid header)" );
486         return VLC_EGENERIC;
487     }
488
489     if( p_input->stream.i_method != INPUT_METHOD_FILE || !p_input->stream.b_seekable )
490     {
491         msg_Err( p_input, "can only read matroska over seekable file yet" );
492         return VLC_EGENERIC;
493     }
494
495     p_input->p_demux_data = p_sys = (demux_sys_t*)malloc( sizeof( demux_sys_t ) );
496     memset( p_sys, 0, sizeof( demux_sys_t ) );
497
498     p_sys->in = new vlc_stream_io_callback( p_input );
499     p_sys->es = new EbmlStream( *p_sys->in );
500     p_sys->f_duration   = -1;
501     p_sys->i_timescale     = MKVD_TIMECODESCALE;
502     p_sys->i_track      = 0;
503     p_sys->track        = (mkv_track_t*)malloc( sizeof( mkv_track_t ) );
504     p_sys->i_pts   = 0;
505     p_sys->i_cues_position = -1;
506     p_sys->i_chapters_position = -1;
507
508     p_sys->i_index      = 0;
509     p_sys->i_index_max  = 1024;
510     p_sys->index        = (mkv_index_t*)malloc( sizeof( mkv_index_t ) * p_sys->i_index_max );
511
512     if( p_sys->es == NULL )
513     {
514         msg_Err( p_input, "failed to create EbmlStream" );
515         delete p_sys->in;
516         free( p_sys );
517         return VLC_EGENERIC;
518     }
519     /* Find the EbmlHead element */
520     el = p_sys->es->FindNextID(EbmlHead::ClassInfos, 0xFFFFFFFFL);
521     if( el == NULL )
522     {
523         msg_Err( p_input, "cannot find EbmlHead" );
524         goto error;
525     }
526     msg_Dbg( p_input, "EbmlHead" );
527     /* skip it */
528     el->SkipData( *p_sys->es, el->Generic().Context );
529     delete el;
530
531     /* Find a segment */
532     el = p_sys->es->FindNextID( KaxSegment::ClassInfos, 0xFFFFFFFFL);
533     if( el == NULL )
534     {
535         msg_Err( p_input, "cannot find KaxSegment" );
536         goto error;
537     }
538     msg_Dbg( p_input, "+ Segment" );
539     p_sys->segment = (KaxSegment*)el;
540     p_sys->cluster = NULL;
541
542     p_sys->ep = new EbmlParser( p_sys->es, el );
543
544     while( ( el1 = p_sys->ep->Get() ) != NULL )
545     {
546         if( EbmlId( *el1 ) == KaxInfo::ClassInfos.GlobalId )
547         {
548             msg_Dbg( p_input, "|   + Informations" );
549
550             p_sys->ep->Down();
551             while( ( el2 = p_sys->ep->Get() ) != NULL )
552             {
553                 if( EbmlId( *el2 ) == KaxTimecodeScale::ClassInfos.GlobalId )
554                 {
555                     KaxTimecodeScale &tcs = *(KaxTimecodeScale*)el2;
556
557                     tcs.ReadData( p_sys->es->I_O() );
558                     p_sys->i_timescale = uint64(tcs);
559
560                     msg_Dbg( p_input, "|   |   + TimecodeScale=%lld", p_sys->i_timescale );
561                 }
562                 else if( EbmlId( *el2 ) == KaxDuration::ClassInfos.GlobalId )
563                 {
564                     KaxDuration &dur = *(KaxDuration*)el2;
565
566                     dur.ReadData( p_sys->es->I_O() );
567                     p_sys->f_duration = float(dur);
568
569                     msg_Dbg( p_input, "|   |   + Duration=%f", p_sys->f_duration );
570                 }
571                 else
572                 {
573                     msg_Dbg( p_input, "|   |   + Unknow (%s)", typeid(*el2).name() );
574                 }
575             }
576             p_sys->ep->Up();
577         }
578         else if( EbmlId( *el1 ) == KaxTracks::ClassInfos.GlobalId )
579         {
580             msg_Dbg( p_input, "|   + Tracks" );
581
582             p_sys->ep->Down();
583             while( ( el2 = p_sys->ep->Get() ) != NULL )
584             {
585                 if( EbmlId( *el2 ) == KaxTrackEntry::ClassInfos.GlobalId )
586                 {
587                     msg_Dbg( p_input, "|   |   + Track Entry" );
588
589                     p_sys->i_track++;
590                     p_sys->track = (mkv_track_t*)realloc( p_sys->track, sizeof( mkv_track_t ) * (p_sys->i_track + 1 ) );
591 #define tk  p_sys->track[p_sys->i_track - 1]
592                     memset( &tk, 0, sizeof( mkv_track_t ) );
593                     tk.i_cat = UNKNOWN_ES;
594                     tk.b_default = VLC_FALSE;
595                     tk.i_number = p_sys->i_track - 1;
596                     tk.i_extra_data = 0;
597                     tk.p_extra_data = NULL;
598                     tk.i_codec = 0;
599                     tk.psz_codec = NULL;
600                     tk.psz_language = NULL;
601                     tk.i_default_duration = 0;
602
603                     tk.b_inited = VLC_FALSE;
604                     tk.i_data_init = 0;
605                     tk.p_data_init = NULL;
606
607                     p_sys->ep->Down();
608
609                     while( ( el3 = p_sys->ep->Get() ) != NULL )
610                     {
611                         if( EbmlId( *el3 ) == KaxTrackNumber::ClassInfos.GlobalId )
612                         {
613                             KaxTrackNumber &tnum = *(KaxTrackNumber*)el3;
614                             tnum.ReadData( p_sys->es->I_O() );
615
616                             tk.i_number = uint32( tnum );
617                             msg_Dbg( p_input, "|   |   |   + Track Number=%u", uint32( tnum ) );
618                         }
619                         else  if( EbmlId( *el3 ) == KaxTrackUID::ClassInfos.GlobalId )
620                         {
621                             KaxTrackUID &tuid = *(KaxTrackUID*)el3;
622                             tuid.ReadData( p_sys->es->I_O() );
623
624                             msg_Dbg( p_input, "|   |   |   + Track UID=%u", uint32( tuid ) );
625                         }
626                         else  if( EbmlId( *el3 ) == KaxTrackDefaultDuration::ClassInfos.GlobalId )
627                         {
628                             KaxTrackDefaultDuration &defd = *(KaxTrackDefaultDuration*)el3;
629                             defd.ReadData( p_sys->es->I_O() );
630
631                             tk.i_default_duration = uint64(defd);
632                             msg_Dbg( p_input, "|   |   |   + Track Default Duration=%lld", uint64(defd) );
633                         }
634                         else  if( EbmlId( *el3 ) == KaxTrackType::ClassInfos.GlobalId )
635                         {
636                             char *psz_type;
637                             KaxTrackType &ttype = *(KaxTrackType*)el3;
638                             ttype.ReadData( p_sys->es->I_O() );
639                             switch( uint8(ttype) )
640                             {
641                                 case track_audio:
642                                     psz_type = "audio";
643                                     tk.i_cat = AUDIO_ES;
644                                     break;
645                                 case track_video:
646                                     psz_type = "video";
647                                     tk.i_cat = VIDEO_ES;
648                                     break;
649                                 case track_subtitle:
650                                     psz_type = "subtitle";
651                                     tk.i_cat = SPU_ES;
652                                     break;
653                                 default:
654                                     psz_type = "unknown";
655                                     tk.i_cat = UNKNOWN_ES;
656                                     break;
657                             }
658
659                             msg_Dbg( p_input, "|   |   |   + Track Type=%s", psz_type );
660                         }
661                         else  if( EbmlId( *el3 ) == KaxTrackAudio::ClassInfos.GlobalId )
662                         {
663                             msg_Dbg( p_input, "|   |   |   + Track Audio" );
664                             tk.i_channels = 0;
665                             tk.i_samplerate = 0;
666                             tk.i_bitspersample = 0;
667
668                             p_sys->ep->Down();
669
670                             while( ( el4 = p_sys->ep->Get() ) != NULL )
671                             {
672                                 if( EbmlId( *el4 ) == KaxAudioSamplingFreq::ClassInfos.GlobalId )
673                                 {
674                                     KaxAudioSamplingFreq &afreq = *(KaxAudioSamplingFreq*)el4;
675                                     afreq.ReadData( p_sys->es->I_O() );
676
677                                     tk.i_samplerate = (int)float( afreq );
678                                     msg_Dbg( p_input, "|   |   |   |   + afreq=%d", tk.i_samplerate );
679                                 }
680                                 else if( EbmlId( *el4 ) == KaxAudioChannels::ClassInfos.GlobalId )
681                                 {
682                                     KaxAudioChannels &achan = *(KaxAudioChannels*)el4;
683                                     achan.ReadData( p_sys->es->I_O() );
684
685                                     tk.i_channels = uint8( achan );
686                                     msg_Dbg( p_input, "|   |   |   |   + achan=%u", uint8( achan ) );
687                                 }
688                                 else if( EbmlId( *el4 ) == KaxAudioBitDepth::ClassInfos.GlobalId )
689                                 {
690                                     KaxAudioBitDepth &abits = *(KaxAudioBitDepth*)el4;
691                                     abits.ReadData( p_sys->es->I_O() );
692
693                                     tk.i_bitspersample = uint8( abits );
694                                     msg_Dbg( p_input, "|   |   |   |   + abits=%u", uint8( abits ) );
695                                 }
696                                 else
697                                 {
698                                     msg_Dbg( p_input, "|   |   |   |   + Unknow (%s)", typeid(*el4).name() );
699                                 }
700                             }
701                             p_sys->ep->Up();
702                         }
703                         else  if( EbmlId( *el3 ) == KaxTrackVideo::ClassInfos.GlobalId )
704                         {
705                             msg_Dbg( p_input, "|   |   |   + Track Video" );
706                             tk.i_width  = 0;
707                             tk.i_height = 0;
708                             tk.i_display_width  = 0;
709                             tk.i_display_height = 0;
710                             tk.f_fps = 0.0;
711
712                             p_sys->ep->Down();
713
714                             while( ( el4 = p_sys->ep->Get() ) != NULL )
715                             {
716                                 if( EbmlId( *el4 ) == KaxVideoPixelWidth::ClassInfos.GlobalId )
717                                 {
718                                     KaxVideoPixelWidth &vwidth = *(KaxVideoPixelWidth*)el4;
719                                     vwidth.ReadData( p_sys->es->I_O() );
720
721                                     tk.i_width = uint16( vwidth );
722                                     msg_Dbg( p_input, "|   |   |   |   + width=%d", uint16( vwidth ) );
723                                 }
724                                 else if( EbmlId( *el4 ) == KaxVideoPixelHeight::ClassInfos.GlobalId )
725                                 {
726                                     KaxVideoPixelWidth &vheight = *(KaxVideoPixelWidth*)el4;
727                                     vheight.ReadData( p_sys->es->I_O() );
728
729                                     tk.i_height = uint16( vheight );
730                                     msg_Dbg( p_input, "|   |   |   |   + height=%d", uint16( vheight ) );
731                                 }
732                                 else if( EbmlId( *el4 ) == KaxVideoDisplayWidth::ClassInfos.GlobalId )
733                                 {
734                                     KaxVideoDisplayWidth &vwidth = *(KaxVideoDisplayWidth*)el4;
735                                     vwidth.ReadData( p_sys->es->I_O() );
736
737                                     tk.i_display_width = uint16( vwidth );
738                                     msg_Dbg( p_input, "|   |   |   |   + display width=%d", uint16( vwidth ) );
739                                 }
740                                 else if( EbmlId( *el4 ) == KaxVideoDisplayHeight::ClassInfos.GlobalId )
741                                 {
742                                     KaxVideoDisplayWidth &vheight = *(KaxVideoDisplayWidth*)el4;
743                                     vheight.ReadData( p_sys->es->I_O() );
744
745                                     tk.i_display_height = uint16( vheight );
746                                     msg_Dbg( p_input, "|   |   |   |   + display height=%d", uint16( vheight ) );
747                                 }
748                                 else if( EbmlId( *el4 ) == KaxVideoFrameRate::ClassInfos.GlobalId )
749                                 {
750                                     KaxVideoFrameRate &vfps = *(KaxVideoFrameRate*)el4;
751                                     vfps.ReadData( p_sys->es->I_O() );
752
753                                     tk.f_fps = float( vfps );
754                                     msg_Dbg( p_input, "   |   |   |   + fps=%f", float( vfps ) );
755                                 }
756                                 else
757                                 {
758                                     msg_Dbg( p_input, "|   |   |   |   + Unknow (%s)", typeid(*el4).name() );
759                                 }
760                             }
761                             p_sys->ep->Up();
762                         }
763                         else  if( EbmlId( *el3 ) == KaxCodecID::ClassInfos.GlobalId )
764                         {
765                             KaxCodecID &codecid = *(KaxCodecID*)el3;
766                             codecid.ReadData( p_sys->es->I_O() );
767
768                             tk.psz_codec = strdup( string( codecid ).c_str() );
769                             msg_Dbg( p_input, "|   |   |   + Track CodecId=%s", string( codecid ).c_str() );
770                         }
771                         else  if( EbmlId( *el3 ) == KaxCodecPrivate::ClassInfos.GlobalId )
772                         {
773                             KaxCodecPrivate &cpriv = *(KaxCodecPrivate*)el3;
774                             cpriv.ReadData( p_sys->es->I_O() );
775
776                             tk.i_extra_data = cpriv.GetSize();
777                             if( tk.i_extra_data > 0 )
778                             {
779                                 tk.p_extra_data = (uint8_t*)malloc( tk.i_extra_data );
780                                 memcpy( tk.p_extra_data, cpriv.GetBuffer(), tk.i_extra_data );
781                             }
782                             msg_Dbg( p_input, "|   |   |   + Track CodecPrivate size=%lld", cpriv.GetSize() );
783                         }
784                         else  if( EbmlId( *el3 ) == KaxTrackFlagDefault::ClassInfos.GlobalId )
785                         {
786                             KaxTrackFlagDefault &fdef = *(KaxTrackFlagDefault*)el3;
787                             fdef.ReadData( p_sys->es->I_O() );
788
789                             tk.b_default = uint32( fdef );
790                             msg_Dbg( p_input, "|   |   |   + Track Default=%u", uint32( fdef )  );
791                         }
792                         else  if( EbmlId( *el3 ) == KaxTrackLanguage::ClassInfos.GlobalId )
793                         {
794                             KaxTrackLanguage &lang = *(KaxTrackLanguage*)el3;
795
796                             lang.ReadData( p_sys->es->I_O() );
797
798                             tk.psz_language = strdup( string( lang ).c_str() );
799                             msg_Dbg( p_input, "|   |   |   + Track Language=`%s'", string( lang ).c_str() );
800                         }
801                         else  if( EbmlId( *el3 ) == KaxTrackFlagLacing::ClassInfos.GlobalId )
802                         {
803                             KaxTrackFlagLacing &lac = *(KaxTrackFlagLacing*)el3;
804                             lac.ReadData( p_sys->es->I_O() );
805
806                             msg_Dbg( p_input, "|   |   |   + Track Lacing=%d", uint32( lac ) );
807                         }
808                         else  if( EbmlId( *el3 ) == KaxTrackMinCache::ClassInfos.GlobalId )
809                         {
810                             KaxTrackMinCache &cmin = *(KaxTrackMinCache*)el3;
811                             cmin.ReadData( p_sys->es->I_O() );
812
813                             msg_Dbg( p_input, "|   |   |   + Track MinCache=%d", uint32( cmin ) );
814                         }
815                         else  if( EbmlId( *el3 ) == KaxTrackMaxCache::ClassInfos.GlobalId )
816                         {
817                             KaxTrackMaxCache &cmax = *(KaxTrackMaxCache*)el3;
818                             cmax.ReadData( p_sys->es->I_O() );
819
820                             msg_Dbg( p_input, "|   |   |   + Track MaxCache=%d", uint32( cmax ) );
821                         }
822                         else
823                         {
824                             msg_Dbg( p_input, "|   |   |   + Unknow (%s)", typeid(*el3).name() );
825                         }
826                     }
827                     p_sys->ep->Up();
828                 }
829                 else
830                 {
831                     msg_Dbg( p_input, "|   |   + Unknow (%s)", typeid(*el2).name() );
832                 }
833 #undef tk
834             }
835             p_sys->ep->Up();
836         }
837         else if( EbmlId( *el1 ) == KaxSeekHead::ClassInfos.GlobalId )
838         {
839             msg_Dbg( p_input, "|   + Seek head" );
840             p_sys->ep->Down();
841             while( ( el = p_sys->ep->Get() ) != NULL )
842             {
843                 if( EbmlId( *el ) == KaxSeek::ClassInfos.GlobalId )
844                 {
845                     EbmlId id = EbmlVoid::ClassInfos.GlobalId;
846                     int64_t i_pos = -1;
847
848                     //msg_Dbg( p_input, "|   |   + Seek" );
849                     p_sys->ep->Down();
850                     while( ( el = p_sys->ep->Get() ) != NULL )
851                     {
852                         if( EbmlId( *el ) == KaxSeekID::ClassInfos.GlobalId )
853                         {
854                             KaxSeekID &sid = *(KaxSeekID*)el;
855
856                             sid.ReadData( p_sys->es->I_O() );
857
858                             id = EbmlId( sid.GetBuffer(), sid.GetSize() );
859                         }
860                         else  if( EbmlId( *el ) == KaxSeekPosition::ClassInfos.GlobalId )
861                         {
862                             KaxSeekPosition &spos = *(KaxSeekPosition*)el;
863
864                             spos.ReadData( p_sys->es->I_O() );
865
866                             i_pos = uint64( spos );
867                         }
868                         else
869                         {
870                             msg_Dbg( p_input, "|   |   |   + Unknow (%s)", typeid(*el).name() );
871                         }
872                     }
873                     p_sys->ep->Up();
874
875                     if( i_pos >= 0 )
876                     {
877                         if( id == KaxCues::ClassInfos.GlobalId )
878                         {
879                             msg_Dbg( p_input, "|   |   |   = cues at %lld", i_pos );
880                             p_sys->i_cues_position = p_sys->segment->GetGlobalPosition( i_pos );
881                         }
882                         else if( id == KaxChapters::ClassInfos.GlobalId )
883                         {
884                             msg_Dbg( p_input, "|   |   |   = chapters at %lld", i_pos );
885                             p_sys->i_chapters_position = p_sys->segment->GetGlobalPosition( i_pos );
886                         }
887                     }
888                 }
889                 else
890                 {
891                     msg_Dbg( p_input, "|   |   + Unknow (%s)", typeid(*el).name() );
892                 }
893             }
894             p_sys->ep->Up();
895         }
896         else if( EbmlId( *el1 ) == KaxCues::ClassInfos.GlobalId )
897         {
898             msg_Dbg( p_input, "|   + Cues" );
899         }
900         else if( EbmlId( *el1 ) == KaxCluster::ClassInfos.GlobalId )
901         {
902             msg_Dbg( p_input, "|   + Cluster" );
903             p_sys->cluster = (KaxCluster*)el1;
904             p_sys->ep->Down();
905
906             /* stop parsing the stream */
907             break;
908         }
909         else if( EbmlId( *el1 ) == KaxAttachements::ClassInfos.GlobalId )
910         {
911             msg_Dbg( p_input, "|   + Attachements FIXME TODO (but probably never supported)" );
912         }
913         else if( EbmlId( *el1 ) == KaxChapters::ClassInfos.GlobalId )
914         {
915             msg_Dbg( p_input, "|   + Chapters FIXME TODO" );
916         }
917         else if( EbmlId( *el1 ) == KaxTag::ClassInfos.GlobalId )
918         {
919             msg_Dbg( p_input, "|   + Tags FIXME TODO" );
920         }
921         else
922         {
923             msg_Dbg( p_input, "|   + Unknow (%s)", typeid(*el1).name() );
924         }
925     }
926
927     if( p_sys->cluster == NULL )
928     {
929         msg_Err( p_input, "cannot find any cluster, damaged file ?" );
930         goto error;
931     }
932
933     if( p_sys->i_chapters_position >= 0 )
934     {
935         msg_Warn( p_input, "chapters unsupported" );
936     }
937
938 #if 0
939     if( p_sys->i_cues_position == -1 && config_GetInt( p_input, "mkv-index" ) != 0 )
940     {
941         int64_t i_sav_position = p_sys->in->getFilePointer();
942         EbmlParser *ep;
943
944         /* parse to find cues gathering info on all clusters */
945         msg_Dbg( p_input, "no cues referenced, looking for one" );
946
947         /* ugly but like easier */
948         p_sys->in->setFilePointer( p_sys->cluster->GetElementPosition(), seek_beginning );
949
950         ep = new EbmlParser( p_sys->es, p_sys->segment );
951         while( ( el = ep->Get() ) != NULL )
952         {
953             if( EbmlId( *el ) == KaxCluster::ClassInfos.GlobalId )
954             {
955                 int64_t i_pos = el->GetElementPosition();
956
957                 msg_Dbg( p_input, "found a cluster at %lld", i_pos );
958             }
959             else if( EbmlId( *el ) == KaxCues::ClassInfos.GlobalId )
960             {
961                 msg_Dbg( p_input, "found a Cues !" );
962             }
963         }
964         delete ep;
965         msg_Dbg( p_input, "lookind done." );
966
967         p_sys->in->setFilePointer( i_sav_position, seek_beginning );
968     }
969 #endif
970
971     /* *** Load the cue if found *** */
972     if( p_sys->i_cues_position >= 0 )
973     {
974         int64_t i_sav_position = p_sys->in->getFilePointer();
975         EbmlParser *ep;
976         EbmlElement *cues;
977
978         msg_Dbg( p_input, "loading cues" );
979         p_sys->in->setFilePointer( p_sys->i_cues_position, seek_beginning );
980         cues = p_sys->es->FindNextID( KaxCues::ClassInfos, 0xFFFFFFFFL);
981
982         ep = new EbmlParser( p_sys->es, cues );
983         while( ( el = ep->Get() ) != NULL )
984         {
985             if( EbmlId( *el ) == KaxCuePoint::ClassInfos.GlobalId )
986             {
987 #define idx p_sys->index[p_sys->i_index]
988
989                 idx.i_track       = -1;
990                 idx.i_block_number= -1;
991                 idx.i_position    = -1;
992                 idx.i_time        = -1;
993                 idx.b_key         = VLC_TRUE;
994
995                 ep->Down();
996                 while( ( el = ep->Get() ) != NULL )
997                 {
998                     if( EbmlId( *el ) == KaxCueTime::ClassInfos.GlobalId )
999                     {
1000                         KaxCueTime &ctime = *(KaxCueTime*)el;
1001
1002                         ctime.ReadData( p_sys->es->I_O() );
1003
1004                         idx.i_time = uint64( ctime ) * (mtime_t)1000000000 / p_sys->i_timescale;
1005                     }
1006                     else if( EbmlId( *el ) == KaxCueTrackPositions::ClassInfos.GlobalId )
1007                     {
1008                         ep->Down();
1009                         while( ( el = ep->Get() ) != NULL )
1010                         {
1011                             if( EbmlId( *el ) == KaxCueTrack::ClassInfos.GlobalId )
1012                             {
1013                                 KaxCueTrack &ctrack = *(KaxCueTrack*)el;
1014
1015                                 ctrack.ReadData( p_sys->es->I_O() );
1016                                 idx.i_track = uint16( ctrack );
1017                             }
1018                             else if( EbmlId( *el ) == KaxCueClusterPosition::ClassInfos.GlobalId )
1019                             {
1020                                 KaxCueClusterPosition &ccpos = *(KaxCueClusterPosition*)el;
1021
1022                                 ccpos.ReadData( p_sys->es->I_O() );
1023                                 idx.i_position = p_sys->segment->GetGlobalPosition( uint64( ccpos ) );
1024                             }
1025                             else if( EbmlId( *el ) == KaxCueBlockNumber::ClassInfos.GlobalId )
1026                             {
1027                                 KaxCueBlockNumber &cbnum = *(KaxCueBlockNumber*)el;
1028
1029                                 cbnum.ReadData( p_sys->es->I_O() );
1030                                 idx.i_block_number = uint32( cbnum );
1031                             }
1032                             else
1033                             {
1034                                 msg_Dbg( p_input, "         * Unknow (%s)", typeid(*el).name() );
1035                             }
1036                         }
1037                         ep->Up();
1038                     }
1039                     else
1040                     {
1041                         msg_Dbg( p_input, "     * Unknow (%s)", typeid(*el).name() );
1042                     }
1043                 }
1044                 ep->Up();
1045
1046                 msg_Dbg( p_input, " * added time=%lld pos=%lld track=%d bnum=%d",
1047                          idx.i_time, idx.i_position, idx.i_track, idx.i_block_number );
1048
1049                 p_sys->i_index++;
1050                 if( p_sys->i_index >= p_sys->i_index_max )
1051                 {
1052                     p_sys->i_index_max += 1024;
1053                     p_sys->index = (mkv_index_t*)realloc( p_sys->index, sizeof( mkv_index_t ) * p_sys->i_index_max );
1054                 }
1055 #undef idx
1056             }
1057             else
1058             {
1059                 msg_Dbg( p_input, " * Unknow (%s)", typeid(*el).name() );
1060             }
1061         }
1062         delete ep;
1063         delete cues;
1064
1065         msg_Dbg( p_input, "loading cues done." );
1066         p_sys->in->setFilePointer( i_sav_position, seek_beginning );
1067     }
1068
1069     if( p_sys->i_index <= 0 )
1070     {
1071         /* FIXME FIXME FIXME */
1072         msg_Warn( p_input, "no cues found -> unseekable stream for now FIXME" );
1073         p_input->stream.b_seekable = VLC_FALSE;
1074         /* FIXME FIXME FIXME */
1075     }
1076
1077     /* Create one program */
1078     vlc_mutex_lock( &p_input->stream.stream_lock );
1079     if( input_InitStream( p_input, 0 ) == -1)
1080     {
1081         vlc_mutex_unlock( &p_input->stream.stream_lock );
1082         msg_Err( p_input, "cannot init stream" );
1083         goto error;
1084     }
1085     if( input_AddProgram( p_input, 0, 0) == NULL )
1086     {
1087         vlc_mutex_unlock( &p_input->stream.stream_lock );
1088         msg_Err( p_input, "cannot add program" );
1089         goto error;
1090     }
1091     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
1092     if( p_sys->f_duration > 1001.0 )
1093     {
1094         mtime_t i_duration = (mtime_t)( p_sys->f_duration / 1000.0 );
1095         p_input->stream.i_mux_rate = p_input->stream.p_selected_area->i_size / 50 / i_duration;
1096     }
1097     else
1098     {
1099         p_input->stream.i_mux_rate = 0;
1100     }
1101     vlc_mutex_unlock( &p_input->stream.stream_lock );
1102
1103     /* add all es */
1104     msg_Dbg( p_input, "found %d es", p_sys->i_track );
1105     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1106     {
1107 #define tk  p_sys->track[i_track]
1108         if( tk.i_cat == UNKNOWN_ES )
1109         {
1110             msg_Warn( p_input, "invalid track[%d, n=%d]", i_track, tk.i_number );
1111             tk.p_es = NULL;
1112             continue;
1113         }
1114         tk.p_es = input_AddES( p_input,
1115                                p_input->stream.p_selected_program,
1116                                i_track + 1,
1117                                tk.i_cat,
1118                                tk.psz_language, 0 );
1119         if( !strcmp( tk.psz_codec, "V_MS/VFW/FOURCC" ) )
1120         {
1121             if( tk.i_extra_data < (int)sizeof( BITMAPINFOHEADER ) )
1122             {
1123                 msg_Err( p_input, "missing/invalid BITMAPINFOHEADER" );
1124                 tk.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1125             }
1126             else
1127             {
1128                 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)tk.p_extra_data;
1129
1130                 p_bih->biSize           = GetDWLE( &p_bih->biSize );
1131                 p_bih->biWidth          = GetDWLE( &p_bih->biWidth );
1132                 p_bih->biHeight         = GetDWLE( &p_bih->biHeight );
1133                 p_bih->biPlanes         = GetWLE( &p_bih->biPlanes );
1134                 p_bih->biBitCount       = GetWLE( &p_bih->biBitCount );
1135                 p_bih->biCompression    = GetFOURCC( &p_bih->biCompression );
1136                 p_bih->biSizeImage      = GetDWLE( &p_bih->biSizeImage );
1137                 p_bih->biXPelsPerMeter  = GetDWLE( &p_bih->biXPelsPerMeter );
1138                 p_bih->biYPelsPerMeter  = GetDWLE( &p_bih->biYPelsPerMeter );
1139                 p_bih->biClrUsed        = GetDWLE( &p_bih->biClrUsed );
1140                 p_bih->biClrImportant   = GetDWLE( &p_bih->biClrImportant );
1141
1142
1143                 tk.i_codec = p_bih->biCompression;
1144                 tk.p_es->p_bitmapinfoheader = p_bih;
1145             }
1146         }
1147         else if( !strcmp( tk.psz_codec, "V_MPEG1" ) ||
1148                  !strcmp( tk.psz_codec, "V_MPEG2" ) )
1149         {
1150             tk.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
1151         }
1152         else if( !strncmp( tk.psz_codec, "V_MPEG4", 7 ) )
1153         {
1154             BITMAPINFOHEADER *p_bih;
1155
1156             tk.i_extra_data = sizeof( BITMAPINFOHEADER );
1157             tk.p_extra_data = (uint8_t*)malloc( tk.i_extra_data );
1158
1159             p_bih = (BITMAPINFOHEADER*)tk.p_extra_data;
1160             memset( p_bih, 0, sizeof( BITMAPINFOHEADER ) );
1161             p_bih->biSize  = sizeof( BITMAPINFOHEADER );
1162             p_bih->biWidth = tk.i_width;
1163             p_bih->biHeight= tk.i_height;
1164
1165             if( !strcmp( tk.psz_codec, "V_MPEG4/MS/V3" ) )
1166             {
1167                 tk.i_codec = VLC_FOURCC( 'D', 'I', 'V', '3' );
1168             }
1169             else
1170             {
1171                 tk.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
1172             }
1173         }
1174         else if( !strcmp( tk.psz_codec, "A_MS/ACM" ) )
1175         {
1176             if( tk.i_extra_data < (int)sizeof( WAVEFORMATEX ) )
1177             {
1178                 msg_Err( p_input, "missing/invalid WAVEFORMATEX" );
1179                 tk.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1180             }
1181             else
1182             {
1183                 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)tk.p_extra_data;
1184
1185                 p_wf->wFormatTag        = GetWLE( &p_wf->wFormatTag );
1186                 p_wf->nChannels         = GetWLE( &p_wf->nChannels );
1187                 p_wf->nSamplesPerSec    = GetDWLE( &p_wf->nSamplesPerSec );
1188                 p_wf->nAvgBytesPerSec   = GetDWLE( &p_wf->nAvgBytesPerSec );
1189                 p_wf->nBlockAlign       = GetWLE( &p_wf->nBlockAlign );
1190                 p_wf->wBitsPerSample    = GetWLE( &p_wf->wBitsPerSample );
1191                 p_wf->cbSize            = GetWLE( &p_wf->cbSize );
1192
1193                 switch( p_wf->wFormatTag )
1194                 {
1195                     case WAVE_FORMAT_PCM:
1196                         tk.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
1197                         break;
1198                     case WAVE_FORMAT_ADPCM:
1199                         tk.i_codec = VLC_FOURCC( 'm', 's', 0x00, 0x02 );
1200                         break;
1201                     case WAVE_FORMAT_ALAW:
1202                         tk.i_codec = VLC_FOURCC( 'a', 'l', 'a', 'w' );
1203                         break;
1204                     case WAVE_FORMAT_MULAW:
1205                         tk.i_codec = VLC_FOURCC( 'm', 'l', 'a', 'w' );
1206                         break;
1207                     case WAVE_FORMAT_IMA_ADPCM:
1208                         tk.i_codec = VLC_FOURCC( 'm', 's', 0x00, 0x11 );
1209                         break;
1210                     case WAVE_FORMAT_MPEG:
1211                     case WAVE_FORMAT_MPEGLAYER3:
1212                         tk.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
1213                         break;
1214                     case WAVE_FORMAT_A52:
1215                         tk.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
1216                         break;
1217                     case WAVE_FORMAT_WMA1:
1218                         tk.i_codec = VLC_FOURCC( 'w', 'm', 'a', '1' );
1219                         break;
1220                     case WAVE_FORMAT_WMA2:
1221                         tk.i_codec = VLC_FOURCC( 'w', 'm', 'a', '2' );
1222                         break;
1223                     case WAVE_FORMAT_WMA3:
1224                         tk.i_codec = VLC_FOURCC( 'w', 'm', 'a', '3' );
1225                         break;
1226                     default:
1227                         msg_Err( p_input, "unknown wFormatTag=0x%x", p_wf->wFormatTag );
1228                         tk.i_codec = VLC_FOURCC( 'm', 's', p_wf->wFormatTag >> 8, p_wf->wFormatTag&0xff );
1229                         break;
1230                 }
1231                 tk.p_es->p_waveformatex = p_wf;
1232             }
1233         }
1234         else if( !strcmp( tk.psz_codec, "A_MPEG/L3" ) ||
1235                  !strcmp( tk.psz_codec, "A_MPEG/L2" ) ||
1236                  !strcmp( tk.psz_codec, "A_MPEG/L1" ) )
1237         {
1238             tk.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
1239         }
1240         else if( !strcmp( tk.psz_codec, "A_AC3" ) )
1241         {
1242             tk.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
1243         }
1244         else if( !strcmp( tk.psz_codec, "A_DTS" ) )
1245         {
1246             tk.i_codec = VLC_FOURCC( 'd', 't', 's', ' ' );
1247         }
1248         else if( !strcmp( tk.psz_codec, "A_VORBIS" ) )
1249         {
1250             tk.i_codec = VLC_FOURCC( 'v', 'o', 'r', 'b' );
1251             tk.i_data_init = tk.i_extra_data;
1252             tk.p_data_init = tk.p_extra_data;
1253         }
1254         else if( !strncmp( tk.psz_codec, "A_AAC/MPEG2/", strlen( "A_AAC/MPEG2/" ) ) ||
1255                  !strncmp( tk.psz_codec, "A_AAC/MPEG4/", strlen( "A_AAC/MPEG4/" ) ) )
1256         {
1257             int i_profile, i_srate;
1258             static int i_sample_rates[] =
1259             {
1260                     96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1261                         16000, 12000, 11025, 8000,  7350,  0,     0,     0
1262             };
1263             WAVEFORMATEX *p_wf;
1264
1265             tk.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
1266             /* create data for faad (MP4DecSpecificDescrTag)*/
1267
1268             if( !strcmp( &tk.psz_codec[12], "MAIN" ) )
1269             {
1270                 i_profile = 0;
1271             }
1272             else if( !strcmp( &tk.psz_codec[12], "LC" ) )
1273             {
1274                 i_profile = 1;
1275             }
1276             else if( !strcmp( &tk.psz_codec[12], "SSR" ) )
1277             {
1278                 i_profile = 2;
1279             }
1280             else
1281             {
1282                 i_profile = 3;
1283             }
1284
1285             for( i_srate = 0; i_srate < 13; i_srate++ )
1286             {
1287                 if( i_sample_rates[i_srate] == tk.i_samplerate )
1288                 {
1289                     break;
1290                 }
1291             }
1292             msg_Dbg( p_input, "profile=%d srate=%d", i_profile, i_srate );
1293
1294             tk.i_extra_data = sizeof( WAVEFORMATEX ) + 2;
1295             tk.p_extra_data = (uint8_t*)malloc( tk.i_extra_data );
1296             p_wf = (WAVEFORMATEX*)tk.p_extra_data;
1297
1298             p_wf->wFormatTag = WAVE_FORMAT_UNKNOWN;
1299             p_wf->nChannels  = tk.i_channels;
1300             p_wf->nSamplesPerSec = tk.i_samplerate;
1301             p_wf->nAvgBytesPerSec = 0;
1302             p_wf->nBlockAlign = 0;
1303             p_wf->wBitsPerSample = 0;
1304             p_wf->cbSize = 2;
1305
1306             tk.p_extra_data[sizeof( WAVEFORMATEX )+ 0] = ((i_profile + 1) << 3) | ((i_srate&0xe) >> 1);
1307             tk.p_extra_data[sizeof( WAVEFORMATEX )+ 1] = ((i_srate & 0x1) << 7) | (tk.i_channels << 3);
1308
1309             tk.p_es->p_waveformatex = p_wf;
1310         }
1311         else if( !strcmp( tk.psz_codec, "A_PCM/INT/BIG" ) ||
1312                  !strcmp( tk.psz_codec, "A_PCM/INT/LIT" ) ||
1313                  !strcmp( tk.psz_codec, "A_PCM/FLOAT/IEEE" ) )
1314         {
1315             WAVEFORMATEX *p_wf;
1316
1317             tk.i_extra_data = sizeof( WAVEFORMATEX );
1318             tk.p_extra_data = (uint8_t*)malloc( tk.i_extra_data );
1319
1320             p_wf = (WAVEFORMATEX*)tk.p_extra_data;
1321
1322             if( !strncmp( &tk.psz_codec[6], "INT", 3 ) )
1323             {
1324                 p_wf->wFormatTag = WAVE_FORMAT_PCM;
1325             }
1326             else
1327             {
1328                 p_wf->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
1329             }
1330             p_wf->nChannels  = tk.i_channels;
1331             p_wf->nSamplesPerSec = tk.i_samplerate;
1332             p_wf->nAvgBytesPerSec = 0;
1333             p_wf->nBlockAlign = ( tk.i_bitspersample + 7 ) / 8 * tk.i_channels;
1334             p_wf->wBitsPerSample = tk.i_bitspersample;
1335             p_wf->cbSize = 0;
1336
1337             tk.p_es->p_waveformatex = p_wf;
1338
1339             if( !strcmp( tk.psz_codec, "A_PCM/INT/BIG" ) )
1340             {
1341                 tk.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
1342             }
1343             else
1344             {
1345                 tk.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
1346             }
1347         }
1348         else if( !strcmp( tk.psz_codec, "S_TEXT/UTF8" ) )
1349         {
1350             tk.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
1351         }
1352         else
1353         {
1354             msg_Err( p_input, "unknow codec id=`%s'", tk.psz_codec );
1355             tk.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1356         }
1357
1358         tk.p_es->i_fourcc = tk.i_codec;
1359 #undef tk
1360     }
1361
1362     /* select track all video, one audio, no spu TODO : improve */
1363     b_audio_selected = VLC_FALSE;
1364     i_audio_channel = 0;
1365     i_spu_channel = 0;
1366     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1367     {
1368 #define tk  p_sys->track[i_track]
1369         switch( tk.i_cat )
1370         {
1371             case VIDEO_ES:
1372                 vlc_mutex_lock( &p_input->stream.stream_lock );
1373                 input_SelectES( p_input, tk.p_es );
1374                 vlc_mutex_unlock( &p_input->stream.stream_lock );
1375                 break;
1376
1377             case AUDIO_ES:
1378                 if( ( !b_audio_selected && config_GetInt( p_input, "audio-channel" ) < 0 ) ||
1379                     i_audio_channel == config_GetInt( p_input, "audio-channel" ) )
1380                 {
1381                     vlc_mutex_lock( &p_input->stream.stream_lock );
1382                     input_SelectES( p_input, tk.p_es );
1383                     vlc_mutex_unlock( &p_input->stream.stream_lock );
1384
1385                     b_audio_selected = tk.p_es->p_decoder_fifo ? VLC_TRUE : VLC_FALSE;
1386                 }
1387                 i_audio_channel++;
1388                 break;
1389             case SPU_ES:
1390                 if( i_spu_channel == config_GetInt( p_input, "spu-channel" ) )
1391                 {
1392                     vlc_mutex_lock( &p_input->stream.stream_lock );
1393                     input_SelectES( p_input, tk.p_es );
1394                     vlc_mutex_unlock( &p_input->stream.stream_lock );
1395                 }
1396                 i_spu_channel++;
1397                 break;
1398         }
1399 #undef tk
1400     }
1401
1402     if( !b_audio_selected )
1403     {
1404         msg_Warn( p_input, "cannot find/select audio track" );
1405     }
1406
1407     return VLC_SUCCESS;
1408
1409 error:
1410     delete p_sys->es;
1411     delete p_sys->in;
1412     free( p_sys );
1413     return VLC_EGENERIC;
1414 }
1415
1416 /*****************************************************************************
1417  * Deactivate: frees unused data
1418  *****************************************************************************/
1419 static void Deactivate( vlc_object_t *p_this )
1420 {
1421     input_thread_t *p_input = (input_thread_t *)p_this;
1422     demux_sys_t    *p_sys   = p_input->p_demux_data;
1423
1424     int             i_track;
1425
1426     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1427     {
1428 #define tk  p_sys->track[i_track]
1429         if( tk.psz_codec )
1430         {
1431             free( tk.psz_codec );
1432         }
1433         if( tk.psz_language )
1434         {
1435             free( tk.psz_language );
1436         }
1437 #undef tk
1438     }
1439     free( p_sys->track );
1440
1441     delete p_sys->ep;
1442     delete p_sys->es;
1443     delete p_sys->in;
1444
1445     free( p_sys );
1446 }
1447
1448 static int BlockGet( input_thread_t *p_input, KaxBlock **pp_block, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration )
1449 {
1450     demux_sys_t    *p_sys   = p_input->p_demux_data;
1451
1452     *pp_block = NULL;
1453     *pi_ref1  = -1;
1454     *pi_ref2  = -1;
1455
1456     for( ;; )
1457     {
1458         EbmlElement *el;
1459         int         i_level;
1460
1461         if( p_input->b_die )
1462         {
1463             return VLC_EGENERIC;
1464         }
1465
1466         el = p_sys->ep->Get();
1467         i_level = p_sys->ep->GetLevel();
1468
1469         if( el == NULL && *pp_block != NULL )
1470         {
1471             return VLC_SUCCESS;
1472         }
1473
1474         if( el == NULL )
1475         {
1476             if( p_sys->ep->GetLevel() > 1 )
1477             {
1478                 p_sys->ep->Up();
1479                 continue;
1480             }
1481             msg_Warn( p_input, "EOF" );
1482             return VLC_EGENERIC;
1483         }
1484
1485         /* do parsing */
1486         if( i_level == 1 )
1487         {
1488             if( EbmlId( *el ) == KaxCluster::ClassInfos.GlobalId )
1489             {
1490                 p_sys->cluster = (KaxCluster*)el;
1491                 p_sys->ep->Down();
1492             }
1493             else if( EbmlId( *el ) == KaxCues::ClassInfos.GlobalId )
1494             {
1495                 msg_Warn( p_input, "find KaxCues FIXME" );
1496                 return VLC_EGENERIC;
1497             }
1498             else
1499             {
1500                 msg_Dbg( p_input, "unknown (%s)", typeid( el ).name() );
1501             }
1502         }
1503         else if( i_level == 2 )
1504         {
1505             if( EbmlId( *el ) == KaxClusterTimecode::ClassInfos.GlobalId )
1506             {
1507                 KaxClusterTimecode &ctc = *(KaxClusterTimecode*)el;
1508
1509                 ctc.ReadData( p_sys->es->I_O() );
1510                 p_sys->cluster->InitTimecode( uint64( ctc ), p_sys->i_timescale );
1511             }
1512             else if( EbmlId( *el ) == KaxBlockGroup::ClassInfos.GlobalId )
1513             {
1514                 p_sys->ep->Down();
1515             }
1516         }
1517         else if( i_level == 3 )
1518         {
1519             if( EbmlId( *el ) == KaxBlock::ClassInfos.GlobalId )
1520             {
1521                 *pp_block = (KaxBlock*)el;
1522
1523                 (*pp_block)->ReadData( p_sys->es->I_O() );
1524                 (*pp_block)->SetParent( *p_sys->cluster );
1525
1526                 p_sys->ep->Keep();
1527             }
1528             else if( EbmlId( *el ) == KaxBlockDuration::ClassInfos.GlobalId )
1529             {
1530                 KaxBlockDuration &dur = *(KaxBlockDuration*)el;
1531
1532                 dur.ReadData( p_sys->es->I_O() );
1533                 *pi_duration = uint64( dur );
1534             }
1535             else if( EbmlId( *el ) == KaxReferenceBlock::ClassInfos.GlobalId )
1536             {
1537                 KaxReferenceBlock &ref = *(KaxReferenceBlock*)el;
1538
1539                 ref.ReadData( p_sys->es->I_O() );
1540                 if( *pi_ref1 == -1 )
1541                 {
1542                     *pi_ref1 = int64( ref );
1543                 }
1544                 else
1545                 {
1546                     *pi_ref2 = int64( ref );
1547                 }
1548             }
1549         }
1550         else
1551         {
1552             msg_Err( p_input, "invalid level = %d", i_level );
1553             return VLC_EGENERIC;
1554         }
1555     }
1556 }
1557
1558 static void BlockDecode( input_thread_t *p_input, KaxBlock *block, mtime_t i_pts, mtime_t i_duration )
1559 {
1560     demux_sys_t    *p_sys   = p_input->p_demux_data;
1561
1562     int             i_track;
1563     pes_packet_t    *p_pes;
1564     unsigned int    i;
1565
1566 #define tk  p_sys->track[i_track]
1567     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1568     {
1569         if( tk.i_number == block->TrackNum() )
1570         {
1571             break;
1572         }
1573     }
1574
1575     if( i_track >= p_sys->i_track )
1576     {
1577         msg_Err( p_input, "invalid track number=%d", block->TrackNum() );
1578         return;
1579     }
1580
1581     if( tk.p_es->p_decoder_fifo == NULL )
1582     {
1583         return;
1584     }
1585
1586     if( ( p_pes = input_NewPES( p_input->p_method_data ) ) == NULL )
1587     {
1588         msg_Err( p_input, "cannot allocate PES" );
1589     }
1590
1591
1592     p_pes->i_pts = i_pts;
1593     p_pes->i_dts = i_pts;
1594     if( tk.i_cat == SPU_ES )
1595     {
1596         /* special case : dts mean end of display */
1597         if( i_duration > 0 )
1598         {
1599             /* FIXME not sure about that */
1600             p_pes->i_dts += i_duration * 1000;// * (mtime_t) 1000 / p_sys->i_timescale;
1601         }
1602         else
1603         {
1604             /* unknown */
1605             p_pes->i_dts = 0;
1606         }
1607     }
1608
1609     p_pes->p_first = p_pes->p_last = NULL;
1610     p_pes->i_nb_data = 0;
1611     p_pes->i_pes_size = 0;
1612
1613     for( i = 0; i < block->NumberFrames(); i++ )
1614     {
1615         data_packet_t *p_data = NULL;
1616         DataBuffer &data = block->GetBuffer(i);
1617
1618         if( ( p_data = input_NewPacket( p_input->p_method_data, data.Size() ) ) != NULL )
1619         {
1620             memcpy( p_data->p_payload_start, data.Buffer(), data.Size() );
1621
1622             p_data->p_payload_end = p_data->p_payload_start + data.Size();
1623
1624             if( p_pes->p_first == NULL )
1625             {
1626                 p_pes->p_first = p_data;
1627             }
1628             else
1629             {
1630                 p_pes->p_last->p_next  = p_data;
1631             }
1632             p_pes->i_nb_data++;
1633             p_pes->i_pes_size += data.Size();
1634             p_pes->p_last  = p_data;
1635         }
1636     }
1637     if( tk.i_cat == SPU_ES && p_pes->p_first && p_pes->i_pes_size > 0 )
1638     {
1639         p_pes->p_first->p_payload_end[-1] = '\0';
1640     }
1641
1642     if( !tk.b_inited && tk.i_data_init > 0 )
1643     {
1644         pes_packet_t *p_init;
1645         data_packet_t *p_data;
1646
1647         msg_Dbg( p_input, "sending header (%d bytes)", tk.i_data_init );
1648
1649         p_init = input_NewPES( p_input->p_method_data );
1650
1651         p_data = input_NewPacket( p_input->p_method_data, tk.i_data_init );
1652         memcpy( p_data->p_payload_start, tk.p_data_init, tk.i_data_init );
1653         p_data->p_payload_end = p_data->p_payload_start + tk.i_data_init;
1654
1655         p_init->p_first = p_init->p_last = p_data;
1656         p_init->i_nb_data = 1;
1657         p_init->i_pes_size = tk.i_data_init;
1658
1659         input_DecodePES( tk.p_es->p_decoder_fifo, p_init );
1660     }
1661     tk.b_inited = VLC_TRUE;
1662
1663     input_DecodePES( tk.p_es->p_decoder_fifo, p_pes );
1664
1665 #undef tk
1666 }
1667
1668 static void Seek( input_thread_t *p_input, mtime_t i_date, int i_percent)
1669 {
1670     demux_sys_t    *p_sys   = p_input->p_demux_data;
1671
1672     KaxBlock    *block;
1673     int64_t     i_block_duration;
1674     int64_t     i_block_ref1;
1675     int64_t     i_block_ref2;
1676
1677     int         i_index;
1678     int         i_track_skipping;
1679     int         i_track;
1680
1681     msg_Dbg( p_input, "seek request to %lld (%d%%)", i_date, i_percent );
1682
1683     for( i_index = 0; i_index < p_sys->i_index; i_index++ )
1684     {
1685         if( p_sys->index[i_index].i_time >= i_date )
1686         {
1687             break;
1688         }
1689     }
1690
1691     if( i_index > 0 )
1692     {
1693         i_index--;
1694     }
1695
1696     msg_Dbg( p_input, "seek got %lld (%d%%)",
1697              p_sys->index[i_index].i_time, (int)(100 * p_sys->index[i_index].i_position /p_input->stream.p_selected_area->i_size ) );
1698
1699     delete p_sys->ep;
1700
1701     p_sys->in->setFilePointer( p_sys->index[i_index].i_position, seek_beginning );
1702
1703     p_sys->ep = new EbmlParser( p_sys->es, p_sys->segment );
1704
1705     /* now parse until key frame */
1706 #define tk  p_sys->track[i_track]
1707     i_track_skipping = 0;
1708     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1709     {
1710         if( tk.i_cat == VIDEO_ES )
1711         {
1712             tk.b_search_keyframe = VLC_TRUE;
1713             i_track_skipping++;
1714         }
1715     }
1716
1717
1718     while( i_track_skipping > 0 )
1719     {
1720         if( BlockGet( p_input, &block, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
1721         {
1722             msg_Warn( p_input, "cannot get block EOF?" );
1723
1724             return;
1725         }
1726
1727         p_sys->i_pts = block->GlobalTimecode() * (mtime_t) 1000 / p_sys->i_timescale;
1728
1729         for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1730         {
1731             if( tk.i_number == block->TrackNum() )
1732             {
1733                 break;
1734             }
1735         }
1736
1737         if( i_track < p_sys->i_track )
1738         {
1739             if( tk.i_cat == VIDEO_ES && i_block_ref1 == -1 && tk.b_search_keyframe )
1740             {
1741                 tk.b_search_keyframe = VLC_FALSE;
1742                 i_track_skipping--;
1743             }
1744             if( tk.i_cat == VIDEO_ES && !tk.b_search_keyframe )
1745             {
1746                 BlockDecode( p_input, block, 0, 0 );
1747             }
1748         }
1749
1750         delete block;
1751     }
1752 #undef tk
1753 }
1754
1755 /*****************************************************************************
1756  * Demux: reads and demuxes data packets
1757  *****************************************************************************
1758  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1759  *****************************************************************************/
1760 static int Demux( input_thread_t * p_input )
1761 {
1762     demux_sys_t    *p_sys   = p_input->p_demux_data;
1763     mtime_t        i_start_pts;
1764     KaxBlock *block;
1765     int64_t i_block_duration;
1766     int64_t i_block_ref1;
1767     int64_t i_block_ref2;
1768
1769     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1770     {
1771         mtime_t i_duration = (mtime_t)( p_sys->f_duration / 1000 );
1772         mtime_t i_date;
1773         int i_percent;
1774
1775         i_date = (mtime_t)1000000 *
1776                  (mtime_t)i_duration*
1777                  (mtime_t)p_sys->in->getFilePointer() /
1778                  (mtime_t)p_input->stream.p_selected_area->i_size;
1779
1780         i_percent = 100 * p_sys->in->getFilePointer() /
1781                         p_input->stream.p_selected_area->i_size;
1782
1783         Seek( p_input, i_date, i_percent);
1784     }
1785
1786     i_start_pts = p_sys->i_pts;
1787
1788     for( ;; )
1789     {
1790         mtime_t i_pts;
1791
1792         if( BlockGet( p_input, &block, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
1793         {
1794             msg_Warn( p_input, "cannot get block EOF?" );
1795
1796             return 0;
1797         }
1798
1799         p_sys->i_pts = block->GlobalTimecode() * (mtime_t) 1000 / p_sys->i_timescale;
1800
1801         if( p_sys->i_pts > 0 )
1802         {
1803             input_ClockManageRef( p_input,
1804                                   p_input->stream.p_selected_program,
1805                                   p_sys->i_pts * 9 / 100 );
1806         }
1807
1808         i_pts = input_ClockGetTS( p_input,
1809                                   p_input->stream.p_selected_program,
1810                                   p_sys->i_pts * 9 / 100 );
1811
1812         BlockDecode( p_input, block, i_pts, i_block_duration );
1813
1814         delete block;
1815
1816         if( i_start_pts == -1 )
1817         {
1818             i_start_pts = p_sys->i_pts;
1819         }
1820         else if( p_sys->i_pts > i_start_pts + (mtime_t)100000)
1821         {
1822             return 1;
1823         }
1824     }
1825 }
1826
1827