* mp4 : improve mp4a detection/handling.
[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.4 2002/07/21 21:18:15 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." );
190                 break;
191         }
192     }
193     else
194     {
195         msg_Info( p_input, "File Type box missing(assume ISO Media file)" );
196     }
197
198     /* the file need to have one moov box */
199     if( !( p_moov = MP4_FindBox( &p_demux->box_root, FOURCC_moov ) ) )
200     {
201         msg_Warn( p_input, "MP4 plugin discarded (missing moov box)" );
202         MP4End( p_input );
203         return( -1 );
204     }
205
206     if( MP4_CountBox( &p_demux->box_root, FOURCC_moov ) != 1 )
207     {
208         msg_Warn( p_input, "more than one \"moov\" box (continuying anyway)" );
209     }
210
211     if( !(p_mvhd = MP4_FindBox( p_moov, FOURCC_mvhd ) ) )
212     {
213         msg_Err( p_input, "cannot find \"mvhd\" box" );
214         MP4End( p_input );
215         return( -1 );
216     }
217     else
218     {
219         p_demux->i_timescale = p_mvhd->data.p_mvhd->i_timescale;
220     }
221     
222     p_demux->i_tracks = MP4_CountBox( p_moov, FOURCC_trak );
223     msg_Dbg( p_input, "find %d track%c",
224                         p_demux->i_tracks,
225                         p_demux->i_tracks ? 's':' ' );
226
227     if( !( p_trak = MP4_FindBox( p_moov, FOURCC_trak ) ) )
228     {
229         msg_Err( p_input, "cannot find /moov/trak !" );
230         MP4End( p_input );
231         return( -1 );
232     }
233
234     /* allocate memory */
235     p_demux->track = calloc( p_demux->i_tracks, sizeof( track_data_mp4_t ) );
236
237     /* now process each track and extract all usefull informations */
238     for( i = 0; i < p_demux->i_tracks; i++ )
239     {
240         MP4_ParseTrack( p_input, &p_demux->track[i], p_trak );
241
242         if( p_demux->track[i].b_ok )
243         {
244             char *psz_cat;
245             switch( p_demux->track[i].i_cat )
246             {
247                 case( VIDEO_ES ):
248                     psz_cat = "video";
249                     break;
250                 case( AUDIO_ES ):
251                     psz_cat = "audio";
252                     break;
253                 default:
254                     psz_cat = "";
255                     break;
256             }
257             
258             msg_Dbg( p_input, "adding track(%d) %s (%s) language %c%c%c",
259                             i,
260                             psz_cat,
261                             p_demux->track[i].b_enable ? "enable":"disable",
262                             p_demux->track[i].i_language[0],
263                             p_demux->track[i].i_language[1], 
264                             p_demux->track[i].i_language[2] );
265         }
266         else
267         {
268             msg_Dbg( p_input, "ignoring track(%d)", i );
269         }
270
271         p_trak = MP4_FindNextBox( p_trak );
272     }
273   
274     /*  create one program */
275     vlc_mutex_lock( &p_input->stream.stream_lock );
276     if( input_InitStream( p_input, 0 ) == -1)
277     {
278         vlc_mutex_unlock( &p_input->stream.stream_lock );
279         msg_Err( p_input, "cannot init stream" );
280         MP4End( p_input );
281         return( -1 );
282     }
283     if( input_AddProgram( p_input, 0, 0) == NULL )
284     {
285         vlc_mutex_unlock( &p_input->stream.stream_lock );
286         msg_Err( p_input, "cannot add program" );
287         MP4End( p_input );
288         return( -1 );
289     }
290     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
291     p_input->stream.i_mux_rate = 0 ; /* FIXME */
292     vlc_mutex_unlock( &p_input->stream.stream_lock );
293    
294     
295     for( i = 0; i < p_demux->i_tracks; i++ )
296     {
297         /* start decoder for this track if enable by default*/
298         if( p_demux->track[i].b_enable )
299         {
300             MP4_StartDecoder( p_input, &p_demux->track[i] );
301         }
302     }
303
304     vlc_mutex_lock( &p_input->stream.stream_lock );
305     p_input->stream.p_selected_program->b_is_ok = 1;
306     vlc_mutex_unlock( &p_input->stream.stream_lock );
307         
308     return( 0 );    
309
310 }
311
312 /*****************************************************************************
313  * MP4Demux: read packet and send them to decoders 
314  *****************************************************************************/
315 static int MP4Demux( input_thread_t *p_input )
316 {
317     demux_data_mp4_t *p_demux = p_input->p_demux_data;
318     int i_track;
319
320     /* first wait for the good time to read a packet */
321
322     input_ClockManageRef( p_input,
323                           p_input->stream.p_selected_program,
324                           p_demux->i_pcr );
325
326
327     /* update pcr XXX in mpeg scale so in 90000 unit/s */
328     p_demux->i_pcr = MP4_GetMoviePTS( p_demux ) * 9 / 100;
329     
330
331     /* we will read 100ms for each stream so ...*/
332     p_demux->i_time += __MAX( p_demux->i_timescale / 10 , 1 );
333     
334
335     for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
336     {
337         if( ( !p_demux->track[i_track].b_ok )||
338             ( !p_demux->track[i_track].p_es )||
339             ( !p_demux->track[i_track].p_es->p_decoder_fifo )||
340             ( MP4_GetTrackPTS( &p_demux->track[i_track] ) >=
341                         MP4_GetMoviePTS( p_demux ) ) )
342         {
343             continue; /* no need to read something */
344         }
345
346         while( MP4_GetTrackPTS( &p_demux->track[i_track] ) <
347                         MP4_GetMoviePTS( p_demux ) )
348         {
349
350             pes_packet_t *p_pes;
351
352             /* read a sample */
353             if( !MP4_ReadSample( p_input ,
354                                  &p_demux->track[i_track],
355                                  &p_pes ) )
356             {
357                 break;
358             }
359
360             /* send it to decoder and update time of this track 
361                  it also launch a new decoder if needed */
362             MP4_DecodeSample( p_input ,
363                               &p_demux->track[i_track],
364                               p_pes );
365         }
366
367     }
368     
369     /* now check if all tracks are finished or unhandled*/
370     
371     for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
372     {
373         if( ( p_demux->track[i_track].b_ok )&&
374             ( p_demux->track[i_track].i_sample < p_demux->track[i_track].i_sample_count )&&
375             ( p_demux->track[i_track].p_es )&&
376             ( p_demux->track[i_track].p_es->p_decoder_fifo ) )
377         {
378             return( 1 );
379         }
380     }
381
382     return( 0 ); /* EOF */
383 }
384
385 /*****************************************************************************
386  * MP4End: frees unused data
387  *****************************************************************************/
388 static void MP4End( input_thread_t *p_input )
389 {   
390 #define FREE( p ) \
391     if( p ) { free( p ); } 
392     int i_track;
393     demux_data_mp4_t *p_demux = p_input->p_demux_data;
394     
395     msg_Dbg( p_input, "Freeing all memory" );
396     MP4_FreeBox( p_input, &p_demux->box_root );
397     for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
398     {
399         int i_chunk;
400         for( i_chunk = 0; 
401                 i_chunk < p_demux->track[i_track].i_chunk_count; i_chunk++ )
402         {
403             if( p_demux->track[i_track].chunk )
404             {
405                FREE(p_demux->track[i_track].chunk[i_chunk].p_sample_count_dts);
406                FREE(p_demux->track[i_track].chunk[i_chunk].p_sample_delta_dts );
407             }
408         }
409 #if 0
410 /*        if( p_demux->track->p_data_init )
411         {
412             input_DeletePacket( p_input->p_method_data, 
413                                 p_demux->track->p_data_init );
414         }
415         */
416 #endif 
417         if( !p_demux->track[i_track].i_sample_size )
418         {
419             FREE( p_demux->track[i_track].p_sample_size );
420         }
421     }
422     FREE( p_demux->track );
423 #undef FREE
424 }
425
426
427 /****************************************************************************
428  * Local functions, specific to vlc
429  ****************************************************************************/
430
431 /****************************************************************************
432  * Parse track information and create all needed data to run a track
433  * If it succeed b_ok is set to 1 else to 0
434  ****************************************************************************/
435 static void MP4_ParseTrack( input_thread_t *p_input,
436                      track_data_mp4_t *p_demux_track,
437                      MP4_Box_t  * p_trak )
438 {
439     int i;
440
441     MP4_Box_t *p_tkhd = MP4_FindBox( p_trak, FOURCC_tkhd );
442     MP4_Box_t *p_tref = MP4_FindBox( p_trak, FOURCC_tref );
443     MP4_Box_t *p_edts = MP4_FindBox( p_trak, FOURCC_edts );
444     MP4_Box_t *p_mdia = MP4_FindBox( p_trak, FOURCC_mdia );
445
446     MP4_Box_t *p_mdhd;
447     MP4_Box_t *p_hdlr;
448     MP4_Box_t *p_minf;
449
450     MP4_Box_t *p_vmhd;
451     MP4_Box_t *p_smhd; 
452
453     /* hint track unsuported */
454
455     /* by default, track isn't usable */
456     p_demux_track->b_ok = 0;
457
458     /* by default, we don't known the categorie */
459     p_demux_track->i_cat = UNKNOWN_ES;
460     
461     if( ( !p_tkhd )||( !p_mdia ) )
462     {
463         return;
464     }
465
466     /* do we launch this track by default ? */
467     p_demux_track->b_enable = ( ( p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED ) != 0 );
468
469     p_demux_track->i_track_ID = p_tkhd->data.p_tkhd->i_track_ID;
470     p_demux_track->i_width = p_tkhd->data.p_tkhd->i_width / 65536;
471     p_demux_track->i_height = p_tkhd->data.p_tkhd->i_height / 65536;
472     
473     if( !p_edts )
474     {
475 //        msg_Warn( p_input, "Unhandled box: edts --> FIXME" );
476     }
477
478     if( !p_tref )
479     {
480 //        msg_Warn( p_input, "Unhandled box: tref --> FIXME" );
481     } 
482
483     p_mdhd = MP4_FindBox( p_mdia, FOURCC_mdhd );
484     p_hdlr = MP4_FindBox( p_mdia, FOURCC_hdlr );
485     p_minf = MP4_FindBox( p_mdia, FOURCC_minf );
486     
487     if( ( !p_mdhd )||( !p_hdlr )||( !p_minf ) )
488     {
489         return;
490     }
491
492     p_demux_track->i_timescale = p_mdhd->data.p_mdhd->i_timescale;
493
494     for( i = 0; i < 3; i++ ) 
495     {
496         p_demux_track->i_language[i] = p_mdhd->data.p_mdhd->i_language[i];
497     }
498     
499     switch( p_hdlr->data.p_hdlr->i_handler_type )
500     {
501         case( FOURCC_soun ):
502             if( !( p_smhd = MP4_FindBox( p_minf, FOURCC_smhd ) ) )
503             {
504                 return;
505             }
506             p_demux_track->i_cat = AUDIO_ES;
507             break;
508
509         case( FOURCC_vide ):
510             if( !( p_vmhd = MP4_FindBox( p_minf, FOURCC_vmhd ) ) )
511             {
512                 return;
513             }
514             p_demux_track->i_cat = VIDEO_ES;
515             break;
516             
517         default:
518             return;
519     }
520 /*  FIXME
521     add support to:
522     p_dinf = MP4_FindBox( p_minf, FOURCC_dinf );
523 */
524     if( !( p_demux_track->p_stbl = MP4_FindBox( p_minf, FOURCC_stbl ) ) )
525     {
526         return;
527     }
528     
529     if( !( p_demux_track->p_stsd = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsd ) ) )
530     {
531         return;
532     }
533     
534     /* Create chunk  index table */
535     if( !MP4_CreateChunksIndex( p_input,p_demux_track  ) )
536     {
537         return; /* cannot create chunks index */
538     }
539     
540     /* create sample index table needed for reading and seeking */
541     if( !MP4_CreateSamplesIndex( p_input, p_demux_track ) )
542     {
543         return; /* cannot create samples index */
544     }
545      
546     p_demux_track->b_ok = 1;        
547 }
548                      
549
550
551 /* now create basic chunk data, the rest will be filled by MP4_CreateSamplesIndex */
552 static int MP4_CreateChunksIndex( input_thread_t *p_input,
553                                    track_data_mp4_t *p_demux_track )
554 {
555     MP4_Box_t *p_co64; /* give offset for each chunk, same for stco and co64 */
556     MP4_Box_t *p_stsc;
557
558     int i_chunk;
559     int i_index, i_last;
560    
561
562     if( ( !(p_co64 = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stco ) )&&
563                  !(p_co64 = MP4_FindBox( p_demux_track->p_stbl, FOURCC_co64 ) ) )|| 
564         ( !(p_stsc = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsc ) ) ))
565     {
566         return( 0 );
567     }
568      
569     p_demux_track->i_chunk_count = p_co64->data.p_co64->i_entry_count;
570     if( !p_demux_track->i_chunk_count )
571     {
572         msg_Warn( p_input, "No chunk defined" );
573         return( 0 );
574     }
575     p_demux_track->chunk = calloc( p_demux_track->i_chunk_count, 
576                                    sizeof( chunk_data_mp4_t ) );
577
578     /* first we read chunk offset */
579     for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
580     {
581         p_demux_track->chunk[i_chunk].i_offset = 
582                 p_co64->data.p_co64->i_chunk_offset[i_chunk];
583     }
584
585     /* now we read index for SampleEntry( soun vide mp4a mp4v ...) 
586         to be used for the sample XXX begin to 1 
587         We construct it begining at the end */
588     i_last = p_demux_track->i_chunk_count; /* last chunk proceded */
589     i_index = p_stsc->data.p_stsc->i_entry_count;
590     if( !i_index )
591     {
592         msg_Warn( p_input, "cannot read chunk table or table empty" );
593         return( 0 );
594     }
595
596     while( i_index )
597     {
598         i_index--;
599         for( i_chunk = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
600                 i_chunk < i_last; i_chunk++ )
601         {
602             p_demux_track->chunk[i_chunk].i_sample_description_index = 
603                     p_stsc->data.p_stsc->i_sample_description_index[i_index];
604             p_demux_track->chunk[i_chunk].i_sample_count =
605                     p_stsc->data.p_stsc->i_samples_per_chunk[i_index];
606         }
607         i_last = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
608     }
609
610     p_demux_track->chunk[i_chunk].i_sample_first = 0;
611     for( i_chunk = 1; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
612     {
613         p_demux_track->chunk[i_chunk].i_sample_first =
614             p_demux_track->chunk[i_chunk-1].i_sample_first + 
615                 p_demux_track->chunk[i_chunk-1].i_sample_count;
616         
617     }
618     
619     msg_Dbg( p_input, "read %d chunk", p_demux_track->i_chunk_count );
620     return( 1 );
621
622 }
623
624
625
626 static int MP4_CreateSamplesIndex( input_thread_t *p_input,
627                                    track_data_mp4_t *p_demux_track )
628 {
629     MP4_Box_t *p_stts; /* makes mapping between sample and decoding time,
630                           ctts make same mapping but for composition time, 
631                           not yet used and probably not usefull */
632     MP4_Box_t *p_stsz; /* gives sample size of each samples, there is also stz2 
633                           that uses a compressed form FIXME make them in libmp4 
634                           as a unique type */
635     /* TODO use also stss and stsh table for seeking */
636     /* FIXME use edit table */
637     int i_sample;
638     int i_chunk;
639
640     int i_index;
641     int i_index_sample_used;
642
643     u64 i_last_dts; 
644     
645     p_stts = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stts );
646     p_stsz = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsz ); /* FIXME and stz2 */
647
648     
649     if( ( !p_stts )||( !p_stsz ) )
650     {
651         msg_Warn( p_input, "cannot read sample table" );
652         return( 0 ); 
653     }
654         
655     p_demux_track->i_sample_count = p_stsz->data.p_stsz->i_sample_count;
656
657
658     /* for sample size, there are 2 case */
659     if( p_stsz->data.p_stsz->i_sample_size )
660     {
661         /* 1: all sample have the same size, so no need to construct a table */
662         p_demux_track->i_sample_size = p_stsz->data.p_stsz->i_sample_size;
663         p_demux_track->p_sample_size = NULL;
664     }
665     else
666     {
667         /* 2: each sample can have a different size */
668         p_demux_track->i_sample_size = 0;
669         p_demux_track->p_sample_size = 
670             calloc( p_demux_track->i_sample_count, sizeof( u32 ) );
671         
672         for( i_sample = 0; i_sample < p_demux_track->i_sample_count; i_sample++ )
673         {
674             p_demux_track->p_sample_size[i_sample] = 
675                     p_stsz->data.p_stsz->i_entry_size[i_sample];
676         }
677     }
678     /* we have extract all information from stsz,
679         now use stts */
680
681     /* if we don't want to waste too much memory, we can't expand
682        the box !, so each chunk will contain an "extract" of this table 
683        for fast research */
684         
685     i_last_dts = 0;
686     i_index = 0; i_index_sample_used =0;
687     /* create and init last data for each chunk */
688     for(i_chunk = 0 ; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
689     {
690
691         int i_entry, i_sample_count, i;
692         /* save last dts */
693         p_demux_track->chunk[i_chunk].i_first_dts = i_last_dts;
694     /* count how many entries needed for this chunk 
695        for p_sample_delta_dts and p_sample_count_dts */
696
697         i_entry = 0;
698         i_sample_count = p_demux_track->chunk[i_chunk].i_sample_count;
699         while( i_sample_count > 0 )
700         {
701             i_sample_count -= p_stts->data.p_stts->i_sample_count[i_index+i_entry];
702             if( i_entry == 0 )
703             {
704                 i_sample_count += i_index_sample_used; /* don't count already used sample 
705                                                    int this entry */
706             }
707             i_entry++;
708         }
709         /* allocate them */
710         p_demux_track->chunk[i_chunk].p_sample_count_dts = 
711             calloc( i_entry, sizeof( u32 ) );
712         p_demux_track->chunk[i_chunk].p_sample_delta_dts =
713             calloc( i_entry, sizeof( u32 ) );
714
715         /* now copy */
716         i_sample_count = p_demux_track->chunk[i_chunk].i_sample_count;
717         for( i = 0; i < i_entry; i++ )
718         {
719             int i_used;
720             int i_rest;
721             
722             i_rest = p_stts->data.p_stts->i_sample_count[i_index] - i_index_sample_used;
723
724             i_used = __MIN( i_rest, i_sample_count );
725
726             i_index_sample_used += i_used;
727
728             p_demux_track->chunk[i_chunk].p_sample_count_dts[i] = i_used;
729
730             p_demux_track->chunk[i_chunk].p_sample_delta_dts[i] =
731                         p_stts->data.p_stts->i_sample_delta[i_index];
732             
733             i_last_dts += i_used * 
734                     p_demux_track->chunk[i_chunk].p_sample_delta_dts[i];
735
736             if( i_index_sample_used >=
737                              p_stts->data.p_stts->i_sample_count[i_index] )
738             {
739                 i_index++;
740                 i_index_sample_used = 0;
741             }
742         }
743         
744     }
745
746     msg_Dbg( p_input, "read %d samples", p_demux_track->i_sample_count );
747
748     return( 1 );
749 }
750
751 static void MP4_StartDecoder( input_thread_t *p_input,
752                                  track_data_mp4_t *p_demux_track )
753 {
754     MP4_Box_t *p_sample;
755     int i;
756     int i_chunk;
757     u8  *p_bmih;
758  
759     int i_codec;
760     char *psz_name;
761     
762     MP4_Box_t *p_esds;
763
764     
765     if( (!p_demux_track->b_ok )||( p_demux_track->i_cat == UNKNOWN_ES ) )
766     {
767         return;
768     }
769     
770     msg_Dbg( p_input, "Starting decoder (track ID 0x%x)",
771                       p_demux_track->i_track_ID );
772
773     /* launch decoder according in chunk we are */
774     i_chunk = p_demux_track->i_chunk;
775
776     if( !p_demux_track->chunk[i_chunk].i_sample_description_index )
777     {
778         msg_Warn( p_input, "invalid SampleEntry index for this track i_cat %d" );
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 )
786     {
787         msg_Warn( p_input, "cannot find SampleEntry for this track" );
788         return;
789     }
790
791     
792     vlc_mutex_lock( &p_input->stream.stream_lock );
793     p_demux_track->p_es = input_AddES( p_input,
794                                        p_input->stream.p_selected_program, 
795                                        p_demux_track->i_track_ID,
796                                        0 );
797     vlc_mutex_unlock( &p_input->stream.stream_lock );
798     /* Initialise ES, first language as description */
799     for( i = 0; i < 3; i++ )
800     {
801         p_demux_track->p_es->psz_desc[i] = p_demux_track->i_language[i];
802     }
803     p_demux_track->p_es->psz_desc[4] = 0;
804     
805     p_demux_track->p_es->i_stream_id = p_demux_track->i_track_ID;
806
807     p_demux_track->p_es->i_type = UNKNOWN_ES;
808     p_demux_track->p_es->i_cat = p_demux_track->i_cat;
809
810     /* search for the codec */
811     if( !MP4_GetCodec( p_sample->i_type, &i_codec, &psz_name ) )
812     {
813         msg_Warn( p_input, "%s (%c%c%c%c) unsupported", 
814                   psz_name,
815                   (p_sample->i_type )&0xff,
816                   (p_sample->i_type >> 8)&0xff,
817                   (p_sample->i_type >> 16)&0xff,
818                   (p_sample->i_type >> 24)&0xff);
819         p_demux_track->b_ok = 0;
820         return;
821     }
822     else
823     {
824         p_demux_track->p_es->i_type = i_codec;
825         msg_Info( p_input, "%s supported(or a subpart)", psz_name );
826     }
827
828
829     /* now see if esds is present and if so create a data packet 
830         with decoder_specific_info  */
831     if( ( p_esds = MP4_FindBox( p_sample, FOURCC_esds ) )&&
832         ( p_esds->data.p_esds->es_descriptor.p_decConfigDescr ) )
833     {
834 #define es_descriptor p_esds->data.p_esds->es_descriptor
835         /* First update information based on i_objectTypeIndication */
836         switch( es_descriptor.p_decConfigDescr->i_objectTypeIndication )
837         {
838             case( 0x20 ):
839                 p_demux_track->p_es->i_type = MPEG4_VIDEO_ES;
840                 break;
841             case( 0x40):
842                 p_demux_track->p_es->i_type = UNKNOWN_ES; /* In fact AAC */
843                 break;
844             case( 0x60):
845             case( 0x61):
846             case( 0x62):
847             case( 0x63):
848             case( 0x64):
849             case( 0x65):
850                 p_demux_track->p_es->i_type = MPEG2_VIDEO_ES;
851                 break;
852             /* Theses are MPEG2-AAC */
853             case( 0x66): /* main profile */
854             case( 0x67): /* Low complexity profile */
855             case( 0x68): /* Scaleable Sampling rate profile */
856                 p_demux_track->p_es->i_type = UNKNOWN_ES; 
857                 break;
858             /* true MPEG 2 audio */
859             case( 0x69): 
860                 p_demux_track->p_es->i_type = MPEG2_AUDIO_ES;
861                 break;
862             case( 0x6a):
863                 p_demux_track->p_es->i_type = MPEG1_VIDEO_ES;
864                 break;
865             case( 0x6b):
866                 p_demux_track->p_es->i_type = MPEG1_AUDIO_ES;
867                 break;
868             case( 0x6c ):
869                 p_demux_track->p_es->i_type = UNKNOWN_ES; /* in fact jpeg */
870                 break;
871             default:
872                 /* Unknown entry, don't touch i_type */
873                 msg_Warn( p_input, "objectTypeIndication(0x%x) unknow",
874                       es_descriptor.p_decConfigDescr->i_objectTypeIndication );
875                 break;
876         }
877
878         /* Create a packet to init the decoder, send with the first frame */
879         if( ( es_descriptor.p_decConfigDescr->i_decoder_specific_info_len )&&
880             ( p_demux_track->p_es->i_type != UNKNOWN_ES ) )
881         {
882             data_packet_t *p_data;
883             int i_size = 
884             
885             i_size = 
886                 es_descriptor.p_decConfigDescr->i_decoder_specific_info_len;
887     
888             /* data packet for the data */
889             if( !(p_data = input_NewPacket( p_input->p_method_data, i_size ) ) )
890             {
891                 return;
892             }
893
894             memcpy( p_data->p_payload_start,
895                     es_descriptor.p_decConfigDescr->p_decoder_specific_info,
896                     i_size ); 
897             p_demux_track->p_data_init = p_data;
898         }
899
900 #undef es_descriptor
901     }
902
903     if( p_demux_track->p_es->i_type == UNKNOWN_ES )
904     {
905         msg_Warn( p_input, "SampleEntry in fact not supported" );
906         p_demux_track->b_ok = 0;
907         return;
908     }
909
910     /* some last initialisation */
911     switch( p_demux_track->i_cat )
912     {
913         case( VIDEO_ES ):    
914             p_demux_track->p_es->b_audio = 0;
915
916             /* now create a bitmapinfoheader_t for decoder */
917             p_bmih = malloc( 40 );
918             memset( p_bmih, 0, 40);
919             MP4_Set4BytesLE( p_bmih, 40 );
920             if( p_sample->data.p_sample_mp4v->i_width )
921             {
922                 MP4_Set4BytesLE( p_bmih + 4, 
923                                  p_sample->data.p_sample_mp4v->i_width );
924             }
925             else
926             {
927                 /* use display size */
928                 MP4_Set4BytesLE( p_bmih + 4, p_demux_track->i_width );
929             }
930             if( p_sample->data.p_sample_mp4v->i_height )
931             {
932                 MP4_Set4BytesLE( p_bmih + 8, 
933                                  p_sample->data.p_sample_mp4v->i_height );
934             }
935             else
936             {
937                 MP4_Set4BytesLE( p_bmih + 8, p_demux_track->i_height );
938             }
939
940             p_demux_track->p_es->p_demux_data = p_bmih;
941             break;
942         case( AUDIO_ES ):
943             p_demux_track->p_es->b_audio = 1;
944             break;
945         default:
946             break;
947     }
948
949
950     vlc_mutex_lock( &p_input->stream.stream_lock );
951     input_SelectES( p_input, p_demux_track->p_es );
952     vlc_mutex_unlock( &p_input->stream.stream_lock );
953
954     p_demux_track->b_ok = 1;
955 }
956
957
958 static void MP4_StopDecoder( input_thread_t *p_input,
959                              track_data_mp4_t *p_demux_track )
960 {
961     msg_Dbg( p_input, "Stopping decoder (track ID 0x%x)",
962                       p_demux_track->i_track_ID );
963
964     input_UnselectES( p_input, p_demux_track->p_es );
965     p_demux_track->p_es = NULL;
966     if( p_demux_track->p_data_init )
967     {
968         input_DeletePacket( p_input->p_method_data, 
969                             p_demux_track->p_data_init );
970         p_demux_track->p_data_init = NULL;
971     }
972     
973 }
974
975 static int  MP4_ReadSample( input_thread_t *p_input,
976                             track_data_mp4_t *p_demux_track,
977                             pes_packet_t **pp_pes )
978 {
979     int i_size;
980     off_t i_pos;
981
982     data_packet_t *p_data;
983
984
985     /* this track have already reach the end */
986     if( p_demux_track->i_sample >= p_demux_track->i_sample_count )
987     {
988         *pp_pes = NULL;
989         return( 0 );
990     }
991     /* caculate size and position for this sample */
992     i_size = p_demux_track->i_sample_size ? 
993         p_demux_track->i_sample_size : p_demux_track->p_sample_size[p_demux_track->i_sample];
994     /* TODO */
995     i_pos  = MP4_GetTrackPos( p_demux_track );
996
997     /* go,go go ! */
998     if( ! MP4_SeekAbsolute( p_input, i_pos ) )
999     {
1000         return( 0 );
1001     }
1002
1003     /* now create a pes */
1004     if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
1005     {
1006         return( 0 );
1007     }
1008     /* and a data packet for the data */
1009     if( !(p_data = input_NewPacket( p_input->p_method_data, i_size ) ) )
1010     {
1011         input_DeletePES( p_input->p_method_data, *pp_pes );
1012         *pp_pes = NULL;
1013         return( 0 );
1014     }
1015     
1016     /* initialisation of all the field */
1017     (*pp_pes)->i_dts =
1018         (*pp_pes)->i_pts = MP4_GetTrackPTS( p_demux_track );
1019     (*pp_pes)->p_first = (*pp_pes)->p_last  = p_data;
1020     (*pp_pes)->i_nb_data = 1;
1021     (*pp_pes)->i_pes_size = i_size;
1022
1023     if( !i_size )    
1024     {
1025         return( 1 );
1026     }
1027     
1028 //    msg_Dbg( p_input, "will read %d bytes", i_size );
1029     if( !MP4_ReadData( p_input, p_data->p_payload_start, i_size ) )
1030     {
1031         input_DeletePES( p_input->p_method_data, *pp_pes );
1032         input_DeletePacket( p_input->p_method_data, p_data );
1033         return( 0 );
1034     }
1035
1036         return( 1 );
1037 }
1038
1039
1040 static int  MP4_DecodeSample( input_thread_t *p_input,
1041                               track_data_mp4_t *p_demux_track,
1042                               pes_packet_t *p_pes )
1043 {
1044
1045     if( !p_pes )
1046     {
1047         return( 0 );
1048     }
1049
1050     /* don't forget to convert in mpeg clock */
1051     /* FIXME correct ffmpeg to use dts instead of pts that it incorrect 
1052        and, set it here ( and correct avi demux ) */
1053     p_pes->i_dts =
1054         p_pes->i_pts = input_ClockGetTS( p_input,
1055                                          p_input->stream.p_selected_program,
1056                                          p_pes->i_pts * 9/100);
1057
1058     
1059     if( p_demux_track->p_data_init )
1060     {
1061         pes_packet_t *p_pes_init;
1062         /* create a pes packet containing decoder initialisation 
1063            with the one we will send to decoder */
1064         if( !(p_pes_init = input_NewPES( p_input->p_method_data ) ) )
1065         {
1066             msg_Err( p_input, "out of memory" );
1067             return( 0 );
1068         }
1069         
1070         p_pes_init->p_first = 
1071             p_pes_init->p_last = p_demux_track->p_data_init;
1072
1073         p_pes_init->i_pes_size = p_demux_track->p_data_init->p_payload_end - 
1074                                    p_demux_track->p_data_init->p_payload_start;
1075         p_pes_init->i_nb_data = 1;
1076
1077         input_DecodePES( p_demux_track->p_es->p_decoder_fifo, p_pes_init );
1078         p_demux_track->p_data_init = NULL;
1079     }
1080
1081     input_DecodePES( p_demux_track->p_es->p_decoder_fifo, p_pes );
1082     
1083     /* now update sample position */
1084     p_demux_track->i_sample++; /* easy ;) */
1085     if( p_demux_track->i_sample >= p_demux_track->i_sample_count )
1086     {
1087         /* we have reach end of the track so free decoder stuff */
1088         MP4_StopDecoder( p_input, p_demux_track );
1089         return( 1 );
1090     }
1091     /* Have we changed chunk ? */
1092     if( p_demux_track->i_sample >=
1093             p_demux_track->chunk[p_demux_track->i_chunk].i_sample_first +
1094                 p_demux_track->chunk[p_demux_track->i_chunk].i_sample_count )
1095     {
1096         /* we haven't reached the end of the track, so see if we 
1097            have to change the decoder for the next frame because 
1098            i_sample_description_index have changed */
1099
1100         p_demux_track->i_chunk++;
1101         if( p_demux_track->chunk[p_demux_track->i_chunk-1].i_sample_description_index 
1102               != p_demux_track->chunk[p_demux_track->i_chunk].i_sample_description_index  )
1103         {
1104             /* FIXME */
1105             msg_Err( p_input, "I need to change the decoder but not yet implemented" );
1106             return( 0 );
1107         }
1108     }
1109
1110     
1111     return( 1 );
1112 }
1113
1114
1115