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