* mp4: prevent float exeption with some truncated file.
[vlc.git] / modules / demux / 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.7 2002/11/26 17:28:22 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 #include "codecs.h"
34 #include "libmp4.h"
35 #include "mp4.h"
36
37 /*****************************************************************************
38  * Local prototypes
39  *****************************************************************************/
40 static int    MP4Init    ( vlc_object_t * );
41 static void __MP4End     ( vlc_object_t * );
42 static int    MP4Demux   ( input_thread_t * );
43
44 /* New input could have something like that... */
45 static int   MP4Seek     ( input_thread_t *, mtime_t );
46
47 #define MP4End(a) __MP4End(VLC_OBJECT(a))
48
49 /*****************************************************************************
50  * Module descriptor
51  *****************************************************************************/
52 vlc_module_begin();
53     set_description( "MP4 demuxer" );
54     set_capability( "demux", 242 );
55     set_callbacks( MP4Init, __MP4End );
56 vlc_module_end();
57
58 /*****************************************************************************
59  * Declaration of local function 
60  *****************************************************************************/
61
62 static int MP4_TrackSynchro( input_thread_t *p_input, track_data_mp4_t *p_track );
63
64 static void MP4_ParseTrack();
65
66 static int MP4_CreateChunksIndex();
67 static int MP4_CreateSamplesIndex();
68
69 static void MP4_StartDecoder();
70 static void MP4_StopDecoder();
71
72 static int  MP4_ReadSample();
73 static int  MP4_DecodeSample();
74
75 #define MP4_Set4BytesLE( p, dw ) \
76     *((uint8_t*)p)   = ( (dw)&0xff ); \
77     *((uint8_t*)p+1) = ( ((dw)>> 8)&0xff ); \
78     *((uint8_t*)p+2) = ( ((dw)>>16)&0xff ); \
79     *((uint8_t*)p+3) = ( ((dw)>>24)&0xff )
80
81 #define MP4_Set2BytesLE( p, dw ) \
82     *((uint8_t*)p) = ( (dw)&0xff ); \
83     *((uint8_t*)p+1) = ( ((dw)>> 8)&0xff )
84
85     
86 /*****************************************************************************
87  * MP4Init: check file and initializes MP4 structures
88  *****************************************************************************/
89 static int MP4Init( vlc_object_t * p_this )
90 {   
91     input_thread_t  *p_input = (input_thread_t *)p_this;
92     uint8_t         *p_peek;
93     uint32_t        i_type;
94     
95     demux_sys_t     *p_demux;
96     
97     MP4_Box_t       *p_ftyp;
98
99
100     MP4_Box_t       *p_mvhd;
101     MP4_Box_t       *p_trak;
102
103     int             i;
104     /* I need to seek */
105     if( !p_input->stream.b_seekable )
106     {
107         msg_Warn( p_input, "MP4 plugin discarded (unseekable)" );
108         return( -1 );
109             
110     } 
111     /* Initialize access plug-in structures. */
112     if( p_input->i_mtu == 0 )
113     {
114         /* Improve speed. */
115         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE ;
116     }
117
118     p_input->pf_demux = MP4Demux;
119
120     /* a little test to see if it could be a mp4 */
121     if( input_Peek( p_input, &p_peek, 8 ) < 8 )
122     {
123         msg_Warn( p_input, "MP4 plugin discarded (cannot peek)" );
124         return( -1 );
125     }
126     i_type = ( p_peek[4] ) + ( p_peek[5] << 8 ) +
127                 ( p_peek[6] << 16 ) + ( p_peek[7] << 24);
128     switch( i_type )
129     {
130         case( FOURCC_ftyp ):
131         case( FOURCC_moov ):
132         case( FOURCC_moof ):
133         case( FOURCC_mdat ):
134         case( FOURCC_udta ): 
135         case( FOURCC_free ):
136         case( FOURCC_skip ):
137         case( FOURCC_wide ): 
138             break;
139          default:
140             msg_Warn( p_input, "MP4 plugin discarded (not a valid file)" );
141             return( -1 );
142     }
143
144     /* create our structure that will contains all data */
145     if( !( p_input->p_demux_data = 
146                 p_demux = malloc( sizeof( demux_sys_t ) ) ) )
147     {
148         msg_Err( p_input, "out of memory" );
149         return( -1 );
150     }
151     memset( p_demux, 0, sizeof( demux_sys_t ) );
152     p_input->p_demux_data = p_demux;
153        
154
155     /* Now load all boxes ( except raw data ) */
156     if( !MP4_BoxGetRoot( p_input, &p_demux->box_root ) )
157     {
158         msg_Warn( p_input, "MP4 plugin discarded (not a valid file)" );
159         return( -1 );
160     }
161
162     MP4_BoxDumpStructure( p_input, &p_demux->box_root );
163
164     if( ( p_ftyp = MP4_BoxGet( &p_demux->box_root, "/ftyp" ) ) )
165     {
166         switch( p_ftyp->data.p_ftyp->i_major_brand )
167         {
168             case( FOURCC_isom ):
169                 msg_Info( p_input, 
170                           "ISO Media file (isom) version %d.",
171                           p_ftyp->data.p_ftyp->i_minor_version );
172                 break;
173             default:
174                 msg_Info( p_input,
175                           "Unrecognize major file specification (%c%c%c%c).",
176                            p_ftyp->data.p_ftyp->i_major_brand&0xff,
177                            ( p_ftyp->data.p_ftyp->i_major_brand >>  8)&0xff,
178                            ( p_ftyp->data.p_ftyp->i_major_brand >> 16 )&0xff,
179                            ( p_ftyp->data.p_ftyp->i_major_brand >> 24 )&0xff );
180                 break;
181         }
182     }
183     else
184     {
185         msg_Info( p_input, "File Type box missing(assume ISO Media file)" );
186     }
187
188     /* the file need to have one moov box */
189     if( MP4_BoxCount( &p_demux->box_root, "/moov" ) != 1 )
190     {
191         msg_Err( p_input, 
192                  "MP4 plugin discarded (%d moov box)",
193                  MP4_BoxCount( &p_demux->box_root, "/moov" ) );
194         MP4End( p_input );
195         return( -1 );
196     }
197
198     if( !(p_mvhd = MP4_BoxGet( &p_demux->box_root, "/moov/mvhd" ) ) )
199     {
200         msg_Err( p_input, "cannot find /moov/mvhd !" );
201         MP4End( p_input );
202         return( -1 );
203     }
204     else
205     {
206         p_demux->i_timescale = p_mvhd->data.p_mvhd->i_timescale;
207         p_demux->i_duration = p_mvhd->data.p_mvhd->i_duration;
208     }
209     
210     if( !( p_demux->i_tracks = 
211                 MP4_BoxCount( &p_demux->box_root, "/moov/trak" ) ) )
212     {
213         msg_Err( p_input, "cannot find any /moov/trak !" );
214         MP4End( p_input );
215         return( -1 );
216     }
217     msg_Dbg( p_input, "find %d track%c",
218                         p_demux->i_tracks,
219                         p_demux->i_tracks ? 's':' ' );
220
221     /* allocate memory */
222     p_demux->track = calloc( p_demux->i_tracks, sizeof( track_data_mp4_t ) );
223
224     /* now process each track and extract all usefull informations */
225     for( i = 0; i < p_demux->i_tracks; i++ )
226     {
227         p_trak = MP4_BoxGet( &p_demux->box_root, "/moov/trak[%d]", i );
228         MP4_ParseTrack( p_input, &p_demux->track[i], p_trak );
229
230         if( p_demux->track[i].b_ok )
231         {
232             char *psz_cat;
233             switch( p_demux->track[i].i_cat )
234             {
235                 case( VIDEO_ES ):
236                     psz_cat = "video";
237                     break;
238                 case( AUDIO_ES ):
239                     psz_cat = "audio";
240                     break;
241                 default:
242                     psz_cat = "unknown";
243                     break;
244             }
245             
246             msg_Dbg( p_input, "adding track[Id 0x%x] %s (%s) language %c%c%c",
247                             p_demux->track[i].i_track_ID,
248                             psz_cat,
249                             p_demux->track[i].b_enable ? "enable":"disable",
250                             p_demux->track[i].i_language[0],
251                             p_demux->track[i].i_language[1], 
252                             p_demux->track[i].i_language[2] );
253         }
254         else
255         {
256             msg_Dbg( p_input, "ignoring track[Id 0x%x]", p_demux->track[i].i_track_ID );
257         }
258
259     }
260   
261     /*  create one program */
262     vlc_mutex_lock( &p_input->stream.stream_lock );
263     if( input_InitStream( p_input, 0 ) == -1)
264     {
265         vlc_mutex_unlock( &p_input->stream.stream_lock );
266         msg_Err( p_input, "cannot init stream" );
267         MP4End( p_input );
268         return( -1 );
269     }
270     if( input_AddProgram( p_input, 0, 0) == NULL )
271     {
272         vlc_mutex_unlock( &p_input->stream.stream_lock );
273         msg_Err( p_input, "cannot add program" );
274         MP4End( p_input );
275         return( -1 );
276     }
277     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
278     /* XXX beurk and beurk, see MP4Demux and MP4Seek */
279     if( p_demux->i_duration/p_demux->i_timescale > 0 )
280     {
281         p_input->stream.i_mux_rate =  
282             p_input->stream.p_selected_area->i_size / 50 / 
283             ( p_demux->i_duration / p_demux->i_timescale );
284     }
285     else
286     {
287         p_input->stream.i_mux_rate = 0;
288     }
289     vlc_mutex_unlock( &p_input->stream.stream_lock );
290    
291     
292     for( i = 0; i < p_demux->i_tracks; i++ )
293     {
294         /* start decoder for this track if enable by default*/
295         if( p_demux->track[i].b_enable )
296         {
297             MP4_StartDecoder( p_input, &p_demux->track[i] );
298         }
299     }
300
301     vlc_mutex_lock( &p_input->stream.stream_lock );
302     p_input->stream.p_selected_program->b_is_ok = 1;
303     vlc_mutex_unlock( &p_input->stream.stream_lock );
304         
305     return( 0 );    
306
307 }
308
309 /*****************************************************************************
310  * MP4Demux: read packet and send them to decoders 
311  *****************************************************************************
312  * TODO check for newly selected track (ie audio upt to now )
313  *****************************************************************************/
314 static int MP4Demux( input_thread_t *p_input )
315 {
316     demux_sys_t *p_demux = p_input->p_demux_data;
317     int i_track;
318
319     /* XXX beurk, beuRK and BEURK, 
320        but only way I've found to detect seek from interface */
321     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
322     {
323         mtime_t i_date;
324         
325         /* first wait for empty buffer, arbitrary time FIXME */
326         msleep( DEFAULT_PTS_DELAY );
327         /* *** calculate new date *** */
328
329         i_date = (mtime_t)1000000 * 
330                  (mtime_t)p_demux->i_duration /
331                  (mtime_t)p_demux->i_timescale * 
332                  (mtime_t)MP4_TellAbsolute( p_input ) /
333                  (mtime_t)p_input->stream.p_selected_area->i_size;
334         MP4Seek( p_input, i_date );
335     }
336     
337     /* first wait for the good time to read a packet */
338     input_ClockManageRef( p_input,
339                           p_input->stream.p_selected_program,
340                           p_demux->i_pcr );
341
342
343     /* update pcr XXX in mpeg scale so in 90000 unit/s */
344     p_demux->i_pcr = MP4_GetMoviePTS( p_demux ) * 9 / 100;
345     
346
347     /* we will read 100ms for each stream so ...*/
348     p_demux->i_time += __MAX( p_demux->i_timescale / 10 , 1 );
349     
350
351     for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
352     {
353         if( ( !p_demux->track[i_track].b_ok )||
354             ( !p_demux->track[i_track].p_es )||
355             ( !p_demux->track[i_track].p_es->p_decoder_fifo )||
356             ( MP4_GetTrackPTS( &p_demux->track[i_track] ) >=
357                         MP4_GetMoviePTS( p_demux ) ) )
358         {
359             continue; /* no need to read something */
360         }
361         while( MP4_GetTrackPTS( &p_demux->track[i_track] ) <
362                         MP4_GetMoviePTS( p_demux ) )
363         {
364
365             pes_packet_t *p_pes;
366
367             /* read a sample */
368             if( !MP4_ReadSample( p_input ,
369                                  &p_demux->track[i_track],
370                                  &p_pes ) )
371             {
372                 break;
373             }
374
375             /* send it to decoder and update time of this track 
376                  it also launch a new decoder if needed */
377             MP4_DecodeSample( p_input ,
378                               &p_demux->track[i_track],
379                               p_pes );
380         }
381
382     }
383     
384     /* now check if all tracks are finished or unhandled*/
385     
386     for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
387     {
388         if( ( p_demux->track[i_track].b_ok )&&
389             ( p_demux->track[i_track].i_sample < p_demux->track[i_track].i_sample_count )&&
390             ( p_demux->track[i_track].p_es )&&
391             ( p_demux->track[i_track].p_es->p_decoder_fifo ) )
392         {
393             return( 1 );
394         }
395     }
396
397     return( 0 ); /* EOF */
398 }
399 /*****************************************************************************
400  * MP4Seek: Got to i_date
401  ******************************************************************************/
402 static int   MP4Seek     ( input_thread_t *p_input, mtime_t i_date )
403 {
404     demux_sys_t *p_demux = p_input->p_demux_data;
405     int i_track;
406
407     /* First update update global time */
408     p_demux->i_time = i_date * p_demux->i_timescale / 1000000;
409     p_demux->i_pcr = __MAX( MP4_GetMoviePTS( p_demux ) - DEFAULT_PTS_DELAY,
410                             0 ) * 9 / 100; 
411     
412     /* Now for each stream try to go to this time */
413     for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
414     {
415         MP4_TrackSynchro( p_input, &p_demux->track[i_track] );
416     }
417     return( 1 );
418 }
419
420 /*****************************************************************************
421  * MP4End: frees unused data
422  *****************************************************************************/
423 static void __MP4End ( vlc_object_t * p_this )
424 {   
425 #define FREE( p ) \
426     if( p ) { free( p ); } 
427     int i_track;
428     input_thread_t *  p_input = (input_thread_t *)p_this;
429     demux_sys_t *p_demux = p_input->p_demux_data;
430     
431     msg_Dbg( p_input, "Freeing all memory" );
432     MP4_BoxFree( p_input, &p_demux->box_root );
433     for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
434     {
435         int i_chunk;
436         for( i_chunk = 0; 
437                 i_chunk < p_demux->track[i_track].i_chunk_count; i_chunk++ )
438         {
439             if( p_demux->track[i_track].chunk )
440             {
441                FREE(p_demux->track[i_track].chunk[i_chunk].p_sample_count_dts);
442                FREE(p_demux->track[i_track].chunk[i_chunk].p_sample_delta_dts );
443             }
444         }
445
446         if( !p_demux->track[i_track].i_sample_size )
447         {
448             FREE( p_demux->track[i_track].p_sample_size );
449         }
450     }
451     FREE( p_demux->track );
452 #undef FREE
453 }
454
455
456 /****************************************************************************
457  * Local functions, specific to vlc
458  ****************************************************************************/
459
460 /****************************************************************************
461  * MP4_TrackSynchro : synchronize a track with movie time after seek or 
462  *                    for newly selected track
463  *****************************************************************************
464  * TODO add support of Edit List (edts/elts) and Shadow Sync Sample(stsh)
465  ****************************************************************************/
466 static int MP4_TrackSynchro( input_thread_t *p_input, track_data_mp4_t *p_track )
467 {
468     demux_sys_t *p_demux = p_input->p_demux_data;
469     int i_chunk_last;
470     MP4_Box_t   *p_stss;
471
472     if( !p_track->b_ok ||
473         !p_track->p_es ||
474         !p_track->p_es->p_decoder_fifo )
475     {
476         return( 0 );
477     }
478     p_track->i_sample = 0;
479     i_chunk_last = p_track->i_chunk;
480     p_track->i_chunk = 0;
481     for( ;; )
482     {
483         if( p_track->i_sample >= p_track->i_sample_count )
484         {
485             msg_Warn( p_input, 
486                         "track[Id 0x%x] will be disabled (seeking too far)",
487                         p_track->i_track_ID );
488             MP4_StopDecoder( p_input, p_track );
489             break;
490         }
491         if( MP4_GetTrackPTS( p_track ) >= MP4_GetMoviePTS( p_demux ) )
492         {
493             break;
494         }
495         /* go one sample after */
496         p_track->i_sample++;
497         if( p_track->i_sample >= p_track->chunk[p_track->i_chunk].i_sample_first +
498                 p_track->chunk[p_track->i_chunk].i_sample_count )
499         {
500             p_track->i_chunk++;
501         }
502         
503     }
504     if( p_track->i_sample >= p_track->i_sample_count )
505     {
506         return( 0 );
507     }
508
509     /* *** Try to find nearest sync points *** */
510     if( ( p_stss = MP4_BoxGet( p_track->p_stbl, "stss" ) ) )
511     {
512         int i_index;
513         msg_Dbg( p_input, 
514                     "track[Id 0x%x] using Sync Sample Box (stss)", 
515                     p_track->i_track_ID );
516         for( i_index = 0; i_index < p_stss->data.p_stss->i_entry_count; i_index++ )
517         {
518             if( p_stss->data.p_stss->i_sample_number[i_index] >= p_track->i_sample )
519             {
520                 if( i_index > 0 )
521                 {
522                     msg_Dbg( p_input, "stts gives %d --> %d (sample number)", 
523                             p_track->i_sample, 
524                             p_stss->data.p_stss->i_sample_number[i_index-1] );
525                     p_track->i_sample = p_stss->data.p_stss->i_sample_number[i_index-1];
526                     /* new track.i_sample is less than old so i_chunk can only decreased */
527                     while( p_track->i_chunk > 0 && 
528                             p_track->i_sample < p_track->chunk[p_track->i_chunk].i_sample_first )
529                     {
530                         p_track->i_chunk--;
531                     }
532                 }
533                 else
534                 {
535                     msg_Dbg( p_input, "stts gives %d --> %d (sample number)", 
536                             p_track->i_sample, 
537                             p_stss->data.p_stss->i_sample_number[i_index-1] );
538                     p_track->i_sample = p_stss->data.p_stss->i_sample_number[i_index];
539                     /* new track.i_sample is more than old so i_chunk can only increased */
540                     while( p_track->i_chunk < p_track->i_chunk_count - 1 &&
541                            p_track->i_sample >= p_track->chunk[p_track->i_chunk].i_sample_first +
542                                                 p_track->chunk[p_track->i_chunk].i_sample_count )
543                     {
544                         p_track->i_chunk++;
545                     }
546                 }
547                 break;
548             }
549         }
550     }
551     else
552     {
553         msg_Dbg( p_input, 
554                     "track[Id 0x%x] doesn't provided Sync Sample Box (stss)", 
555                     p_track->i_track_ID );
556     }
557
558     /* *** If i_sample_description_index has changed restart decoder *** */
559     if( p_track->chunk[i_chunk_last].i_sample_description_index !=
560             p_track->chunk[p_track->i_chunk].i_sample_description_index )
561     {
562         msg_Warn( p_input,
563                 "SampleEntry has changed, restarting decoder" );
564         MP4_StopDecoder( p_input, p_track );
565         MP4_StartDecoder( p_input, p_track );
566     }
567     return( 1 );
568 }
569
570 /****************************************************************************
571  * Parse track information and create all needed data to run a track
572  * If it succeed b_ok is set to 1 else to 0
573  ****************************************************************************/
574 static void MP4_ParseTrack( input_thread_t *p_input,
575                      track_data_mp4_t *p_demux_track,
576                      MP4_Box_t  * p_trak )
577 {
578     int i;
579
580     MP4_Box_t *p_tkhd = MP4_BoxGet( p_trak, "tkhd" );
581     MP4_Box_t *p_tref = MP4_BoxGet( p_trak, "tref" );
582     MP4_Box_t *p_elst;
583
584     MP4_Box_t *p_mdhd;
585     MP4_Box_t *p_hdlr;
586
587     MP4_Box_t *p_vmhd;
588     MP4_Box_t *p_smhd; 
589
590     /* hint track unsuported */
591
592     /* by default, track isn't usable */
593     p_demux_track->b_ok = 0;
594
595     /* by default, we don't known the categorie */
596     p_demux_track->i_cat = UNKNOWN_ES;
597     
598     if( !p_tkhd )
599     {
600         return;
601     }
602
603     /* do we launch this track by default ? */
604     p_demux_track->b_enable = 
605         ( ( p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED ) != 0 );
606
607     p_demux_track->i_track_ID = p_tkhd->data.p_tkhd->i_track_ID;
608     p_demux_track->i_width = p_tkhd->data.p_tkhd->i_width / 65536;
609     p_demux_track->i_height = p_tkhd->data.p_tkhd->i_height / 65536;
610     
611     if( ( p_elst = MP4_BoxGet( p_trak, "edts/elst" ) ) )
612     {
613 /*        msg_Warn( p_input, "Unhandled box: edts --> FIXME" ); */
614     }
615
616     if( p_tref )
617     {
618 /*        msg_Warn( p_input, "Unhandled box: tref --> FIXME" ); */
619     } 
620
621     p_mdhd = MP4_BoxGet( p_trak, "mdia/mdhd" );
622     p_hdlr = MP4_BoxGet( p_trak, "mdia/hdlr" );
623     
624     if( ( !p_mdhd )||( !p_hdlr ) )
625     {
626         return;
627     }
628
629     p_demux_track->i_timescale = p_mdhd->data.p_mdhd->i_timescale;
630
631     for( i = 0; i < 3; i++ ) 
632     {
633         p_demux_track->i_language[i] = p_mdhd->data.p_mdhd->i_language[i];
634     }
635     p_mdhd->data.p_mdhd->i_language[3] = 0;
636     
637     switch( p_hdlr->data.p_hdlr->i_handler_type )
638     {
639         case( FOURCC_soun ):
640             if( !( p_smhd = MP4_BoxGet( p_trak, "mdia/minf/smhd" ) ) )
641             {
642                 return;
643             }
644             p_demux_track->i_cat = AUDIO_ES;
645             break;
646
647         case( FOURCC_vide ):
648             if( !( p_vmhd = MP4_BoxGet( p_trak, "mdia/minf/vmhd" ) ) )
649             {
650                 return;
651             }
652             p_demux_track->i_cat = VIDEO_ES;
653             break;
654             
655         default:
656             return;
657     }
658 /*  TODO
659     add support for:
660     p_dinf = MP4_BoxGet( p_minf, "dinf" );
661 */
662     if( !( p_demux_track->p_stbl = MP4_BoxGet( p_trak,"mdia/minf/stbl" ) ) )
663     {
664         return;
665     }
666     
667     if( !( p_demux_track->p_stsd = MP4_BoxGet( p_trak,"mdia/minf/stbl/stsd") ) )
668     {
669         return;
670     }
671     
672     /* Create chunk  index table */
673     if( !MP4_CreateChunksIndex( p_input,p_demux_track  ) )
674     {
675         return; /* cannot create chunks index */
676     }
677     
678     /* create sample index table needed for reading and seeking */
679     if( !MP4_CreateSamplesIndex( p_input, p_demux_track ) )
680     {
681         return; /* cannot create samples index */
682     }
683      
684     p_demux_track->b_ok = 1;        
685 }
686                      
687
688
689 /* now create basic chunk data, the rest will be filled by MP4_CreateSamplesIndex */
690 static int MP4_CreateChunksIndex( input_thread_t *p_input,
691                                    track_data_mp4_t *p_demux_track )
692 {
693     MP4_Box_t *p_co64; /* give offset for each chunk, same for stco and co64 */
694     MP4_Box_t *p_stsc;
695
696     int i_chunk;
697     int i_index, i_last;
698    
699
700     if( ( !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "stco" ) )&&
701           !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "co64" ) ) )|| 
702         ( !(p_stsc = MP4_BoxGet( p_demux_track->p_stbl, "stsc" ) ) ))
703     {
704         return( 0 );
705     }
706      
707     p_demux_track->i_chunk_count = p_co64->data.p_co64->i_entry_count;
708     if( !p_demux_track->i_chunk_count )
709     {
710         msg_Warn( p_input, "No chunk defined" );
711         return( 0 );
712     }
713     p_demux_track->chunk = calloc( p_demux_track->i_chunk_count, 
714                                    sizeof( chunk_data_mp4_t ) );
715
716     /* first we read chunk offset */
717     for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
718     {
719         p_demux_track->chunk[i_chunk].i_offset = 
720                 p_co64->data.p_co64->i_chunk_offset[i_chunk];
721     }
722
723     /* now we read index for SampleEntry( soun vide mp4a mp4v ...) 
724         to be used for the sample XXX begin to 1 
725         We construct it begining at the end */
726     i_last = p_demux_track->i_chunk_count; /* last chunk proceded */
727     i_index = p_stsc->data.p_stsc->i_entry_count;
728     if( !i_index )
729     {
730         msg_Warn( p_input, "cannot read chunk table or table empty" );
731         return( 0 );
732     }
733
734     while( i_index )
735     {
736         i_index--;
737         for( i_chunk = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
738                 i_chunk < i_last; i_chunk++ )
739         {
740             p_demux_track->chunk[i_chunk].i_sample_description_index = 
741                     p_stsc->data.p_stsc->i_sample_description_index[i_index];
742             p_demux_track->chunk[i_chunk].i_sample_count =
743                     p_stsc->data.p_stsc->i_samples_per_chunk[i_index];
744         }
745         i_last = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
746     }
747
748     p_demux_track->chunk[i_chunk].i_sample_first = 0;
749     for( i_chunk = 1; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
750     {
751         p_demux_track->chunk[i_chunk].i_sample_first =
752             p_demux_track->chunk[i_chunk-1].i_sample_first + 
753                 p_demux_track->chunk[i_chunk-1].i_sample_count;
754         
755     }
756     
757     msg_Dbg( p_input, 
758              "track[Id 0x%x] read %d chunk",
759              p_demux_track->i_track_ID,
760             p_demux_track->i_chunk_count );
761     return( 1 );
762
763 }
764
765
766
767 static int MP4_CreateSamplesIndex( input_thread_t *p_input,
768                                    track_data_mp4_t *p_demux_track )
769 {
770     MP4_Box_t *p_stts; /* makes mapping between sample and decoding time,
771                           ctts make same mapping but for composition time, 
772                           not yet used and probably not usefull */
773     MP4_Box_t *p_stsz; /* gives sample size of each samples, there is also stz2 
774                           that uses a compressed form FIXME make them in libmp4 
775                           as a unique type */
776     /* TODO use also stss and stsh table for seeking */
777     /* FIXME use edit table */
778     int64_t i_sample;
779     int64_t i_chunk;
780
781     int64_t i_index;
782     int64_t i_index_sample_used;
783
784     int64_t i_last_dts; 
785     
786     p_stts = MP4_BoxGet( p_demux_track->p_stbl, "stts" );
787     p_stsz = MP4_BoxGet( p_demux_track->p_stbl, "stsz" ); /* FIXME and stz2 */
788
789     
790     if( ( !p_stts )||( !p_stsz ) )
791     {
792         msg_Warn( p_input, "cannot read sample table" );
793         return( 0 ); 
794     }
795         
796     p_demux_track->i_sample_count = p_stsz->data.p_stsz->i_sample_count;
797
798
799     /* for sample size, there are 2 case */
800     if( p_stsz->data.p_stsz->i_sample_size )
801     {
802         /* 1: all sample have the same size, so no need to construct a table */
803         p_demux_track->i_sample_size = p_stsz->data.p_stsz->i_sample_size;
804         p_demux_track->p_sample_size = NULL;
805     }
806     else
807     {
808         /* 2: each sample can have a different size */
809         p_demux_track->i_sample_size = 0;
810         p_demux_track->p_sample_size = 
811             calloc( p_demux_track->i_sample_count, sizeof( uint32_t ) );
812         
813         for( i_sample = 0; i_sample < p_demux_track->i_sample_count; i_sample++ )
814         {
815             p_demux_track->p_sample_size[i_sample] = 
816                     p_stsz->data.p_stsz->i_entry_size[i_sample];
817         }
818     }
819     /* we have extract all information from stsz,
820         now use stts */
821
822     /* if we don't want to waste too much memory, we can't expand
823        the box !, so each chunk will contain an "extract" of this table 
824        for fast research */
825         
826     i_last_dts = 0;
827     i_index = 0; i_index_sample_used =0;
828
829     /* create and init last data for each chunk */
830     for(i_chunk = 0 ; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
831     {
832
833         int64_t i_entry, i_sample_count, i;
834         /* save last dts */
835         p_demux_track->chunk[i_chunk].i_first_dts = i_last_dts;
836     /* count how many entries needed for this chunk 
837        for p_sample_delta_dts and p_sample_count_dts */
838
839         i_sample_count = p_demux_track->chunk[i_chunk].i_sample_count;
840
841         i_entry = 0;
842         while( i_sample_count > 0 )
843         {
844             i_sample_count -= p_stts->data.p_stts->i_sample_count[i_index+i_entry];
845             if( i_entry == 0 )
846             {
847                 i_sample_count += i_index_sample_used; /* don't count already used sample 
848                                                    int this entry */
849             }
850             i_entry++;
851         }
852
853         /* allocate them */
854         p_demux_track->chunk[i_chunk].p_sample_count_dts = 
855             calloc( i_entry, sizeof( uint32_t ) );
856         p_demux_track->chunk[i_chunk].p_sample_delta_dts =
857             calloc( i_entry, sizeof( uint32_t ) );
858
859         /* now copy */
860         i_sample_count = p_demux_track->chunk[i_chunk].i_sample_count;
861         for( i = 0; i < i_entry; i++ )
862         {
863             int64_t i_used;
864             int64_t i_rest;
865             
866             i_rest = p_stts->data.p_stts->i_sample_count[i_index] - i_index_sample_used;
867
868             i_used = __MIN( i_rest, i_sample_count );
869
870             i_index_sample_used += i_used;
871             i_sample_count -= i_used;
872
873             p_demux_track->chunk[i_chunk].p_sample_count_dts[i] = i_used;
874
875             p_demux_track->chunk[i_chunk].p_sample_delta_dts[i] =
876                         p_stts->data.p_stts->i_sample_delta[i_index];
877             
878             i_last_dts += i_used * 
879                     p_demux_track->chunk[i_chunk].p_sample_delta_dts[i];
880
881             if( i_index_sample_used >=
882                              p_stts->data.p_stts->i_sample_count[i_index] )
883             {
884
885                 i_index++;
886                 i_index_sample_used = 0;
887             }
888         }
889         
890     }
891
892     msg_Dbg( p_input, 
893              "track[Id 0x%x] read %d samples length:"I64Fd"s", 
894              p_demux_track->i_track_ID,
895              p_demux_track->i_sample_count,
896              i_last_dts / p_demux_track->i_timescale );
897
898     return( 1 );
899 }
900
901 static void MP4_StartDecoder( input_thread_t *p_input,
902                                  track_data_mp4_t *p_demux_track )
903 {
904     MP4_Box_t   *p_sample;
905     int         i;
906     int         i_chunk;
907
908     int         i_decoder_specific_info_len;
909     uint8_t     *p_decoder_specific_info;
910     
911     uint8_t             *p_init;
912     BITMAPINFOHEADER    *p_bih;
913
914     MP4_Box_t   *p_esds;
915
916     
917     if( (!p_demux_track->b_ok )||( p_demux_track->i_cat == UNKNOWN_ES ) )
918     {
919         return;
920     }
921     
922     msg_Dbg( p_input, "Starting decoder for track[Id 0x%x]",
923                       p_demux_track->i_track_ID );
924
925     /* launch decoder according in chunk we are */
926     i_chunk = p_demux_track->i_chunk;
927
928     if( !p_demux_track->chunk[i_chunk].i_sample_description_index )
929     {
930         msg_Warn( p_input, 
931                   "invalid SampleEntry index (track[Id 0x%x])",
932                   p_demux_track->i_track_ID );
933         return;
934     } 
935     p_sample = MP4_BoxGet(  p_demux_track->p_stsd, 
936                             "[%d]", 
937                 p_demux_track->chunk[i_chunk].i_sample_description_index - 1 );
938
939     if( ( !p_sample )||( !p_sample->data.p_data ) )
940     {
941         msg_Warn( p_input, 
942                   "cannot find SampleEntry (track[Id 0x%x])",
943                   p_demux_track->i_track_ID );
944         return;
945     }
946
947     vlc_mutex_lock( &p_input->stream.stream_lock );
948     p_demux_track->p_es = input_AddES( p_input,
949                                        p_input->stream.p_selected_program, 
950                                        p_demux_track->i_track_ID,
951                                        0 );
952     vlc_mutex_unlock( &p_input->stream.stream_lock );
953     /* Initialise ES, first language as description */
954     for( i = 0; i < 3; i++ )
955     {
956         p_demux_track->p_es->psz_desc[i] = p_demux_track->i_language[i];
957     }
958     p_demux_track->p_es->psz_desc[3] = '\0';
959     
960     p_demux_track->p_es->i_stream_id = p_demux_track->i_track_ID;
961
962     /* It's a little ugly but .. there are special cases */
963     switch( p_sample->i_type )
964     {
965         case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
966         case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
967             p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' );
968             break;
969         default:
970             p_demux_track->p_es->i_fourcc = p_sample->i_type;
971             break;
972     }
973     
974     p_demux_track->p_es->i_cat = p_demux_track->i_cat;
975     
976     i_decoder_specific_info_len = 0;
977     p_decoder_specific_info = NULL;
978
979     /* now see if esds is present and if so create a data packet 
980         with decoder_specific_info  */
981 #define p_decconfig p_esds->data.p_esds->es_descriptor.p_decConfigDescr
982     if( ( p_esds = MP4_BoxGet( p_sample, "esds" ) )&&
983         ( p_esds->data.p_esds )&&
984         ( p_decconfig ) )
985     {
986         /* First update information based on i_objectTypeIndication */
987         switch( p_decconfig->i_objectTypeIndication )
988         {
989             case( 0x20 ): /* MPEG4 VIDEO */
990                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','v' );
991                 break;
992             case( 0x40):
993                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','a' );
994                 break;
995             case( 0x60):
996             case( 0x61):
997             case( 0x62):
998             case( 0x63):
999             case( 0x64):
1000             case( 0x65): /* MPEG2 video */
1001                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','v' );
1002                 break;
1003             /* Theses are MPEG2-AAC */
1004             case( 0x66): /* main profile */
1005             case( 0x67): /* Low complexity profile */
1006             case( 0x68): /* Scaleable Sampling rate profile */
1007                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','a' );
1008                 break;
1009             /* true MPEG 2 audio */
1010             case( 0x69): 
1011                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','a' );
1012                 break;
1013             case( 0x6a): /* MPEG1 video */
1014                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','v' );
1015                 break;
1016             case( 0x6b): /* MPEG1 audio */
1017                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','a' );
1018                 break;
1019             case( 0x6c ): /* jpeg */
1020                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'j','p','e','g' );
1021                 break;
1022             default:
1023                 /* Unknown entry, but don't touch i_fourcc */
1024                 msg_Warn( p_input, 
1025                           "objectTypeIndication(0x%x) unknow (Track[ID 0x%x])",
1026                           p_decconfig->i_objectTypeIndication,
1027                           p_demux_track->i_track_ID );
1028                 break;
1029         }
1030         i_decoder_specific_info_len = 
1031                 p_decconfig->i_decoder_specific_info_len;
1032         p_decoder_specific_info = 
1033                 p_decconfig->p_decoder_specific_info;
1034     }
1035
1036 #undef p_decconfig
1037
1038     /* some last initialisation */
1039     /* XXX I create a bitmapinfoheader_t or 
1040        waveformatex_t for each stream, up to now it's the best thing 
1041        I've found but it could exist a better solution :) as something 
1042        like adding some new fields in p_es ...
1043
1044        XXX I don't set all values, only thoses that are interesting or known
1045         --> bitmapinfoheader_t : width and height 
1046         --> waveformatex_t : channels, samplerate, bitspersample
1047         and at the end I add p_decoder_specific_info 
1048         
1049         TODO set more values
1050      
1051      */
1052
1053     switch( p_demux_track->i_cat )
1054     {
1055         case( VIDEO_ES ):    
1056             /* now create a bitmapinfoheader_t for decoder and 
1057                add information found in p_esds */
1058             p_init = malloc( sizeof( BITMAPINFOHEADER ) + i_decoder_specific_info_len );
1059             p_bih = (BITMAPINFOHEADER*)p_init;
1060
1061             p_bih->biSize     = sizeof( BITMAPINFOHEADER ) + i_decoder_specific_info_len;
1062             p_bih->biWidth    = p_sample->data.p_sample_vide->i_width;
1063             p_bih->biHeight   = p_sample->data.p_sample_vide->i_height;
1064             p_bih->biPlanes   = 1;      // FIXME
1065             p_bih->biBitCount = 0;      // FIXME
1066             p_bih->biCompression   = 0; // FIXME
1067             p_bih->biSizeImage     = 0; // FIXME
1068             p_bih->biXPelsPerMeter = 0; // FIXME
1069             p_bih->biYPelsPerMeter = 0; // FIXME
1070             p_bih->biClrUsed       = 0; // FIXME
1071             p_bih->biClrImportant  = 0; // FIXME
1072
1073             if( p_bih->biWidth == 0 )
1074             {
1075                 // fall on display size
1076                 p_bih->biWidth = p_demux_track->i_width;
1077             }
1078             if( p_bih->biHeight == 0 )
1079             {
1080                 // fall on display size
1081                 p_bih->biHeight = p_demux_track->i_height;
1082             }
1083             
1084             if( i_decoder_specific_info_len )
1085             {
1086                 memcpy( p_init + sizeof( BITMAPINFOHEADER ), 
1087                         p_decoder_specific_info,
1088                         i_decoder_specific_info_len);
1089             }
1090             break;
1091
1092         case( AUDIO_ES ):
1093             p_init = malloc( 18 + i_decoder_specific_info_len);
1094             memset( p_init, 0, 18 + i_decoder_specific_info_len);
1095             MP4_Set2BytesLE( p_init + 2, /* i_channel */
1096                              p_sample->data.p_sample_soun->i_channelcount );
1097             MP4_Set4BytesLE( p_init + 4, /* samplepersec */
1098                              p_sample->data.p_sample_soun->i_sampleratehi );
1099             MP4_Set4BytesLE( p_init + 8, /* avgbytespersec */
1100                              p_sample->data.p_sample_soun->i_channelcount *
1101                                 p_sample->data.p_sample_soun->i_sampleratehi *
1102                              (p_sample->data.p_sample_soun->i_samplesize/8) );
1103             MP4_Set2BytesLE( p_init + 14, /* bits/sample */
1104                              p_sample->data.p_sample_soun->i_samplesize );
1105
1106             MP4_Set2BytesLE( p_init + 16, /* i_size, specific info len*/
1107                              i_decoder_specific_info_len );
1108             if( i_decoder_specific_info_len )
1109             {
1110                 memcpy( p_init + 18, 
1111                         p_decoder_specific_info,
1112                         i_decoder_specific_info_len);
1113             }
1114             break;
1115
1116         default:
1117             p_init = NULL;
1118             break;
1119     }
1120
1121     p_demux_track->p_es->p_demux_data = (es_sys_t *)p_init;
1122     vlc_mutex_lock( &p_input->stream.stream_lock );
1123     input_SelectES( p_input, p_demux_track->p_es );
1124     vlc_mutex_unlock( &p_input->stream.stream_lock );
1125
1126     p_demux_track->b_ok = 1;
1127     p_demux_track->b_selected = 1;
1128 }
1129
1130 static void MP4_StopDecoder( input_thread_t *p_input,
1131                              track_data_mp4_t *p_demux_track )
1132 {
1133     msg_Dbg( p_input, "Stopping decoder (track[Id 0x%x])",
1134                       p_demux_track->i_track_ID );
1135
1136     input_UnselectES( p_input, p_demux_track->p_es );
1137     p_demux_track->p_es = NULL;
1138
1139     p_demux_track->b_selected = 0;
1140 }
1141
1142 static int  MP4_ReadSample( input_thread_t *p_input,
1143                             track_data_mp4_t *p_demux_track,
1144                             pes_packet_t **pp_pes )
1145 {
1146     int i_size;
1147     off_t i_pos;
1148
1149     data_packet_t *p_data;
1150
1151
1152     /* this track have already reach the end */
1153     if( p_demux_track->i_sample >= p_demux_track->i_sample_count )
1154     {
1155         *pp_pes = NULL;
1156         return( 0 );
1157     }
1158     /* caculate size and position for this sample */
1159     i_size = p_demux_track->i_sample_size ? 
1160                     p_demux_track->i_sample_size : 
1161                     p_demux_track->p_sample_size[p_demux_track->i_sample];
1162
1163     i_pos  = MP4_GetTrackPos( p_demux_track );
1164
1165     /* go,go go ! */
1166     if( ! MP4_SeekAbsolute( p_input, i_pos ) )
1167     {
1168         return( 0 );
1169     }
1170
1171     /* now create a pes */
1172     if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
1173     {
1174         return( 0 );
1175     }
1176     /* and a data packet for the data */
1177     if( !(p_data = input_NewPacket( p_input->p_method_data, i_size ) ) )
1178     {
1179         input_DeletePES( p_input->p_method_data, *pp_pes );
1180         *pp_pes = NULL;
1181         return( 0 );
1182     }
1183     
1184     /* initialisation of all the field */
1185     (*pp_pes)->i_dts =
1186         (*pp_pes)->i_pts = MP4_GetTrackPTS( p_demux_track );
1187     (*pp_pes)->p_first = (*pp_pes)->p_last  = p_data;
1188     (*pp_pes)->i_nb_data = 1;
1189     (*pp_pes)->i_pes_size = i_size;
1190
1191     if( !i_size )    
1192     {
1193         return( 1 );
1194     }
1195     
1196 /*    msg_Dbg( p_input, "will read %d bytes", i_size ); */
1197     if( !MP4_ReadData( p_input, p_data->p_payload_start, i_size ) )
1198     {
1199         input_DeletePES( p_input->p_method_data, *pp_pes );
1200         input_DeletePacket( p_input->p_method_data, p_data );
1201         return( 0 );
1202     }
1203
1204         return( 1 );
1205 }
1206
1207
1208 static int  MP4_DecodeSample( input_thread_t *p_input,
1209                               track_data_mp4_t *p_demux_track,
1210                               pes_packet_t *p_pes )
1211 {
1212
1213     if( !p_pes )
1214     {
1215         return( 0 );
1216     }
1217
1218     /* don't forget to convert in mpeg clock */
1219     /* FIXME correct ffmpeg to use dts instead of pts that it incorrect 
1220        and, set it here ( and correct avi demux ) */
1221     p_pes->i_dts =
1222         p_pes->i_pts = input_ClockGetTS( p_input,
1223                                          p_input->stream.p_selected_program,
1224                                          p_pes->i_pts * 9/100);
1225
1226     
1227     input_DecodePES( p_demux_track->p_es->p_decoder_fifo, p_pes );
1228     
1229     /* now update sample position */
1230     p_demux_track->i_sample++; /* easy ;) */
1231     if( p_demux_track->i_sample >= p_demux_track->i_sample_count )
1232     {
1233         /* we have reach end of the track so free decoder stuff */
1234         MP4_StopDecoder( p_input, p_demux_track );
1235         return( 1 );
1236     }
1237     /* Have we changed chunk ? */
1238     if( p_demux_track->i_sample >=
1239             p_demux_track->chunk[p_demux_track->i_chunk].i_sample_first +
1240                 p_demux_track->chunk[p_demux_track->i_chunk].i_sample_count )
1241     {
1242         /* we haven't reached the end of the track, so see if we 
1243            have to change the decoder for the next frame because 
1244            i_sample_description_index has changed */
1245
1246         p_demux_track->i_chunk++;
1247         if( p_demux_track->chunk[p_demux_track->i_chunk-1].i_sample_description_index 
1248               != p_demux_track->chunk[p_demux_track->i_chunk].i_sample_description_index  )
1249         {
1250             /* FIXME */
1251             msg_Warn( p_input, 
1252                       "SampleEntry has changed, starting a new decoder" );
1253             MP4_StopDecoder( p_input, p_demux_track );
1254             MP4_StartDecoder( p_input, p_demux_track );
1255         }
1256     }
1257
1258     
1259     return( 1 );
1260 }
1261
1262
1263