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