demux: mp4: more insane rtp cleanup
[vlc.git] / modules / demux / mp4 / mp4.c
1 /*****************************************************************************
2  * mp4.c : MP4 file input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001-2004, 2010 VLC authors and VideoLAN
5  *
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include "mp4.h"
30
31 #include <vlc_demux.h>
32 #include <vlc_charset.h>                           /* EnsureUTF8 */
33 #include <vlc_input.h>
34 #include <vlc_aout.h>
35 #include <vlc_plugin.h>
36 #include <assert.h>
37 #include <limits.h>
38 #include "../codec/cc.h"
39
40 /*****************************************************************************
41  * Module descriptor
42  *****************************************************************************/
43 static int  Open ( vlc_object_t * );
44 static void Close( vlc_object_t * );
45
46 vlc_module_begin ()
47     set_category( CAT_INPUT )
48     set_subcategory( SUBCAT_INPUT_DEMUX )
49     set_description( N_("MP4 stream demuxer") )
50     set_shortname( N_("MP4") )
51     set_capability( "demux", 240 )
52     set_callbacks( Open, Close )
53 vlc_module_end ()
54
55 /*****************************************************************************
56  * Local prototypes
57  *****************************************************************************/
58 static int   Demux   ( demux_t * );
59 static int   DemuxRef( demux_t *p_demux ){ (void)p_demux; return 0;}
60 static int   DemuxFrg( demux_t * );
61 static int   DemuxAsLeaf( demux_t * );
62 static int   Seek    ( demux_t *, mtime_t );
63 static int   Control ( demux_t *, int, va_list );
64
65 struct demux_sys_t
66 {
67     MP4_Box_t    *p_root;      /* container for the whole file */
68
69     mtime_t      i_pcr;
70
71     uint64_t     i_overall_duration; /* Full duration, including all fragments */
72     uint64_t     i_time;         /* time position of the presentation
73                                   * in movie timescale */
74     uint32_t     i_timescale;    /* movie time scale */
75     unsigned int i_tracks;       /* number of tracks */
76     mp4_track_t  *track;         /* array of track */
77     float        f_fps;          /* number of frame per seconds */
78
79     bool         b_fragmented;   /* fMP4 */
80     bool         b_seekable;
81     bool         b_fastseekable;
82     bool         b_seekmode;
83
84     bool            b_index_probed;
85     bool            b_fragments_probed;
86
87     mp4_fragments_t fragments;
88
89     struct
90     {
91         mp4_fragment_t *p_fragment;
92         uint32_t        i_current_box_type;
93         uint32_t        i_mdatbytesleft;
94         uint32_t        i_lastseqnumber;
95     } context;
96
97     /* */
98     MP4_Box_t    *p_tref_chap;
99
100     /* */
101     input_title_t *p_title;
102
103     /* ASF in MP4 */
104     asf_packet_sys_t asfpacketsys;
105     uint64_t i_preroll;         /* foobar */
106     int64_t  i_preroll_start;
107 };
108
109 /*****************************************************************************
110  * Declaration of local function
111  *****************************************************************************/
112 static void MP4_TrackCreate ( demux_t *, mp4_track_t *, MP4_Box_t  *, bool, bool );
113 static void MP4_TrackDestroy( demux_t *, mp4_track_t * );
114
115 static block_t * MP4_Block_Read( demux_t *, const mp4_track_t *, int );
116 static void MP4_Block_Send( demux_t *, mp4_track_t *, block_t * );
117
118 static int  MP4_TrackSelect ( demux_t *, mp4_track_t *, mtime_t );
119 static void MP4_TrackUnselect(demux_t *, mp4_track_t * );
120
121 static int  MP4_TrackSeek   ( demux_t *, mp4_track_t *, mtime_t );
122
123 static uint64_t MP4_TrackGetPos    ( mp4_track_t * );
124 static uint32_t MP4_TrackGetReadSize( mp4_track_t *, uint32_t * );
125 static int      MP4_TrackNextSample( demux_t *, mp4_track_t *, uint32_t );
126 static void     MP4_TrackSetELST( demux_t *, mp4_track_t *, int64_t );
127 static bool     MP4_TrackIsInterleaved( const mp4_track_t * );
128
129 static void     MP4_UpdateSeekpoint( demux_t * );
130
131 static MP4_Box_t * MP4_GetTrexByTrackID( MP4_Box_t *p_moov, const uint32_t i_id );
132 static void MP4_GetDefaultSizeAndDuration( demux_t *p_demux,
133                                            const MP4_Box_data_tfhd_t *p_tfhd_data,
134                                            uint32_t *pi_default_size,
135                                            uint32_t *pi_default_duration );
136
137 static bool AddFragment( demux_t *p_demux, MP4_Box_t *p_moox );
138 static int  ProbeFragments( demux_t *p_demux, bool b_force );
139 static int  ProbeIndex( demux_t *p_demux );
140
141 static int LeafIndexGetMoofPosByTime( demux_t *p_demux, const mtime_t i_target_time,
142                                       uint64_t *pi_pos, mtime_t *pi_mooftime );
143 static int LeafGetTrackAndChunkByMOOVPos( demux_t *p_demux, uint64_t *pi_pos,
144                                       mp4_track_t **pp_tk, unsigned int *pi_chunk );
145 static int LeafMapTrafTrunContextes( demux_t *p_demux, MP4_Box_t *p_moof );
146
147 /* ASF Handlers */
148 static asf_track_info_t * MP4ASF_GetTrackInfo( asf_packet_sys_t *p_packetsys, uint8_t i_stream_number );
149 static void MP4ASF_Send(asf_packet_sys_t *p_packetsys, uint8_t i_stream_number, block_t **pp_frame);
150 static void MP4ASF_ResetFrames( demux_sys_t *p_sys );
151
152 /* RTP Hint track */
153 static block_t * MP4_RTPHint_Convert( demux_t *p_demux, block_t *p_block, vlc_fourcc_t i_codec );
154 static block_t * MP4_RTPHintToFrame( demux_t *p_demux, block_t *p_block, uint32_t packetcount );
155
156 /* Helpers */
157
158 static uint32_t stream_ReadU32( stream_t *s, void *p_read, uint32_t i_toread )
159 {
160     ssize_t i_return = 0;
161     if ( i_toread > INT32_MAX )
162     {
163         i_return = stream_Read( s, p_read, (size_t) INT32_MAX );
164         if ( i_return < INT32_MAX )
165             return i_return;
166         else
167             i_toread -= INT32_MAX;
168     }
169     i_return += stream_Read( s, (uint8_t *)p_read + i_return, (size_t) i_toread );
170     return i_return;
171 }
172
173 static MP4_Box_t * MP4_GetTrexByTrackID( MP4_Box_t *p_moov, const uint32_t i_id )
174 {
175     if(!p_moov)
176         return NULL;
177     MP4_Box_t *p_trex = MP4_BoxGet( p_moov, "mvex/trex" );
178     while( p_trex )
179     {
180         if ( p_trex->i_type == ATOM_trex &&
181              BOXDATA(p_trex) && BOXDATA(p_trex)->i_track_ID == i_id )
182                 break;
183         else
184             p_trex = p_trex->p_next;
185     }
186     return p_trex;
187 }
188
189 static MP4_Box_t * MP4_GetTrakByTrackID( MP4_Box_t *p_moov, const uint32_t i_id )
190 {
191     MP4_Box_t *p_trak = MP4_BoxGet( p_moov, "trak" );
192     MP4_Box_t *p_tkhd;
193     while( p_trak )
194     {
195         if( p_trak->i_type == ATOM_trak &&
196             (p_tkhd = MP4_BoxGet( p_trak, "tkhd" )) && BOXDATA(p_tkhd) &&
197             BOXDATA(p_tkhd)->i_track_ID == i_id )
198                 break;
199         else
200             p_trak = p_trak->p_next;
201     }
202     return p_trak;
203 }
204
205 static es_out_id_t * MP4_AddTrackES( es_out_t *out, mp4_track_t *p_track )
206 {
207     es_out_id_t *p_es = es_out_Add( out, &p_track->fmt );
208     /* Force SPU which isn't selected/defaulted */
209     if( p_track->fmt.i_cat == SPU_ES && p_es && p_track->b_forced_spu )
210         es_out_Control( out, ES_OUT_SET_ES_DEFAULT, p_es );
211
212     return p_es;
213 }
214
215 /* Return time in microsecond of a track */
216 static inline int64_t MP4_TrackGetDTS( demux_t *p_demux, mp4_track_t *p_track )
217 {
218     demux_sys_t *p_sys = p_demux->p_sys;
219     const mp4_chunk_t *p_chunk;
220     if( p_sys->b_fragmented )
221         p_chunk = p_track->cchunk;
222     else
223         p_chunk = &p_track->chunk[p_track->i_chunk];
224
225     unsigned int i_index = 0;
226     unsigned int i_sample = p_track->i_sample - p_chunk->i_sample_first;
227     int64_t i_dts = p_chunk->i_first_dts;
228
229     while( i_sample > 0 && i_index < p_chunk->i_entries_dts )
230     {
231         if( i_sample > p_chunk->p_sample_count_dts[i_index] )
232         {
233             i_dts += p_chunk->p_sample_count_dts[i_index] *
234                 p_chunk->p_sample_delta_dts[i_index];
235             i_sample -= p_chunk->p_sample_count_dts[i_index];
236             i_index++;
237         }
238         else
239         {
240             i_dts += i_sample * p_chunk->p_sample_delta_dts[i_index];
241             break;
242         }
243     }
244
245     /* now handle elst */
246     if( p_track->p_elst )
247     {
248         demux_sys_t         *p_sys = p_demux->p_sys;
249         MP4_Box_data_elst_t *elst = p_track->BOXDATA(p_elst);
250
251         /* convert to offset */
252         if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
253               elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&
254             elst->i_media_time[p_track->i_elst] > 0 )
255         {
256             i_dts -= elst->i_media_time[p_track->i_elst];
257         }
258
259         /* add i_elst_time */
260         i_dts += p_track->i_elst_time * p_track->i_timescale /
261             p_sys->i_timescale;
262
263         if( i_dts < 0 ) i_dts = 0;
264     }
265
266     return CLOCK_FREQ * i_dts / p_track->i_timescale;
267 }
268
269 static inline bool MP4_TrackGetPTSDelta( demux_t *p_demux, mp4_track_t *p_track,
270                                          int64_t *pi_delta )
271 {
272     demux_sys_t *p_sys = p_demux->p_sys;
273     mp4_chunk_t *ck;
274     if( p_sys->b_fragmented )
275         ck = p_track->cchunk;
276     else
277         ck = &p_track->chunk[p_track->i_chunk];
278
279     unsigned int i_index = 0;
280     unsigned int i_sample = p_track->i_sample - ck->i_sample_first;
281
282     if( ck->p_sample_count_pts == NULL || ck->p_sample_offset_pts == NULL )
283         return false;
284
285     for( i_index = 0; i_index < ck->i_entries_pts ; i_index++ )
286     {
287         if( i_sample < ck->p_sample_count_pts[i_index] )
288         {
289             *pi_delta = ck->p_sample_offset_pts[i_index] * CLOCK_FREQ /
290                         (int64_t)p_track->i_timescale;
291             return true;
292         }
293
294         i_sample -= ck->p_sample_count_pts[i_index];
295     }
296     return false;
297 }
298
299 static inline int64_t MP4_GetMoviePTS(demux_sys_t *p_sys )
300 {
301     return CLOCK_FREQ * p_sys->i_time / p_sys->i_timescale;
302 }
303
304 static void LoadChapter( demux_t  *p_demux );
305
306 static int LoadInitFrag( demux_t *p_demux )
307 {
308     demux_sys_t *p_sys = p_demux->p_sys;
309
310     /* Load all boxes ( except raw data ) */
311     if( ( p_sys->p_root = MP4_BoxGetRoot( p_demux->s ) ) == NULL )
312     {
313         goto LoadInitFragError;
314     }
315
316     return VLC_SUCCESS;
317
318 LoadInitFragError:
319     msg_Warn( p_demux, "MP4 plugin discarded (not a valid initialization chunk)" );
320     return VLC_EGENERIC;
321 }
322
323 static int AllocateTracks( demux_t *p_demux, unsigned i_tracks )
324 {
325     demux_sys_t *p_sys = p_demux->p_sys;
326
327     p_sys->track = calloc( i_tracks, sizeof( mp4_track_t ) );
328     if( p_sys->track == NULL )
329         return VLC_ENOMEM;
330     p_sys->i_tracks = i_tracks;
331
332     if( p_sys->b_fragmented )
333     {
334         for( unsigned i = 0; i < i_tracks; i++ )
335         {
336             mp4_track_t *p_track = &p_sys->track[i];
337             p_track->cchunk = calloc( 1, sizeof( mp4_chunk_t ) );
338             if( unlikely( !p_track->cchunk ) )
339                 return VLC_ENOMEM;
340         }
341     }
342     return VLC_SUCCESS;
343 }
344
345 static block_t * MP4_EIA608_Convert( block_t * p_block )
346 {
347     /* Rebuild codec data from encap */
348     size_t i_copied = 0;
349     size_t i_remaining = __MIN(p_block->i_buffer, INT64_MAX / 3);
350     uint32_t i_bytes = 0;
351     block_t *p_newblock;
352
353     /* always need at least 10 bytes (atom size+header+1pair)*/
354     if ( i_remaining < 10 ||
355          !(i_bytes = GetDWBE(p_block->p_buffer)) ||
356          (i_bytes > i_remaining) ||
357          memcmp("cdat", &p_block->p_buffer[4], 4) ||
358          !(p_newblock = block_Alloc( i_remaining * 3 - 8 )) )
359     {
360         p_block->i_buffer = 0;
361         return p_block;
362     }
363
364     uint8_t *p_write = p_newblock->p_buffer;
365     uint8_t *p_read = &p_block->p_buffer[8];
366     i_bytes -= 8;
367     i_remaining -= 8;
368
369     do
370     {
371         p_write[i_copied++] = 0; /* cc1 == field 0 */
372         p_write[i_copied++] = p_read[0];
373         p_write[i_copied++] = p_read[1];
374         p_read += 2;
375         i_bytes -= 2;
376         i_remaining -= 2;
377     } while( i_bytes >= 2 );
378
379     /* cdt2 is optional */
380     if ( i_remaining >= 10 &&
381          (i_bytes = GetDWBE(p_read)) &&
382          (i_bytes <= i_remaining) &&
383          !memcmp("cdt2", &p_read[4], 4) )
384     {
385         p_read += 8;
386         i_bytes -= 8;
387         i_remaining -= 8;
388         do
389         {
390             p_write[i_copied++] = 0; /* cc1 == field 0 */
391             p_write[i_copied++] = p_read[0];
392             p_write[i_copied++] = p_read[1];
393             p_read += 2;
394             i_bytes -= 2;
395         } while( i_bytes >= 2 );
396     }
397
398     block_Release( p_block );
399     p_newblock->i_buffer = i_copied;
400     p_newblock->i_flags = BLOCK_FLAG_ORDERED_CAPTIONS;
401     return p_newblock;
402 }
403
404 static block_t * MP4_Block_Read( demux_t *p_demux, const mp4_track_t *p_track, int i_size )
405 {
406     block_t *p_block = stream_Block( p_demux->s, i_size );
407     if ( !p_block )
408         return NULL;
409
410     /* might have some encap */
411     if( p_track->fmt.i_cat == SPU_ES )
412     {
413         switch( p_track->fmt.i_codec )
414         {
415             case VLC_CODEC_TX3G:
416             case VLC_CODEC_SPU:
417             /* accept as-is */
418             break;
419             case VLC_CODEC_EIA608_1:
420                 p_block = MP4_EIA608_Convert( p_block );
421             break;
422         default:
423             p_block->i_buffer = 0;
424             break;
425         }
426     }
427     else if( p_track->fmt.i_original_fourcc == ATOM_rrtp )
428     {
429         p_block = MP4_RTPHint_Convert( p_demux, p_block, p_track->fmt.i_codec );
430     }
431
432     return p_block;
433 }
434
435 static void MP4_Block_Send( demux_t *p_demux, mp4_track_t *p_track, block_t *p_block )
436 {
437     if ( p_track->b_chans_reorder && aout_BitsPerSample( p_track->fmt.i_codec ) )
438     {
439         aout_ChannelReorder( p_block->p_buffer, p_block->i_buffer,
440                              p_track->fmt.audio.i_channels,
441                              p_track->rgi_chans_reordering,
442                              p_track->fmt.i_codec );
443     }
444
445     p_block->i_flags |= p_track->i_block_flags;
446
447     /* ASF packets in mov */
448     if( p_track->p_asf )
449     {
450         /* Fake a new stream from MP4 block */
451         stream_t *p_stream = p_demux->s;
452         p_demux->s = stream_MemoryNew( p_demux, p_block->p_buffer, p_block->i_buffer, true );
453         if ( p_demux->s )
454         {
455             p_track->i_dts_backup = p_block->i_dts;
456             p_track->i_pts_backup = p_block->i_pts;
457             /* And demux it as ASF packet */
458             DemuxASFPacket( &p_demux->p_sys->asfpacketsys, p_block->i_buffer, p_block->i_buffer );
459             stream_Delete(p_demux->s);
460         }
461         block_Release(p_block);
462         p_demux->s = p_stream;
463     }
464     else
465         es_out_Send( p_demux->out, p_track->p_es, p_block );
466 }
467
468 /*****************************************************************************
469  * Open: check file and initializes MP4 structures
470  *****************************************************************************/
471 static int Open( vlc_object_t * p_this )
472 {
473     demux_t  *p_demux = (demux_t *)p_this;
474     demux_sys_t     *p_sys;
475
476     const uint8_t   *p_peek;
477
478     MP4_Box_t       *p_ftyp;
479     MP4_Box_t       *p_rmra;
480     MP4_Box_t       *p_mvhd;
481     MP4_Box_t       *p_trak;
482
483     unsigned int    i;
484     bool      b_enabled_es;
485
486     /* A little test to see if it could be a mp4 */
487     if( stream_Peek( p_demux->s, &p_peek, 11 ) < 11 ) return VLC_EGENERIC;
488
489     switch( VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] ) )
490     {
491         case ATOM_moov:
492         case ATOM_foov:
493         case ATOM_moof:
494         case ATOM_mdat:
495         case ATOM_udta:
496         case ATOM_free:
497         case ATOM_skip:
498         case ATOM_wide:
499         case ATOM_uuid:
500         case VLC_FOURCC( 'p', 'n', 'o', 't' ):
501             break;
502         case ATOM_ftyp:
503             /* We don't yet support f4v, but avformat does. */
504             if( p_peek[8] == 'f' && p_peek[9] == '4' && p_peek[10] == 'v' )
505                 return VLC_EGENERIC;
506             break;
507          default:
508             return VLC_EGENERIC;
509     }
510
511     /* create our structure that will contains all data */
512     p_sys = calloc( 1, sizeof( demux_sys_t ) );
513     if ( !p_sys )
514         return VLC_EGENERIC;
515
516     /* I need to seek */
517     stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
518     stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &p_sys->b_fastseekable );
519     p_sys->b_seekmode = p_sys->b_fastseekable;
520
521     /*Set exported functions */
522     p_demux->pf_demux = Demux;
523     p_demux->pf_control = Control;
524
525     p_sys->context.i_lastseqnumber = 1;
526
527     MP4_Fragments_Init( &p_sys->fragments );
528
529     p_demux->p_sys = p_sys;
530
531     if( LoadInitFrag( p_demux ) != VLC_SUCCESS )
532         goto error;
533
534
535     if( ( p_ftyp = MP4_BoxGet( p_sys->p_root, "/ftyp" ) ) )
536     {
537         switch( BOXDATA(p_ftyp)->i_major_brand )
538         {
539             case MAJOR_isom:
540                 msg_Dbg( p_demux,
541                          "ISO Media (isom) version %d.",
542                          BOXDATA(p_ftyp)->i_minor_version );
543                 break;
544             case MAJOR_3gp4:
545             case MAJOR_3gp5:
546             case MAJOR_3gp6:
547             case MAJOR_3gp7:
548                 msg_Dbg( p_demux, "3GPP Media Release: %4.4s",
549                          (char *)&BOXDATA(p_ftyp)->i_major_brand );
550                 break;
551             case MAJOR_qt__:
552                 msg_Dbg( p_demux, "Apple QuickTime media" );
553                 break;
554             case MAJOR_isml:
555                 msg_Dbg( p_demux, "PIFF (= isml = fMP4) media" );
556                 break;
557             case MAJOR_dash:
558                 msg_Dbg( p_demux, "DASH Stream" );
559                 break;
560             default:
561                 msg_Dbg( p_demux,
562                          "unrecognized major media specification (%4.4s).",
563                           (char*)&BOXDATA(p_ftyp)->i_major_brand );
564                 break;
565         }
566         /* also lookup in compatibility list */
567         for(uint32_t i=0; i<BOXDATA(p_ftyp)->i_compatible_brands_count; i++)
568         {
569             if (BOXDATA(p_ftyp)->i_compatible_brands[i] == MAJOR_dash)
570             {
571                 msg_Dbg( p_demux, "DASH Stream" );
572             }
573             else if (BOXDATA(p_ftyp)->i_compatible_brands[i] == VLC_FOURCC('s', 'm', 'o', 'o') )
574             {
575                 msg_Dbg( p_demux, "Handling VLC Smooth Stream" );
576             }
577         }
578     }
579     else
580     {
581         msg_Dbg( p_demux, "file type box missing (assuming ISO Media)" );
582     }
583
584     if( MP4_BoxCount( p_sys->p_root, "/moov/mvex" ) > 0 )
585     {
586         if ( p_sys->b_seekable )
587         {
588             /* Probe remaining to check if there's really fragments
589                or if that file is just ready to append fragments */
590             ProbeFragments( p_demux, false );
591             p_sys->b_fragmented = !!MP4_BoxCount( p_sys->p_root, "/moof" );
592
593             if ( p_sys->b_fragmented && !p_sys->i_overall_duration )
594                 ProbeFragments( p_demux, true );
595
596             MP4_Box_t *p_mdat = MP4_BoxGet( p_sys->p_root, "mdat" );
597             if ( p_mdat )
598             {
599                 stream_Seek( p_demux->s, p_mdat->i_pos );
600                 msg_Dbg( p_demux, "rewinding to mdat %"PRId64, p_mdat->i_pos );
601             }
602         }
603         else
604             p_sys->b_fragmented = true;
605     }
606
607     if ( !MP4_Fragment_Moov(&p_sys->fragments)->p_moox )
608         AddFragment( p_demux, MP4_BoxGet( p_sys->p_root, "/moov" ) );
609
610     if ( !MP4_Fragment_Moov(&p_sys->fragments)->p_moox )
611         goto error;
612
613     MP4_BoxDumpStructure( p_demux->s, p_sys->p_root );
614
615     if( p_sys->b_fragmented )
616     {
617         p_demux->pf_demux = DemuxAsLeaf;
618         msg_Dbg( p_demux, "Set experimental DemuxLeaf mode" );
619     }
620
621     if( !p_sys->b_seekable && p_demux->pf_demux == Demux )
622     {
623         msg_Warn( p_demux, "MP4 plugin discarded (not seekable)" );
624         goto error;
625     }
626
627     /* the file need to have one moov box */
628     MP4_Fragment_Moov(&p_sys->fragments)->p_moox = MP4_BoxGet( p_sys->p_root, "/moov", 0 );
629     if( !MP4_Fragment_Moov(&p_sys->fragments)->p_moox )
630     {
631         MP4_Box_t *p_foov = MP4_BoxGet( p_sys->p_root, "/foov" );
632
633         if( !p_foov )
634         {
635             msg_Err( p_demux, "MP4 plugin discarded (no moov,foov,moof box)" );
636             goto error;
637         }
638         /* we have a free box as a moov, rename it */
639         p_foov->i_type = ATOM_moov;
640         MP4_Fragment_Moov(&p_sys->fragments)->p_moox = p_foov;
641     }
642
643     if( ( p_rmra = MP4_BoxGet( p_sys->p_root,  "/moov/rmra" ) ) )
644     {
645         int        i_count = MP4_BoxCount( p_rmra, "rmda" );
646         int        i;
647
648         msg_Dbg( p_demux, "detected playlist mov file (%d ref)", i_count );
649
650         input_thread_t *p_input = p_demux->p_input;
651         input_item_t *p_current = input_GetItem( p_input );
652
653         input_item_node_t *p_subitems = input_item_node_Create( p_current );
654
655         for( i = 0; i < i_count; i++ )
656         {
657             MP4_Box_t *p_rdrf = MP4_BoxGet( p_rmra, "rmda[%d]/rdrf", i );
658             char      *psz_ref;
659             uint32_t  i_ref_type;
660
661             if( !p_rdrf || !BOXDATA(p_rdrf) || !( psz_ref = strdup( BOXDATA(p_rdrf)->psz_ref ) ) )
662             {
663                 continue;
664             }
665             i_ref_type = BOXDATA(p_rdrf)->i_ref_type;
666
667             msg_Dbg( p_demux, "new ref=`%s' type=%4.4s",
668                      psz_ref, (char*)&i_ref_type );
669
670             if( i_ref_type == VLC_FOURCC( 'u', 'r', 'l', ' ' ) )
671             {
672                 if( strstr( psz_ref, "qt5gateQT" ) )
673                 {
674                     msg_Dbg( p_demux, "ignoring pseudo ref =`%s'", psz_ref );
675                     continue;
676                 }
677                 if( !strncmp( psz_ref, "http://", 7 ) ||
678                     !strncmp( psz_ref, "rtsp://", 7 ) )
679                 {
680                     ;
681                 }
682                 else
683                 {
684                     char *psz_absolute;
685                     char *psz_path = strdup( p_demux->psz_location );
686                     char *end = strrchr( psz_path, '/' );
687                     if( end ) end[1] = '\0';
688                     else *psz_path = '\0';
689
690                     if( asprintf( &psz_absolute, "%s://%s%s",
691                                   p_demux->psz_access, psz_path, psz_ref ) < 0 )
692                     {
693                         free( psz_ref );
694                         free( psz_path );
695                         input_item_node_Delete( p_subitems );
696                         return VLC_ENOMEM;
697                     }
698
699                     free( psz_ref );
700                     psz_ref = psz_absolute;
701                     free( psz_path );
702                 }
703                 msg_Dbg( p_demux, "adding ref = `%s'", psz_ref );
704                 input_item_t *p_item = input_item_New( psz_ref, NULL );
705                 input_item_CopyOptions( p_item, p_current );
706                 input_item_node_AppendItem( p_subitems, p_item );
707                 vlc_gc_decref( p_item );
708             }
709             else
710             {
711                 msg_Err( p_demux, "unknown ref type=%4.4s FIXME (send a bug report)",
712                          (char*)&BOXDATA(p_rdrf)->i_ref_type );
713             }
714             free( psz_ref );
715         }
716         input_item_node_PostAndDelete( p_subitems );
717     }
718
719     if( !(p_mvhd = MP4_BoxGet( p_sys->p_root, "/moov/mvhd" ) ) )
720     {
721         if( !p_rmra )
722         {
723             msg_Err( p_demux, "cannot find /moov/mvhd" );
724             goto error;
725         }
726         else
727         {
728             msg_Warn( p_demux, "cannot find /moov/mvhd (pure ref file)" );
729             p_demux->pf_demux = DemuxRef;
730             return VLC_SUCCESS;
731         }
732     }
733     else
734     {
735         p_sys->i_timescale = BOXDATA(p_mvhd)->i_timescale;
736         if( p_sys->i_timescale == 0 )
737         {
738             msg_Err( p_this, "bad timescale" );
739             goto error;
740         }
741     }
742
743     const unsigned i_tracks = MP4_BoxCount( p_sys->p_root, "/moov/trak" );
744     if( i_tracks < 1 )
745     {
746         msg_Err( p_demux, "cannot find any /moov/trak" );
747         goto error;
748     }
749     msg_Dbg( p_demux, "found %u track%c", i_tracks, i_tracks ? 's':' ' );
750
751     if( AllocateTracks( p_demux, i_tracks ) != VLC_SUCCESS )
752         goto error;
753
754     /* Search the first chap reference (like quicktime) and
755      * check that at least 1 stream is enabled */
756     p_sys->p_tref_chap = NULL;
757     b_enabled_es = false;
758     for( i = 0; i < p_sys->i_tracks; i++ )
759     {
760         MP4_Box_t *p_trak = MP4_BoxGet( p_sys->p_root, "/moov/trak[%d]", i );
761
762
763         MP4_Box_t *p_tkhd = MP4_BoxGet( p_trak, "tkhd" );
764         if( p_tkhd && BOXDATA(p_tkhd) && (BOXDATA(p_tkhd)->i_flags&MP4_TRACK_ENABLED) )
765             b_enabled_es = true;
766
767         MP4_Box_t *p_chap = MP4_BoxGet( p_trak, "tref/chap", i );
768         if( p_chap && p_chap->data.p_tref_generic &&
769             p_chap->data.p_tref_generic->i_entry_count > 0 && !p_sys->p_tref_chap )
770             p_sys->p_tref_chap = p_chap;
771     }
772
773     /* now process each track and extract all useful information */
774     for( i = 0; i < p_sys->i_tracks; i++ )
775     {
776         p_trak = MP4_BoxGet( p_sys->p_root, "/moov/trak[%d]", i );
777         MP4_TrackCreate( p_demux, &p_sys->track[i], p_trak, true, !b_enabled_es );
778
779         if( p_sys->track[i].b_ok && !p_sys->track[i].b_chapters_source )
780         {
781             const char *psz_cat;
782             switch( p_sys->track[i].fmt.i_cat )
783             {
784                 case( VIDEO_ES ):
785                     psz_cat = "video";
786                     break;
787                 case( AUDIO_ES ):
788                     psz_cat = "audio";
789                     break;
790                 case( SPU_ES ):
791                     psz_cat = "subtitle";
792                     break;
793
794                 default:
795                     psz_cat = "unknown";
796                     break;
797             }
798
799             msg_Dbg( p_demux, "adding track[Id 0x%x] %s (%s) language %s",
800                      p_sys->track[i].i_track_ID, psz_cat,
801                      p_sys->track[i].b_enable ? "enable":"disable",
802                      p_sys->track[i].fmt.psz_language ?
803                      p_sys->track[i].fmt.psz_language : "undef" );
804         }
805         else if( p_sys->track[i].b_ok && p_sys->track[i].b_chapters_source )
806         {
807             msg_Dbg( p_demux, "using track[Id 0x%x] for chapter language %s",
808                      p_sys->track[i].i_track_ID,
809                      p_sys->track[i].fmt.psz_language ?
810                      p_sys->track[i].fmt.psz_language : "undef" );
811         }
812         else
813         {
814             msg_Dbg( p_demux, "ignoring track[Id 0x%x]",
815                      p_sys->track[i].i_track_ID );
816         }
817     }
818
819     if ( p_sys->i_overall_duration == 0 )
820     {
821         /* Try in mehd if fragmented */
822         MP4_Box_t *p_mehd = MP4_BoxGet( p_demux->p_sys->p_root, "moov/mvex/mehd");
823         if ( p_mehd && p_mehd->data.p_mehd )
824             p_sys->i_overall_duration = p_mehd->data.p_mehd->i_fragment_duration;
825         else
826         {
827             for( i = 0; i < p_sys->i_tracks; i++ )
828             {
829                 mtime_t i_duration = GetTrackTotalDuration( &p_sys->fragments, p_sys->track[i].i_track_ID );
830                 p_sys->i_overall_duration = __MAX( p_sys->i_overall_duration, (uint64_t)i_duration );
831             }
832         }
833     }
834
835 #ifdef MP4_VERBOSE
836     DumpFragments( VLC_OBJECT(p_demux), &p_sys->fragments, p_sys->i_timescale );
837 #endif
838
839     if( !p_sys->b_fragmented && p_sys->i_tracks > 1 && p_sys->b_seekable && !p_sys->b_seekmode )
840     {
841         for( unsigned i = 0; i < p_sys->i_tracks; i++ )
842         {
843             mp4_track_t *tk = &p_sys->track[i];
844             if( !MP4_TrackIsInterleaved( tk ) )
845             {
846                 msg_Warn( p_demux, "that media doesn't look interleaved, will need to seek");
847                 p_sys->b_seekmode = true;
848                 break;
849             }
850         }
851     }
852
853     /* */
854     LoadChapter( p_demux );
855
856     p_sys->asfpacketsys.p_demux = p_demux;
857     p_sys->asfpacketsys.pi_preroll = &p_sys->i_preroll;
858     p_sys->asfpacketsys.pi_preroll_start = &p_sys->i_preroll_start;
859     p_sys->asfpacketsys.pf_doskip = NULL;
860     p_sys->asfpacketsys.pf_send = MP4ASF_Send;
861     p_sys->asfpacketsys.pf_gettrackinfo = MP4ASF_GetTrackInfo;
862     p_sys->asfpacketsys.pf_updatetime = NULL;
863     p_sys->asfpacketsys.pf_setaspectratio = NULL;
864
865     return VLC_SUCCESS;
866
867 error:
868     if( stream_Tell( p_demux->s ) > 0 )
869         stream_Seek( p_demux->s, 0 );
870
871     if( p_sys->p_root )
872     {
873         MP4_BoxFree( p_sys->p_root );
874     }
875     free( p_sys );
876     return VLC_EGENERIC;
877 }
878
879 const unsigned int SAMPLEHEADERSIZE = 4;
880 const unsigned int RTPPACKETSIZE = 12;
881 const unsigned int CONSTRUCTORSIZE = 16;
882
883 /*******************************************************************************
884  * MP4_RTPHintToFrame: converts RTP Reception Hint Track sample to H.264 frame
885  *******************************************************************************/
886 static block_t * MP4_RTPHintToFrame( demux_t *p_demux, block_t *p_block, uint32_t packetcount )
887 {
888     uint8_t *p_slice = p_block->p_buffer + SAMPLEHEADERSIZE;
889     block_t *p_newblock = NULL;
890     size_t i_payload = 0;
891
892     if( p_block->i_buffer < SAMPLEHEADERSIZE + RTPPACKETSIZE + CONSTRUCTORSIZE )
893     {
894         msg_Err( p_demux, "Sample not large enough for necessary structs");
895         block_Release( p_block );
896         return NULL;
897     }
898
899     for( uint32_t i = 0; i < packetcount; ++i )
900     {
901         if( (size_t)(p_slice - p_block->p_buffer) + RTPPACKETSIZE + CONSTRUCTORSIZE > p_block->i_buffer )
902             goto error;
903
904         /* skip RTP header in sample. Could be used to detect packet losses */
905         p_slice += RTPPACKETSIZE;
906
907         mp4_rtpsampleconstructor_t sample_cons;
908
909         sample_cons.type =                      p_slice[0];
910         sample_cons.trackrefindex =             p_slice[1];
911         sample_cons.length =          GetWBE(  &p_slice[2] );
912         sample_cons.samplenumber =    GetDWBE( &p_slice[4] );
913         sample_cons.sampleoffset =    GetDWBE( &p_slice[8] );
914         sample_cons.bytesperblock =   GetWBE(  &p_slice[12] );
915         sample_cons.samplesperblock = GetWBE(  &p_slice[14] );
916
917         /* skip packet constructor */
918         p_slice += CONSTRUCTORSIZE;
919
920         /* check that is RTPsampleconstructor, referencing itself and no weird audio stuff */
921         if( sample_cons.type != 2||sample_cons.trackrefindex != -1
922             ||sample_cons.samplesperblock != 1||sample_cons.bytesperblock != 1 )
923         {
924             msg_Err(p_demux, "Unhandled constructor in RTP Reception Hint Track. Type:%u", sample_cons.type);
925             goto error;
926         }
927
928         /* slice doesn't fit in buffer */
929         if( sample_cons.sampleoffset + sample_cons.length > p_block->i_buffer)
930         {
931             msg_Err(p_demux, "Sample buffer is smaller than sample" );
932             goto error;
933         }
934
935         block_t *p_realloc = block_Realloc( p_newblock, 0, i_payload + sample_cons.length + 4 );
936         if( !p_realloc )
937             goto error;
938
939         p_newblock = p_realloc;
940         uint8_t *p_dst = &p_newblock->p_buffer[i_payload];
941
942         const uint8_t* p_src = p_block->p_buffer + sample_cons.sampleoffset;
943         uint8_t i_type = (*p_src) & ((1<<5)-1);
944
945         const uint8_t synccode[4] = { 0, 0, 0, 1 };
946         if( memcmp( p_src, synccode, 4 ) )
947         {
948             if( i_type == 7 || i_type == 8 )
949                 *p_dst++=0;
950
951             p_dst[0] = 0;
952             p_dst[1] = 0;
953             p_dst[2] = 1;
954             p_dst += 3;
955         }
956
957         memcpy( p_dst, p_src, sample_cons.length );
958         p_dst += sample_cons.length;
959
960         i_payload += p_dst - p_newblock->p_buffer;
961     }
962
963     block_Release( p_block );
964     if( p_newblock )
965         p_newblock->i_buffer = i_payload;
966     return p_newblock;
967
968 error:
969     block_Release( p_block );
970     if( p_newblock )
971         block_Release( p_newblock );
972     return NULL;
973 }
974
975 /* RTP Reception Hint Track */
976 static block_t * MP4_RTPHint_Convert( demux_t *p_demux, block_t *p_block, vlc_fourcc_t i_codec )
977 {
978     block_t *p_converted = NULL;
979     if( p_block->i_buffer < 2 )
980     {
981         block_Release( p_block );
982         return NULL;
983     }
984
985     /* number of RTP packets contained in this sample */
986     const uint16_t i_packets = GetWBE( p_block->p_buffer );
987     if( i_packets <= 1 || i_codec != VLC_CODEC_H264 )
988     {
989         const size_t i_skip = SAMPLEHEADERSIZE + i_packets * ( RTPPACKETSIZE + CONSTRUCTORSIZE );
990         if( i_packets == 1 && i_skip < p_block->i_buffer )
991         {
992             p_block->p_buffer += i_skip;
993             p_converted = p_block;
994         }
995         else
996         {
997             block_Release( p_block );
998         }
999     }
1000     else
1001     {
1002         p_converted = MP4_RTPHintToFrame( p_demux, p_block, i_packets );
1003     }
1004
1005     return p_converted;
1006 }
1007
1008 /*****************************************************************************
1009  * Demux: read packet and send them to decoders
1010  *****************************************************************************
1011  * TODO check for newly selected track (ie audio upt to now )
1012  *****************************************************************************/
1013 static int Demux( demux_t *p_demux )
1014 {
1015     demux_sys_t *p_sys = p_demux->p_sys;
1016     unsigned int i_track;
1017
1018
1019     unsigned int i_track_selected;
1020
1021     /* check for newly selected/unselected track */
1022     for( i_track = 0, i_track_selected = 0; i_track < p_sys->i_tracks;
1023          i_track++ )
1024     {
1025         mp4_track_t *tk = &p_sys->track[i_track];
1026         bool b;
1027
1028         if( !tk->b_ok || tk->b_chapters_source ||
1029             ( tk->b_selected && tk->i_sample >= tk->i_sample_count ) )
1030         {
1031             continue;
1032         }
1033
1034         es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
1035
1036         if( tk->b_selected && !b )
1037         {
1038             MP4_TrackUnselect( p_demux, tk );
1039         }
1040         else if( !tk->b_selected && b)
1041         {
1042             MP4_TrackSelect( p_demux, tk, MP4_GetMoviePTS( p_sys ) );
1043         }
1044
1045         if( tk->b_selected )
1046         {
1047             i_track_selected++;
1048         }
1049     }
1050
1051     if( i_track_selected <= 0 )
1052     {
1053         p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 );
1054         if( p_sys->i_timescale > 0 )
1055         {
1056             int64_t i_length = CLOCK_FREQ *
1057                                (mtime_t)p_sys->i_overall_duration /
1058                                (mtime_t)p_sys->i_timescale;
1059             if( MP4_GetMoviePTS( p_sys ) >= i_length )
1060                 return VLC_DEMUXER_EOF;
1061             return VLC_DEMUXER_SUCCESS;
1062         }
1063
1064         msg_Warn( p_demux, "no track selected, exiting..." );
1065         return VLC_DEMUXER_EOF;
1066     }
1067
1068     /* */
1069     MP4_UpdateSeekpoint( p_demux );
1070
1071     /* first wait for the good time to read a packet */
1072     p_sys->i_pcr = MP4_GetMoviePTS( p_sys );
1073
1074     bool b_data_sent = false;
1075
1076     /* Find next track matching contiguous data */
1077     mp4_track_t *tk = NULL;
1078     uint64_t i_candidate_pos = UINT64_MAX;
1079     mtime_t i_candidate_dts = INT64_MAX;
1080     for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
1081     {
1082         mp4_track_t *tk_tmp = &p_sys->track[i_track];
1083         if( !tk_tmp->b_ok || tk_tmp->b_chapters_source || !tk_tmp->b_selected || tk_tmp->i_sample >= tk_tmp->i_sample_count )
1084             continue;
1085
1086         if ( p_sys->b_seekmode )
1087         {
1088             mtime_t i_dts = MP4_TrackGetDTS( p_demux, tk_tmp );
1089             if ( i_dts <= i_candidate_dts )
1090             {
1091                 tk = tk_tmp;
1092                 i_candidate_dts = i_dts;
1093                 i_candidate_pos = MP4_TrackGetPos( tk_tmp );
1094             }
1095         }
1096         else
1097         {
1098             /* Try to avoid seeking on non fastseekable. Will fail with non interleaved content */
1099             uint64_t i_pos = MP4_TrackGetPos( tk_tmp );
1100             if ( i_pos <= i_candidate_pos )
1101             {
1102                 i_candidate_pos = i_pos;
1103                 tk = tk_tmp;
1104             }
1105         }
1106     }
1107
1108     uint32_t i_nb_samples = 0;
1109     uint32_t i_samplessize = 0;
1110
1111     if ( !tk )
1112     {
1113         msg_Dbg( p_demux, "Could not select track by data position" );
1114         goto end;
1115     }
1116     else if ( p_sys->b_seekmode )
1117     {
1118         if( stream_Seek( p_demux->s, i_candidate_pos ) )
1119         {
1120             msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)",
1121                       tk->i_track_ID );
1122             MP4_TrackUnselect( p_demux, tk );
1123             goto end;
1124         }
1125     }
1126
1127 #if 0
1128     msg_Dbg( p_demux, "tk(%i)=%"PRId64" mv=%"PRId64" pos=%"PRIu64, tk->i_track_ID,
1129              MP4_TrackGetDTS( p_demux, tk ),
1130              MP4_GetMoviePTS( p_sys ), i_candidate_pos );
1131 #endif
1132
1133     i_samplessize = MP4_TrackGetReadSize( tk, &i_nb_samples );
1134     if( i_samplessize > 0 )
1135     {
1136         block_t *p_block;
1137         int64_t i_delta;
1138         uint64_t i_current_pos;
1139
1140         /* go,go go ! */
1141         i_current_pos = stream_Tell( p_demux->s );
1142
1143         if( i_current_pos != i_candidate_pos )
1144         {
1145             if( stream_Seek( p_demux->s, i_candidate_pos ) )
1146             {
1147                 msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)"
1148                           ": Failed to seek to %"PRIu64,
1149                           tk->i_track_ID, i_candidate_pos );
1150                 MP4_TrackUnselect( p_demux, tk );
1151                 goto end;
1152             }
1153             i_current_pos = i_candidate_pos;
1154         }
1155
1156         /* now read pes */
1157         if( !(p_block = MP4_Block_Read( p_demux, tk, i_samplessize )) )
1158         {
1159             msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)"
1160                       ": Failed to read %d bytes sample at %"PRIu64,
1161                       tk->i_track_ID, i_samplessize, i_current_pos );
1162             MP4_TrackUnselect( p_demux, tk );
1163             goto end;
1164         }
1165
1166         /* dts */
1167         p_block->i_dts = VLC_TS_0 + MP4_TrackGetDTS( p_demux, tk );
1168         /* pts */
1169         if( MP4_TrackGetPTSDelta( p_demux, tk, &i_delta ) )
1170             p_block->i_pts = p_block->i_dts + i_delta;
1171         else if( tk->fmt.i_cat != VIDEO_ES )
1172             p_block->i_pts = p_block->i_dts;
1173         else
1174             p_block->i_pts = VLC_TS_INVALID;
1175
1176         if ( !b_data_sent )
1177         {
1178             es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_pcr );
1179             b_data_sent = true;
1180         }
1181         MP4_Block_Send( p_demux, tk, p_block );
1182     }
1183
1184     /* Next sample */
1185     if ( i_nb_samples ) /* sample size could be 0, need to go fwd. see return */
1186         MP4_TrackNextSample( p_demux, tk, i_nb_samples );
1187
1188 end:
1189     if ( b_data_sent )
1190     {
1191         p_sys->i_pcr = INT64_MAX;
1192         for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
1193         {
1194             mp4_track_t *tk = &p_sys->track[i_track];
1195             if ( !tk->b_ok || !tk->b_selected  ||
1196                  (tk->fmt.i_cat != AUDIO_ES && tk->fmt.i_cat != VIDEO_ES) )
1197                 continue;
1198
1199             mtime_t i_dts = MP4_TrackGetDTS( p_demux, tk );
1200             p_sys->i_pcr = __MIN( i_dts, p_sys->i_pcr );
1201             p_sys->i_time = p_sys->i_pcr * p_sys->i_timescale / CLOCK_FREQ;
1202         }
1203     }
1204
1205     return (b_data_sent || ( i_samplessize == 0 && i_nb_samples )) ? VLC_DEMUXER_SUCCESS : VLC_DEMUXER_EOF;
1206 }
1207
1208 static void MP4_UpdateSeekpoint( demux_t *p_demux )
1209 {
1210     demux_sys_t *p_sys = p_demux->p_sys;
1211     int64_t i_time;
1212     int i;
1213     if( !p_sys->p_title )
1214         return;
1215     i_time = MP4_GetMoviePTS( p_sys );
1216     for( i = 0; i < p_sys->p_title->i_seekpoint; i++ )
1217     {
1218         if( i_time < p_sys->p_title->seekpoint[i]->i_time_offset )
1219             break;
1220     }
1221     i--;
1222
1223     if( i != p_demux->info.i_seekpoint && i >= 0 )
1224     {
1225         p_demux->info.i_seekpoint = i;
1226         p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
1227     }
1228 }
1229 /*****************************************************************************
1230  * Seek: Go to i_date
1231 ******************************************************************************/
1232 static int Seek( demux_t *p_demux, mtime_t i_date )
1233 {
1234     demux_sys_t *p_sys = p_demux->p_sys;
1235     unsigned int i_track;
1236
1237     /* First update global time */
1238     p_sys->i_time = i_date * p_sys->i_timescale / CLOCK_FREQ;
1239     p_sys->i_pcr  = VLC_TS_INVALID;
1240
1241     /* Now for each stream try to go to this time */
1242     for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
1243     {
1244         mp4_track_t *tk = &p_sys->track[i_track];
1245         MP4_TrackSeek( p_demux, tk, i_date );
1246     }
1247     MP4_UpdateSeekpoint( p_demux );
1248
1249     MP4ASF_ResetFrames( p_sys );
1250     es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_date );
1251
1252     return VLC_SUCCESS;
1253 }
1254
1255 static int LeafSeekIntoFragment( demux_t *p_demux, mp4_fragment_t *p_fragment )
1256 {
1257     demux_sys_t *p_sys = p_demux->p_sys;
1258     uint64_t i64 = p_fragment->i_chunk_range_min_offset;
1259
1260     if ( p_fragment->p_moox->i_type == ATOM_moov )
1261     {
1262         mp4_track_t *p_track;
1263         unsigned int i_chunk;
1264         int i_ret = LeafGetTrackAndChunkByMOOVPos( p_demux, &i64, &p_track, &i_chunk );
1265         if ( i_ret == VLC_EGENERIC )
1266         {
1267             msg_Dbg( p_demux, "moov seek failed to identify %"PRIu64, i64 );
1268             return i_ret;
1269         }
1270         msg_Dbg( p_demux, "moov seeking to %"PRIu64, i64 );
1271     }
1272     else
1273     {
1274         i64 = p_fragment->i_chunk_range_min_offset;
1275         msg_Dbg( p_demux, "moof seeking to %"PRIu64, i64 );
1276     }
1277
1278     if( stream_Seek( p_demux->s, i64 ) )
1279     {
1280         msg_Err( p_demux, "seek failed to %"PRIu64, i64 );
1281         return VLC_EGENERIC;
1282     }
1283
1284     /* map context */
1285     p_sys->context.p_fragment = p_fragment;
1286     p_sys->context.i_current_box_type = ATOM_mdat;
1287     LeafMapTrafTrunContextes( p_demux, p_fragment->p_moox );
1288     p_sys->context.i_mdatbytesleft = p_fragment->i_chunk_range_max_offset - i64;
1289
1290     mtime_t i_time_base = 0;
1291     for( unsigned int i_track = 0; i_track < p_sys->i_tracks; i_track++ )
1292     {
1293         stime_t i_tracktime = GetTrackFragmentTimeOffset( &p_sys->fragments, p_fragment,
1294                                 p_sys->track[i_track].i_track_ID );
1295         p_sys->track[i_track].i_time = i_tracktime *  p_sys->track[i_track].i_timescale / p_sys->i_timescale;
1296         i_time_base = __MIN( i_time_base, i_tracktime );
1297     }
1298     p_sys->i_time = i_time_base;
1299     p_sys->i_pcr  = VLC_TS_INVALID;
1300
1301     return VLC_SUCCESS;
1302 }
1303
1304 static int LeafSeekToTime( demux_t *p_demux, mtime_t i_nztime )
1305 {
1306     demux_sys_t *p_sys = p_demux->p_sys;
1307     mp4_fragment_t *p_fragment = NULL;
1308     uint64_t i64 = 0;
1309     if ( !p_sys->i_timescale || !p_sys->i_overall_duration || !p_sys->b_seekable )
1310          return VLC_EGENERIC;
1311
1312     if ( !p_sys->b_fragments_probed && !p_sys->b_index_probed && p_sys->b_seekable )
1313     {
1314         ProbeIndex( p_demux );
1315         p_sys->b_index_probed = true;
1316     }
1317
1318     if ( p_demux->p_sys->b_fragments_probed )
1319     {
1320         /* Fill out temp track ID list */
1321         unsigned *pi_tracksid = (unsigned *) malloc( sizeof(unsigned) * p_sys->i_tracks );
1322         if(pi_tracksid)
1323         {
1324             for( unsigned i=0; i<p_sys->i_tracks; i++ )
1325                 pi_tracksid[i] = p_sys->track[i].i_track_ID;
1326
1327             p_fragment = GetFragmentByTime( &p_sys->fragments, i_nztime,
1328                                         p_sys->i_tracks, pi_tracksid,
1329                                         p_sys->i_timescale );
1330             free( pi_tracksid );
1331         }
1332     }
1333
1334     if ( !p_fragment )
1335     {
1336         mtime_t i_mooftime;
1337         msg_Dbg( p_demux, "seek can't find matching fragment for %"PRId64", trying index", i_nztime );
1338         if ( LeafIndexGetMoofPosByTime( p_demux, i_nztime, &i64, &i_mooftime ) == VLC_SUCCESS )
1339         {
1340             msg_Dbg( p_demux, "seek trying to go to unknown but indexed fragment at %"PRId64, i64 );
1341             if( stream_Seek( p_demux->s, i64 ) )
1342             {
1343                 msg_Err( p_demux, "seek to moof failed %"PRId64, i64 );
1344                 return VLC_EGENERIC;
1345             }
1346             p_sys->context.i_current_box_type = 0;
1347             p_sys->context.i_mdatbytesleft = 0;
1348             p_sys->context.p_fragment = NULL;
1349             for( unsigned int i_track = 0; i_track < p_sys->i_tracks; i_track++ )
1350             {
1351                 p_sys->track[i_track].i_time = i_mooftime / CLOCK_FREQ * p_sys->track[i_track].i_timescale;
1352             }
1353             p_sys->i_time = i_mooftime / CLOCK_FREQ * p_sys->i_timescale;
1354             p_sys->i_pcr  = VLC_TS_INVALID;
1355         }
1356         else
1357         {
1358             msg_Warn( p_demux, "seek by index failed" );
1359             return VLC_EGENERIC;
1360         }
1361     }
1362     else
1363     {
1364         msg_Dbg( p_demux, "seeking to fragment data starting at %"PRIu64" for time %"PRId64,
1365                            p_fragment->i_chunk_range_min_offset, i_nztime );
1366         if ( LeafSeekIntoFragment( p_demux, p_fragment ) != VLC_SUCCESS )
1367             return VLC_EGENERIC;
1368     }
1369
1370     MP4ASF_ResetFrames( p_sys );
1371     /* And set next display time in that trun/fragment */
1372     es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, VLC_TS_0 + i_nztime );
1373     return VLC_SUCCESS;
1374 }
1375
1376 static int LeafSeekToPos( demux_t *p_demux, double f )
1377 {
1378     demux_sys_t *p_sys = p_demux->p_sys;
1379     if ( !p_sys->b_seekable )
1380         return VLC_EGENERIC;
1381
1382     if ( p_sys->i_timescale && p_sys->i_overall_duration )
1383     {
1384         return LeafSeekToTime( p_demux,
1385                     (mtime_t)( f * CLOCK_FREQ * p_sys->i_overall_duration /
1386                                p_sys->i_timescale ) );
1387     }
1388
1389     if ( !p_sys->b_fragments_probed && !p_sys->b_index_probed && p_sys->b_seekable )
1390     {
1391         ProbeIndex( p_demux );
1392         p_sys->b_index_probed = true;
1393     }
1394
1395     /* Blind seek to pos only */
1396     uint64_t i64 = (uint64_t) stream_Size( p_demux->s ) * f;
1397     mp4_fragment_t *p_fragment = GetFragmentByPos( &p_sys->fragments, i64, false );
1398     if ( p_fragment )
1399     {
1400         msg_Dbg( p_demux, "fragment matched %"PRIu64" << %"PRIu64" << %"PRIu64,
1401                  p_fragment->i_chunk_range_min_offset, i64,
1402                  p_fragment->i_chunk_range_max_offset );
1403         msg_Dbg( p_demux, "Seeking to fragment data starting at %"PRIu64" for pos %"PRIu64,
1404                  p_fragment->i_chunk_range_min_offset, i64 );
1405         return LeafSeekIntoFragment( p_demux, p_fragment );
1406     }
1407     else
1408     {
1409         msg_Dbg( p_demux, "Cant get fragment for data starting at %"PRIu64, i64 );
1410         return VLC_EGENERIC;
1411     }
1412 }
1413
1414 static int MP4_frg_Seek( demux_t *p_demux, double f )
1415 {
1416     demux_sys_t *p_sys = p_demux->p_sys;
1417
1418     int64_t i64 = stream_Size( p_demux->s );
1419     if( stream_Seek( p_demux->s, (int64_t)(i64 * f) ) )
1420     {
1421         return VLC_EGENERIC;
1422     }
1423     else
1424     {
1425         /* update global time */
1426         p_sys->i_time = (uint64_t)(f * (double)p_sys->i_overall_duration);
1427         p_sys->i_pcr  = MP4_GetMoviePTS( p_sys );
1428
1429         for( unsigned i_track = 0; i_track < p_sys->i_tracks; i_track++ )
1430         {
1431             mp4_track_t *tk = &p_sys->track[i_track];
1432
1433             /* We don't want the current chunk to be flushed */
1434             tk->cchunk->i_sample = tk->cchunk->i_sample_count;
1435
1436             /* reset/update some values */
1437             tk->i_sample = tk->i_sample_first = 0;
1438             tk->i_first_dts = p_sys->i_time;
1439
1440             /* We want to discard the current chunk and get the next one at once */
1441             tk->b_has_non_empty_cchunk = false;
1442         }
1443         es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, p_sys->i_pcr );
1444         return VLC_SUCCESS;
1445     }
1446 }
1447
1448 static bool imageTypeCompatible( const MP4_Box_data_data_t *p_data )
1449 {
1450     return p_data && (
1451     p_data->e_wellknowntype == DATA_WKT_PNG ||
1452     p_data->e_wellknowntype == DATA_WKT_JPEG ||
1453     p_data->e_wellknowntype == DATA_WKT_BMP );
1454 }
1455
1456 /*****************************************************************************
1457  * Control:
1458  *****************************************************************************/
1459 static int Control( demux_t *p_demux, int i_query, va_list args )
1460 {
1461     demux_sys_t *p_sys = p_demux->p_sys;
1462
1463     double f, *pf;
1464     int64_t i64, *pi64;
1465
1466     const char *psz_roots[] = { "/moov/udta/meta/ilst",
1467                                 "/moov/meta/ilst",
1468                                 "/moov/udta/meta",
1469                                 "/moov/udta",
1470                                 "/meta/ilst",
1471                                 "/udta",
1472                                 NULL };
1473     const uint32_t rgi_pict_atoms[2] = { ATOM_PICT, ATOM_pict };
1474
1475     switch( i_query )
1476     {
1477         case DEMUX_CAN_SEEK:
1478             *va_arg( args, bool * ) = p_sys->b_seekable;
1479             return VLC_SUCCESS;
1480
1481         case DEMUX_GET_POSITION:
1482             pf = (double*)va_arg( args, double * );
1483             if( p_sys->i_overall_duration > 0 )
1484             {
1485                 *pf = (double)p_sys->i_time / (double)p_sys->i_overall_duration;
1486             }
1487             else
1488             {
1489                 *pf = 0.0;
1490             }
1491             return VLC_SUCCESS;
1492
1493         case DEMUX_SET_POSITION:
1494             f = (double)va_arg( args, double );
1495             if ( p_demux->pf_demux == DemuxAsLeaf )
1496                 return LeafSeekToPos( p_demux, f );
1497             else if ( p_demux->pf_demux == DemuxFrg )
1498                 return MP4_frg_Seek( p_demux, f );
1499             else if( p_sys->i_timescale > 0 )
1500             {
1501                 i64 = (int64_t)( f * CLOCK_FREQ *
1502                                  (double)p_sys->i_overall_duration /
1503                                  (double)p_sys->i_timescale );
1504                 return Seek( p_demux, i64 );
1505             }
1506             else return VLC_EGENERIC;
1507
1508         case DEMUX_GET_TIME:
1509             pi64 = (int64_t*)va_arg( args, int64_t * );
1510             if( p_sys->i_timescale > 0 )
1511             {
1512                 *pi64 = CLOCK_FREQ *
1513                         (mtime_t)p_sys->i_time /
1514                         (mtime_t)p_sys->i_timescale;
1515             }
1516             else *pi64 = 0;
1517             return VLC_SUCCESS;
1518
1519         case DEMUX_SET_TIME:
1520             i64 = (int64_t)va_arg( args, int64_t );
1521             if ( p_demux->pf_demux == DemuxAsLeaf )
1522                 return LeafSeekToTime( p_demux, i64 );
1523             else
1524                 return Seek( p_demux, i64 );
1525
1526         case DEMUX_GET_LENGTH:
1527             pi64 = (int64_t*)va_arg( args, int64_t * );
1528             if( p_sys->i_timescale > 0 )
1529             {
1530                 *pi64 = CLOCK_FREQ *
1531                         (mtime_t)p_sys->i_overall_duration /
1532                         (mtime_t)p_sys->i_timescale;
1533             }
1534             else *pi64 = 0;
1535             return VLC_SUCCESS;
1536
1537         case DEMUX_GET_FPS:
1538             pf = (double*)va_arg( args, double* );
1539             *pf = p_sys->f_fps;
1540             return VLC_SUCCESS;
1541
1542         case DEMUX_GET_ATTACHMENTS:
1543         {
1544             input_attachment_t ***ppp_attach = va_arg( args, input_attachment_t*** );
1545             int *pi_int = va_arg( args, int * );
1546
1547             MP4_Box_t *p_udta = NULL;
1548             size_t i_count = 0;
1549             int i_index = 0;
1550
1551             /* Count number of total attachments */
1552             for( ; psz_roots[i_index] && !p_udta; i_index++ )
1553             {
1554                 p_udta = MP4_BoxGet( p_sys->p_root, psz_roots[i_index] );
1555                 if ( p_udta )
1556                     i_count += MP4_BoxCount( p_udta, "covr/data" );
1557             }
1558
1559             for ( size_t i=0; i< ARRAY_SIZE(rgi_pict_atoms); i++ )
1560             {
1561                 char rgsz_path[5];
1562                 snprintf( rgsz_path, 5, "%4.4s", (char*)&rgi_pict_atoms[i] );
1563                 i_count += MP4_BoxCount( p_sys->p_root, rgsz_path );
1564             }
1565
1566             if ( i_count == 0 )
1567                 return VLC_EGENERIC;
1568
1569             *ppp_attach = (input_attachment_t**)
1570                     malloc( sizeof(input_attachment_t*) * i_count );
1571             if( !(*ppp_attach) ) return VLC_ENOMEM;
1572
1573             /* First add cover attachments */
1574             i_count = 0;
1575             size_t i_box_count = 0;
1576             if ( p_udta )
1577             {
1578                 const MP4_Box_t *p_data = MP4_BoxGet( p_udta, "covr/data" );
1579                 for( ; p_data; p_data = p_data->p_next )
1580                 {
1581                     char *psz_mime;
1582                     char *psz_filename;
1583                     i_box_count++;
1584
1585                     if ( p_data->i_type != ATOM_data || !imageTypeCompatible( BOXDATA(p_data) ) )
1586                         continue;
1587
1588                     switch( BOXDATA(p_data)->e_wellknowntype )
1589                     {
1590                     case DATA_WKT_PNG:
1591                         psz_mime = strdup( "image/png" );
1592                         break;
1593                     case DATA_WKT_JPEG:
1594                         psz_mime = strdup( "image/jpeg" );
1595                         break;
1596                     case DATA_WKT_BMP:
1597                         psz_mime = strdup( "image/bmp" );
1598                         break;
1599                     default:
1600                         continue;
1601                     }
1602
1603                     if ( asprintf( &psz_filename, "%s/covr/data[%"PRIu64"]", psz_roots[i_index - 1],
1604                                    (uint64_t) i_box_count - 1 ) >= 0 )
1605                     {
1606                         (*ppp_attach)[i_count++] =
1607                             vlc_input_attachment_New( psz_filename, psz_mime, "Cover picture",
1608                                 BOXDATA(p_data)->p_blob, BOXDATA(p_data)->i_blob );
1609                         msg_Dbg( p_demux, "adding attachment %s", psz_filename );
1610                         free( psz_filename );
1611                     }
1612
1613                     free( psz_mime );
1614                 }
1615             }
1616
1617             /* Then quickdraw pict ones */
1618             for ( size_t i=0; i< ARRAY_SIZE(rgi_pict_atoms); i++ )
1619             {
1620                 char rgsz_path[5];
1621                 snprintf( rgsz_path, 5, "%4.4s", (char*)&rgi_pict_atoms[i] );
1622                 const MP4_Box_t *p_pict = MP4_BoxGet( p_sys->p_root, rgsz_path );
1623                 i_box_count = 0;
1624                 for( ; p_pict; p_pict = p_pict->p_next )
1625                 {
1626                     if ( i_box_count++ == UINT16_MAX ) /* pnot only handles 2^16 */
1627                         break;
1628                     if ( p_pict->i_type != rgi_pict_atoms[i] )
1629                         continue;
1630                     char rgsz_location[12];
1631                     snprintf( rgsz_location, 12, "%4.4s[%"PRIu16"]", (char*)&rgi_pict_atoms[i],
1632                               (uint16_t) i_box_count - 1 );
1633                     (*ppp_attach)[i_count] = vlc_input_attachment_New( rgsz_location, "image/x-pict",
1634                         "Quickdraw image", p_pict->data.p_binary->p_blob, p_pict->data.p_binary->i_blob );
1635                     if ( !(*ppp_attach)[i_count] )
1636                     {
1637                         i_count = 0;
1638                         break;
1639                     }
1640                     i_count++;
1641                     msg_Dbg( p_demux, "adding attachment %s", rgsz_location );
1642                 }
1643             }
1644
1645             if ( i_count == 0 )
1646             {
1647                 free( *ppp_attach );
1648                 return VLC_EGENERIC;
1649             }
1650
1651             *pi_int = i_count;
1652
1653             return VLC_SUCCESS;
1654         }
1655
1656         case DEMUX_GET_META:
1657         {
1658             vlc_meta_t *p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t*);
1659
1660             MP4_Box_t *p_data = NULL;
1661             MP4_Box_t *p_udta = NULL;
1662             bool b_attachment_set = false;
1663
1664             for( int i_index = 0; psz_roots[i_index] && !p_udta; i_index++ )
1665             {
1666                 p_udta = MP4_BoxGet( p_sys->p_root, psz_roots[i_index] );
1667                 if ( p_udta )
1668                 {
1669                     p_data = MP4_BoxGet( p_udta, "covr/data" );
1670                     if ( p_data && imageTypeCompatible( BOXDATA(p_data) ) )
1671                     {
1672                         char *psz_attachment;
1673                         if ( -1 != asprintf( &psz_attachment, "attachment://%s/covr/data[0]",
1674                                              psz_roots[i_index] ) )
1675                         {
1676                             vlc_meta_SetArtURL( p_meta, psz_attachment );
1677                             b_attachment_set = true;
1678                             free( psz_attachment );
1679                         }
1680                     }
1681                 }
1682             }
1683
1684             const MP4_Box_t *p_pnot;
1685             if ( !b_attachment_set && (p_pnot = MP4_BoxGet( p_sys->p_root, "pnot" )) )
1686             {
1687                 for ( size_t i=0; i< ARRAY_SIZE(rgi_pict_atoms) && !b_attachment_set; i++ )
1688                 {
1689                     if ( rgi_pict_atoms[i] == BOXDATA(p_pnot)->i_type )
1690                     {
1691                         char rgsz_path[26];
1692                         snprintf( rgsz_path, 26, "attachment://%4.4s[%"PRIu16"]",
1693                                   (char*)&rgi_pict_atoms[i], BOXDATA(p_pnot)->i_index - 1 );
1694                         vlc_meta_SetArtURL( p_meta, rgsz_path );
1695                         b_attachment_set = true;
1696                     }
1697                 }
1698             }
1699
1700             if( p_udta == NULL && !b_attachment_set )
1701                 return VLC_EGENERIC;
1702
1703             SetupMeta( p_meta, p_udta );
1704
1705             return VLC_SUCCESS;
1706         }
1707
1708         case DEMUX_GET_TITLE_INFO:
1709         {
1710             input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
1711             int *pi_int    = (int*)va_arg( args, int* );
1712             int *pi_title_offset = (int*)va_arg( args, int* );
1713             int *pi_seekpoint_offset = (int*)va_arg( args, int* );
1714
1715             if( !p_sys->p_title )
1716                 return VLC_EGENERIC;
1717
1718             *pi_int = 1;
1719             *ppp_title = malloc( sizeof( input_title_t*) );
1720             (*ppp_title)[0] = vlc_input_title_Duplicate( p_sys->p_title );
1721             *pi_title_offset = 0;
1722             *pi_seekpoint_offset = 0;
1723             return VLC_SUCCESS;
1724         }
1725         case DEMUX_SET_TITLE:
1726         {
1727             const int i_title = (int)va_arg( args, int );
1728             if( !p_sys->p_title || i_title != 0 )
1729                 return VLC_EGENERIC;
1730             return VLC_SUCCESS;
1731         }
1732         case DEMUX_SET_SEEKPOINT:
1733         {
1734             const int i_seekpoint = (int)va_arg( args, int );
1735             if( !p_sys->p_title )
1736                 return VLC_EGENERIC;
1737             return Seek( p_demux, p_sys->p_title->seekpoint[i_seekpoint]->i_time_offset );
1738         }
1739         case DEMUX_GET_PTS_DELAY:
1740         {
1741             for( unsigned int i = 0; i < p_sys->i_tracks; i++ )
1742             {
1743                 const MP4_Box_t *p_load;
1744                 if ( (p_load = MP4_BoxGet( p_sys->track[i].p_track, "load" )) &&
1745                      BOXDATA(p_load)->i_duration > 0 )
1746                 {
1747                     *va_arg(args, int64_t *) = BOXDATA(p_load)->i_duration *
1748                             CLOCK_FREQ / p_sys->track[i].i_timescale;
1749                     return VLC_SUCCESS;
1750                 }
1751             }
1752             return VLC_EGENERIC;
1753         }
1754         case DEMUX_SET_NEXT_DEMUX_TIME:
1755         case DEMUX_SET_GROUP:
1756         case DEMUX_HAS_UNSUPPORTED_META:
1757         case DEMUX_CAN_RECORD:
1758             return VLC_EGENERIC;
1759
1760         default:
1761             msg_Warn( p_demux, "control query %u unimplemented", i_query );
1762             return VLC_EGENERIC;
1763     }
1764 }
1765
1766 /*****************************************************************************
1767  * Close: frees unused data
1768  *****************************************************************************/
1769 static void Close ( vlc_object_t * p_this )
1770 {
1771     demux_t *  p_demux = (demux_t *)p_this;
1772     demux_sys_t *p_sys = p_demux->p_sys;
1773     unsigned int i_track;
1774
1775     msg_Dbg( p_demux, "freeing all memory" );
1776
1777     MP4_BoxFree( p_sys->p_root );
1778     for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
1779     {
1780         MP4_TrackDestroy( p_demux, &p_sys->track[i_track] );
1781     }
1782     free( p_sys->track );
1783
1784     if( p_sys->p_title )
1785         vlc_input_title_Delete( p_sys->p_title );
1786
1787     MP4_Fragments_Clean( &p_sys->fragments );
1788
1789     free( p_sys );
1790 }
1791
1792
1793
1794 /****************************************************************************
1795  * Local functions, specific to vlc
1796  ****************************************************************************/
1797 /* Chapters */
1798 static void LoadChapterGpac( demux_t  *p_demux, MP4_Box_t *p_chpl )
1799 {
1800     demux_sys_t *p_sys = p_demux->p_sys;
1801     int i;
1802
1803     p_sys->p_title = vlc_input_title_New();
1804     for( i = 0; i < BOXDATA(p_chpl)->i_chapter; i++ )
1805     {
1806         seekpoint_t *s = vlc_seekpoint_New();
1807
1808         s->psz_name = strdup( BOXDATA(p_chpl)->chapter[i].psz_name );
1809         EnsureUTF8( s->psz_name );
1810         s->i_time_offset = BOXDATA(p_chpl)->chapter[i].i_start / 10;
1811         TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
1812     }
1813 }
1814 static void LoadChapterApple( demux_t  *p_demux, mp4_track_t *tk )
1815 {
1816     demux_sys_t *p_sys = p_demux->p_sys;
1817
1818     for( tk->i_sample = 0; tk->i_sample < tk->i_sample_count; tk->i_sample++ )
1819     {
1820         const int64_t i_dts = MP4_TrackGetDTS( p_demux, tk );
1821         int64_t i_pts_delta;
1822         if ( !MP4_TrackGetPTSDelta( p_demux, tk, &i_pts_delta ) )
1823             i_pts_delta = 0;
1824         uint32_t i_nb_samples = 0;
1825         const uint32_t i_size = MP4_TrackGetReadSize( tk, &i_nb_samples );
1826
1827         if( i_size > 0 && !stream_Seek( p_demux->s, MP4_TrackGetPos( tk ) ) )
1828         {
1829             char p_buffer[256];
1830             const uint32_t i_read = stream_ReadU32( p_demux->s, p_buffer,
1831                                                     __MIN( sizeof(p_buffer), i_size ) );
1832             const uint32_t i_len = __MIN( GetWBE(p_buffer), i_read-2 );
1833
1834             if( i_len > 0 )
1835             {
1836                 seekpoint_t *s = vlc_seekpoint_New();
1837
1838                 s->psz_name = strndup( &p_buffer[2], i_len );
1839                 EnsureUTF8( s->psz_name );
1840
1841                 s->i_time_offset = i_dts + __MAX( i_pts_delta, 0 );
1842
1843                 if( !p_sys->p_title )
1844                     p_sys->p_title = vlc_input_title_New();
1845                 TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
1846             }
1847         }
1848         if( tk->i_sample+1 >= tk->chunk[tk->i_chunk].i_sample_first +
1849                               tk->chunk[tk->i_chunk].i_sample_count )
1850             tk->i_chunk++;
1851     }
1852 }
1853 static void LoadChapter( demux_t  *p_demux )
1854 {
1855     demux_sys_t *p_sys = p_demux->p_sys;
1856     MP4_Box_t *p_chpl;
1857
1858     if( ( p_chpl = MP4_BoxGet( p_sys->p_root, "/moov/udta/chpl" ) ) &&
1859           BOXDATA(p_chpl) && BOXDATA(p_chpl)->i_chapter > 0 )
1860     {
1861         LoadChapterGpac( p_demux, p_chpl );
1862     }
1863     else if( p_sys->p_tref_chap )
1864     {
1865         MP4_Box_data_tref_generic_t *p_chap = p_sys->p_tref_chap->data.p_tref_generic;
1866         unsigned int i, j;
1867
1868         /* Load the first subtitle track like quicktime */
1869         for( i = 0; i < p_chap->i_entry_count; i++ )
1870         {
1871             for( j = 0; j < p_sys->i_tracks; j++ )
1872             {
1873                 mp4_track_t *tk = &p_sys->track[j];
1874                 if( tk->b_ok && tk->i_track_ID == p_chap->i_track_ID[i] &&
1875                     tk->fmt.i_cat == SPU_ES && tk->fmt.i_codec == VLC_CODEC_TX3G )
1876                     break;
1877             }
1878             if( j < p_sys->i_tracks )
1879             {
1880                 LoadChapterApple( p_demux, &p_sys->track[j] );
1881                 break;
1882             }
1883         }
1884     }
1885
1886     /* Add duration if titles are enabled */
1887     if( p_sys->p_title )
1888     {
1889         p_sys->p_title->i_length = CLOCK_FREQ *
1890                        (uint64_t)p_sys->i_overall_duration / (uint64_t)p_sys->i_timescale;
1891     }
1892 }
1893
1894 static bool MP4_TrackIsInterleaved( const mp4_track_t *p_track )
1895 {
1896     const MP4_Box_t *p_stsc = MP4_BoxGet( p_track->p_stbl, "stsc" );
1897     const MP4_Box_t *p_stsz = MP4_BoxGet( p_track->p_stbl, "stsz" );
1898     if( p_stsc && BOXDATA(p_stsc) && p_stsz && BOXDATA(p_stsz) )
1899     {
1900         if( BOXDATA(p_stsc)->i_entry_count == 1 &&
1901             BOXDATA(p_stsz)->i_sample_count > 1 &&
1902             BOXDATA(p_stsc)->i_samples_per_chunk[0] == BOXDATA(p_stsz)->i_sample_count )
1903             return false;
1904     }
1905
1906     return true;
1907 }
1908
1909 /* now create basic chunk data, the rest will be filled by MP4_CreateSamplesIndex */
1910 static int TrackCreateChunksIndex( demux_t *p_demux,
1911                                    mp4_track_t *p_demux_track )
1912 {
1913     demux_sys_t *p_sys = p_demux->p_sys;
1914
1915     MP4_Box_t *p_co64; /* give offset for each chunk, same for stco and co64 */
1916     MP4_Box_t *p_stsc;
1917
1918     unsigned int i_chunk;
1919     unsigned int i_index, i_last;
1920
1921     if( ( !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "stco" ) )&&
1922           !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "co64" ) ) )||
1923         ( !(p_stsc = MP4_BoxGet( p_demux_track->p_stbl, "stsc" ) ) ))
1924     {
1925         return( VLC_EGENERIC );
1926     }
1927
1928     p_demux_track->i_chunk_count = BOXDATA(p_co64)->i_entry_count;
1929     if( !p_demux_track->i_chunk_count )
1930     {
1931         msg_Warn( p_demux, "no chunk defined" );
1932     }
1933     p_demux_track->chunk = calloc( p_demux_track->i_chunk_count,
1934                                    sizeof( mp4_chunk_t ) );
1935     if( p_demux_track->chunk == NULL )
1936     {
1937         return VLC_ENOMEM;
1938     }
1939
1940     /* first we read chunk offset */
1941     for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
1942     {
1943         mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];
1944
1945         ck->i_offset = BOXDATA(p_co64)->i_chunk_offset[i_chunk];
1946
1947         ck->i_first_dts = 0;
1948         ck->i_entries_dts = 0;
1949         ck->p_sample_count_dts = NULL;
1950         ck->p_sample_delta_dts = NULL;
1951         ck->i_entries_pts = 0;
1952         ck->p_sample_count_pts = NULL;
1953         ck->p_sample_offset_pts = NULL;
1954     }
1955
1956     /* now we read index for SampleEntry( soun vide mp4a mp4v ...)
1957         to be used for the sample XXX begin to 1
1958         We construct it begining at the end */
1959     i_last = p_demux_track->i_chunk_count; /* last chunk proceded */
1960     i_index = BOXDATA(p_stsc)->i_entry_count;
1961
1962     while( i_index-- > 0 )
1963     {
1964         for( i_chunk = BOXDATA(p_stsc)->i_first_chunk[i_index] - 1;
1965              i_chunk < i_last; i_chunk++ )
1966         {
1967             if( i_chunk >= p_demux_track->i_chunk_count )
1968             {
1969                 msg_Warn( p_demux, "corrupted chunk table" );
1970                 return VLC_EGENERIC;
1971             }
1972
1973             p_demux_track->chunk[i_chunk].i_sample_description_index =
1974                     BOXDATA(p_stsc)->i_sample_description_index[i_index];
1975             p_demux_track->chunk[i_chunk].i_sample_count =
1976                     BOXDATA(p_stsc)->i_samples_per_chunk[i_index];
1977         }
1978         i_last = BOXDATA(p_stsc)->i_first_chunk[i_index] - 1;
1979     }
1980
1981     if ( p_demux_track->i_chunk_count )
1982     {
1983         p_demux_track->chunk[0].i_sample_first = 0;
1984         for( i_chunk = 1; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
1985         {
1986             p_demux_track->chunk[i_chunk].i_sample_first =
1987                 p_demux_track->chunk[i_chunk-1].i_sample_first +
1988                     p_demux_track->chunk[i_chunk-1].i_sample_count;
1989         }
1990     }
1991
1992     msg_Dbg( p_demux, "track[Id 0x%x] read %d chunk",
1993              p_demux_track->i_track_ID, p_demux_track->i_chunk_count );
1994
1995     mp4_fragment_t *p_moovfragment = MP4_Fragment_Moov( &p_sys->fragments );
1996     if ( p_demux_track->i_chunk_count && (
1997              p_moovfragment->i_chunk_range_min_offset == 0 ||
1998              p_moovfragment->i_chunk_range_min_offset > p_demux_track->chunk[0].i_offset
1999              ) )
2000         p_moovfragment->i_chunk_range_min_offset = p_demux_track->chunk[0].i_offset;
2001
2002     return VLC_SUCCESS;
2003 }
2004
2005 static int xTTS_CountEntries( demux_t *p_demux, uint32_t *pi_entry /* out */,
2006                               const uint32_t i_index,
2007                               uint32_t i_index_samples_left,
2008                               uint32_t i_sample_count,
2009                               const uint32_t *pi_index_sample_count,
2010                               const uint32_t i_table_count )
2011 {
2012     uint32_t i_array_offset;
2013     while( i_sample_count > 0 )
2014     {
2015         if ( likely((UINT32_MAX - i_index) >= *pi_entry) )
2016             i_array_offset = i_index + *pi_entry;
2017         else
2018             return VLC_EGENERIC;
2019
2020         if ( i_array_offset >= i_table_count )
2021         {
2022             msg_Err( p_demux, "invalid index counting total samples %u %u", i_array_offset,  i_table_count );
2023             return VLC_ENOVAR;
2024         }
2025
2026         if ( i_index_samples_left )
2027         {
2028             if ( i_index_samples_left > i_sample_count )
2029             {
2030                 i_index_samples_left -= i_sample_count;
2031                 i_sample_count = 0;
2032                 *pi_entry +=1; /* No samples left, go copy */
2033                 break;
2034             }
2035             else
2036             {
2037                 i_sample_count -= i_index_samples_left;
2038                 i_index_samples_left = 0;
2039                 *pi_entry += 1;
2040                 continue;
2041             }
2042         }
2043         else
2044         {
2045             i_sample_count -= __MIN( i_sample_count, pi_index_sample_count[i_array_offset] );
2046             *pi_entry += 1;
2047         }
2048     }
2049
2050     return VLC_SUCCESS;
2051 }
2052
2053 static int TrackCreateSamplesIndex( demux_t *p_demux,
2054                                     mp4_track_t *p_demux_track )
2055 {
2056     demux_sys_t *p_sys = p_demux->p_sys;
2057
2058     MP4_Box_t *p_box;
2059     MP4_Box_data_stsz_t *stsz;
2060     /* TODO use also stss and stsh table for seeking */
2061     /* FIXME use edit table */
2062
2063     /* Find stsz
2064      *  Gives the sample size for each samples. There is also a stz2 table
2065      *  (compressed form) that we need to implement TODO */
2066     p_box = MP4_BoxGet( p_demux_track->p_stbl, "stsz" );
2067     if( !p_box )
2068     {
2069         /* FIXME and stz2 */
2070         msg_Warn( p_demux, "cannot find STSZ box" );
2071         return VLC_EGENERIC;
2072     }
2073     stsz = p_box->data.p_stsz;
2074
2075     /* Use stsz table to create a sample number -> sample size table */
2076     p_demux_track->i_sample_count = stsz->i_sample_count;
2077     if( stsz->i_sample_size )
2078     {
2079         /* 1: all sample have the same size, so no need to construct a table */
2080         p_demux_track->i_sample_size = stsz->i_sample_size;
2081         p_demux_track->p_sample_size = NULL;
2082     }
2083     else
2084     {
2085         /* 2: each sample can have a different size */
2086         p_demux_track->i_sample_size = 0;
2087         p_demux_track->p_sample_size =
2088             calloc( p_demux_track->i_sample_count, sizeof( uint32_t ) );
2089         if( p_demux_track->p_sample_size == NULL )
2090             return VLC_ENOMEM;
2091
2092         for( uint32_t i_sample = 0; i_sample < p_demux_track->i_sample_count; i_sample++ )
2093         {
2094             p_demux_track->p_sample_size[i_sample] =
2095                     stsz->i_entry_size[i_sample];
2096         }
2097     }
2098
2099     if ( p_demux_track->i_chunk_count )
2100     {
2101         mp4_chunk_t *lastchunk = &p_demux_track->chunk[p_demux_track->i_chunk_count - 1];
2102         uint64_t i_total_size = lastchunk->i_offset;
2103
2104         if ( p_demux_track->i_sample_size != 0 ) /* all samples have same size */
2105         {
2106             i_total_size += (uint64_t)p_demux_track->i_sample_size * lastchunk->i_sample_count;
2107         }
2108         else
2109         {
2110             if( (uint64_t)lastchunk->i_sample_count + p_demux_track->i_chunk_count - 1 > stsz->i_sample_count )
2111             {
2112                 msg_Err( p_demux, "invalid samples table: stsz table is too small" );
2113                 return VLC_EGENERIC;
2114             }
2115
2116             for( uint32_t i=stsz->i_sample_count - lastchunk->i_sample_count;
2117                  i<stsz->i_sample_count; i++)
2118             {
2119                 i_total_size += stsz->i_entry_size[i];
2120             }
2121         }
2122
2123         if ( i_total_size > MP4_Fragment_Moov( &p_sys->fragments )->i_chunk_range_max_offset )
2124             MP4_Fragment_Moov( &p_sys->fragments )->i_chunk_range_max_offset = i_total_size;
2125     }
2126
2127     /* Use stts table to create a sample number -> dts table.
2128      * XXX: if we don't want to waste too much memory, we can't expand
2129      *  the box! so each chunk will contain an "extract" of this table
2130      *  for fast research (problem with raw stream where a sample is sometime
2131      *  just channels*bits_per_sample/8 */
2132
2133      /* FIXME: refactor STTS & CTTS, STTS having now only few extra lines and
2134       *        differing in 2/2 fields and 1 signedness */
2135
2136     mtime_t i_next_dts = 0;
2137     /* Find stts
2138      *  Gives mapping between sample and decoding time
2139      */
2140     p_box = MP4_BoxGet( p_demux_track->p_stbl, "stts" );
2141     if( !p_box )
2142     {
2143         msg_Warn( p_demux, "cannot find STTS box" );
2144         return VLC_EGENERIC;
2145     }
2146     else
2147     {
2148         MP4_Box_data_stts_t *stts = p_box->data.p_stts;
2149
2150         msg_Warn( p_demux, "STTS table of %"PRIu32" entries", stts->i_entry_count );
2151
2152         /* Create sample -> dts table per chunk */
2153         uint32_t i_index = 0;
2154         uint32_t i_current_index_samples_left = 0;
2155
2156         for( uint32_t i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
2157         {
2158             mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];
2159             uint32_t i_sample_count;
2160
2161             /* save first dts */
2162             ck->i_first_dts = i_next_dts;
2163             ck->i_last_dts  = i_next_dts;
2164
2165             /* count how many entries are needed for this chunk
2166              * for p_sample_delta_dts and p_sample_count_dts */
2167             ck->i_entries_dts = 0;
2168
2169             int i_ret = xTTS_CountEntries( p_demux, &ck->i_entries_dts, i_index,
2170                                            i_current_index_samples_left,
2171                                            ck->i_sample_count,
2172                                            stts->pi_sample_count,
2173                                            stts->i_entry_count );
2174             if ( i_ret == VLC_EGENERIC )
2175                 return i_ret;
2176
2177             /* allocate them */
2178             ck->p_sample_count_dts = calloc( ck->i_entries_dts, sizeof( uint32_t ) );
2179             ck->p_sample_delta_dts = calloc( ck->i_entries_dts, sizeof( uint32_t ) );
2180             if( !ck->p_sample_count_dts || !ck->p_sample_delta_dts )
2181             {
2182                 free( ck->p_sample_count_dts );
2183                 free( ck->p_sample_delta_dts );
2184                 msg_Err( p_demux, "can't allocate memory for i_entry=%"PRIu32, ck->i_entries_dts );
2185                 ck->i_entries_dts = 0;
2186                 return VLC_ENOMEM;
2187             }
2188
2189             /* now copy */
2190             i_sample_count = ck->i_sample_count;
2191
2192             for( uint32_t i = 0; i < ck->i_entries_dts; i++ )
2193             {
2194                 if ( i_current_index_samples_left )
2195                 {
2196                     if ( i_current_index_samples_left > i_sample_count )
2197                     {
2198                         if ( i_sample_count ) ck->i_last_dts = i_next_dts;
2199                         ck->p_sample_count_dts[i] = i_sample_count;
2200                         ck->p_sample_delta_dts[i] = stts->pi_sample_delta[i_index];
2201                         i_next_dts += ck->p_sample_count_dts[i] * stts->pi_sample_delta[i_index];
2202                         i_current_index_samples_left -= i_sample_count;
2203                         i_sample_count = 0;
2204                         assert( i == ck->i_entries_dts - 1 );
2205                         break;
2206                     }
2207                     else
2208                     {
2209                         if ( i_current_index_samples_left ) ck->i_last_dts = i_next_dts;
2210                         ck->p_sample_count_dts[i] = i_current_index_samples_left;
2211                         ck->p_sample_delta_dts[i] = stts->pi_sample_delta[i_index];
2212                         i_next_dts += ck->p_sample_count_dts[i] * stts->pi_sample_delta[i_index];
2213                         i_sample_count -= i_current_index_samples_left;
2214                         i_current_index_samples_left = 0;
2215                         i_index++;
2216                     }
2217                 }
2218                 else
2219                 {
2220                     if ( stts->pi_sample_count[i_index] > i_sample_count )
2221                     {
2222                         if ( i_sample_count ) ck->i_last_dts = i_next_dts;
2223                         ck->p_sample_count_dts[i] = i_sample_count;
2224                         ck->p_sample_delta_dts[i] = stts->pi_sample_delta[i_index];
2225                         i_next_dts += ck->p_sample_count_dts[i] * stts->pi_sample_delta[i_index];
2226                         i_current_index_samples_left = stts->pi_sample_count[i_index] - i_sample_count;
2227                         i_sample_count = 0;
2228                         assert( i == ck->i_entries_dts - 1 );
2229                         // keep building from same index
2230                     }
2231                     else
2232                     {
2233                         if ( stts->pi_sample_count[i_index] ) ck->i_last_dts = i_next_dts;
2234                         ck->p_sample_count_dts[i] = stts->pi_sample_count[i_index];
2235                         ck->p_sample_delta_dts[i] = stts->pi_sample_delta[i_index];
2236                         i_next_dts += ck->p_sample_count_dts[i] * stts->pi_sample_delta[i_index];
2237                         i_sample_count -= stts->pi_sample_count[i_index];
2238                         i_index++;
2239                     }
2240                 }
2241
2242             }
2243         }
2244     }
2245
2246
2247     /* Find ctts
2248      *  Gives the delta between decoding time (dts) and composition table (pts)
2249      */
2250     p_box = MP4_BoxGet( p_demux_track->p_stbl, "ctts" );
2251     if( p_box && p_box->data.p_ctts )
2252     {
2253         MP4_Box_data_ctts_t *ctts = p_box->data.p_ctts;
2254
2255         msg_Warn( p_demux, "CTTS table of %"PRIu32" entries", ctts->i_entry_count );
2256
2257         /* Create pts-dts table per chunk */
2258         uint32_t i_index = 0;
2259         uint32_t i_current_index_samples_left = 0;
2260
2261         for( uint32_t i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
2262         {
2263             mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];
2264             uint32_t i_sample_count;
2265
2266             /* count how many entries are needed for this chunk
2267              * for p_sample_offset_pts and p_sample_count_pts */
2268             ck->i_entries_pts = 0;
2269             int i_ret = xTTS_CountEntries( p_demux, &ck->i_entries_pts, i_index,
2270                                            i_current_index_samples_left,
2271                                            ck->i_sample_count,
2272                                            ctts->pi_sample_count,
2273                                            ctts->i_entry_count );
2274             if ( i_ret == VLC_EGENERIC )
2275                 return i_ret;
2276
2277             /* allocate them */
2278             ck->p_sample_count_pts = calloc( ck->i_entries_pts, sizeof( uint32_t ) );
2279             ck->p_sample_offset_pts = calloc( ck->i_entries_pts, sizeof( int32_t ) );
2280             if( !ck->p_sample_count_pts || !ck->p_sample_offset_pts )
2281             {
2282                 free( ck->p_sample_count_pts );
2283                 free( ck->p_sample_offset_pts );
2284                 msg_Err( p_demux, "can't allocate memory for i_entry=%"PRIu32, ck->i_entries_pts );
2285                 ck->i_entries_pts = 0;
2286                 return VLC_ENOMEM;
2287             }
2288
2289             /* now copy */
2290             i_sample_count = ck->i_sample_count;
2291
2292             for( uint32_t i = 0; i < ck->i_entries_pts; i++ )
2293             {
2294                 if ( i_current_index_samples_left )
2295                 {
2296                     if ( i_current_index_samples_left > i_sample_count )
2297                     {
2298                         ck->p_sample_count_pts[i] = i_sample_count;
2299                         ck->p_sample_offset_pts[i] = ctts->pi_sample_offset[i_index];
2300                         i_current_index_samples_left -= i_sample_count;
2301                         i_sample_count = 0;
2302                         assert( i == ck->i_entries_pts - 1 );
2303                         break;
2304                     }
2305                     else
2306                     {
2307                         ck->p_sample_count_pts[i] = i_current_index_samples_left;
2308                         ck->p_sample_offset_pts[i] = ctts->pi_sample_offset[i_index];
2309                         i_sample_count -= i_current_index_samples_left;
2310                         i_current_index_samples_left = 0;
2311                         i_index++;
2312                     }
2313                 }
2314                 else
2315                 {
2316                     if ( ctts->pi_sample_count[i_index] > i_sample_count )
2317                     {
2318                         ck->p_sample_count_pts[i] = i_sample_count;
2319                         ck->p_sample_offset_pts[i] = ctts->pi_sample_offset[i_index];
2320                         i_current_index_samples_left = ctts->pi_sample_count[i_index] - i_sample_count;
2321                         i_sample_count = 0;
2322                         assert( i == ck->i_entries_pts - 1 );
2323                         // keep building from same index
2324                     }
2325                     else
2326                     {
2327                         ck->p_sample_count_pts[i] = ctts->pi_sample_count[i_index];
2328                         ck->p_sample_offset_pts[i] = ctts->pi_sample_offset[i_index];
2329                         i_sample_count -= ctts->pi_sample_count[i_index];
2330                         i_index++;
2331                     }
2332                 }
2333
2334
2335             }
2336         }
2337     }
2338
2339     msg_Dbg( p_demux, "track[Id 0x%x] read %"PRIu32" samples length:%"PRId64"s",
2340              p_demux_track->i_track_ID, p_demux_track->i_sample_count,
2341              i_next_dts / p_demux_track->i_timescale );
2342
2343     return VLC_SUCCESS;
2344 }
2345
2346
2347 /**
2348  * It computes the sample rate for a video track using the given sample
2349  * description index
2350  */
2351 static void TrackGetESSampleRate( demux_t *p_demux,
2352                                   unsigned *pi_num, unsigned *pi_den,
2353                                   const mp4_track_t *p_track,
2354                                   unsigned i_sd_index,
2355                                   unsigned i_chunk )
2356 {
2357     *pi_num = 0;
2358     *pi_den = 0;
2359
2360     MP4_Box_t *p_trak = MP4_GetTrakByTrackID( MP4_BoxGet( p_demux->p_sys->p_root, "/moov" ),
2361                                               p_track->i_track_ID );
2362     MP4_Box_t *p_mdhd = MP4_BoxGet( p_trak, "mdia/mdhd" );
2363     if ( p_mdhd && BOXDATA(p_mdhd) )
2364     {
2365         vlc_ureduce( pi_num, pi_den,
2366                      (uint64_t) BOXDATA(p_mdhd)->i_timescale * p_track->i_sample_count,
2367                      (uint64_t) BOXDATA(p_mdhd)->i_duration,
2368                      UINT16_MAX );
2369         return;
2370     }
2371
2372     if( p_track->i_chunk_count == 0 )
2373         return;
2374
2375     /* */
2376     const mp4_chunk_t *p_chunk = &p_track->chunk[i_chunk];
2377     while( p_chunk > &p_track->chunk[0] &&
2378            p_chunk[-1].i_sample_description_index == i_sd_index )
2379     {
2380         p_chunk--;
2381     }
2382
2383     uint64_t i_sample = 0;
2384     uint64_t i_first_dts = p_chunk->i_first_dts;
2385     uint64_t i_last_dts;
2386     do
2387     {
2388         i_sample += p_chunk->i_sample_count;
2389         i_last_dts = p_chunk->i_last_dts;
2390         p_chunk++;
2391     }
2392     while( p_chunk < &p_track->chunk[p_track->i_chunk_count] &&
2393            p_chunk->i_sample_description_index == i_sd_index );
2394
2395     if( i_sample > 1 && i_first_dts < i_last_dts )
2396         vlc_ureduce( pi_num, pi_den,
2397                      ( i_sample - 1) *  p_track->i_timescale,
2398                      i_last_dts - i_first_dts,
2399                      UINT16_MAX);
2400 }
2401
2402 /*
2403  * TrackCreateES:
2404  * Create ES and PES to init decoder if needed, for a track starting at i_chunk
2405  */
2406 static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
2407                           unsigned int i_chunk, es_out_id_t **pp_es )
2408 {
2409     demux_sys_t *p_sys = p_demux->p_sys;
2410     unsigned int i_sample_description_index;
2411
2412     if( p_sys->b_fragmented || p_track->i_chunk_count == 0 )
2413         i_sample_description_index = 1; /* XXX */
2414     else
2415         i_sample_description_index =
2416                 p_track->chunk[i_chunk].i_sample_description_index;
2417
2418     if( pp_es )
2419         *pp_es = NULL;
2420
2421     if( !i_sample_description_index )
2422     {
2423         msg_Warn( p_demux, "invalid SampleEntry index (track[Id 0x%x])",
2424                   p_track->i_track_ID );
2425         return VLC_EGENERIC;
2426     }
2427
2428     MP4_Box_t *p_sample = MP4_BoxGet(  p_track->p_stsd, "[%d]",
2429                             i_sample_description_index - 1 );
2430
2431     if( !p_sample ||
2432         ( !p_sample->data.p_payload && p_track->fmt.i_cat != SPU_ES ) )
2433     {
2434         msg_Warn( p_demux, "cannot find SampleEntry (track[Id 0x%x])",
2435                   p_track->i_track_ID );
2436         return VLC_EGENERIC;
2437     }
2438
2439     p_track->p_sample = p_sample;
2440
2441     MP4_Box_t   *p_frma;
2442     if( ( p_frma = MP4_BoxGet( p_track->p_sample, "sinf/frma" ) ) && p_frma->data.p_frma )
2443     {
2444         msg_Warn( p_demux, "Original Format Box: %4.4s", (char *)&p_frma->data.p_frma->i_type );
2445
2446         p_sample->i_type = p_frma->data.p_frma->i_type;
2447     }
2448
2449     /* */
2450     switch( p_track->fmt.i_cat )
2451     {
2452     case VIDEO_ES:
2453         if ( !SetupVideoES( p_demux, p_track, p_sample ) )
2454             return VLC_EGENERIC;
2455
2456         /* Set frame rate */
2457         TrackGetESSampleRate( p_demux,
2458                               &p_track->fmt.video.i_frame_rate,
2459                               &p_track->fmt.video.i_frame_rate_base,
2460                               p_track, i_sample_description_index, i_chunk );
2461
2462         p_demux->p_sys->f_fps = (float)p_track->fmt.video.i_frame_rate /
2463                                 (float)p_track->fmt.video.i_frame_rate_base;
2464
2465         break;
2466
2467     case AUDIO_ES:
2468         if ( !SetupAudioES( p_demux, p_track, p_sample ) )
2469             return VLC_EGENERIC;
2470         break;
2471
2472     case SPU_ES:
2473         switch( p_sample->i_handler )
2474         {
2475             case ATOM_clcp:
2476                 if ( !SetupCCES( p_demux, p_track, p_sample ) )
2477                     return VLC_EGENERIC;
2478                 break;
2479             default:
2480                 if ( !SetupSpuES( p_demux, p_track, p_sample ) )
2481                  return VLC_EGENERIC;
2482         }
2483
2484     default:
2485         break;
2486     }
2487
2488     if( pp_es )
2489         *pp_es = MP4_AddTrackES( p_demux->out, p_track );
2490
2491     return VLC_SUCCESS;
2492 }
2493
2494 /* *** Try to find nearest sync points *** */
2495 static int TrackGetNearestSeekPoint( demux_t *p_demux, mp4_track_t *p_track,
2496                                      uint32_t i_sample, uint32_t *pi_sync_sample )
2497 {
2498     int i_ret = VLC_EGENERIC;
2499     *pi_sync_sample = 0;
2500
2501     const MP4_Box_t *p_stss;
2502     if( ( p_stss = MP4_BoxGet( p_track->p_stbl, "stss" ) ) )
2503     {
2504         const MP4_Box_data_stss_t *p_stss_data = BOXDATA(p_stss);
2505         msg_Dbg( p_demux, "track[Id 0x%x] using Sync Sample Box (stss)",
2506                  p_track->i_track_ID );
2507         for( unsigned i_index = 0; i_index < p_stss_data->i_entry_count; i_index++ )
2508         {
2509             if( i_index >= p_stss_data->i_entry_count - 1 ||
2510                 i_sample < p_stss_data->i_sample_number[i_index+1] )
2511             {
2512                 *pi_sync_sample = p_stss_data->i_sample_number[i_index];
2513                 msg_Dbg( p_demux, "stss gives %d --> %" PRIu32 " (sample number)",
2514                          i_sample, *pi_sync_sample );
2515                 i_ret = VLC_SUCCESS;
2516                 break;
2517             }
2518         }
2519     }
2520
2521     /* try rap samples groups */
2522     const MP4_Box_t *p_sbgp = MP4_BoxGet( p_track->p_stbl, "sbgp" );
2523     for( ; p_sbgp; p_sbgp = p_sbgp->p_next )
2524     {
2525         const MP4_Box_data_sbgp_t *p_sbgp_data = BOXDATA(p_sbgp);
2526         if( p_sbgp->i_type != ATOM_sbgp || !p_sbgp_data )
2527             continue;
2528
2529         if( p_sbgp_data->i_grouping_type == SAMPLEGROUP_rap )
2530         {
2531             uint32_t i_group_sample = 0;
2532             for ( uint32_t i=0; i<p_sbgp_data->i_entry_count; i++ )
2533             {
2534                 /* Sample belongs to rap group ? */
2535                 if( p_sbgp_data->entries.pi_group_description_index[i] != 0 )
2536                 {
2537                     if( i_sample < i_group_sample )
2538                     {
2539                         msg_Dbg( p_demux, "sbgp lookup failed %" PRIu32 " (sample number)",
2540                                  i_sample );
2541                         break;
2542                     }
2543                     else if ( i_sample >= i_group_sample &&
2544                               *pi_sync_sample < i_group_sample )
2545                     {
2546                         *pi_sync_sample = i_group_sample;
2547                         i_ret = VLC_SUCCESS;
2548                     }
2549                 }
2550                 i_group_sample += p_sbgp_data->entries.pi_sample_count[i];
2551             }
2552
2553             if( i_ret == VLC_SUCCESS && *pi_sync_sample )
2554             {
2555                 msg_Dbg( p_demux, "sbgp gives %d --> %" PRIu32 " (sample number)",
2556                          i_sample, *pi_sync_sample );
2557             }
2558         }
2559     }
2560
2561     return i_ret;
2562 }
2563
2564 /* given a time it return sample/chunk
2565  * it also update elst field of the track
2566  */
2567 static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
2568                                    int64_t i_start, uint32_t *pi_chunk,
2569                                    uint32_t *pi_sample )
2570 {
2571     demux_sys_t *p_sys = p_demux->p_sys;
2572     uint64_t     i_dts;
2573     unsigned int i_sample;
2574     unsigned int i_chunk;
2575     int          i_index;
2576
2577     /* FIXME see if it's needed to check p_track->i_chunk_count */
2578     if( p_track->i_chunk_count == 0 )
2579         return( VLC_EGENERIC );
2580
2581     /* handle elst (find the correct one) */
2582     MP4_TrackSetELST( p_demux, p_track, i_start );
2583     if( p_track->p_elst && p_track->BOXDATA(p_elst)->i_entry_count > 0 )
2584     {
2585         MP4_Box_data_elst_t *elst = p_track->BOXDATA(p_elst);
2586         int64_t i_mvt= i_start * p_sys->i_timescale / CLOCK_FREQ;
2587
2588         /* now calculate i_start for this elst */
2589         /* offset */
2590         i_start -= p_track->i_elst_time * CLOCK_FREQ / p_sys->i_timescale;
2591         if( i_start < 0 )
2592         {
2593             *pi_chunk = 0;
2594             *pi_sample= 0;
2595
2596             return VLC_SUCCESS;
2597         }
2598         /* to track time scale */
2599         i_start  = i_start * p_track->i_timescale / CLOCK_FREQ;
2600         /* add elst offset */
2601         if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
2602              elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&
2603             elst->i_media_time[p_track->i_elst] > 0 )
2604         {
2605             i_start += elst->i_media_time[p_track->i_elst];
2606         }
2607
2608         msg_Dbg( p_demux, "elst (%d) gives %"PRId64"ms (movie)-> %"PRId64
2609                  "ms (track)", p_track->i_elst,
2610                  i_mvt * 1000 / p_sys->i_timescale,
2611                  i_start * 1000 / p_track->i_timescale );
2612     }
2613     else
2614     {
2615         /* convert absolute time to in timescale unit */
2616         i_start = i_start * p_track->i_timescale / CLOCK_FREQ;
2617     }
2618
2619     /* we start from sample 0/chunk 0, hope it won't take too much time */
2620     /* *** find good chunk *** */
2621     for( i_chunk = 0; ; i_chunk++ )
2622     {
2623         if( i_chunk + 1 >= p_track->i_chunk_count )
2624         {
2625             /* at the end and can't check if i_start in this chunk,
2626                it will be check while searching i_sample */
2627             i_chunk = p_track->i_chunk_count - 1;
2628             break;
2629         }
2630
2631         if( (uint64_t)i_start >= p_track->chunk[i_chunk].i_first_dts &&
2632             (uint64_t)i_start <  p_track->chunk[i_chunk + 1].i_first_dts )
2633         {
2634             break;
2635         }
2636     }
2637
2638     /* *** find sample in the chunk *** */
2639     i_sample = p_track->chunk[i_chunk].i_sample_first;
2640     i_dts    = p_track->chunk[i_chunk].i_first_dts;
2641     for( i_index = 0; i_sample < p_track->chunk[i_chunk].i_sample_count; )
2642     {
2643         if( i_dts +
2644             p_track->chunk[i_chunk].p_sample_count_dts[i_index] *
2645             p_track->chunk[i_chunk].p_sample_delta_dts[i_index] < (uint64_t)i_start )
2646         {
2647             i_dts    +=
2648                 p_track->chunk[i_chunk].p_sample_count_dts[i_index] *
2649                 p_track->chunk[i_chunk].p_sample_delta_dts[i_index];
2650
2651             i_sample += p_track->chunk[i_chunk].p_sample_count_dts[i_index];
2652             i_index++;
2653         }
2654         else
2655         {
2656             if( p_track->chunk[i_chunk].p_sample_delta_dts[i_index] <= 0 )
2657             {
2658                 break;
2659             }
2660             i_sample += ( i_start - i_dts ) /
2661                 p_track->chunk[i_chunk].p_sample_delta_dts[i_index];
2662             break;
2663         }
2664     }
2665
2666     if( i_sample >= p_track->i_sample_count )
2667     {
2668         msg_Warn( p_demux, "track[Id 0x%x] will be disabled "
2669                   "(seeking too far) chunk=%d sample=%d",
2670                   p_track->i_track_ID, i_chunk, i_sample );
2671         return( VLC_EGENERIC );
2672     }
2673
2674
2675     /* *** Try to find nearest sync points *** */
2676     uint32_t i_sync_sample;
2677     if( VLC_SUCCESS ==
2678         TrackGetNearestSeekPoint( p_demux, p_track, i_sample, &i_sync_sample ) )
2679     {
2680         /* Go to chunk */
2681         if( i_sync_sample <= i_sample )
2682         {
2683             while( i_chunk > 0 &&
2684                    i_sync_sample < p_track->chunk[i_chunk].i_sample_first )
2685                 i_chunk--;
2686         }
2687         else
2688         {
2689             while( i_chunk < p_track->i_chunk_count - 1 &&
2690                    i_sync_sample >= p_track->chunk[i_chunk].i_sample_first +
2691                                     p_track->chunk[i_chunk].i_sample_count )
2692                 i_chunk++;
2693         }
2694         i_sample = i_sync_sample;
2695     }
2696
2697     *pi_chunk  = i_chunk;
2698     *pi_sample = i_sample;
2699
2700     return VLC_SUCCESS;
2701 }
2702
2703 static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
2704                                  unsigned int i_chunk, unsigned int i_sample )
2705 {
2706     bool b_reselect = false;
2707
2708     /* now see if actual es is ok */
2709     if( p_track->i_chunk >= p_track->i_chunk_count ||
2710         p_track->chunk[p_track->i_chunk].i_sample_description_index !=
2711             p_track->chunk[i_chunk].i_sample_description_index )
2712     {
2713         msg_Warn( p_demux, "recreate ES for track[Id 0x%x]",
2714                   p_track->i_track_ID );
2715
2716         es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
2717                         p_track->p_es, &b_reselect );
2718
2719         es_out_Del( p_demux->out, p_track->p_es );
2720
2721         p_track->p_es = NULL;
2722
2723         if( TrackCreateES( p_demux, p_track, i_chunk, &p_track->p_es ) )
2724         {
2725             msg_Err( p_demux, "cannot create es for track[Id 0x%x]",
2726                      p_track->i_track_ID );
2727
2728             p_track->b_ok       = false;
2729             p_track->b_selected = false;
2730             return VLC_EGENERIC;
2731         }
2732     }
2733
2734     /* select again the new decoder */
2735     if( b_reselect )
2736     {
2737         es_out_Control( p_demux->out, ES_OUT_SET_ES, p_track->p_es );
2738     }
2739
2740     p_track->i_chunk    = i_chunk;
2741     p_track->chunk[i_chunk].i_sample = i_sample - p_track->chunk[i_chunk].i_sample_first;
2742     p_track->i_sample   = i_sample;
2743
2744     return p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC;
2745 }
2746
2747 static void MP4_TrackRestart( demux_t *p_demux, mp4_track_t *p_track,
2748                               MP4_Box_t *p_params_box )
2749 {
2750     bool b_reselect = false;
2751     if( p_track->p_es )
2752     {
2753         es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
2754                         p_track->p_es, &b_reselect );
2755     }
2756
2757     /* Save previous fragmented pos */
2758     uint32_t i_sample_pos_backup = p_track->i_sample;
2759     mp4_chunk_t *cchunk_backup = p_track->cchunk;
2760     p_track->cchunk = NULL;
2761     mtime_t time_backup = p_track->i_time * p_track->i_timescale;
2762
2763     /* Save previous format and ES */
2764     es_format_t fmtbackup;
2765     es_out_id_t *p_es_backup = p_track->p_es;
2766     p_track->p_es = NULL;
2767     es_format_Init( &fmtbackup, UNKNOWN_ES, 0 );
2768     es_format_Copy( &fmtbackup, &p_track->fmt );
2769     es_format_Clean( &p_track->fmt );
2770
2771
2772     /* do the cleanup and recycle track / restart */
2773     MP4_TrackDestroy( p_demux, p_track );
2774     memset( p_track, 0, sizeof(*p_track) );
2775
2776     assert(p_params_box->i_type == ATOM_trak);
2777     MP4_TrackCreate( p_demux, p_track, p_params_box, false, true );
2778
2779     if( p_track->b_ok )
2780     {
2781         if( !es_format_IsSimilar( &fmtbackup, &p_track->fmt ) ||
2782             fmtbackup.i_extra != p_track->fmt.i_extra ||
2783             memcmp( &fmtbackup.p_extra, &p_track->fmt.p_extra, fmtbackup.i_extra ) )
2784         {
2785             if( p_es_backup )
2786                 es_out_Del( p_demux->out, p_es_backup );
2787
2788             if( !p_track->b_chapters_source )
2789             {
2790                 p_track->p_es = MP4_AddTrackES( p_demux->out, p_track );
2791                 p_track->b_ok = !!p_track->p_es;
2792             }
2793         }
2794         else
2795         {
2796             p_track->p_es = p_es_backup;
2797         }
2798     }
2799     else if( p_es_backup )
2800     {
2801         es_out_Del( p_demux->out, p_es_backup );
2802     }
2803
2804     /* select again the new decoder */
2805     if( b_reselect && p_track->p_es )
2806         es_out_Control( p_demux->out, ES_OUT_SET_ES, p_track->p_es );
2807
2808     es_format_Clean( &fmtbackup );
2809
2810     /* Restore fragmented pos */
2811     p_track->cchunk = cchunk_backup;
2812     p_track->i_sample = i_sample_pos_backup;
2813     if( p_track->i_timescale )
2814         p_track->i_time = time_backup / p_track->i_timescale;
2815 }
2816
2817 /****************************************************************************
2818  * MP4_TrackCreate:
2819  ****************************************************************************
2820  * Parse track information and create all needed data to run a track
2821  * If it succeed b_ok is set to 1 else to 0
2822  ****************************************************************************/
2823 static void MP4_TrackCreate( demux_t *p_demux, mp4_track_t *p_track,
2824                              MP4_Box_t *p_box_trak,
2825                              bool b_create_es, bool b_force_enable )
2826 {
2827     demux_sys_t *p_sys = p_demux->p_sys;
2828
2829     p_track->p_track = p_box_trak;
2830
2831     char language[4] = { '\0' };
2832     char sdp_media_type[8] = { '\0' };
2833
2834     es_format_Init( &p_track->fmt, UNKNOWN_ES, 0 );
2835
2836     const MP4_Box_t *p_tkhd = MP4_BoxGet( p_box_trak, "tkhd" );
2837     if( !p_tkhd )
2838     {
2839         return;
2840     }
2841
2842     /* do we launch this track by default ? */
2843     p_track->b_enable =
2844         ( ( BOXDATA(p_tkhd)->i_flags&MP4_TRACK_ENABLED ) != 0 );
2845     if( !p_track->b_enable )
2846         p_track->fmt.i_priority = ES_PRIORITY_NOT_DEFAULTABLE;
2847
2848     p_track->i_track_ID = BOXDATA(p_tkhd)->i_track_ID;
2849
2850     p_track->i_width = BOXDATA(p_tkhd)->i_width / BLOCK16x16;
2851     p_track->i_height = BOXDATA(p_tkhd)->i_height / BLOCK16x16;
2852     p_track->f_rotation = BOXDATA(p_tkhd)->f_rotation;
2853
2854     /* FIXME: unhandled box: tref */
2855
2856     const MP4_Box_t *p_mdhd = MP4_BoxGet( p_box_trak, "mdia/mdhd" );
2857     const MP4_Box_t *p_hdlr = MP4_BoxGet( p_box_trak, "mdia/hdlr" );
2858
2859     if( ( !p_mdhd )||( !p_hdlr ) )
2860     {
2861         return;
2862     }
2863
2864     p_track->i_timescale = BOXDATA(p_mdhd)->i_timescale;
2865     if( p_track->i_timescale == 0 )
2866         return;
2867
2868     memcpy( &language, BOXDATA(p_mdhd)->rgs_language, 3 );
2869     p_track->b_mac_encoding = BOXDATA(p_mdhd)->b_mac_encoding;
2870
2871     switch( p_hdlr->data.p_hdlr->i_handler_type )
2872     {
2873         case( ATOM_soun ):
2874             if( !MP4_BoxGet( p_box_trak, "mdia/minf/smhd" ) )
2875             {
2876                 return;
2877             }
2878             p_track->fmt.i_cat = AUDIO_ES;
2879             break;
2880
2881         case( ATOM_vide ):
2882             if( !MP4_BoxGet( p_box_trak, "mdia/minf/vmhd") )
2883             {
2884                 return;
2885             }
2886             p_track->fmt.i_cat = VIDEO_ES;
2887             break;
2888
2889         case( ATOM_hint ):
2890             if( !MP4_BoxGet( p_box_trak, "mdia/minf/hmhd" ) )
2891             {
2892                 break;
2893             }
2894             MP4_Box_t *p_sdp;
2895
2896             /* parse the sdp message to find out whether the RTP stream contained audio or video */
2897             if( !( p_sdp  = MP4_BoxGet( p_box_trak, "udta/hnti/sdp " ) ) )
2898             {
2899                 msg_Warn( p_demux, "Didn't find sdp box to determine stream type" );
2900                 return;
2901             }
2902
2903             memcpy( sdp_media_type, BOXDATA(p_sdp)->psz_text, 7 );
2904             if( !strcmp(sdp_media_type, "m=audio") )
2905             {
2906                 msg_Dbg( p_demux, "Found audio Rtp: %s", sdp_media_type );
2907                 p_track->fmt.i_cat = AUDIO_ES;
2908             }
2909             else if( !strcmp(sdp_media_type, "m=video") )
2910             {
2911                 msg_Dbg( p_demux, "Found video Rtp: %s", sdp_media_type );
2912                 p_track->fmt.i_cat = VIDEO_ES;
2913             }
2914             else
2915             {
2916                 msg_Warn( p_demux, "Malformed track SDP message: %s", sdp_media_type );
2917                 return;
2918             }
2919             p_track->p_sdp = p_sdp;
2920             break;
2921
2922         case( ATOM_tx3g ):
2923         case( ATOM_text ):
2924         case( ATOM_subp ):
2925         case( ATOM_sbtl ):
2926             p_track->fmt.i_cat = SPU_ES;
2927             break;
2928
2929         /* closed captions */
2930         case( ATOM_clcp ):
2931             p_track->fmt.i_cat = SPU_ES;
2932             break;
2933
2934         default:
2935             return;
2936     }
2937
2938     p_track->asfinfo.i_cat = p_track->fmt.i_cat;
2939
2940     const MP4_Box_t *p_elst;
2941     p_track->i_elst = 0;
2942     p_track->i_elst_time = 0;
2943     if( ( p_track->p_elst = p_elst = MP4_BoxGet( p_box_trak, "edts/elst" ) ) )
2944     {
2945         MP4_Box_data_elst_t *elst = BOXDATA(p_elst);
2946         unsigned int i;
2947
2948         msg_Warn( p_demux, "elst box found" );
2949         for( i = 0; i < elst->i_entry_count; i++ )
2950         {
2951             msg_Dbg( p_demux, "   - [%d] duration=%"PRId64"ms media time=%"PRId64
2952                      "ms) rate=%d.%d", i,
2953                      elst->i_segment_duration[i] * 1000 / p_sys->i_timescale,
2954                      elst->i_media_time[i] >= 0 ?
2955                      (int64_t)(elst->i_media_time[i] * 1000 / p_track->i_timescale) :
2956                      INT64_C(-1),
2957                      elst->i_media_rate_integer[i],
2958                      elst->i_media_rate_fraction[i] );
2959         }
2960     }
2961
2962
2963 /*  TODO
2964     add support for:
2965     p_dinf = MP4_BoxGet( p_minf, "dinf" );
2966 */
2967     if( !( p_track->p_stbl = MP4_BoxGet( p_box_trak,"mdia/minf/stbl" ) ) ||
2968         !( p_track->p_stsd = MP4_BoxGet( p_box_trak,"mdia/minf/stbl/stsd") ) )
2969     {
2970         return;
2971     }
2972
2973     /* Set language */
2974     if( *language && strcmp( language, "```" ) && strcmp( language, "und" ) )
2975     {
2976         p_track->fmt.psz_language = strdup( language );
2977     }
2978
2979     const MP4_Box_t *p_udta = MP4_BoxGet( p_box_trak, "udta" );
2980     if( p_udta )
2981     {
2982         const MP4_Box_t *p_box_iter;
2983         for( p_box_iter = p_udta->p_first; p_box_iter != NULL;
2984                  p_box_iter = p_box_iter->p_next )
2985         {
2986             switch( p_box_iter->i_type )
2987             {
2988                 case ATOM_0xa9nam:
2989                 case ATOM_name:
2990                     p_track->fmt.psz_description =
2991                         strdup( p_box_iter->data.p_string->psz_text );
2992                 default:
2993                     break;
2994             }
2995         }
2996     }
2997
2998     /* Create chunk index table and sample index table */
2999     if( TrackCreateChunksIndex( p_demux,p_track  ) ||
3000         TrackCreateSamplesIndex( p_demux, p_track ) )
3001     {
3002         msg_Err( p_demux, "cannot create chunks index" );
3003         return; /* cannot create chunks index */
3004     }
3005
3006     p_track->i_chunk  = 0;
3007     p_track->i_sample = 0;
3008
3009     /* Mark chapter only track */
3010     if( p_sys->p_tref_chap )
3011     {
3012         MP4_Box_data_tref_generic_t *p_chap = p_sys->p_tref_chap->data.p_tref_generic;
3013         unsigned int i;
3014
3015         for( i = 0; i < p_chap->i_entry_count; i++ )
3016         {
3017             if( p_track->i_track_ID == p_chap->i_track_ID[i] &&
3018                 p_track->fmt.i_cat == UNKNOWN_ES )
3019             {
3020                 p_track->b_chapters_source = true;
3021                 p_track->b_enable = false;
3022                 break;
3023             }
3024         }
3025     }
3026
3027     const MP4_Box_t *p_tsel;
3028     /* now create es */
3029     if( b_force_enable &&
3030         ( p_track->fmt.i_cat == VIDEO_ES || p_track->fmt.i_cat == AUDIO_ES ) )
3031     {
3032         msg_Warn( p_demux, "Enabling track[Id 0x%x] (buggy file without enabled track)",
3033                   p_track->i_track_ID );
3034         p_track->b_enable = true;
3035         p_track->fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN;
3036     }
3037     else if ( (p_tsel = MP4_BoxGet( p_box_trak, "udta/tsel" )) )
3038     {
3039         if ( BOXDATA(p_tsel) && BOXDATA(p_tsel)->i_switch_group )
3040         {
3041             p_track->i_switch_group = BOXDATA(p_tsel)->i_switch_group;
3042             int i_priority = ES_PRIORITY_SELECTABLE_MIN;
3043             for ( unsigned int i = 0; i < p_sys->i_tracks; i++ )
3044             {
3045                 const mp4_track_t *p_other = &p_sys->track[i];
3046                 if( p_other && p_other != p_track &&
3047                     p_other->fmt.i_cat == p_track->fmt.i_cat &&
3048                     p_track->i_switch_group == p_other->i_switch_group )
3049                         i_priority = __MAX( i_priority, p_other->fmt.i_priority + 1 );
3050             }
3051             /* VLC only support ES priority for AUDIO_ES and SPU_ES.
3052                If there's another VIDEO_ES in the same group, we need to unselect it then */
3053             if ( p_track->fmt.i_cat == VIDEO_ES && i_priority > ES_PRIORITY_SELECTABLE_MIN )
3054                 p_track->fmt.i_priority = ES_PRIORITY_NOT_DEFAULTABLE;
3055             else
3056                 p_track->fmt.i_priority = i_priority;
3057         }
3058     }
3059     /* If there's no tsel, try to enable the track coming first in edit list */
3060     else if ( p_track->p_elst && p_track->fmt.i_priority == ES_PRIORITY_SELECTABLE_MIN )
3061     {
3062 #define MAX_SELECTABLE (INT_MAX - ES_PRIORITY_SELECTABLE_MIN)
3063         for ( uint32_t i=0; i<p_track->BOXDATA(p_elst)->i_entry_count; i++ )
3064         {
3065             if ( p_track->BOXDATA(p_elst)->i_media_time[i] >= 0 &&
3066                  p_track->BOXDATA(p_elst)->i_segment_duration[i] )
3067             {
3068                 /* We do selection by inverting start time into priority.
3069                    The track with earliest edit will have the highest prio */
3070                 const int i_time = __MIN( MAX_SELECTABLE, p_track->BOXDATA(p_elst)->i_media_time[i] );
3071                 p_track->fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + MAX_SELECTABLE - i_time;
3072                 break;
3073             }
3074         }
3075     }
3076
3077     if( TrackCreateES( p_demux,
3078                        p_track, p_track->i_chunk,
3079                       (p_track->b_chapters_source || !b_create_es) ? NULL : &p_track->p_es ) )
3080     {
3081         msg_Err( p_demux, "cannot create es for track[Id 0x%x]",
3082                  p_track->i_track_ID );
3083         return;
3084     }
3085
3086     p_track->b_ok = true;
3087 }
3088
3089 static void DestroyChunk( mp4_chunk_t *ck )
3090 {
3091     free( ck->p_sample_count_dts );
3092     free( ck->p_sample_delta_dts );
3093     free( ck->p_sample_count_pts );
3094     free( ck->p_sample_offset_pts );
3095
3096     if( ck->p_sample_data )
3097     {
3098         for( uint32_t i = 0; i < ck->i_sample_count; i++ )
3099             free( ck->p_sample_data[i] );
3100         free( ck->p_sample_data );
3101     }
3102     free( ck->p_sample_size );
3103 }
3104
3105 /****************************************************************************
3106  * MP4_TrackDestroy:
3107  ****************************************************************************
3108  * Destroy a track created by MP4_TrackCreate.
3109  ****************************************************************************/
3110 static void MP4_TrackDestroy( demux_t *p_demux, mp4_track_t *p_track )
3111 {
3112     es_format_Clean( &p_track->fmt );
3113
3114     if( p_track->p_es )
3115         es_out_Del( p_demux->out, p_track->p_es );
3116
3117     if( p_track->chunk )
3118     {
3119         for( unsigned int i_chunk = 0; i_chunk < p_track->i_chunk_count; i_chunk++ )
3120             DestroyChunk( &p_track->chunk[i_chunk] );
3121     }
3122     free( p_track->chunk );
3123
3124     if( p_track->cchunk )
3125     {
3126         assert( p_demux->p_sys->b_fragmented );
3127         DestroyChunk( p_track->cchunk );
3128         free( p_track->cchunk );
3129     }
3130
3131     if( !p_track->i_sample_size )
3132         free( p_track->p_sample_size );
3133
3134     if ( p_track->asfinfo.p_frame )
3135         block_ChainRelease( p_track->asfinfo.p_frame );
3136 }
3137
3138 static int MP4_TrackSelect( demux_t *p_demux, mp4_track_t *p_track,
3139                             mtime_t i_start )
3140 {
3141     if( !p_track->b_ok || p_track->b_chapters_source )
3142     {
3143         return VLC_EGENERIC;
3144     }
3145
3146     if( p_track->b_selected )
3147     {
3148         msg_Warn( p_demux, "track[Id 0x%x] already selected",
3149                   p_track->i_track_ID );
3150         return VLC_SUCCESS;
3151     }
3152
3153     return MP4_TrackSeek( p_demux, p_track, i_start );
3154 }
3155
3156 static void MP4_TrackUnselect( demux_t *p_demux, mp4_track_t *p_track )
3157 {
3158     if( !p_track->b_ok || p_track->b_chapters_source )
3159     {
3160         return;
3161     }
3162
3163     if( !p_track->b_selected )
3164     {
3165         msg_Warn( p_demux, "track[Id 0x%x] already unselected",
3166                   p_track->i_track_ID );
3167         return;
3168     }
3169     if( p_track->p_es )
3170     {
3171         es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE,
3172                         p_track->p_es, false );
3173     }
3174
3175     p_track->b_selected = false;
3176 }
3177
3178 static int MP4_TrackSeek( demux_t *p_demux, mp4_track_t *p_track,
3179                           mtime_t i_start )
3180 {
3181     uint32_t i_chunk;
3182     uint32_t i_sample;
3183
3184     if( !p_track->b_ok || p_track->b_chapters_source )
3185         return VLC_EGENERIC;
3186
3187     p_track->b_selected = false;
3188
3189     if( TrackTimeToSampleChunk( p_demux, p_track, i_start,
3190                                 &i_chunk, &i_sample ) )
3191     {
3192         msg_Warn( p_demux, "cannot select track[Id 0x%x]",
3193                   p_track->i_track_ID );
3194         return VLC_EGENERIC;
3195     }
3196
3197     p_track->b_selected = true;
3198     if( !TrackGotoChunkSample( p_demux, p_track, i_chunk, i_sample ) )
3199         p_track->b_selected = true;
3200
3201     return p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC;
3202 }
3203
3204
3205 /*
3206  * 3 types: for audio
3207  *
3208  */
3209 static inline uint32_t MP4_GetFixedSampleSize( const mp4_track_t *p_track,
3210                                                const MP4_Box_data_sample_soun_t *p_soun )
3211 {
3212     uint32_t i_size = p_track->i_sample_size;
3213
3214     assert( p_track->i_sample_size != 0 );
3215
3216      /* QuickTime "built-in" support case fixups */
3217     if( p_track->fmt.i_cat == AUDIO_ES &&
3218         p_soun->i_compressionid == 0 && p_track->i_sample_size == 1 )
3219     {
3220         switch( p_track->fmt.i_codec )
3221         {
3222         case VLC_CODEC_GSM:
3223             i_size = p_soun->i_channelcount;
3224             break;
3225         case VLC_FOURCC( 'N', 'O', 'N', 'E' ):
3226         case ATOM_twos:
3227         case ATOM_sowt:
3228         case ATOM_raw:
3229             i_size = ((p_soun->i_samplesize+7)/8) * p_soun->i_channelcount;
3230             break;
3231         case VLC_CODEC_ALAW:
3232         case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
3233             i_size = p_soun->i_channelcount;
3234             break;
3235         default:
3236             break;
3237         }
3238     }
3239
3240     return i_size;
3241 }
3242
3243 static uint32_t MP4_TrackGetReadSize( mp4_track_t *p_track, uint32_t *pi_nb_samples )
3244 {
3245     uint32_t i_size = 0;
3246     *pi_nb_samples = 0;
3247
3248     if ( p_track->i_sample == p_track->i_sample_count )
3249         return 0;
3250
3251     if ( p_track->fmt.i_cat != AUDIO_ES )
3252     {
3253         *pi_nb_samples = 1;
3254
3255         if( p_track->i_sample_size == 0 ) /* all sizes are different */
3256             return p_track->p_sample_size[p_track->i_sample];
3257         else
3258             return p_track->i_sample_size;
3259     }
3260     else
3261     {
3262         const MP4_Box_data_sample_soun_t *p_soun = p_track->p_sample->data.p_sample_soun;
3263         const mp4_chunk_t *p_chunk = &p_track->chunk[p_track->i_chunk];
3264         uint32_t i_max_samples = p_chunk->i_sample_count - p_chunk->i_sample;
3265
3266         /* Group audio packets so we don't call demux for single sample unit */
3267         if( p_track->fmt.i_original_fourcc == VLC_CODEC_DVD_LPCM &&
3268             p_soun->i_constLPCMframesperaudiopacket &&
3269             p_soun->i_constbytesperaudiopacket )
3270         {
3271             /* uncompressed case */
3272             uint32_t i_packets = i_max_samples / p_soun->i_constLPCMframesperaudiopacket;
3273             if ( UINT32_MAX / p_soun->i_constbytesperaudiopacket < i_packets )
3274                 i_packets = UINT32_MAX / p_soun->i_constbytesperaudiopacket;
3275             *pi_nb_samples = i_packets * p_soun->i_constLPCMframesperaudiopacket;
3276             return i_packets * p_soun->i_constbytesperaudiopacket;
3277         }
3278
3279         if( p_track->fmt.i_original_fourcc == VLC_FOURCC('r','r','t','p') )
3280         {
3281             *pi_nb_samples = 1;
3282             return p_track->i_sample_size;
3283         }
3284
3285         /* all samples have a different size */
3286         if( p_track->i_sample_size == 0 )
3287         {
3288             *pi_nb_samples = 1;
3289             return p_track->p_sample_size[p_track->i_sample];
3290         }
3291
3292         if( p_soun->i_qt_version == 1 )
3293         {
3294             if ( p_soun->i_compressionid == 0xFFFE )
3295             {
3296                 *pi_nb_samples = 1; /* != number of audio samples */
3297                 if ( p_track->i_sample_size )
3298                     return p_track->i_sample_size;
3299                 else
3300                     return p_track->p_sample_size[p_track->i_sample];
3301             }
3302             else if ( p_soun->i_compressionid != 0 || p_soun->i_bytes_per_sample > 1 ) /* compressed */
3303             {
3304                 /* in this case we are dealing with compressed data
3305                    -2 in V1: additional fields are meaningless (VBR and such) */
3306                 *pi_nb_samples = i_max_samples;//p_track->chunk[p_track->i_chunk].i_sample_count;
3307                 if( p_track->fmt.audio.i_blockalign > 1 )
3308                     *pi_nb_samples = p_soun->i_sample_per_packet;
3309                 i_size = *pi_nb_samples / p_soun->i_sample_per_packet * p_soun->i_bytes_per_frame;
3310                 return i_size;
3311             }
3312             else /* uncompressed case */
3313             {
3314                 uint32_t i_packets;
3315                 if( p_track->fmt.audio.i_blockalign > 1 )
3316                     i_packets = 1;
3317                 else
3318                     i_packets = i_max_samples / p_soun->i_sample_per_packet;
3319
3320                 if ( UINT32_MAX / p_soun->i_bytes_per_frame < i_packets )
3321                     i_packets = UINT32_MAX / p_soun->i_bytes_per_frame;
3322
3323                 *pi_nb_samples = i_packets * p_soun->i_sample_per_packet;
3324                 i_size = i_packets * p_soun->i_bytes_per_frame;
3325                 return i_size;
3326             }
3327         }
3328
3329         /* uncompressed v0 (qt) or... not (ISO) */
3330
3331         /* Quicktime built-in support handling */
3332         if( p_soun->i_compressionid == 0 && p_track->i_sample_size == 1 )
3333         {
3334             switch( p_track->fmt.i_codec )
3335             {
3336                 /* sample size is not integer */
3337                 case VLC_CODEC_GSM:
3338                     *pi_nb_samples = 160 * p_track->fmt.audio.i_channels;
3339                     return 33 * p_track->fmt.audio.i_channels;
3340                 default:
3341                     break;
3342             }
3343         }
3344
3345         /* More regular V0 cases */
3346         uint32_t i_max_v0_samples;
3347         switch( p_track->fmt.i_codec )
3348         {
3349             /* Compressed samples in V0 */
3350             case VLC_CODEC_AMR_NB:
3351             case VLC_CODEC_AMR_WB:
3352                 i_max_v0_samples = 16;
3353                 break;
3354             default:
3355                 /* Read 25ms of samples (uncompressed) */
3356                 i_max_v0_samples = p_track->fmt.audio.i_rate / 40 *
3357                                    p_track->fmt.audio.i_channels;
3358                 if( i_max_v0_samples < 1 )
3359                     i_max_v0_samples = 1;
3360                 break;
3361         }
3362
3363         *pi_nb_samples = 0;
3364         for( uint32_t i=p_track->i_sample;
3365              i<p_chunk->i_sample_first+p_chunk->i_sample_count &&
3366              i<p_track->i_sample_count;
3367              i++ )
3368         {
3369             (*pi_nb_samples)++;
3370             if ( p_track->i_sample_size == 0 )
3371                 i_size += p_track->p_sample_size[i];
3372             else
3373                 i_size += MP4_GetFixedSampleSize( p_track, p_soun );
3374
3375             /* Try to detect compression in ISO */
3376             if(p_soun->i_compressionid != 0)
3377             {
3378                 /* Return only 1 sample */
3379                 break;
3380             }
3381
3382             if ( *pi_nb_samples == i_max_v0_samples )
3383                 break;
3384         }
3385     }
3386
3387     //fprintf( stderr, "size=%d\n", i_size );
3388     return i_size;
3389 }
3390
3391 static uint64_t MP4_TrackGetPos( mp4_track_t *p_track )
3392 {
3393     unsigned int i_sample;
3394     uint64_t i_pos;
3395
3396     i_pos = p_track->chunk[p_track->i_chunk].i_offset;
3397
3398     if( p_track->i_sample_size )
3399     {
3400         MP4_Box_data_sample_soun_t *p_soun =
3401             p_track->p_sample->data.p_sample_soun;
3402
3403         /* Quicktime builtin support, _must_ ignore sample tables */
3404         if( p_track->fmt.i_cat == AUDIO_ES && p_soun->i_compressionid == 0 &&
3405             p_track->i_sample_size == 1 )
3406         {
3407             switch( p_track->fmt.i_codec )
3408             {
3409             case VLC_CODEC_GSM: /* # Samples > data size */
3410                 i_pos += ( p_track->i_sample -
3411                            p_track->chunk[p_track->i_chunk].i_sample_first ) / 160 * 33;
3412                 return i_pos;
3413             default:
3414                 break;
3415             }
3416         }
3417
3418         if( p_track->fmt.i_cat != AUDIO_ES || p_soun->i_qt_version == 0 ||
3419             p_track->fmt.audio.i_blockalign <= 1 ||
3420             p_soun->i_sample_per_packet * p_soun->i_bytes_per_frame == 0 )
3421         {
3422             i_pos += ( p_track->i_sample -
3423                        p_track->chunk[p_track->i_chunk].i_sample_first ) *
3424                      MP4_GetFixedSampleSize( p_track, p_soun );
3425         }
3426         else
3427         {
3428             /* we read chunk by chunk unless a blockalign is requested */
3429             i_pos += ( p_track->i_sample - p_track->chunk[p_track->i_chunk].i_sample_first ) /
3430                         p_soun->i_sample_per_packet * p_soun->i_bytes_per_frame;
3431         }
3432     }
3433     else
3434     {
3435         for( i_sample = p_track->chunk[p_track->i_chunk].i_sample_first;
3436              i_sample < p_track->i_sample; i_sample++ )
3437         {
3438             i_pos += p_track->p_sample_size[i_sample];
3439         }
3440     }
3441
3442     return i_pos;
3443 }
3444
3445 static int MP4_TrackNextSample( demux_t *p_demux, mp4_track_t *p_track, uint32_t i_samples )
3446 {
3447     if ( UINT32_MAX - p_track->i_sample < i_samples )
3448     {
3449         p_track->i_sample = UINT32_MAX;
3450         return VLC_EGENERIC;
3451     }
3452
3453     p_track->i_sample += i_samples;
3454
3455     if( p_track->i_sample >= p_track->i_sample_count )
3456         return VLC_EGENERIC;
3457
3458     /* Have we changed chunk ? */
3459     if( p_track->i_sample >=
3460             p_track->chunk[p_track->i_chunk].i_sample_first +
3461             p_track->chunk[p_track->i_chunk].i_sample_count )
3462     {
3463         if( TrackGotoChunkSample( p_demux, p_track, p_track->i_chunk + 1,
3464                                   p_track->i_sample ) )
3465         {
3466             msg_Warn( p_demux, "track[0x%x] will be disabled "
3467                       "(cannot restart decoder)", p_track->i_track_ID );
3468             MP4_TrackUnselect( p_demux, p_track );
3469             return VLC_EGENERIC;
3470         }
3471     }
3472
3473     /* Have we changed elst */
3474     if( p_track->p_elst && p_track->BOXDATA(p_elst)->i_entry_count > 0 )
3475     {
3476         demux_sys_t *p_sys = p_demux->p_sys;
3477         MP4_Box_data_elst_t *elst = p_track->BOXDATA(p_elst);
3478         uint64_t i_mvt = MP4_TrackGetDTS( p_demux, p_track ) *
3479                         p_sys->i_timescale / CLOCK_FREQ;
3480
3481         if( (unsigned int)p_track->i_elst < elst->i_entry_count &&
3482             i_mvt >= p_track->i_elst_time +
3483                      elst->i_segment_duration[p_track->i_elst] )
3484         {
3485             MP4_TrackSetELST( p_demux, p_track,
3486                               MP4_TrackGetDTS( p_demux, p_track ) );
3487         }
3488     }
3489
3490     return VLC_SUCCESS;
3491 }
3492
3493 static void MP4_TrackSetELST( demux_t *p_demux, mp4_track_t *tk,
3494                               int64_t i_time )
3495 {
3496     demux_sys_t *p_sys = p_demux->p_sys;
3497     int         i_elst_last = tk->i_elst;
3498
3499     /* handle elst (find the correct one) */
3500     tk->i_elst      = 0;
3501     tk->i_elst_time = 0;
3502     if( tk->p_elst && tk->BOXDATA(p_elst)->i_entry_count > 0 )
3503     {
3504         MP4_Box_data_elst_t *elst = tk->BOXDATA(p_elst);
3505         int64_t i_mvt= i_time * p_sys->i_timescale / CLOCK_FREQ;
3506
3507         for( tk->i_elst = 0; (unsigned int)tk->i_elst < elst->i_entry_count; tk->i_elst++ )
3508         {
3509             mtime_t i_dur = elst->i_segment_duration[tk->i_elst];
3510
3511             if( tk->i_elst_time <= i_mvt && i_mvt < tk->i_elst_time + i_dur )
3512             {
3513                 break;
3514             }
3515             tk->i_elst_time += i_dur;
3516         }
3517
3518         if( (unsigned int)tk->i_elst >= elst->i_entry_count )
3519         {
3520             /* msg_Dbg( p_demux, "invalid number of entry in elst" ); */
3521             tk->i_elst = elst->i_entry_count - 1;
3522             tk->i_elst_time -= elst->i_segment_duration[tk->i_elst];
3523         }
3524
3525         if( elst->i_media_time[tk->i_elst] < 0 )
3526         {
3527             /* track offset */
3528             tk->i_elst_time += elst->i_segment_duration[tk->i_elst];
3529         }
3530     }
3531     if( i_elst_last != tk->i_elst )
3532     {
3533         msg_Warn( p_demux, "elst old=%d new=%d", i_elst_last, tk->i_elst );
3534     }
3535 }
3536
3537 /******************************************************************************
3538  *     Here are the functions used for fragmented MP4
3539  *****************************************************************************/
3540
3541 /**
3542  * Return the track identified by tid
3543  */
3544 static mp4_track_t *MP4_frg_GetTrackByID( demux_t *p_demux, const uint32_t tid )
3545 {