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