366ce71a53bc077f8b6cb78ccabf5b3b63162d4c
[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.5 2002/07/23 00:39:17 sam 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     MP4_Box_t *p_esds;
760
761     
762     if( (!p_demux_track->b_ok )||( p_demux_track->i_cat == UNKNOWN_ES ) )
763     {
764         return;
765     }
766     
767     msg_Dbg( p_input, "Starting decoder (track ID 0x%x)",
768                       p_demux_track->i_track_ID );
769
770     /* launch decoder according in chunk we are */
771     i_chunk = p_demux_track->i_chunk;
772
773     if( !p_demux_track->chunk[i_chunk].i_sample_description_index )
774     {
775         msg_Warn( p_input, "invalid SampleEntry index for this track i_cat %d" );
776         return;
777     } 
778     
779     p_sample = MP4_FindNbBox( p_demux_track->p_stsd,
780                               p_demux_track->chunk[i_chunk].i_sample_description_index - 1);
781
782     if( !p_sample )
783     {
784         msg_Warn( p_input, "cannot find SampleEntry for this track" );
785         return;
786     }
787
788     
789     vlc_mutex_lock( &p_input->stream.stream_lock );
790     p_demux_track->p_es = input_AddES( p_input,
791                                        p_input->stream.p_selected_program, 
792                                        p_demux_track->i_track_ID,
793                                        0 );
794     vlc_mutex_unlock( &p_input->stream.stream_lock );
795     /* Initialise ES, first language as description */
796     for( i = 0; i < 3; i++ )
797     {
798         p_demux_track->p_es->psz_desc[i] = p_demux_track->i_language[i];
799     }
800     p_demux_track->p_es->psz_desc[4] = 0;
801     
802     p_demux_track->p_es->i_stream_id = p_demux_track->i_track_ID;
803
804     p_demux_track->p_es->i_fourcc = p_sample->i_type;
805     p_demux_track->p_es->i_cat = p_demux_track->i_cat;
806
807     /* now see if esds is present and if so create a data packet 
808         with decoder_specific_info  */
809 #define p_decconfig p_esds->data.p_esds->es_descriptor.p_decConfigDescr
810     if( ( p_esds = MP4_FindBox( p_sample, FOURCC_esds ) )
811          && p_decconfig && p_decconfig->i_decoder_specific_info_len )
812     {
813         data_packet_t *p_data;
814         int i_size = p_decconfig->i_decoder_specific_info_len;
815
816         /* data packet for the data */
817         if( !(p_data = input_NewPacket( p_input->p_method_data, i_size ) ) )
818         {
819             return;
820         }
821
822         memcpy( p_data->p_payload_start,
823                 p_decconfig->p_decoder_specific_info,
824                 i_size ); 
825         p_demux_track->p_data_init = p_data;
826     }
827 #undef p_decconfig
828
829     /* some last initialisation */
830     switch( p_demux_track->i_cat )
831     {
832         case( VIDEO_ES ):    
833             /* now create a bitmapinfoheader_t for decoder */
834             p_bmih = malloc( 40 );
835             memset( p_bmih, 0, 40);
836             MP4_Set4BytesLE( p_bmih, 40 );
837             if( p_sample->data.p_sample_mp4v
838                  && p_sample->data.p_sample_mp4v->i_width )
839             {
840                 MP4_Set4BytesLE( p_bmih + 4, 
841                                  p_sample->data.p_sample_mp4v->i_width );
842             }
843             else
844             {
845                 /* use display size */
846                 MP4_Set4BytesLE( p_bmih + 4, p_demux_track->i_width );
847             }
848             if( p_sample->data.p_sample_mp4v
849                  && p_sample->data.p_sample_mp4v->i_height )
850             {
851                 MP4_Set4BytesLE( p_bmih + 8, 
852                                  p_sample->data.p_sample_mp4v->i_height );
853             }
854             else
855             {
856                 MP4_Set4BytesLE( p_bmih + 8, p_demux_track->i_height );
857             }
858
859             p_demux_track->p_es->p_demux_data = p_bmih;
860             break;
861         case( AUDIO_ES ):
862             break;
863         default:
864             break;
865     }
866
867
868     vlc_mutex_lock( &p_input->stream.stream_lock );
869     input_SelectES( p_input, p_demux_track->p_es );
870     vlc_mutex_unlock( &p_input->stream.stream_lock );
871
872     p_demux_track->b_ok = 1;
873 }
874
875
876 static void MP4_StopDecoder( input_thread_t *p_input,
877                              track_data_mp4_t *p_demux_track )
878 {
879     msg_Dbg( p_input, "Stopping decoder (track ID 0x%x)",
880                       p_demux_track->i_track_ID );
881
882     input_UnselectES( p_input, p_demux_track->p_es );
883     p_demux_track->p_es = NULL;
884     if( p_demux_track->p_data_init )
885     {
886         input_DeletePacket( p_input->p_method_data, 
887                             p_demux_track->p_data_init );
888         p_demux_track->p_data_init = NULL;
889     }
890     
891 }
892
893 static int  MP4_ReadSample( input_thread_t *p_input,
894                             track_data_mp4_t *p_demux_track,
895                             pes_packet_t **pp_pes )
896 {
897     int i_size;
898     off_t i_pos;
899
900     data_packet_t *p_data;
901
902
903     /* this track have already reach the end */
904     if( p_demux_track->i_sample >= p_demux_track->i_sample_count )
905     {
906         *pp_pes = NULL;
907         return( 0 );
908     }
909     /* caculate size and position for this sample */
910     i_size = p_demux_track->i_sample_size ? 
911         p_demux_track->i_sample_size : p_demux_track->p_sample_size[p_demux_track->i_sample];
912     /* TODO */
913     i_pos  = MP4_GetTrackPos( p_demux_track );
914
915     /* go,go go ! */
916     if( ! MP4_SeekAbsolute( p_input, i_pos ) )
917     {
918         return( 0 );
919     }
920
921     /* now create a pes */
922     if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
923     {
924         return( 0 );
925     }
926     /* and a data packet for the data */
927     if( !(p_data = input_NewPacket( p_input->p_method_data, i_size ) ) )
928     {
929         input_DeletePES( p_input->p_method_data, *pp_pes );
930         *pp_pes = NULL;
931         return( 0 );
932     }
933     
934     /* initialisation of all the field */
935     (*pp_pes)->i_dts =
936         (*pp_pes)->i_pts = MP4_GetTrackPTS( p_demux_track );
937     (*pp_pes)->p_first = (*pp_pes)->p_last  = p_data;
938     (*pp_pes)->i_nb_data = 1;
939     (*pp_pes)->i_pes_size = i_size;
940
941     if( !i_size )    
942     {
943         return( 1 );
944     }
945     
946 //    msg_Dbg( p_input, "will read %d bytes", i_size );
947     if( !MP4_ReadData( p_input, p_data->p_payload_start, i_size ) )
948     {
949         input_DeletePES( p_input->p_method_data, *pp_pes );
950         input_DeletePacket( p_input->p_method_data, p_data );
951         return( 0 );
952     }
953
954         return( 1 );
955 }
956
957
958 static int  MP4_DecodeSample( input_thread_t *p_input,
959                               track_data_mp4_t *p_demux_track,
960                               pes_packet_t *p_pes )
961 {
962
963     if( !p_pes )
964     {
965         return( 0 );
966     }
967
968     /* don't forget to convert in mpeg clock */
969     /* FIXME correct ffmpeg to use dts instead of pts that it incorrect 
970        and, set it here ( and correct avi demux ) */
971     p_pes->i_dts =
972         p_pes->i_pts = input_ClockGetTS( p_input,
973                                          p_input->stream.p_selected_program,
974                                          p_pes->i_pts * 9/100);
975
976     
977     if( p_demux_track->p_data_init )
978     {
979         pes_packet_t *p_pes_init;
980         /* create a pes packet containing decoder initialisation 
981            with the one we will send to decoder */
982         if( !(p_pes_init = input_NewPES( p_input->p_method_data ) ) )
983         {
984             msg_Err( p_input, "out of memory" );
985             return( 0 );
986         }
987         
988         p_pes_init->p_first = 
989             p_pes_init->p_last = p_demux_track->p_data_init;
990
991         p_pes_init->i_pes_size = p_demux_track->p_data_init->p_payload_end - 
992                                    p_demux_track->p_data_init->p_payload_start;
993         p_pes_init->i_nb_data = 1;
994
995         input_DecodePES( p_demux_track->p_es->p_decoder_fifo, p_pes_init );
996         p_demux_track->p_data_init = NULL;
997     }
998
999     input_DecodePES( p_demux_track->p_es->p_decoder_fifo, p_pes );
1000     
1001     /* now update sample position */
1002     p_demux_track->i_sample++; /* easy ;) */
1003     if( p_demux_track->i_sample >= p_demux_track->i_sample_count )
1004     {
1005         /* we have reach end of the track so free decoder stuff */
1006         MP4_StopDecoder( p_input, p_demux_track );
1007         return( 1 );
1008     }
1009     /* Have we changed chunk ? */
1010     if( p_demux_track->i_sample >=
1011             p_demux_track->chunk[p_demux_track->i_chunk].i_sample_first +
1012                 p_demux_track->chunk[p_demux_track->i_chunk].i_sample_count )
1013     {
1014         /* we haven't reached the end of the track, so see if we 
1015            have to change the decoder for the next frame because 
1016            i_sample_description_index have changed */
1017
1018         p_demux_track->i_chunk++;
1019         if( p_demux_track->chunk[p_demux_track->i_chunk-1].i_sample_description_index 
1020               != p_demux_track->chunk[p_demux_track->i_chunk].i_sample_description_index  )
1021         {
1022             /* FIXME */
1023             msg_Err( p_input, "I need to change the decoder but not yet implemented" );
1024             return( 0 );
1025         }
1026     }
1027
1028     
1029     return( 1 );
1030 }
1031
1032
1033