* cinepak: add a new fourcc
[vlc.git] / plugins / mp4 / mp4.c
1 /*****************************************************************************
2  * mp4.c : MP4 file input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: mp4.c,v 1.6 2002/07/23 17:19:02 fenrir Exp $
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include <stdlib.h>                                      /* malloc(), free() */
27 #include <string.h>                                              /* strdup() */
28 #include <errno.h>
29 #include <sys/types.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/input.h>
33
34 #include "libmp4.h"
35 #include "mp4.h"
36
37 /*****************************************************************************
38  * Local prototypes
39  *****************************************************************************/
40 static void input_getfunctions( function_list_t * );
41 static int  MP4Demux         ( input_thread_t * );
42 static int  MP4Init          ( input_thread_t * );
43 static void MP4End           ( input_thread_t * );
44
45 /*****************************************************************************
46  * Build configuration tree.
47  *****************************************************************************/
48 MODULE_CONFIG_START
49 MODULE_CONFIG_STOP
50
51 MODULE_INIT_START
52     SET_DESCRIPTION( "MP4 file input" )
53     ADD_CAPABILITY( DEMUX, 242 )
54 MODULE_INIT_STOP
55
56 MODULE_ACTIVATE_START
57     input_getfunctions( &p_module->p_functions->demux );
58 MODULE_ACTIVATE_STOP
59
60 MODULE_DEACTIVATE_START
61 MODULE_DEACTIVATE_STOP
62
63 /*****************************************************************************
64  * Functions exported as capabilities. They are declared as static so that
65  * we don't pollute the namespace too much.
66  *****************************************************************************/
67 static void input_getfunctions( function_list_t * p_function_list )
68 {
69 #define input p_function_list->functions.demux
70     input.pf_init             = MP4Init;
71     input.pf_end              = MP4End;
72     input.pf_demux            = MP4Demux;
73     input.pf_rewind           = NULL;
74 #undef input
75 }
76
77 /*****************************************************************************
78  * Declaration of local function 
79  *****************************************************************************/
80 static void MP4_ParseTrack();
81
82 static int MP4_CreateChunksIndex();
83 static int MP4_CreateSamplesIndex();
84
85 static void MP4_StartDecoder();
86 static void MP4_StopDecoder();
87
88 static int  MP4_ReadSample();
89 static int  MP4_DecodeSample();
90
91 #define MP4_Set4BytesLE( p, dw ) \
92     *((u8*)p)   = ( (dw)&0xff ); \
93     *((u8*)p+1) = ( ((dw)>> 8)&0xff ); \
94     *((u8*)p+2) = ( ((dw)>>16)&0xff ); \
95     *((u8*)p+3) = ( ((dw)>>24)&0xff )
96
97 #define MP4_Set2BytesLE( p, dw ) \
98     *((u8*)p) = ( (dw)&0xff ); \
99     *((u8*)p+1) = ( ((dw)>> 8)&0xff )
100
101     
102 /*****************************************************************************
103  * MP4Init: check file and initializes MP4 structures
104  *****************************************************************************/
105 static int MP4Init( input_thread_t *p_input )
106 {
107     u8  *p_peek;
108     u32 i_type;
109     
110     demux_data_mp4_t *p_demux;
111     
112     MP4_Box_t *p_moov;    
113     MP4_Box_t *p_ftyp;
114
115
116     MP4_Box_t *p_mvhd;
117     MP4_Box_t *p_trak;
118
119     int i;
120     /* I need to seek */
121     if( !p_input->stream.b_seekable )
122     {
123         msg_Warn( p_input, "MP4 plugin discarded (unseekable)" );
124         return( -1 );
125             
126     } 
127     /* Initialize access plug-in structures. */
128     if( p_input->i_mtu == 0 )
129     {
130         /* Improve speed. */
131         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE ;
132     }
133
134     /* a little test to see if it could be a mp4 */
135     if( input_Peek( p_input, &p_peek, 8 ) < 8 )
136     {
137         msg_Warn( p_input, "MP4 plugin discarded (cannot peek)" );
138         return( -1 );
139     }
140     i_type = ( p_peek[4] ) + ( p_peek[5] << 8 ) +
141                 ( p_peek[6] << 16 ) + ( p_peek[7] << 24);
142     switch( i_type )
143     {
144         case( FOURCC_ftyp ):
145         case( FOURCC_moov ):
146         case( FOURCC_moof ):
147         case( FOURCC_mdat ):
148         case( FOURCC_udta ): /* should never match but ... */
149         case( FOURCC_free ):
150         case( FOURCC_skip ):
151         case( FOURCC_wide ): /* not mp4 compliant but ... */
152             break;
153          default:
154             msg_Warn( p_input, "MP4 plugin discarded (not a valid file)" );
155             return( -1 );
156     }
157
158     /* create our structure that will contains all data */
159     if( !( p_input->p_demux_data = 
160                 p_demux = malloc( sizeof( demux_data_mp4_t ) ) ) )
161     {
162         msg_Err( p_input, "out of memory" );
163         return( -1 );
164     }
165     memset( p_demux, 0, sizeof( demux_data_mp4_t ) );
166     p_input->p_demux_data = p_demux;
167        
168
169     /* Now load all boxes ( except raw data ) */
170     if( !MP4_ReadBoxRoot( p_input, &p_demux->box_root ) )
171     {
172         msg_Warn( p_input, "MP4 plugin discarded (not a valid file)" );
173         return( -1 );
174     }
175
176     MP4_DumpBoxStructure( p_input, &p_demux->box_root );
177
178     if( ( p_ftyp = MP4_FindBox( &p_demux->box_root, FOURCC_ftyp ) ) )
179     {
180         switch( p_ftyp->data.p_ftyp->i_major_brand )
181         {
182             case( FOURCC_isom ):
183                 msg_Info( p_input, 
184                           "ISO Media file (isom) version %d.",
185                           p_ftyp->data.p_ftyp->i_minor_version );
186                 break;
187             default:
188                 msg_Info( p_input,
189                           "Unrecognize major file specification (%c%c%c%c).",
190                            p_ftyp->data.p_ftyp->i_major_brand&0xff,
191                            ( p_ftyp->data.p_ftyp->i_major_brand >>  8)&0xff,
192                            ( p_ftyp->data.p_ftyp->i_major_brand >> 16 )&0xff,
193                            ( p_ftyp->data.p_ftyp->i_major_brand >> 24 )&0xff );
194                 break;
195         }
196     }
197     else
198     {
199         msg_Info( p_input, "File Type box missing(assume ISO Media file)" );
200     }
201
202     /* the file need to have one moov box */
203     if( !( p_moov = MP4_FindBox( &p_demux->box_root, FOURCC_moov ) ) )
204     {
205         msg_Warn( p_input, "MP4 plugin discarded (missing moov box)" );
206         MP4End( p_input );
207         return( -1 );
208     }
209
210     if( MP4_CountBox( &p_demux->box_root, FOURCC_moov ) != 1 )
211     {
212         msg_Warn( p_input, "more than one \"moov\" box (continuying anyway)" );
213     }
214
215     if( !(p_mvhd = MP4_FindBox( p_moov, FOURCC_mvhd ) ) )
216     {
217         msg_Err( p_input, "cannot find \"mvhd\" box" );
218         MP4End( p_input );
219         return( -1 );
220     }
221     else
222     {
223         p_demux->i_timescale = p_mvhd->data.p_mvhd->i_timescale;
224     }
225     
226     p_demux->i_tracks = MP4_CountBox( p_moov, FOURCC_trak );
227     msg_Dbg( p_input, "find %d track%c",
228                         p_demux->i_tracks,
229                         p_demux->i_tracks ? 's':' ' );
230
231     if( !( p_trak = MP4_FindBox( p_moov, FOURCC_trak ) ) )
232     {
233         msg_Err( p_input, "cannot find /moov/trak !" );
234         MP4End( p_input );
235         return( -1 );
236     }
237
238     /* allocate memory */
239     p_demux->track = calloc( p_demux->i_tracks, sizeof( track_data_mp4_t ) );
240
241     /* now process each track and extract all usefull informations */
242     for( i = 0; i < p_demux->i_tracks; i++ )
243     {
244         MP4_ParseTrack( p_input, &p_demux->track[i], p_trak );
245
246         if( p_demux->track[i].b_ok )
247         {
248             char *psz_cat;
249             switch( p_demux->track[i].i_cat )
250             {
251                 case( VIDEO_ES ):
252                     psz_cat = "video";
253                     break;
254                 case( AUDIO_ES ):
255                     psz_cat = "audio";
256                     break;
257                 default:
258                     psz_cat = "";
259                     break;
260             }
261             
262             msg_Dbg( p_input, "adding track(%d) %s (%s) language %c%c%c",
263                             i,
264                             psz_cat,
265                             p_demux->track[i].b_enable ? "enable":"disable",
266                             p_demux->track[i].i_language[0],
267                             p_demux->track[i].i_language[1], 
268                             p_demux->track[i].i_language[2] );
269         }
270         else
271         {
272             msg_Dbg( p_input, "ignoring track(%d)", i );
273         }
274
275         p_trak = MP4_FindNextBox( p_trak );
276     }
277   
278     /*  create one program */
279     vlc_mutex_lock( &p_input->stream.stream_lock );
280     if( input_InitStream( p_input, 0 ) == -1)
281     {
282         vlc_mutex_unlock( &p_input->stream.stream_lock );
283         msg_Err( p_input, "cannot init stream" );
284         MP4End( p_input );
285         return( -1 );
286     }
287     if( input_AddProgram( p_input, 0, 0) == NULL )
288     {
289         vlc_mutex_unlock( &p_input->stream.stream_lock );
290         msg_Err( p_input, "cannot add program" );
291         MP4End( p_input );
292         return( -1 );
293     }
294     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
295     p_input->stream.i_mux_rate = 0 ; /* FIXME */
296     vlc_mutex_unlock( &p_input->stream.stream_lock );
297    
298     
299     for( i = 0; i < p_demux->i_tracks; i++ )
300     {
301         /* start decoder for this track if enable by default*/
302         if( p_demux->track[i].b_enable )
303         {
304             MP4_StartDecoder( p_input, &p_demux->track[i] );
305         }
306     }
307
308     vlc_mutex_lock( &p_input->stream.stream_lock );
309     p_input->stream.p_selected_program->b_is_ok = 1;
310     vlc_mutex_unlock( &p_input->stream.stream_lock );
311         
312     return( 0 );    
313
314 }
315
316 /*****************************************************************************
317  * MP4Demux: read packet and send them to decoders 
318  *****************************************************************************/
319 static int MP4Demux( input_thread_t *p_input )
320 {
321     demux_data_mp4_t *p_demux = p_input->p_demux_data;
322     int i_track;
323
324     /* first wait for the good time to read a packet */
325
326     input_ClockManageRef( p_input,
327                           p_input->stream.p_selected_program,
328                           p_demux->i_pcr );
329
330
331     /* update pcr XXX in mpeg scale so in 90000 unit/s */
332     p_demux->i_pcr = MP4_GetMoviePTS( p_demux ) * 9 / 100;
333     
334
335     /* we will read 100ms for each stream so ...*/
336     p_demux->i_time += __MAX( p_demux->i_timescale / 10 , 1 );
337     
338
339     for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
340     {
341         if( ( !p_demux->track[i_track].b_ok )||
342             ( !p_demux->track[i_track].p_es )||
343             ( !p_demux->track[i_track].p_es->p_decoder_fifo )||
344             ( MP4_GetTrackPTS( &p_demux->track[i_track] ) >=
345                         MP4_GetMoviePTS( p_demux ) ) )
346         {
347             continue; /* no need to read something */
348         }
349
350         while( MP4_GetTrackPTS( &p_demux->track[i_track] ) <
351                         MP4_GetMoviePTS( p_demux ) )
352         {
353
354             pes_packet_t *p_pes;
355
356             /* read a sample */
357             if( !MP4_ReadSample( p_input ,
358                                  &p_demux->track[i_track],
359                                  &p_pes ) )
360             {
361                 break;
362             }
363
364             /* send it to decoder and update time of this track 
365                  it also launch a new decoder if needed */
366             MP4_DecodeSample( p_input ,
367                               &p_demux->track[i_track],
368                               p_pes );
369         }
370
371     }
372     
373     /* now check if all tracks are finished or unhandled*/
374     
375     for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
376     {
377         if( ( p_demux->track[i_track].b_ok )&&
378             ( p_demux->track[i_track].i_sample < p_demux->track[i_track].i_sample_count )&&
379             ( p_demux->track[i_track].p_es )&&
380             ( p_demux->track[i_track].p_es->p_decoder_fifo ) )
381         {
382             return( 1 );
383         }
384     }
385
386     return( 0 ); /* EOF */
387 }
388
389 /*****************************************************************************
390  * MP4End: frees unused data
391  *****************************************************************************/
392 static void MP4End( input_thread_t *p_input )
393 {   
394 #define FREE( p ) \
395     if( p ) { free( p ); } 
396     int i_track;
397     demux_data_mp4_t *p_demux = p_input->p_demux_data;
398     
399     msg_Dbg( p_input, "Freeing all memory" );
400     MP4_FreeBox( p_input, &p_demux->box_root );
401     for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
402     {
403         int i_chunk;
404         for( i_chunk = 0; 
405                 i_chunk < p_demux->track[i_track].i_chunk_count; i_chunk++ )
406         {
407             if( p_demux->track[i_track].chunk )
408             {
409                FREE(p_demux->track[i_track].chunk[i_chunk].p_sample_count_dts);
410                FREE(p_demux->track[i_track].chunk[i_chunk].p_sample_delta_dts );
411             }
412         }
413
414         if( !p_demux->track[i_track].i_sample_size )
415         {
416             FREE( p_demux->track[i_track].p_sample_size );
417         }
418     }
419     FREE( p_demux->track );
420 #undef FREE
421 }
422
423
424 /****************************************************************************
425  * Local functions, specific to vlc
426  ****************************************************************************/
427
428 /****************************************************************************
429  * Parse track information and create all needed data to run a track
430  * If it succeed b_ok is set to 1 else to 0
431  ****************************************************************************/
432 static void MP4_ParseTrack( input_thread_t *p_input,
433                      track_data_mp4_t *p_demux_track,
434                      MP4_Box_t  * p_trak )
435 {
436     int i;
437
438     MP4_Box_t *p_tkhd = MP4_FindBox( p_trak, FOURCC_tkhd );
439     MP4_Box_t *p_tref = MP4_FindBox( p_trak, FOURCC_tref );
440     MP4_Box_t *p_edts = MP4_FindBox( p_trak, FOURCC_edts );
441     MP4_Box_t *p_mdia = MP4_FindBox( p_trak, FOURCC_mdia );
442
443     MP4_Box_t *p_mdhd;
444     MP4_Box_t *p_hdlr;
445     MP4_Box_t *p_minf;
446
447     MP4_Box_t *p_vmhd;
448     MP4_Box_t *p_smhd; 
449
450     /* hint track unsuported */
451
452     /* by default, track isn't usable */
453     p_demux_track->b_ok = 0;
454
455     /* by default, we don't known the categorie */
456     p_demux_track->i_cat = UNKNOWN_ES;
457     
458     if( ( !p_tkhd )||( !p_mdia ) )
459     {
460         return;
461     }
462
463     /* do we launch this track by default ? */
464     p_demux_track->b_enable = ( ( p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED ) != 0 );
465
466     p_demux_track->i_track_ID = p_tkhd->data.p_tkhd->i_track_ID;
467     p_demux_track->i_width = p_tkhd->data.p_tkhd->i_width / 65536;
468     p_demux_track->i_height = p_tkhd->data.p_tkhd->i_height / 65536;
469     
470     if( !p_edts )
471     {
472 //        msg_Warn( p_input, "Unhandled box: edts --> FIXME" );
473     }
474
475     if( !p_tref )
476     {
477 //        msg_Warn( p_input, "Unhandled box: tref --> FIXME" );
478     } 
479
480     p_mdhd = MP4_FindBox( p_mdia, FOURCC_mdhd );
481     p_hdlr = MP4_FindBox( p_mdia, FOURCC_hdlr );
482     p_minf = MP4_FindBox( p_mdia, FOURCC_minf );
483     
484     if( ( !p_mdhd )||( !p_hdlr )||( !p_minf ) )
485     {
486         return;
487     }
488
489     p_demux_track->i_timescale = p_mdhd->data.p_mdhd->i_timescale;
490
491     for( i = 0; i < 3; i++ ) 
492     {
493         p_demux_track->i_language[i] = p_mdhd->data.p_mdhd->i_language[i];
494     }
495     
496     switch( p_hdlr->data.p_hdlr->i_handler_type )
497     {
498         case( FOURCC_soun ):
499             if( !( p_smhd = MP4_FindBox( p_minf, FOURCC_smhd ) ) )
500             {
501                 return;
502             }
503             p_demux_track->i_cat = AUDIO_ES;
504             break;
505
506         case( FOURCC_vide ):
507             if( !( p_vmhd = MP4_FindBox( p_minf, FOURCC_vmhd ) ) )
508             {
509                 return;
510             }
511             p_demux_track->i_cat = VIDEO_ES;
512             break;
513             
514         default:
515             return;
516     }
517 /*  FIXME
518     add support to:
519     p_dinf = MP4_FindBox( p_minf, FOURCC_dinf );
520 */
521     if( !( p_demux_track->p_stbl = MP4_FindBox( p_minf, FOURCC_stbl ) ) )
522     {
523         return;
524     }
525     
526     if( !( p_demux_track->p_stsd = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsd ) ) )
527     {
528         return;
529     }
530     
531     /* Create chunk  index table */
532     if( !MP4_CreateChunksIndex( p_input,p_demux_track  ) )
533     {
534         return; /* cannot create chunks index */
535     }
536     
537     /* create sample index table needed for reading and seeking */
538     if( !MP4_CreateSamplesIndex( p_input, p_demux_track ) )
539     {
540         return; /* cannot create samples index */
541     }
542      
543     p_demux_track->b_ok = 1;        
544 }
545                      
546
547
548 /* now create basic chunk data, the rest will be filled by MP4_CreateSamplesIndex */
549 static int MP4_CreateChunksIndex( input_thread_t *p_input,
550                                    track_data_mp4_t *p_demux_track )
551 {
552     MP4_Box_t *p_co64; /* give offset for each chunk, same for stco and co64 */
553     MP4_Box_t *p_stsc;
554
555     int i_chunk;
556     int i_index, i_last;
557    
558
559     if( ( !(p_co64 = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stco ) )&&
560                  !(p_co64 = MP4_FindBox( p_demux_track->p_stbl, FOURCC_co64 ) ) )|| 
561         ( !(p_stsc = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsc ) ) ))
562     {
563         return( 0 );
564     }
565      
566     p_demux_track->i_chunk_count = p_co64->data.p_co64->i_entry_count;
567     if( !p_demux_track->i_chunk_count )
568     {
569         msg_Warn( p_input, "No chunk defined" );
570         return( 0 );
571     }
572     p_demux_track->chunk = calloc( p_demux_track->i_chunk_count, 
573                                    sizeof( chunk_data_mp4_t ) );
574
575     /* first we read chunk offset */
576     for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
577     {
578         p_demux_track->chunk[i_chunk].i_offset = 
579                 p_co64->data.p_co64->i_chunk_offset[i_chunk];
580     }
581
582     /* now we read index for SampleEntry( soun vide mp4a mp4v ...) 
583         to be used for the sample XXX begin to 1 
584         We construct it begining at the end */
585     i_last = p_demux_track->i_chunk_count; /* last chunk proceded */
586     i_index = p_stsc->data.p_stsc->i_entry_count;
587     if( !i_index )
588     {
589         msg_Warn( p_input, "cannot read chunk table or table empty" );
590         return( 0 );
591     }
592
593     while( i_index )
594     {
595         i_index--;
596         for( i_chunk = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
597                 i_chunk < i_last; i_chunk++ )
598         {
599             p_demux_track->chunk[i_chunk].i_sample_description_index = 
600                     p_stsc->data.p_stsc->i_sample_description_index[i_index];
601             p_demux_track->chunk[i_chunk].i_sample_count =
602                     p_stsc->data.p_stsc->i_samples_per_chunk[i_index];
603         }
604         i_last = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
605     }
606
607     p_demux_track->chunk[i_chunk].i_sample_first = 0;
608     for( i_chunk = 1; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
609     {
610         p_demux_track->chunk[i_chunk].i_sample_first =
611             p_demux_track->chunk[i_chunk-1].i_sample_first + 
612                 p_demux_track->chunk[i_chunk-1].i_sample_count;
613         
614     }
615     
616     msg_Dbg( p_input, "read %d chunk", p_demux_track->i_chunk_count );
617     return( 1 );
618
619 }
620
621
622
623 static int MP4_CreateSamplesIndex( input_thread_t *p_input,
624                                    track_data_mp4_t *p_demux_track )
625 {
626     MP4_Box_t *p_stts; /* makes mapping between sample and decoding time,
627                           ctts make same mapping but for composition time, 
628                           not yet used and probably not usefull */
629     MP4_Box_t *p_stsz; /* gives sample size of each samples, there is also stz2 
630                           that uses a compressed form FIXME make them in libmp4 
631                           as a unique type */
632     /* TODO use also stss and stsh table for seeking */
633     /* FIXME use edit table */
634     int i_sample;
635     int i_chunk;
636
637     int i_index;
638     int i_index_sample_used;
639
640     u64 i_last_dts; 
641     
642     p_stts = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stts );
643     p_stsz = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsz ); /* FIXME and stz2 */
644
645     
646     if( ( !p_stts )||( !p_stsz ) )
647     {
648         msg_Warn( p_input, "cannot read sample table" );
649         return( 0 ); 
650     }
651         
652     p_demux_track->i_sample_count = p_stsz->data.p_stsz->i_sample_count;
653
654
655     /* for sample size, there are 2 case */
656     if( p_stsz->data.p_stsz->i_sample_size )
657     {
658         /* 1: all sample have the same size, so no need to construct a table */
659         p_demux_track->i_sample_size = p_stsz->data.p_stsz->i_sample_size;
660         p_demux_track->p_sample_size = NULL;
661     }
662     else
663     {
664         /* 2: each sample can have a different size */
665         p_demux_track->i_sample_size = 0;
666         p_demux_track->p_sample_size = 
667             calloc( p_demux_track->i_sample_count, sizeof( u32 ) );
668         
669         for( i_sample = 0; i_sample < p_demux_track->i_sample_count; i_sample++ )
670         {
671             p_demux_track->p_sample_size[i_sample] = 
672                     p_stsz->data.p_stsz->i_entry_size[i_sample];
673         }
674     }
675     /* we have extract all information from stsz,
676         now use stts */
677
678     /* if we don't want to waste too much memory, we can't expand
679        the box !, so each chunk will contain an "extract" of this table 
680        for fast research */
681         
682     i_last_dts = 0;
683     i_index = 0; i_index_sample_used =0;
684     /* create and init last data for each chunk */
685     for(i_chunk = 0 ; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
686     {
687
688         int i_entry, i_sample_count, i;
689         /* save last dts */
690         p_demux_track->chunk[i_chunk].i_first_dts = i_last_dts;
691     /* count how many entries needed for this chunk 
692        for p_sample_delta_dts and p_sample_count_dts */
693
694         i_entry = 0;
695         i_sample_count = p_demux_track->chunk[i_chunk].i_sample_count;
696         while( i_sample_count > 0 )
697         {
698             i_sample_count -= p_stts->data.p_stts->i_sample_count[i_index+i_entry];
699             if( i_entry == 0 )
700             {
701                 i_sample_count += i_index_sample_used; /* don't count already used sample 
702                                                    int this entry */
703             }
704             i_entry++;
705         }
706         /* allocate them */
707         p_demux_track->chunk[i_chunk].p_sample_count_dts = 
708             calloc( i_entry, sizeof( u32 ) );
709         p_demux_track->chunk[i_chunk].p_sample_delta_dts =
710             calloc( i_entry, sizeof( u32 ) );
711
712         /* now copy */
713         i_sample_count = p_demux_track->chunk[i_chunk].i_sample_count;
714         for( i = 0; i < i_entry; i++ )
715         {
716             int i_used;
717             int i_rest;
718             
719             i_rest = p_stts->data.p_stts->i_sample_count[i_index] - i_index_sample_used;
720
721             i_used = __MIN( i_rest, i_sample_count );
722
723             i_index_sample_used += i_used;
724
725             p_demux_track->chunk[i_chunk].p_sample_count_dts[i] = i_used;
726
727             p_demux_track->chunk[i_chunk].p_sample_delta_dts[i] =
728                         p_stts->data.p_stts->i_sample_delta[i_index];
729             
730             i_last_dts += i_used * 
731                     p_demux_track->chunk[i_chunk].p_sample_delta_dts[i];
732
733             if( i_index_sample_used >=
734                              p_stts->data.p_stts->i_sample_count[i_index] )
735             {
736                 i_index++;
737                 i_index_sample_used = 0;
738             }
739         }
740         
741     }
742
743     msg_Dbg( p_input, "read %d samples", p_demux_track->i_sample_count );
744
745     return( 1 );
746 }
747
748 static void MP4_StartDecoder( input_thread_t *p_input,
749                                  track_data_mp4_t *p_demux_track )
750 {
751     MP4_Box_t *p_sample;
752     int i;
753     int i_chunk;
754
755     int i_decoder_specific_info_len;
756     u8  *p_decoder_specific_info;
757     
758     u8  *p_init;
759  
760     MP4_Box_t *p_esds;
761
762     
763     if( (!p_demux_track->b_ok )||( p_demux_track->i_cat == UNKNOWN_ES ) )
764     {
765         return;
766     }
767     
768     msg_Dbg( p_input, "Starting decoder (track ID 0x%x)",
769                       p_demux_track->i_track_ID );
770
771     /* launch decoder according in chunk we are */
772     i_chunk = p_demux_track->i_chunk;
773
774     if( !p_demux_track->chunk[i_chunk].i_sample_description_index )
775     {
776         msg_Warn( p_input, 
777                   "invalid SampleEntry index (track ID 0x%x)",
778                   p_demux_track->i_track_ID );
779         return;
780     } 
781     
782     p_sample = MP4_FindNbBox( p_demux_track->p_stsd,
783                  p_demux_track->chunk[i_chunk].i_sample_description_index - 1);
784
785     if( ( !p_sample )||( !p_sample->data.p_data ) )
786     {
787         msg_Warn( p_input, 
788                   "cannot find SampleEntry (track ID 0x%x)",
789                   p_demux_track->i_track_ID );
790         return;
791     }
792
793     if( !p_sample->data.p_data )
794     {
795         printf( "\nAhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh %.4s\n",
796                 &p_sample->i_type );
797         return;
798     } 
799     vlc_mutex_lock( &p_input->stream.stream_lock );
800     p_demux_track->p_es = input_AddES( p_input,
801                                        p_input->stream.p_selected_program, 
802                                        p_demux_track->i_track_ID,
803                                        0 );
804     vlc_mutex_unlock( &p_input->stream.stream_lock );
805     /* Initialise ES, first language as description */
806     for( i = 0; i < 3; i++ )
807     {
808         p_demux_track->p_es->psz_desc[i] = p_demux_track->i_language[i];
809     }
810     p_demux_track->p_es->psz_desc[4] = 0;
811     
812     p_demux_track->p_es->i_stream_id = p_demux_track->i_track_ID;
813
814     p_demux_track->p_es->i_fourcc = p_sample->i_type;
815     p_demux_track->p_es->i_cat = p_demux_track->i_cat;
816     
817     i_decoder_specific_info_len = 0;
818     p_decoder_specific_info = NULL;
819
820     /* now see if esds is present and if so create a data packet 
821         with decoder_specific_info  */
822 #define p_decconfig p_esds->data.p_esds->es_descriptor.p_decConfigDescr
823     if( ( p_esds = MP4_FindBox( p_sample, FOURCC_esds ) )&&
824         ( p_esds->data.p_esds )&&
825         ( p_decconfig ) )
826     {
827         /* First update information based on i_objectTypeIndication */
828         switch( p_decconfig->i_objectTypeIndication )
829         {
830             case( 0x20 ): /* MPEG4 VIDEO */
831                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','v' );
832                 break;
833             case( 0x40):
834                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','a' );
835                 break;
836             case( 0x60):
837             case( 0x61):
838             case( 0x62):
839             case( 0x63):
840             case( 0x64):
841             case( 0x65): /* MPEG2 video */
842                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','v' );
843                 break;
844             /* Theses are MPEG2-AAC (what is this codec ?) */
845             case( 0x66): /* main profile */
846             case( 0x67): /* Low complexity profile */
847             case( 0x68): /* Scaleable Sampling rate profile */
848                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','a' );
849                 break;
850             /* true MPEG 2 audio */
851             case( 0x69): 
852                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','a' );
853                 break;
854             case( 0x6a): /* MPEG1 video */
855                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','v' );
856                 break;
857             case( 0x6b): /* MPEG1 audio */
858                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','a' );
859                 break;
860             case( 0x6c ): /* jpeg */
861                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'j','p','e','g' );
862                 break;
863             default:
864                 /* Unknown entry, but don't touch i_fourcc */
865                 msg_Warn( p_input, 
866                           "objectTypeIndication(0x%x) unknow (Track ID 0x%x)",
867                           p_decconfig->i_objectTypeIndication,
868                           p_demux_track->i_track_ID );
869                 break;
870         }
871         i_decoder_specific_info_len = 
872                 p_decconfig->i_decoder_specific_info_len;
873         p_decoder_specific_info = 
874                 p_decconfig->p_decoder_specific_info;
875     }
876
877 #undef p_decconfig
878
879     /* some last initialisation */
880     /* XXX I create a bitmapinfoheader_t or 
881        waveformatex_t for each stream, up to now it's the best thing 
882        I've found but it could exist a better solution :) as something 
883        like adding some new fields in p_es ...
884
885        XXX I don't set all values, only thoses that are interesting or known
886         --> bitmapinfoheader_t : width and height 
887         --> waveformatex_t : channels, samplerate, bitspersample
888         and at the end I add p_decoder_specific_info 
889         
890         TODO set more values
891      
892      */
893
894     switch( p_demux_track->i_cat )
895     {
896         case( VIDEO_ES ):    
897             /* now create a bitmapinfoheader_t for decoder and 
898                add information found in p_esds */
899             p_init = malloc( 40 + i_decoder_specific_info_len);
900             memset( p_init, 0, 40 + i_decoder_specific_info_len);
901             MP4_Set4BytesLE( p_init, 40 + i_decoder_specific_info_len );
902             if( p_sample->data.p_sample_vide->i_width )
903             {
904                 MP4_Set4BytesLE( p_init + 4, 
905                                  p_sample->data.p_sample_vide->i_width );
906             }
907             else
908             {
909                 /* use display size */
910                 MP4_Set4BytesLE( p_init + 4, p_demux_track->i_width );
911             }
912             if( p_sample->data.p_sample_vide->i_height )
913             {
914                 MP4_Set4BytesLE( p_init + 8, 
915                                  p_sample->data.p_sample_vide->i_height );
916             }
917             else
918             {
919                 MP4_Set4BytesLE( p_init + 8, p_demux_track->i_height );
920             }
921             if( i_decoder_specific_info_len )
922             {
923                 memcpy( p_init + 40, 
924                         p_decoder_specific_info,
925                         i_decoder_specific_info_len);
926             }
927             break;
928
929         case( AUDIO_ES ):
930             p_init = malloc( 18 + i_decoder_specific_info_len);
931             memset( p_init, 0, 18 + i_decoder_specific_info_len);
932             MP4_Set2BytesLE( p_init + 2, /* i_channel */
933                              p_sample->data.p_sample_soun->i_channelcount );
934             MP4_Set4BytesLE( p_init + 4, /* samplepersec */
935                              p_sample->data.p_sample_soun->i_sampleratehi );
936             MP4_Set4BytesLE( p_init + 8, /* avgbytespersec */
937                              p_sample->data.p_sample_soun->i_channelcount *
938                                 p_sample->data.p_sample_soun->i_sampleratehi *
939                              (p_sample->data.p_sample_soun->i_samplesize/8) );
940             MP4_Set2BytesLE( p_init + 14, /* bits/sample */
941                              p_sample->data.p_sample_soun->i_samplesize );
942
943             MP4_Set2BytesLE( p_init + 16, /* i_size, specific info len*/
944                              i_decoder_specific_info_len );
945             if( i_decoder_specific_info_len )
946             {
947                 memcpy( p_init + 18, 
948                         p_decoder_specific_info,
949                         i_decoder_specific_info_len);
950             }
951             break;
952
953         default:
954             p_init = NULL;
955             break;
956     }
957
958     p_demux_track->p_es->p_demux_data = p_init;
959     vlc_mutex_lock( &p_input->stream.stream_lock );
960     input_SelectES( p_input, p_demux_track->p_es );
961     vlc_mutex_unlock( &p_input->stream.stream_lock );
962
963     p_demux_track->b_ok = 1;
964 }
965
966 static void MP4_StopDecoder( input_thread_t *p_input,
967                              track_data_mp4_t *p_demux_track )
968 {
969     msg_Dbg( p_input, "Stopping decoder (track ID 0x%x)",
970                       p_demux_track->i_track_ID );
971
972     input_UnselectES( p_input, p_demux_track->p_es );
973     p_demux_track->p_es = NULL;
974 }
975
976 static int  MP4_ReadSample( input_thread_t *p_input,
977                             track_data_mp4_t *p_demux_track,
978                             pes_packet_t **pp_pes )
979 {
980     int i_size;
981     off_t i_pos;
982
983     data_packet_t *p_data;
984
985
986     /* this track have already reach the end */
987     if( p_demux_track->i_sample >= p_demux_track->i_sample_count )
988     {
989         *pp_pes = NULL;
990         return( 0 );
991     }
992     /* caculate size and position for this sample */
993     i_size = p_demux_track->i_sample_size ? 
994                     p_demux_track->i_sample_size : 
995                     p_demux_track->p_sample_size[p_demux_track->i_sample];
996     /* TODO */
997     i_pos  = MP4_GetTrackPos( p_demux_track );
998
999     /* go,go go ! */
1000     if( ! MP4_SeekAbsolute( p_input, i_pos ) )
1001     {
1002         return( 0 );
1003     }
1004
1005     /* now create a pes */
1006     if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
1007     {
1008         return( 0 );
1009     }
1010     /* and a data packet for the data */
1011     if( !(p_data = input_NewPacket( p_input->p_method_data, i_size ) ) )
1012     {
1013         input_DeletePES( p_input->p_method_data, *pp_pes );
1014         *pp_pes = NULL;
1015         return( 0 );
1016     }
1017     
1018     /* initialisation of all the field */
1019     (*pp_pes)->i_dts =
1020         (*pp_pes)->i_pts = MP4_GetTrackPTS( p_demux_track );
1021     (*pp_pes)->p_first = (*pp_pes)->p_last  = p_data;
1022     (*pp_pes)->i_nb_data = 1;
1023     (*pp_pes)->i_pes_size = i_size;
1024
1025     if( !i_size )    
1026     {
1027         return( 1 );
1028     }
1029     
1030 //    msg_Dbg( p_input, "will read %d bytes", i_size );
1031     if( !MP4_ReadData( p_input, p_data->p_payload_start, i_size ) )
1032     {
1033         input_DeletePES( p_input->p_method_data, *pp_pes );
1034         input_DeletePacket( p_input->p_method_data, p_data );
1035         return( 0 );
1036     }
1037
1038         return( 1 );
1039 }
1040
1041
1042 static int  MP4_DecodeSample( input_thread_t *p_input,
1043                               track_data_mp4_t *p_demux_track,
1044                               pes_packet_t *p_pes )
1045 {
1046
1047     if( !p_pes )
1048     {
1049         return( 0 );
1050     }
1051
1052     /* don't forget to convert in mpeg clock */
1053     /* FIXME correct ffmpeg to use dts instead of pts that it incorrect 
1054        and, set it here ( and correct avi demux ) */
1055     p_pes->i_dts =
1056         p_pes->i_pts = input_ClockGetTS( p_input,
1057                                          p_input->stream.p_selected_program,
1058                                          p_pes->i_pts * 9/100);
1059
1060     
1061     input_DecodePES( p_demux_track->p_es->p_decoder_fifo, p_pes );
1062     
1063     /* now update sample position */
1064     p_demux_track->i_sample++; /* easy ;) */
1065     if( p_demux_track->i_sample >= p_demux_track->i_sample_count )
1066     {
1067         /* we have reach end of the track so free decoder stuff */
1068         MP4_StopDecoder( p_input, p_demux_track );
1069         return( 1 );
1070     }
1071     /* Have we changed chunk ? */
1072     if( p_demux_track->i_sample >=
1073             p_demux_track->chunk[p_demux_track->i_chunk].i_sample_first +
1074                 p_demux_track->chunk[p_demux_track->i_chunk].i_sample_count )
1075     {
1076         /* we haven't reached the end of the track, so see if we 
1077            have to change the decoder for the next frame because 
1078            i_sample_description_index have changed */
1079
1080         p_demux_track->i_chunk++;
1081         if( p_demux_track->chunk[p_demux_track->i_chunk-1].i_sample_description_index 
1082               != p_demux_track->chunk[p_demux_track->i_chunk].i_sample_description_index  )
1083         {
1084             /* FIXME */
1085             msg_Warn( p_input, 
1086                       "SampleEntry have changed, starting a new decoder" );
1087             MP4_StopDecoder( p_input, p_demux_track );
1088             MP4_StartDecoder( p_input, p_demux_track );
1089         }
1090     }
1091
1092     
1093     return( 1 );
1094 }
1095
1096
1097