* mkv: basic seek support (only with file with cues, it doesn't search key
[vlc.git] / modules / demux / mkv.cpp
1 /*****************************************************************************
2  * mkv.cpp : matroska demuxer
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: mkv.cpp,v 1.2 2003/06/22 12:27:16 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 } mkv_track_t;
403
404 typedef struct
405 {
406     int     i_track;
407     int     i_block_number;
408
409     int64_t i_position;
410     int64_t i_time;
411
412     vlc_bool_t b_key;
413 } mkv_index_t;
414
415 struct demux_sys_t
416 {
417     vlc_stream_io_callback  *in;
418     EbmlStream              *es;
419     EbmlParser              *ep;
420
421     /* time scale */
422     uint64_t                i_timescale;
423
424     /* duration of the segment */
425     float                   f_duration;
426
427     /* all tracks */
428     int                     i_track;
429     mkv_track_t             *track;
430
431     /* from seekhead */
432     int64_t                 i_cues_position;
433     int64_t                 i_chapters_position;
434
435     /* current data */
436     KaxSegment              *segment;
437     KaxCluster              *cluster;
438
439     mtime_t                 i_pts;
440
441     int                     i_index;
442     int                     i_index_max;
443     mkv_index_t             *index;
444 };
445
446 #define MKVD_TIMECODESCALE 1000000
447
448 /*****************************************************************************
449  * Activate: initializes matroska demux structures
450  *****************************************************************************/
451 static int Activate( vlc_object_t * p_this )
452 {
453     input_thread_t *p_input = (input_thread_t *)p_this;
454     demux_sys_t    *p_sys;
455     uint8_t        *p_peek;
456
457     int             i_track;
458     vlc_bool_t      b_audio_selected;
459     int             i_spu_channel, i_audio_channel;
460
461     EbmlElement     *el = NULL, *el1 = NULL, *el2 = NULL, *el3 = NULL, *el4 = NULL;
462
463     /* Initialize access plug-in structures. */
464     if( p_input->i_mtu == 0 )
465     {
466         /* Improve speed. */
467         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
468     }
469
470     /* Set the demux function */
471     p_input->pf_demux = Demux;
472
473     /* peek the begining */
474     if( input_Peek( p_input, &p_peek, 4 ) < 4 )
475     {
476         msg_Warn( p_input, "cannot peek" );
477         return VLC_EGENERIC;
478     }
479
480     /* is a valid file */
481     if( p_peek[0] != 0x1a || p_peek[1] != 0x45 || p_peek[2] != 0xdf || p_peek[3] != 0xa3 )
482     {
483         msg_Warn( p_input, "matroska module discarded (invalid header)" );
484         return VLC_EGENERIC;
485     }
486
487     if( p_input->stream.i_method != INPUT_METHOD_FILE || !p_input->stream.b_seekable )
488     {
489         msg_Err( p_input, "can only read matroska over seekable file yet" );
490         return VLC_EGENERIC;
491     }
492
493     p_input->p_demux_data = p_sys = (demux_sys_t*)malloc( sizeof( demux_sys_t ) );
494     memset( p_sys, 0, sizeof( demux_sys_t ) );
495
496     p_sys->in = new vlc_stream_io_callback( p_input );
497     p_sys->es = new EbmlStream( *p_sys->in );
498     p_sys->f_duration   = -1;
499     p_sys->i_timescale     = MKVD_TIMECODESCALE;
500     p_sys->i_track      = 0;
501     p_sys->track        = (mkv_track_t*)malloc( sizeof( mkv_track_t ) );
502     p_sys->i_pts   = 0;
503     p_sys->i_cues_position = -1;
504     p_sys->i_chapters_position = -1;
505
506     p_sys->i_index      = 0;
507     p_sys->i_index_max  = 1024;
508     p_sys->index        = (mkv_index_t*)malloc( sizeof( mkv_index_t ) * p_sys->i_index_max );
509
510     if( p_sys->es == NULL )
511     {
512         msg_Err( p_input, "failed to create EbmlStream" );
513         delete p_sys->in;
514         free( p_sys );
515         return VLC_EGENERIC;
516     }
517     /* Find the EbmlHead element */
518     el = p_sys->es->FindNextID(EbmlHead::ClassInfos, 0xFFFFFFFFL);
519     if( el == NULL )
520     {
521         msg_Err( p_input, "cannot find EbmlHead" );
522         goto error;
523     }
524     msg_Dbg( p_input, "EbmlHead" );
525     /* skip it */
526     el->SkipData( *p_sys->es, el->Generic().Context );
527     delete el;
528
529     /* Find a segment */
530     el = p_sys->es->FindNextID( KaxSegment::ClassInfos, 0xFFFFFFFFL);
531     if( el == NULL )
532     {
533         msg_Err( p_input, "cannot find KaxSegment" );
534         goto error;
535     }
536     msg_Dbg( p_input, "+ Segment" );
537     p_sys->segment = (KaxSegment*)el;
538     p_sys->cluster = NULL;
539
540     p_sys->ep = new EbmlParser( p_sys->es, el );
541
542     while( ( el1 = p_sys->ep->Get() ) != NULL )
543     {
544         if( EbmlId( *el1 ) == KaxInfo::ClassInfos.GlobalId )
545         {
546             msg_Dbg( p_input, "|   + Informations" );
547
548             p_sys->ep->Down();
549             while( ( el2 = p_sys->ep->Get() ) != NULL )
550             {
551                 if( EbmlId( *el2 ) == KaxTimecodeScale::ClassInfos.GlobalId )
552                 {
553                     KaxTimecodeScale &tcs = *(KaxTimecodeScale*)el2;
554
555                     tcs.ReadData( p_sys->es->I_O() );
556                     p_sys->i_timescale = uint64(tcs);
557
558                     msg_Dbg( p_input, "|   |   + TimecodeScale=%lld", p_sys->i_timescale );
559                 }
560                 else if( EbmlId( *el2 ) == KaxDuration::ClassInfos.GlobalId )
561                 {
562                     KaxDuration &dur = *(KaxDuration*)el2;
563
564                     dur.ReadData( p_sys->es->I_O() );
565                     p_sys->f_duration = float(dur);
566
567                     msg_Dbg( p_input, "|   |   + Duration=%f", p_sys->f_duration );
568                 }
569                 else
570                 {
571                     msg_Dbg( p_input, "|   |   + Unknow (%s)", typeid(*el2).name() );
572                 }
573             }
574             p_sys->ep->Up();
575         }
576         else if( EbmlId( *el1 ) == KaxTracks::ClassInfos.GlobalId )
577         {
578             msg_Dbg( p_input, "|   + Tracks" );
579
580             p_sys->ep->Down();
581             while( ( el2 = p_sys->ep->Get() ) != NULL )
582             {
583                 if( EbmlId( *el2 ) == KaxTrackEntry::ClassInfos.GlobalId )
584                 {
585                     msg_Dbg( p_input, "|   |   + Track Entry" );
586
587                     p_sys->i_track++;
588                     p_sys->track = (mkv_track_t*)realloc( p_sys->track, sizeof( mkv_track_t ) * (p_sys->i_track + 1 ) );
589 #define tk  p_sys->track[p_sys->i_track - 1]
590                     memset( &tk, 0, sizeof( mkv_track_t ) );
591                     tk.i_cat = UNKNOWN_ES;
592                     tk.b_default = VLC_FALSE;
593                     tk.i_number = p_sys->i_track - 1;
594                     tk.i_extra_data = 0;
595                     tk.p_extra_data = NULL;
596                     tk.i_codec = 0;
597                     tk.psz_codec = NULL;
598                     tk.psz_language = NULL;
599                     tk.i_default_duration = 0;
600
601                     tk.b_inited = VLC_FALSE;
602                     tk.i_data_init = 0;
603                     tk.p_data_init = NULL;
604
605                     p_sys->ep->Down();
606
607                     while( ( el3 = p_sys->ep->Get() ) != NULL )
608                     {
609                         if( EbmlId( *el3 ) == KaxTrackNumber::ClassInfos.GlobalId )
610                         {
611                             KaxTrackNumber &tnum = *(KaxTrackNumber*)el3;
612                             tnum.ReadData( p_sys->es->I_O() );
613
614                             tk.i_number = uint32( tnum );
615                             msg_Dbg( p_input, "|   |   |   + Track Number=%u", uint32( tnum ) );
616                         }
617                         else  if( EbmlId( *el3 ) == KaxTrackUID::ClassInfos.GlobalId )
618                         {
619                             KaxTrackUID &tuid = *(KaxTrackUID*)el3;
620                             tuid.ReadData( p_sys->es->I_O() );
621
622                             msg_Dbg( p_input, "|   |   |   + Track UID=%u", uint32( tuid ) );
623                         }
624                         else  if( EbmlId( *el3 ) == KaxTrackDefaultDuration::ClassInfos.GlobalId )
625                         {
626                             KaxTrackDefaultDuration &defd = *(KaxTrackDefaultDuration*)el3;
627                             defd.ReadData( p_sys->es->I_O() );
628
629                             tk.i_default_duration = uint64(defd);
630                             msg_Dbg( p_input, "|   |   |   + Track Default Duration=%lld", uint64(defd) );
631                         }
632                         else  if( EbmlId( *el3 ) == KaxTrackType::ClassInfos.GlobalId )
633                         {
634                             char *psz_type;
635                             KaxTrackType &ttype = *(KaxTrackType*)el3;
636                             ttype.ReadData( p_sys->es->I_O() );
637                             switch( uint8(ttype) )
638                             {
639                                 case track_audio:
640                                     psz_type = "audio";
641                                     tk.i_cat = AUDIO_ES;
642                                     break;
643                                 case track_video:
644                                     psz_type = "video";
645                                     tk.i_cat = VIDEO_ES;
646                                     break;
647                                 case track_subtitle:
648                                     psz_type = "subtitle";
649                                     tk.i_cat = SPU_ES;
650                                     break;
651                                 default:
652                                     psz_type = "unknown";
653                                     tk.i_cat = UNKNOWN_ES;
654                                     break;
655                             }
656
657                             msg_Dbg( p_input, "|   |   |   + Track Type=%s", psz_type );
658                         }
659                         else  if( EbmlId( *el3 ) == KaxTrackAudio::ClassInfos.GlobalId )
660                         {
661                             msg_Dbg( p_input, "|   |   |   + Track Audio" );
662                             tk.i_channels = 0;
663                             tk.i_samplerate = 0;
664                             tk.i_bitspersample = 0;
665
666                             p_sys->ep->Down();
667
668                             while( ( el4 = p_sys->ep->Get() ) != NULL )
669                             {
670                                 if( EbmlId( *el4 ) == KaxAudioSamplingFreq::ClassInfos.GlobalId )
671                                 {
672                                     KaxAudioSamplingFreq &afreq = *(KaxAudioSamplingFreq*)el4;
673                                     afreq.ReadData( p_sys->es->I_O() );
674
675                                     tk.i_samplerate = (int)float( afreq );
676                                     msg_Dbg( p_input, "|   |   |   |   + afreq=%d", tk.i_samplerate );
677                                 }
678                                 else if( EbmlId( *el4 ) == KaxAudioChannels::ClassInfos.GlobalId )
679                                 {
680                                     KaxAudioChannels &achan = *(KaxAudioChannels*)el4;
681                                     achan.ReadData( p_sys->es->I_O() );
682
683                                     tk.i_channels = uint8( achan );
684                                     msg_Dbg( p_input, "|   |   |   |   + achan=%u", uint8( achan ) );
685                                 }
686                                 else if( EbmlId( *el4 ) == KaxAudioBitDepth::ClassInfos.GlobalId )
687                                 {
688                                     KaxAudioBitDepth &abits = *(KaxAudioBitDepth*)el4;
689                                     abits.ReadData( p_sys->es->I_O() );
690
691                                     tk.i_bitspersample = uint8( abits );
692                                     msg_Dbg( p_input, "|   |   |   |   + abits=%u", uint8( abits ) );
693                                 }
694                                 else
695                                 {
696                                     msg_Dbg( p_input, "|   |   |   |   + Unknow (%s)", typeid(*el4).name() );
697                                 }
698                             }
699                             p_sys->ep->Up();
700                         }
701                         else  if( EbmlId( *el3 ) == KaxTrackVideo::ClassInfos.GlobalId )
702                         {
703                             msg_Dbg( p_input, "|   |   |   + Track Video" );
704                             tk.i_width  = 0;
705                             tk.i_height = 0;
706                             tk.i_display_width  = 0;
707                             tk.i_display_height = 0;
708                             tk.f_fps = 0.0;
709
710                             p_sys->ep->Down();
711
712                             while( ( el4 = p_sys->ep->Get() ) != NULL )
713                             {
714                                 if( EbmlId( *el4 ) == KaxVideoPixelWidth::ClassInfos.GlobalId )
715                                 {
716                                     KaxVideoPixelWidth &vwidth = *(KaxVideoPixelWidth*)el4;
717                                     vwidth.ReadData( p_sys->es->I_O() );
718
719                                     tk.i_width = uint16( vwidth );
720                                     msg_Dbg( p_input, "|   |   |   |   + width=%d", uint16( vwidth ) );
721                                 }
722                                 else if( EbmlId( *el4 ) == KaxVideoPixelHeight::ClassInfos.GlobalId )
723                                 {
724                                     KaxVideoPixelWidth &vheight = *(KaxVideoPixelWidth*)el4;
725                                     vheight.ReadData( p_sys->es->I_O() );
726
727                                     tk.i_height = uint16( vheight );
728                                     msg_Dbg( p_input, "|   |   |   |   + height=%d", uint16( vheight ) );
729                                 }
730                                 else if( EbmlId( *el4 ) == KaxVideoDisplayWidth::ClassInfos.GlobalId )
731                                 {
732                                     KaxVideoDisplayWidth &vwidth = *(KaxVideoDisplayWidth*)el4;
733                                     vwidth.ReadData( p_sys->es->I_O() );
734
735                                     tk.i_display_width = uint16( vwidth );
736                                     msg_Dbg( p_input, "|   |   |   |   + display width=%d", uint16( vwidth ) );
737                                 }
738                                 else if( EbmlId( *el4 ) == KaxVideoDisplayHeight::ClassInfos.GlobalId )
739                                 {
740                                     KaxVideoDisplayWidth &vheight = *(KaxVideoDisplayWidth*)el4;
741                                     vheight.ReadData( p_sys->es->I_O() );
742
743                                     tk.i_display_height = uint16( vheight );
744                                     msg_Dbg( p_input, "|   |   |   |   + display height=%d", uint16( vheight ) );
745                                 }
746                                 else if( EbmlId( *el4 ) == KaxVideoFrameRate::ClassInfos.GlobalId )
747                                 {
748                                     KaxVideoFrameRate &vfps = *(KaxVideoFrameRate*)el4;
749                                     vfps.ReadData( p_sys->es->I_O() );
750
751                                     tk.f_fps = float( vfps );
752                                     msg_Dbg( p_input, "   |   |   |   + fps=%f", float( vfps ) );
753                                 }
754                                 else
755                                 {
756                                     msg_Dbg( p_input, "|   |   |   |   + Unknow (%s)", typeid(*el4).name() );
757                                 }
758                             }
759                             p_sys->ep->Up();
760                         }
761                         else  if( EbmlId( *el3 ) == KaxCodecID::ClassInfos.GlobalId )
762                         {
763                             KaxCodecID &codecid = *(KaxCodecID*)el3;
764                             codecid.ReadData( p_sys->es->I_O() );
765
766                             tk.psz_codec = strdup( string( codecid ).c_str() );
767                             msg_Dbg( p_input, "|   |   |   + Track CodecId=%s", string( codecid ).c_str() );
768                         }
769                         else  if( EbmlId( *el3 ) == KaxCodecPrivate::ClassInfos.GlobalId )
770                         {
771                             KaxCodecPrivate &cpriv = *(KaxCodecPrivate*)el3;
772                             cpriv.ReadData( p_sys->es->I_O() );
773
774                             tk.i_extra_data = cpriv.GetSize();
775                             if( tk.i_extra_data > 0 )
776                             {
777                                 tk.p_extra_data = (uint8_t*)malloc( tk.i_extra_data );
778                                 memcpy( tk.p_extra_data, cpriv.GetBuffer(), tk.i_extra_data );
779                             }
780                             msg_Dbg( p_input, "|   |   |   + Track CodecPrivate size=%lld", cpriv.GetSize() );
781                         }
782                         else  if( EbmlId( *el3 ) == KaxTrackFlagDefault::ClassInfos.GlobalId )
783                         {
784                             KaxTrackFlagDefault &fdef = *(KaxTrackFlagDefault*)el3;
785                             fdef.ReadData( p_sys->es->I_O() );
786
787                             tk.b_default = uint32( fdef );
788                             msg_Dbg( p_input, "|   |   |   + Track Default=%u", uint32( fdef )  );
789                         }
790                         else  if( EbmlId( *el3 ) == KaxTrackLanguage::ClassInfos.GlobalId )
791                         {
792                             KaxTrackLanguage &lang = *(KaxTrackLanguage*)el3;
793
794                             lang.ReadData( p_sys->es->I_O() );
795
796                             tk.psz_language = strdup( string( lang ).c_str() );
797                             msg_Dbg( p_input, "|   |   |   + Track Language=`%s'", string( lang ).c_str() );
798                         }
799                         else  if( EbmlId( *el3 ) == KaxTrackFlagLacing::ClassInfos.GlobalId )
800                         {
801                             KaxTrackFlagLacing &lac = *(KaxTrackFlagLacing*)el3;
802                             lac.ReadData( p_sys->es->I_O() );
803
804                             msg_Dbg( p_input, "|   |   |   + Track Lacing=%d", uint32( lac ) );
805                         }
806                         else  if( EbmlId( *el3 ) == KaxTrackMinCache::ClassInfos.GlobalId )
807                         {
808                             KaxTrackMinCache &cmin = *(KaxTrackMinCache*)el3;
809                             cmin.ReadData( p_sys->es->I_O() );
810
811                             msg_Dbg( p_input, "|   |   |   + Track MinCache=%d", uint32( cmin ) );
812                         }
813                         else  if( EbmlId( *el3 ) == KaxTrackMaxCache::ClassInfos.GlobalId )
814                         {
815                             KaxTrackMaxCache &cmax = *(KaxTrackMaxCache*)el3;
816                             cmax.ReadData( p_sys->es->I_O() );
817
818                             msg_Dbg( p_input, "|   |   |   + Track MaxCache=%d", uint32( cmax ) );
819                         }
820                         else
821                         {
822                             msg_Dbg( p_input, "|   |   |   + Unknow (%s)", typeid(*el3).name() );
823                         }
824                     }
825                     p_sys->ep->Up();
826                 }
827                 else
828                 {
829                     msg_Dbg( p_input, "|   |   + Unknow (%s)", typeid(*el2).name() );
830                 }
831 #undef tk
832             }
833             p_sys->ep->Up();
834         }
835         else if( EbmlId( *el1 ) == KaxSeekHead::ClassInfos.GlobalId )
836         {
837             msg_Dbg( p_input, "|   + Seek head" );
838             p_sys->ep->Down();
839             while( ( el = p_sys->ep->Get() ) != NULL )
840             {
841                 if( EbmlId( *el ) == KaxSeek::ClassInfos.GlobalId )
842                 {
843                     EbmlId id = EbmlVoid::ClassInfos.GlobalId;
844                     int64_t i_pos = -1;
845
846                     //msg_Dbg( p_input, "|   |   + Seek" );
847                     p_sys->ep->Down();
848                     while( ( el = p_sys->ep->Get() ) != NULL )
849                     {
850                         if( EbmlId( *el ) == KaxSeekID::ClassInfos.GlobalId )
851                         {
852                             KaxSeekID &sid = *(KaxSeekID*)el;
853
854                             sid.ReadData( p_sys->es->I_O() );
855
856                             id = EbmlId( sid.GetBuffer(), sid.GetSize() );
857                         }
858                         else  if( EbmlId( *el ) == KaxSeekPosition::ClassInfos.GlobalId )
859                         {
860                             KaxSeekPosition &spos = *(KaxSeekPosition*)el;
861
862                             spos.ReadData( p_sys->es->I_O() );
863
864                             i_pos = uint64( spos );
865                         }
866                         else
867                         {
868                             msg_Dbg( p_input, "|   |   |   + Unknow (%s)", typeid(*el).name() );
869                         }
870                     }
871                     p_sys->ep->Up();
872
873                     if( i_pos >= 0 )
874                     {
875                         if( id == KaxCues::ClassInfos.GlobalId )
876                         {
877                             msg_Dbg( p_input, "|   |   |   = cues at %lld", i_pos );
878                             p_sys->i_cues_position = p_sys->segment->GetGlobalPosition( i_pos );
879                         }
880                         else if( id == KaxChapters::ClassInfos.GlobalId )
881                         {
882                             msg_Dbg( p_input, "|   |   |   = chapters at %lld", i_pos );
883                             p_sys->i_chapters_position = p_sys->segment->GetGlobalPosition( i_pos );
884                         }
885                     }
886                 }
887                 else
888                 {
889                     msg_Dbg( p_input, "|   |   + Unknow (%s)", typeid(*el).name() );
890                 }
891             }
892             p_sys->ep->Up();
893         }
894         else if( EbmlId( *el1 ) == KaxCues::ClassInfos.GlobalId )
895         {
896             msg_Dbg( p_input, "|   + Cues" );
897         }
898         else if( EbmlId( *el1 ) == KaxCluster::ClassInfos.GlobalId )
899         {
900             msg_Dbg( p_input, "|   + Cluster" );
901             p_sys->cluster = (KaxCluster*)el1;
902             p_sys->ep->Down();
903
904             /* stop parsing the stream */
905             break;
906         }
907         else if( EbmlId( *el1 ) == KaxAttachements::ClassInfos.GlobalId )
908         {
909             msg_Dbg( p_input, "|   + Attachements FIXME TODO (but probably never supported)" );
910         }
911         else if( EbmlId( *el1 ) == KaxChapters::ClassInfos.GlobalId )
912         {
913             msg_Dbg( p_input, "|   + Chapters FIXME TODO" );
914         }
915         else if( EbmlId( *el1 ) == KaxTag::ClassInfos.GlobalId )
916         {
917             msg_Dbg( p_input, "|   + Tags FIXME TODO" );
918         }
919         else
920         {
921             msg_Dbg( p_input, "|   + Unknow (%s)", typeid(*el1).name() );
922         }
923     }
924
925     if( p_sys->cluster == NULL )
926     {
927         msg_Err( p_input, "cannot find any cluster, damaged file ?" );
928         goto error;
929     }
930
931     if( p_sys->i_chapters_position >= 0 )
932     {
933         msg_Warn( p_input, "chapters unsupported" );
934     }
935
936 #if 0
937     if( p_sys->i_cues_position == -1 && config_GetInt( p_input, "mkv-index" ) != 0 )
938     {
939         int64_t i_sav_position = p_sys->in->getFilePointer();
940         EbmlParser *ep;
941
942         /* parse to find cues gathering info on all clusters */
943         msg_Dbg( p_input, "no cues referenced, looking for one" );
944
945         /* ugly but like easier */
946         p_sys->in->setFilePointer( p_sys->cluster->GetElementPosition(), seek_beginning );
947
948         ep = new EbmlParser( p_sys->es, p_sys->segment );
949         while( ( el = ep->Get() ) != NULL )
950         {
951             if( EbmlId( *el ) == KaxCluster::ClassInfos.GlobalId )
952             {
953                 int64_t i_pos = el->GetElementPosition();
954
955                 msg_Dbg( p_input, "found a cluster at %lld", i_pos );
956             }
957             else if( EbmlId( *el ) == KaxCues::ClassInfos.GlobalId )
958             {
959                 msg_Dbg( p_input, "found a Cues !" );
960             }
961         }
962         delete ep;
963         msg_Dbg( p_input, "lookind done." );
964
965         p_sys->in->setFilePointer( i_sav_position, seek_beginning );
966     }
967 #endif
968
969     /* *** Load the cue if found *** */
970     if( p_sys->i_cues_position >= 0 )
971     {
972         int64_t i_sav_position = p_sys->in->getFilePointer();
973         EbmlParser *ep;
974         EbmlElement *cues;
975
976         msg_Dbg( p_input, "loading cues" );
977         p_sys->in->setFilePointer( p_sys->i_cues_position, seek_beginning );
978         cues = p_sys->es->FindNextID( KaxCues::ClassInfos, 0xFFFFFFFFL);
979
980         ep = new EbmlParser( p_sys->es, cues );
981         while( ( el = ep->Get() ) != NULL )
982         {
983             if( EbmlId( *el ) == KaxCuePoint::ClassInfos.GlobalId )
984             {
985 #define idx p_sys->index[p_sys->i_index]
986
987                 idx.i_track       = -1;
988                 idx.i_block_number= -1;
989                 idx.i_position    = -1;
990                 idx.i_time        = -1;
991                 idx.b_key         = VLC_TRUE;
992
993                 ep->Down();
994                 while( ( el = ep->Get() ) != NULL )
995                 {
996                     if( EbmlId( *el ) == KaxCueTime::ClassInfos.GlobalId )
997                     {
998                         KaxCueTime &ctime = *(KaxCueTime*)el;
999
1000                         ctime.ReadData( p_sys->es->I_O() );
1001
1002                         idx.i_time = uint64( ctime ) * (mtime_t)1000000000 / p_sys->i_timescale;
1003                     }
1004                     else if( EbmlId( *el ) == KaxCueTrackPositions::ClassInfos.GlobalId )
1005                     {
1006                         ep->Down();
1007                         while( ( el = ep->Get() ) != NULL )
1008                         {
1009                             if( EbmlId( *el ) == KaxCueTrack::ClassInfos.GlobalId )
1010                             {
1011                                 KaxCueTrack &ctrack = *(KaxCueTrack*)el;
1012
1013                                 ctrack.ReadData( p_sys->es->I_O() );
1014                                 idx.i_track = uint16( ctrack );
1015                             }
1016                             else if( EbmlId( *el ) == KaxCueClusterPosition::ClassInfos.GlobalId )
1017                             {
1018                                 KaxCueClusterPosition &ccpos = *(KaxCueClusterPosition*)el;
1019
1020                                 ccpos.ReadData( p_sys->es->I_O() );
1021                                 idx.i_position = p_sys->segment->GetGlobalPosition( uint64( ccpos ) );
1022                             }
1023                             else if( EbmlId( *el ) == KaxCueBlockNumber::ClassInfos.GlobalId )
1024                             {
1025                                 KaxCueBlockNumber &cbnum = *(KaxCueBlockNumber*)el;
1026
1027                                 cbnum.ReadData( p_sys->es->I_O() );
1028                                 idx.i_block_number = uint32( cbnum );
1029                             }
1030                             else
1031                             {
1032                                 msg_Dbg( p_input, "         * Unknow (%s)", typeid(*el).name() );
1033                             }
1034                         }
1035                         ep->Up();
1036                     }
1037                     else
1038                     {
1039                         msg_Dbg( p_input, "     * Unknow (%s)", typeid(*el).name() );
1040                     }
1041                 }
1042                 ep->Up();
1043
1044                 msg_Dbg( p_input, " * added time=%lld pos=%lld track=%d bnum=%d",
1045                          idx.i_time, idx.i_position, idx.i_track, idx.i_block_number );
1046
1047                 p_sys->i_index++;
1048                 if( p_sys->i_index >= p_sys->i_index_max )
1049                 {
1050                     p_sys->i_index_max += 1024;
1051                     p_sys->index = (mkv_index_t*)realloc( p_sys->index, sizeof( mkv_index_t ) * p_sys->i_index_max );
1052                 }
1053 #undef idx
1054             }
1055             else
1056             {
1057                 msg_Dbg( p_input, " * Unknow (%s)", typeid(*el).name() );
1058             }
1059         }
1060         delete ep;
1061         delete cues;
1062
1063         msg_Dbg( p_input, "loading cues done." );
1064         p_sys->in->setFilePointer( i_sav_position, seek_beginning );
1065     }
1066
1067     if( p_sys->i_index <= 0 )
1068     {
1069         /* FIXME FIXME FIXME */
1070         msg_Warn( p_input, "no cues found -> unseekable stream for now FIXME" );
1071         p_input->stream.b_seekable = VLC_FALSE;
1072         /* FIXME FIXME FIXME */
1073     }
1074
1075     /* Create one program */
1076     vlc_mutex_lock( &p_input->stream.stream_lock );
1077     if( input_InitStream( p_input, 0 ) == -1)
1078     {
1079         vlc_mutex_unlock( &p_input->stream.stream_lock );
1080         msg_Err( p_input, "cannot init stream" );
1081         goto error;
1082     }
1083     if( input_AddProgram( p_input, 0, 0) == NULL )
1084     {
1085         vlc_mutex_unlock( &p_input->stream.stream_lock );
1086         msg_Err( p_input, "cannot add program" );
1087         goto error;
1088     }
1089     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
1090     if( p_sys->f_duration > 1001.0 )
1091     {
1092         mtime_t i_duration = (mtime_t)( p_sys->f_duration / 1000.0 );
1093         p_input->stream.i_mux_rate = p_input->stream.p_selected_area->i_size / 50 / i_duration;
1094     }
1095     else
1096     {
1097         p_input->stream.i_mux_rate = 0;
1098     }
1099     vlc_mutex_unlock( &p_input->stream.stream_lock );
1100
1101     /* add all es */
1102     msg_Dbg( p_input, "found %d es", p_sys->i_track );
1103     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1104     {
1105 #define tk  p_sys->track[i_track]
1106         if( tk.i_cat == UNKNOWN_ES )
1107         {
1108             msg_Warn( p_input, "invalid track[%d, n=%d]", i_track, tk.i_number );
1109             tk.p_es = NULL;
1110             continue;
1111         }
1112         tk.p_es = input_AddES( p_input,
1113                                p_input->stream.p_selected_program,
1114                                i_track + 1,
1115                                tk.i_cat,
1116                                tk.psz_language, 0 );
1117         if( !strcmp( tk.psz_codec, "V_MS/VFW/FOURCC" ) )
1118         {
1119             if( tk.i_extra_data < (int)sizeof( BITMAPINFOHEADER ) )
1120             {
1121                 msg_Err( p_input, "missing/invalid BITMAPINFOHEADER" );
1122                 tk.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1123             }
1124             else
1125             {
1126                 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)tk.p_extra_data;
1127
1128                 p_bih->biSize           = GetDWLE( &p_bih->biSize );
1129                 p_bih->biWidth          = GetDWLE( &p_bih->biWidth );
1130                 p_bih->biHeight         = GetDWLE( &p_bih->biHeight );
1131                 p_bih->biPlanes         = GetWLE( &p_bih->biPlanes );
1132                 p_bih->biBitCount       = GetWLE( &p_bih->biBitCount );
1133                 p_bih->biCompression    = GetFOURCC( &p_bih->biCompression );
1134                 p_bih->biSizeImage      = GetDWLE( &p_bih->biSizeImage );
1135                 p_bih->biXPelsPerMeter  = GetDWLE( &p_bih->biXPelsPerMeter );
1136                 p_bih->biYPelsPerMeter  = GetDWLE( &p_bih->biYPelsPerMeter );
1137                 p_bih->biClrUsed        = GetDWLE( &p_bih->biClrUsed );
1138                 p_bih->biClrImportant   = GetDWLE( &p_bih->biClrImportant );
1139
1140
1141                 tk.i_codec = p_bih->biCompression;
1142                 tk.p_es->p_bitmapinfoheader = p_bih;
1143             }
1144         }
1145         else if( !strcmp( tk.psz_codec, "V_MPEG1" ) ||
1146                  !strcmp( tk.psz_codec, "V_MPEG2" ) )
1147         {
1148             tk.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
1149         }
1150         else if( !strncmp( tk.psz_codec, "V_MPEG4", 7 ) )
1151         {
1152             BITMAPINFOHEADER *p_bih;
1153
1154             tk.i_extra_data = sizeof( BITMAPINFOHEADER );
1155             tk.p_extra_data = (uint8_t*)malloc( tk.i_extra_data );
1156
1157             p_bih = (BITMAPINFOHEADER*)tk.p_extra_data;
1158             memset( p_bih, 0, sizeof( BITMAPINFOHEADER ) );
1159             p_bih->biSize  = sizeof( BITMAPINFOHEADER );
1160             p_bih->biWidth = tk.i_width;
1161             p_bih->biHeight= tk.i_height;
1162
1163             if( !strcmp( tk.psz_codec, "V_MPEG4/MS/V3" ) )
1164             {
1165                 tk.i_codec = VLC_FOURCC( 'D', 'I', 'V', '3' );
1166             }
1167             else
1168             {
1169                 tk.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
1170             }
1171         }
1172         else if( !strcmp( tk.psz_codec, "A_MS/ACM" ) )
1173         {
1174             if( tk.i_extra_data < (int)sizeof( WAVEFORMATEX ) )
1175             {
1176                 msg_Err( p_input, "missing/invalid WAVEFORMATEX" );
1177                 tk.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1178             }
1179             else
1180             {
1181                 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)tk.p_extra_data;
1182
1183                 p_wf->wFormatTag        = GetWLE( &p_wf->wFormatTag );
1184                 p_wf->nChannels         = GetWLE( &p_wf->nChannels );
1185                 p_wf->nSamplesPerSec    = GetDWLE( &p_wf->nSamplesPerSec );
1186                 p_wf->nAvgBytesPerSec   = GetDWLE( &p_wf->nAvgBytesPerSec );
1187                 p_wf->nBlockAlign       = GetWLE( &p_wf->nBlockAlign );
1188                 p_wf->wBitsPerSample    = GetWLE( &p_wf->wBitsPerSample );
1189                 p_wf->cbSize            = GetWLE( &p_wf->cbSize );
1190
1191                 switch( p_wf->wFormatTag )
1192                 {
1193                     case WAVE_FORMAT_PCM:
1194                         tk.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
1195                         break;
1196                     case WAVE_FORMAT_ADPCM:
1197                         tk.i_codec = VLC_FOURCC( 'm', 's', 0x00, 0x02 );
1198                         break;
1199                     case WAVE_FORMAT_ALAW:
1200                         tk.i_codec = VLC_FOURCC( 'a', 'l', 'a', 'w' );
1201                         break;
1202                     case WAVE_FORMAT_MULAW:
1203                         tk.i_codec = VLC_FOURCC( 'm', 'l', 'a', 'w' );
1204                         break;
1205                     case WAVE_FORMAT_IMA_ADPCM:
1206                         tk.i_codec = VLC_FOURCC( 'm', 's', 0x00, 0x11 );
1207                         break;
1208                     case WAVE_FORMAT_MPEG:
1209                     case WAVE_FORMAT_MPEGLAYER3:
1210                         tk.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
1211                         break;
1212                     case WAVE_FORMAT_A52:
1213                         tk.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
1214                         break;
1215                     case WAVE_FORMAT_WMA1:
1216                         tk.i_codec = VLC_FOURCC( 'w', 'm', 'a', '1' );
1217                         break;
1218                     case WAVE_FORMAT_WMA2:
1219                         tk.i_codec = VLC_FOURCC( 'w', 'm', 'a', '2' );
1220                         break;
1221                     case WAVE_FORMAT_WMA3:
1222                         tk.i_codec = VLC_FOURCC( 'w', 'm', 'a', '3' );
1223                         break;
1224                     default:
1225                         msg_Err( p_input, "unknown wFormatTag=0x%x", p_wf->wFormatTag );
1226                         tk.i_codec = VLC_FOURCC( 'm', 's', p_wf->wFormatTag >> 8, p_wf->wFormatTag&0xff );
1227                         break;
1228                 }
1229                 tk.p_es->p_waveformatex = p_wf;
1230             }
1231         }
1232         else if( !strcmp( tk.psz_codec, "A_MPEG/L3" ) ||
1233                  !strcmp( tk.psz_codec, "A_MPEG/L2" ) ||
1234                  !strcmp( tk.psz_codec, "A_MPEG/L1" ) )
1235         {
1236             tk.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
1237         }
1238         else if( !strcmp( tk.psz_codec, "A_AC3" ) )
1239         {
1240             tk.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
1241         }
1242         else if( !strcmp( tk.psz_codec, "A_DTS" ) )
1243         {
1244             tk.i_codec = VLC_FOURCC( 'd', 't', 's', ' ' );
1245         }
1246         else if( !strcmp( tk.psz_codec, "A_VORBIS" ) )
1247         {
1248             tk.i_codec = VLC_FOURCC( 'v', 'o', 'r', 'b' );
1249             tk.i_data_init = tk.i_extra_data;
1250             tk.p_data_init = tk.p_extra_data;
1251         }
1252         else if( !strncmp( tk.psz_codec, "A_AAC/MPEG2/", strlen( "A_AAC/MPEG2/" ) ) ||
1253                  !strncmp( tk.psz_codec, "A_AAC/MPEG4/", strlen( "A_AAC/MPEG4/" ) ) )
1254         {
1255             int i_profile, i_srate;
1256             static int i_sample_rates[] =
1257             {
1258                     96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1259                         16000, 12000, 11025, 8000,  7350,  0,     0,     0
1260             };
1261             WAVEFORMATEX *p_wf;
1262
1263             tk.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' );
1264             /* create data for faad (MP4DecSpecificDescrTag)*/
1265
1266             if( !strcmp( &tk.psz_codec[12], "MAIN" ) )
1267             {
1268                 i_profile = 0;
1269             }
1270             else if( !strcmp( &tk.psz_codec[12], "LC" ) )
1271             {
1272                 i_profile = 1;
1273             }
1274             else if( !strcmp( &tk.psz_codec[12], "SSR" ) )
1275             {
1276                 i_profile = 2;
1277             }
1278             else
1279             {
1280                 i_profile = 3;
1281             }
1282
1283             for( i_srate = 0; i_srate < 13; i_srate++ )
1284             {
1285                 if( i_sample_rates[i_srate] == tk.i_samplerate )
1286                 {
1287                     break;
1288                 }
1289             }
1290             msg_Dbg( p_input, "profile=%d srate=%d", i_profile, i_srate );
1291
1292             tk.i_extra_data = sizeof( WAVEFORMATEX ) + 2;
1293             tk.p_extra_data = (uint8_t*)malloc( tk.i_extra_data );
1294             p_wf = (WAVEFORMATEX*)tk.p_extra_data;
1295
1296             p_wf->wFormatTag = WAVE_FORMAT_UNKNOWN;
1297             p_wf->nChannels  = tk.i_channels;
1298             p_wf->nSamplesPerSec = tk.i_samplerate;
1299             p_wf->nAvgBytesPerSec = 0;
1300             p_wf->nBlockAlign = 0;
1301             p_wf->wBitsPerSample = 0;
1302             p_wf->cbSize = 2;
1303
1304             tk.p_extra_data[sizeof( WAVEFORMATEX )+ 0] = ((i_profile + 1) << 3) | ((i_srate&0xe) >> 1);
1305             tk.p_extra_data[sizeof( WAVEFORMATEX )+ 1] = ((i_srate & 0x1) << 7) | (tk.i_channels << 3);
1306
1307             tk.p_es->p_waveformatex = p_wf;
1308         }
1309         else if( !strcmp( tk.psz_codec, "A_PCM/INT/BIG" ) ||
1310                  !strcmp( tk.psz_codec, "A_PCM/INT/LIT" ) ||
1311                  !strcmp( tk.psz_codec, "A_PCM/FLOAT/IEEE" ) )
1312         {
1313             WAVEFORMATEX *p_wf;
1314
1315             tk.i_extra_data = sizeof( WAVEFORMATEX );
1316             tk.p_extra_data = (uint8_t*)malloc( tk.i_extra_data );
1317
1318             p_wf = (WAVEFORMATEX*)tk.p_extra_data;
1319
1320             if( !strncmp( &tk.psz_codec[6], "INT", 3 ) )
1321             {
1322                 p_wf->wFormatTag = WAVE_FORMAT_PCM;
1323             }
1324             else
1325             {
1326                 p_wf->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
1327             }
1328             p_wf->nChannels  = tk.i_channels;
1329             p_wf->nSamplesPerSec = tk.i_samplerate;
1330             p_wf->nAvgBytesPerSec = 0;
1331             p_wf->nBlockAlign = ( tk.i_bitspersample + 7 ) / 8 * tk.i_channels;
1332             p_wf->wBitsPerSample = tk.i_bitspersample;
1333             p_wf->cbSize = 0;
1334
1335             tk.p_es->p_waveformatex = p_wf;
1336
1337             if( !strcmp( tk.psz_codec, "A_PCM/INT/BIG" ) )
1338             {
1339                 tk.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
1340             }
1341             else
1342             {
1343                 tk.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
1344             }
1345         }
1346         else if( !strcmp( tk.psz_codec, "S_TEXT/UTF8" ) )
1347         {
1348             tk.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
1349         }
1350         else
1351         {
1352             msg_Err( p_input, "unknow codec id=`%s'", tk.psz_codec );
1353             tk.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
1354         }
1355
1356         tk.p_es->i_fourcc = tk.i_codec;
1357 #undef tk
1358     }
1359
1360     /* select track all video, one audio, no spu TODO : improve */
1361     b_audio_selected = VLC_FALSE;
1362     i_audio_channel = 0;
1363     i_spu_channel = 0;
1364     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1365     {
1366 #define tk  p_sys->track[i_track]
1367         switch( tk.i_cat )
1368         {
1369             case VIDEO_ES:
1370                 vlc_mutex_lock( &p_input->stream.stream_lock );
1371                 input_SelectES( p_input, tk.p_es );
1372                 vlc_mutex_unlock( &p_input->stream.stream_lock );
1373                 break;
1374
1375             case AUDIO_ES:
1376                 if( ( !b_audio_selected && config_GetInt( p_input, "audio-channel" ) < 0 ) ||
1377                     i_audio_channel == config_GetInt( p_input, "audio-channel" ) )
1378                 {
1379                     vlc_mutex_lock( &p_input->stream.stream_lock );
1380                     input_SelectES( p_input, tk.p_es );
1381                     vlc_mutex_unlock( &p_input->stream.stream_lock );
1382
1383                     b_audio_selected = tk.p_es->p_decoder_fifo ? VLC_TRUE : VLC_FALSE;
1384                 }
1385                 i_audio_channel++;
1386                 break;
1387             case SPU_ES:
1388                 if( i_spu_channel == config_GetInt( p_input, "spu-channel" ) )
1389                 {
1390                     vlc_mutex_lock( &p_input->stream.stream_lock );
1391                     input_SelectES( p_input, tk.p_es );
1392                     vlc_mutex_unlock( &p_input->stream.stream_lock );
1393                 }
1394                 i_spu_channel++;
1395                 break;
1396         }
1397 #undef tk
1398     }
1399
1400     if( !b_audio_selected )
1401     {
1402         msg_Warn( p_input, "cannot find/select audio track" );
1403     }
1404
1405     return VLC_SUCCESS;
1406
1407 error:
1408     delete p_sys->es;
1409     delete p_sys->in;
1410     free( p_sys );
1411     return VLC_EGENERIC;
1412 }
1413
1414 /*****************************************************************************
1415  * Deactivate: frees unused data
1416  *****************************************************************************/
1417 static void Deactivate( vlc_object_t *p_this )
1418 {
1419     input_thread_t *p_input = (input_thread_t *)p_this;
1420     demux_sys_t    *p_sys   = p_input->p_demux_data;
1421
1422     int             i_track;
1423
1424     for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1425     {
1426 #define tk  p_sys->track[i_track]
1427         if( tk.psz_codec )
1428         {
1429             free( tk.psz_codec );
1430         }
1431         if( tk.psz_language )
1432         {
1433             free( tk.psz_language );
1434         }
1435 #undef tk
1436     }
1437     free( p_sys->track );
1438
1439     delete p_sys->ep;
1440     delete p_sys->es;
1441     delete p_sys->in;
1442
1443     free( p_sys );
1444 }
1445
1446 static void Seek( input_thread_t *p_input, mtime_t i_date, int i_percent)
1447 {
1448     demux_sys_t    *p_sys   = p_input->p_demux_data;
1449
1450     int i_index;
1451
1452     msg_Dbg( p_input, "seek request to %lld (%d%%)", i_date, i_percent );
1453
1454     for( i_index = 0; i_index < p_sys->i_index; i_index++ )
1455     {
1456         if( p_sys->index[i_index].i_time >= i_date )
1457         {
1458             break;
1459         }
1460     }
1461
1462     if( i_index > 0 )
1463     {
1464         i_index--;
1465     }
1466
1467     msg_Dbg( p_input, "seek got %lld (%d%%)",
1468              p_sys->index[i_index].i_time, (int)(100 * p_sys->index[i_index].i_position /p_input->stream.p_selected_area->i_size ) );
1469
1470     delete p_sys->ep;
1471
1472     p_sys->in->setFilePointer( p_sys->index[i_index].i_position, seek_beginning );
1473
1474     p_sys->ep = new EbmlParser( p_sys->es, p_sys->segment );
1475
1476 //    p_sys->cluster = p_sys->es->FindNextElement( p_sys->segment->Generic().Context,
1477 //                                                 i_ulev, 0xFFFFFFFFL, true, 1);
1478
1479 }
1480
1481 /*****************************************************************************
1482  * Demux: reads and demuxes data packets
1483  *****************************************************************************
1484  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1485  *****************************************************************************/
1486 static int Demux( input_thread_t * p_input )
1487 {
1488     demux_sys_t    *p_sys   = p_input->p_demux_data;
1489     mtime_t        i_start_pts = p_sys->i_pts;
1490     KaxBlock *block = NULL;
1491     int64_t i_block_duration = -1;
1492     int64_t i_block_ref1 = 0;
1493     int64_t i_block_ref2 = 0;
1494
1495     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1496     {
1497         mtime_t i_duration = (mtime_t)( p_sys->f_duration / 1000 );
1498         mtime_t i_date;
1499         int i_percent;
1500
1501         i_date = (mtime_t)1000000 *
1502                  (mtime_t)i_duration*
1503                  (mtime_t)p_sys->in->getFilePointer() /
1504                  (mtime_t)p_input->stream.p_selected_area->i_size;
1505
1506         i_percent = 100 * p_sys->in->getFilePointer() /
1507                         p_input->stream.p_selected_area->i_size;
1508
1509         Seek( p_input, i_date, i_percent);
1510         i_start_pts = -1;
1511     }
1512
1513     for( ;; )
1514     {
1515         EbmlElement *el;
1516         int         i_level;
1517
1518         el = p_sys->ep->Get();
1519         i_level = p_sys->ep->GetLevel();
1520
1521         /* First send last collected blocks (before ep->Up, because of cluster) */
1522         if( el == NULL && block != NULL )
1523         {
1524             /* we have data */
1525             int i_track;
1526 #define tk  p_sys->track[i_track]
1527             for( i_track = 0; i_track < p_sys->i_track; i_track++ )
1528             {
1529                 if( tk.i_number == block->TrackNum() )
1530                 {
1531                     break;
1532                 }
1533             }
1534
1535             p_sys->i_pts = block->GlobalTimecode() * (mtime_t) 1000 / p_sys->i_timescale;
1536
1537             if( p_sys->i_pts > 0 )
1538             {
1539                 input_ClockManageRef( p_input,
1540                                       p_input->stream.p_selected_program,
1541                                       p_sys->i_pts * 9 / 100 );
1542             }
1543
1544             if( i_track >= p_sys->i_track )
1545             {
1546                 msg_Err( p_input, "invalid track number=%d", block->TrackNum() );
1547             }
1548             else if( tk.p_es->p_decoder_fifo != NULL )
1549             {
1550                 pes_packet_t  *p_pes;
1551                 unsigned int i;
1552
1553                 if( ( p_pes = input_NewPES( p_input->p_method_data ) ) != NULL )
1554                 {
1555                     mtime_t i_pts;
1556
1557                     i_pts = input_ClockGetTS( p_input,
1558                                               p_input->stream.p_selected_program,
1559                                               p_sys->i_pts * 9 / 100 );
1560
1561                     p_pes->i_pts = i_pts;
1562                     p_pes->i_dts = i_pts;
1563                     if( tk.i_cat == SPU_ES )
1564                     {
1565                         /* special case : dts mean end of display */
1566                         if( i_block_duration > 0 )
1567                         {
1568                             /* FIXME not sure about that */
1569                             p_pes->i_dts += i_block_duration * 1000;// * (mtime_t) 1000 / p_sys->i_timescale;
1570                         }
1571                         else
1572                         {
1573                             /* unknown */
1574                             p_pes->i_dts = 0;
1575                         }
1576                     }
1577
1578                     p_pes->p_first = p_pes->p_last = NULL;
1579                     p_pes->i_nb_data = 0;
1580                     p_pes->i_pes_size = 0;
1581
1582                     for( i = 0; i < block->NumberFrames(); i++ )
1583                     {
1584                         data_packet_t *p_data = NULL;
1585                         DataBuffer &data = block->GetBuffer(i);
1586
1587                         if( ( p_data = input_NewPacket( p_input->p_method_data, data.Size() ) ) != NULL )
1588                         {
1589                             memcpy( p_data->p_payload_start, data.Buffer(), data.Size() );
1590
1591                             p_data->p_payload_end = p_data->p_payload_start + data.Size();
1592
1593                             if( p_pes->p_first == NULL )
1594                             {
1595                                 p_pes->p_first = p_data;
1596                             }
1597                             else
1598                             {
1599                                 p_pes->p_last->p_next  = p_data;
1600                             }
1601                             p_pes->i_nb_data++;
1602                             p_pes->i_pes_size += data.Size();
1603                             p_pes->p_last  = p_data;
1604                         }
1605                     }
1606                     if( tk.i_cat == SPU_ES && p_pes->p_first && p_pes->i_pes_size > 0 )
1607                     {
1608                         p_pes->p_first->p_payload_end[-1] = '\0';
1609                     }
1610
1611                     if( !tk.b_inited && tk.i_data_init > 0 )
1612                     {
1613                         pes_packet_t *p_init;
1614                         data_packet_t *p_data;
1615
1616                         msg_Dbg( p_input, "sending header (%d bytes)", tk.i_data_init );
1617
1618                         p_init = input_NewPES( p_input->p_method_data );
1619
1620                         p_data = input_NewPacket( p_input->p_method_data, tk.i_data_init );
1621                         memcpy( p_data->p_payload_start, tk.p_data_init, tk.i_data_init );
1622                         p_data->p_payload_end = p_data->p_payload_start + tk.i_data_init;
1623
1624                         p_init->p_first = p_init->p_last = p_data;
1625                         p_init->i_nb_data = 1;
1626                         p_init->i_pes_size = tk.i_data_init;
1627
1628                         input_DecodePES( tk.p_es->p_decoder_fifo, p_init );
1629                     }
1630                     tk.b_inited = VLC_TRUE;
1631
1632                     input_DecodePES( tk.p_es->p_decoder_fifo, p_pes );
1633                 }
1634                 else
1635                 {
1636                     tk.b_inited = VLC_FALSE;
1637                 }
1638             }
1639 #undef tk
1640             delete block;
1641             block = NULL;
1642
1643             if( i_start_pts == -1 )
1644             {
1645                 i_start_pts = p_sys->i_pts;
1646             }
1647             else if( p_sys->i_pts > i_start_pts + (mtime_t)100000)
1648             {
1649                 return 1;
1650             }
1651         }
1652
1653         if( el == NULL )
1654         {
1655             if( p_sys->ep->GetLevel() > 1 )
1656             {
1657                 p_sys->ep->Up();
1658                 continue;
1659             }
1660             msg_Warn( p_input, "EOF" );
1661             return 0;
1662         }
1663
1664         /* do parsing */
1665         if( i_level == 1 )
1666         {
1667             if( EbmlId( *el ) == KaxCluster::ClassInfos.GlobalId )
1668             {
1669                 p_sys->cluster = (KaxCluster*)el;
1670                 p_sys->ep->Down();
1671             }
1672             else if( EbmlId( *el ) == KaxCues::ClassInfos.GlobalId )
1673             {
1674                 msg_Warn( p_input, "find KaxCues FIXME" );
1675                 return 0;
1676             }
1677             else
1678             {
1679                 msg_Dbg( p_input, "unknown (%s)", typeid( el ).name() );
1680             }
1681         }
1682         else if( i_level == 2 )
1683         {
1684             if( EbmlId( *el ) == KaxClusterTimecode::ClassInfos.GlobalId )
1685             {
1686                 KaxClusterTimecode &ctc = *(KaxClusterTimecode*)el;
1687
1688                 ctc.ReadData( p_sys->es->I_O() );
1689                 p_sys->cluster->InitTimecode( uint64( ctc ), p_sys->i_timescale );
1690             }
1691             else if( EbmlId( *el ) == KaxBlockGroup::ClassInfos.GlobalId )
1692             {
1693                 p_sys->ep->Down();
1694             }
1695         }
1696         else if( i_level == 3 )
1697         {
1698             if( EbmlId( *el ) == KaxBlock::ClassInfos.GlobalId )
1699             {
1700                 block = (KaxBlock*)el;
1701
1702                 block->ReadData( p_sys->es->I_O() );
1703                 block->SetParent( *p_sys->cluster );
1704
1705                 p_sys->ep->Keep();
1706             }
1707             else if( EbmlId( *el ) == KaxBlockDuration::ClassInfos.GlobalId )
1708             {
1709                 KaxBlockDuration &dur = *(KaxBlockDuration*)el;
1710
1711                 dur.ReadData( p_sys->es->I_O() );
1712                 i_block_duration = uint64( dur );
1713             }
1714             else if( EbmlId( *el ) == KaxReferenceBlock::ClassInfos.GlobalId )
1715             {
1716                 KaxReferenceBlock &ref = *(KaxReferenceBlock*)el;
1717
1718                 ref.ReadData( p_sys->es->I_O() );
1719                 if( i_block_ref1 == 0 )
1720                 {
1721                     i_block_ref1 = int64( ref );
1722                 }
1723                 else
1724                 {
1725                     i_block_ref2 = int64( ref );
1726                 }
1727             }
1728         }
1729         else
1730         {
1731             msg_Err( p_input, "invalid level = %d", i_level );
1732             return 0;
1733         }
1734     }
1735
1736 }
1737
1738