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