root/modules/demux/mp4/mp4.c

Revision 4fa0611dd2ce05655d8e3be69452290e7b28cf51, 85.8 kB (checked in by Rémi Duraffort <ivoire@videolan.org>, 2 months ago)

Avoid a malloc(0)

  • Property mode set to 100644
Line 
1 /*****************************************************************************
2  * mp4.c : MP4 file input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001-2004 the VideoLAN team
5  * $Id$
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33
34
35 #include <vlc_demux.h>
36 #include <vlc_md5.h>
37 #include <vlc_charset.h>
38 #include <vlc_iso_lang.h>
39 #include <vlc_meta.h>
40 #include <vlc_input.h>
41
42 #include "libmp4.h"
43 #include "drms.h"
44
45 #ifdef UNDER_CE
46 #define uint64_t int64_t
47 #endif
48
49 /*****************************************************************************
50  * Module descriptor
51  *****************************************************************************/
52 static int  Open ( vlc_object_t * );
53 static void Close( vlc_object_t * );
54
55 vlc_module_begin();
56     set_category( CAT_INPUT );
57     set_subcategory( SUBCAT_INPUT_DEMUX );
58     set_description( N_("MP4 stream demuxer") );
59     set_capability( "demux", 242 );
60     set_callbacks( Open, Close );
61 vlc_module_end();
62
63 /*****************************************************************************
64  * Local prototypes
65  *****************************************************************************/
66 static int   Demux   ( demux_t * );
67 static int   DemuxRef( demux_t *p_demux ){ (void)p_demux; return 0;}
68 static int   Seek    ( demux_t *, mtime_t );
69 static int   Control ( demux_t *, int, va_list );
70
71 /* Contain all information about a chunk */
72 typedef struct
73 {
74     uint64_t     i_offset; /* absolute position of this chunk in the file */
75     uint32_t     i_sample_description_index; /* index for SampleEntry to use */
76     uint32_t     i_sample_count; /* how many samples in this chunk */
77     uint32_t     i_sample_first; /* index of the first sample in this chunk */
78
79     /* now provide way to calculate pts, dts, and offset without to
80         much memory and with fast acces */
81
82     /* with this we can calculate dts/pts without waste memory */
83     uint64_t     i_first_dts;
84     uint32_t     *p_sample_count_dts;
85     uint32_t     *p_sample_delta_dts;   /* dts delta */
86
87     uint32_t     *p_sample_count_pts;
88     int32_t      *p_sample_offset_pts;  /* pts-dts */
89
90     /* TODO if needed add pts
91         but quickly *add* support for edts and seeking */
92
93 } mp4_chunk_t;
94
95  /* Contain all needed information for read all track with vlc */
96 typedef struct
97 {
98     unsigned int i_track_ID;/* this should be unique */
99
100     int b_ok;               /* The track is usable */
101     int b_enable;           /* is the trak enable by default */
102     bool b_selected;  /* is the trak being played */
103     bool b_chapter;   /* True when used for chapter only */
104
105     bool b_mac_encoding;
106
107     es_format_t fmt;
108     es_out_id_t *p_es;
109
110     /* display size only ! */
111     int i_width;
112     int i_height;
113
114     /* more internal data */
115     uint64_t        i_timescale;    /* time scale for this track only */
116
117     /* elst */
118     int             i_elst;         /* current elst */
119     int64_t         i_elst_time;    /* current elst start time (in movie time scale)*/
120     MP4_Box_t       *p_elst;        /* elst (could be NULL) */
121
122     /* give the next sample to read, i_chunk is to find quickly where
123       the sample is located */
124     uint32_t         i_sample;       /* next sample to read */
125     uint32_t         i_chunk;        /* chunk where next sample is stored */
126     /* total count of chunk and sample */
127     uint32_t         i_chunk_count;
128     uint32_t         i_sample_count;
129
130     mp4_chunk_t    *chunk; /* always defined  for each chunk */
131
132     /* sample size, p_sample_size defined only if i_sample_size == 0
133         else i_sample_size is size for all sample */
134     uint32_t         i_sample_size;
135     uint32_t         *p_sample_size; /* XXX perhaps add file offset if take
136                                     too much time to do sumations each time*/
137
138     MP4_Box_t *p_stbl;  /* will contain all timing information */
139     MP4_Box_t *p_stsd;  /* will contain all data to initialize decoder */
140     MP4_Box_t *p_sample;/* point on actual sdsd */
141
142     bool b_drms;
143     void      *p_drms;
144
145 } mp4_track_t;
146
147
148 struct demux_sys_t
149 {
150     MP4_Box_t    *p_root;      /* container for the whole file */
151
152     mtime_t      i_pcr;
153
154     uint64_t     i_time;         /* time position of the presentation
155                                   * in movie timescale */
156     uint64_t     i_timescale;    /* movie time scale */
157     uint64_t     i_duration;     /* movie duration */
158     unsigned int i_tracks;       /* number of tracks */
159     mp4_track_t  *track;         /* array of track */
160
161     /* */
162     MP4_Box_t    *p_tref_chap;
163
164     /* */
165     input_title_t *p_title;
166 };
167
168 /*****************************************************************************
169  * Declaration of local function
170  *****************************************************************************/
171 static void MP4_TrackCreate ( demux_t *, mp4_track_t *, MP4_Box_t  *, bool b_force_enable );
172 static void MP4_TrackDestroy(  mp4_track_t * );
173
174 static int  MP4_TrackSelect ( demux_t *, mp4_track_t *, mtime_t );
175 static void MP4_TrackUnselect(demux_t *, mp4_track_t * );
176
177 static int  MP4_TrackSeek   ( demux_t *, mp4_track_t *, mtime_t );
178
179 static uint64_t MP4_TrackGetPos    ( mp4_track_t * );
180 static int      MP4_TrackSampleSize( mp4_track_t * );
181 static int      MP4_TrackNextSample( demux_t *, mp4_track_t * );
182 static void     MP4_TrackSetELST( demux_t *, mp4_track_t *, int64_t );
183
184 static void     MP4_UpdateSeekpoint( demux_t * );
185 static const char *MP4_ConvertMacCode( uint16_t );
186
187 /* Return time in s of a track */
188 static inline int64_t MP4_TrackGetDTS( demux_t *p_demux, mp4_track_t *p_track )
189 {
190 #define chunk p_track->chunk[p_track->i_chunk]
191
192     unsigned int i_index = 0;
193     unsigned int i_sample = p_track->i_sample - chunk.i_sample_first;
194     int64_t i_dts = chunk.i_first_dts;
195
196     while( i_sample > 0 )
197     {
198         if( i_sample > chunk.p_sample_count_dts[i_index] )
199         {
200             i_dts += chunk.p_sample_count_dts[i_index] *
201                 chunk.p_sample_delta_dts[i_index];
202             i_sample -= chunk.p_sample_count_dts[i_index];
203             i_index++;
204         }
205         else
206         {
207             i_dts += i_sample * chunk.p_sample_delta_dts[i_index];
208             i_sample = 0;
209             break;
210         }
211     }
212
213 #undef chunk
214
215     /* now handle elst */
216     if( p_track->p_elst )
217     {
218         demux_sys_t         *p_sys = p_demux->p_sys;
219         MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;
220
221         /* convert to offset */
222         if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
223               elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&
224             elst->i_media_time[p_track->i_elst] > 0 )
225         {
226             i_dts -= elst->i_media_time[p_track->i_elst];
227         }
228
229         /* add i_elst_time */
230         i_dts += p_track->i_elst_time * p_track->i_timescale /
231             p_sys->i_timescale;
232
233         if( i_dts < 0 ) i_dts = 0;
234     }
235
236     return INT64_C(1000000) * i_dts / p_track->i_timescale;
237 }
238
239 static inline int64_t MP4_TrackGetPTSDelta( mp4_track_t *p_track )
240 {
241     mp4_chunk_t *ck = &p_track->chunk[p_track->i_chunk];
242     unsigned int i_index = 0;
243     unsigned int i_sample = p_track->i_sample - ck->i_sample_first;
244
245     if( ck->p_sample_count_pts == NULL || ck->p_sample_offset_pts == NULL )
246         return -1;
247
248     for( i_index = 0;; i_index++ )
249     {
250         if( i_sample < ck->p_sample_count_pts[i_index] )
251             return ck->p_sample_offset_pts[i_index] * INT64_C(1000000) /
252                    (int64_t)p_track->i_timescale;
253
254         i_sample -= ck->p_sample_count_pts[i_index];
255     }
256 }
257
258 static inline int64_t MP4_GetMoviePTS(demux_sys_t *p_sys )
259 {
260     return INT64_C(1000000) * p_sys->i_time / p_sys->i_timescale;
261 }
262
263 static void LoadChapter( demux_t  *p_demux );
264
265 /*****************************************************************************
266  * Open: check file and initializes MP4 structures
267  *****************************************************************************/
268 static int Open( vlc_object_t * p_this )
269 {
270     demux_t  *p_demux = (demux_t *)p_this;
271     demux_sys_t     *p_sys;
272
273     const uint8_t   *p_peek;
274
275     MP4_Box_t       *p_ftyp;
276     MP4_Box_t       *p_rmra;
277     MP4_Box_t       *p_mvhd;
278     MP4_Box_t       *p_trak;
279
280     unsigned int    i;
281     bool      b_seekable;
282     bool      b_enabled_es;
283
284     /* A little test to see if it could be a mp4 */
285     if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 ) return VLC_EGENERIC;
286
287     switch( VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] ) )
288     {
289         case FOURCC_ftyp:
290         case FOURCC_moov:
291         case FOURCC_foov:
292         case FOURCC_moof:
293         case FOURCC_mdat:
294         case FOURCC_udta:
295         case FOURCC_free:
296         case FOURCC_skip:
297         case FOURCC_wide:
298         case VLC_FOURCC( 'p', 'n', 'o', 't' ):
299             break;
300          default:
301             return VLC_EGENERIC;
302     }
303
304     /* I need to seek */
305     stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_seekable );
306     if( !b_seekable )
307     {
308         msg_Warn( p_demux, "MP4 plugin discarded (unseekable)" );
309         return VLC_EGENERIC;
310     }
311
312     /*Set exported functions */
313     p_demux->pf_demux = Demux;
314     p_demux->pf_control = Control;
315
316     /* create our structure that will contains all data */
317     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
318     memset( p_sys, 0, sizeof( demux_sys_t ) );
319
320     /* Now load all boxes ( except raw data ) */
321     if( ( p_sys->p_root = MP4_BoxGetRoot( p_demux->s ) ) == NULL )
322     {
323         msg_Warn( p_demux, "MP4 plugin discarded (not a valid file)" );
324         goto error;
325     }
326
327     MP4_BoxDumpStructure( p_demux->s, p_sys->p_root );
328
329     if( ( p_ftyp = MP4_BoxGet( p_sys->p_root, "/ftyp" ) ) )
330     {
331         switch( p_ftyp->data.p_ftyp->i_major_brand )
332         {
333             case( FOURCC_isom ):
334                 msg_Dbg( p_demux,
335                          "ISO Media file (isom) version %d.",
336                          p_ftyp->data.p_ftyp->i_minor_version );
337                 break;
338             default:
339                 msg_Dbg( p_demux,
340                          "unrecognized major file specification (%4.4s).",
341                           (char*)&p_ftyp->data.p_ftyp->i_major_brand );
342                 break;
343         }
344     }
345     else
346     {
347         msg_Dbg( p_demux, "file type box missing (assuming ISO Media file)" );
348     }
349
350     /* the file need to have one moov box */
351     if( MP4_BoxCount( p_sys->p_root, "/moov" ) <= 0 )
352     {
353         MP4_Box_t *p_foov = MP4_BoxGet( p_sys->p_root, "/foov" );
354
355         if( !p_foov )
356         {
357             msg_Err( p_demux, "MP4 plugin discarded (no moov box)" );
358             goto error;
359         }
360         /* we have a free box as a moov, rename it */
361         p_foov->i_type = FOURCC_moov;
362     }
363
364     if( ( p_rmra = MP4_BoxGet( p_sys->p_root,  "/moov/rmra" ) ) )
365     {
366         int        i_count = MP4_BoxCount( p_rmra, "rmda" );
367         int        i;
368
369         msg_Dbg( p_demux, "detected playlist mov file (%d ref)", i_count );
370
371         input_thread_t * p_input = vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );
372         input_item_t * p_current = input_GetItem( p_input );
373         p_current->i_type = ITEM_TYPE_PLAYLIST;
374
375         for( i = 0; i < i_count; i++ )
376         {
377             MP4_Box_t *p_rdrf = MP4_BoxGet( p_rmra, "rmda[%d]/rdrf", i );
378             char      *psz_ref;
379             uint32_t  i_ref_type;
380
381             if( !p_rdrf || !( psz_ref = strdup( p_rdrf->data.p_rdrf->psz_ref ) ) )
382             {
383                 continue;
384             }
385             i_ref_type = p_rdrf->data.p_rdrf->i_ref_type;
386
387             msg_Dbg( p_demux, "new ref=`%s' type=%4.4s",
388                      psz_ref, (char*)&i_ref_type );
389
390             if( i_ref_type == VLC_FOURCC( 'u', 'r', 'l', ' ' ) )
391             {
392                 if( strstr( psz_ref, "qt5gateQT" ) )
393                 {
394                     msg_Dbg( p_demux, "ignoring pseudo ref =`%s'", psz_ref );
395                     continue;
396                 }
397                 if( !strncmp( psz_ref, "http://", 7 ) ||
398                     !strncmp( psz_ref, "rtsp://", 7 ) )
399                 {
400                     ;
401                 }
402                 else
403                 {
404                     char *psz_absolute;
405                     char *psz_path = strdup( p_demux->psz_path );
406                     char *end = strrchr( psz_path, '/' );
407                     if( end ) end[1] = '\0';
408                     else *psz_path = '\0';
409
410                     if( asprintf( &psz_absolute, "%s://%s%s",
411                                   p_demux->psz_access, psz_path, psz_ref ) < 0 )
412                         return VLC_ENOMEM;
413
414                     free( psz_ref );
415                     psz_ref = psz_absolute;
416                     free( psz_path );
417                 }
418                 input_item_t *p_input;
419                 msg_Dbg( p_demux, "adding ref = `%s'", psz_ref );
420                 p_input = input_item_NewExt( p_demux, psz_ref, NULL,
421                                     0, NULL, -1 );
422                 input_item_CopyOptions( p_current, p_input );
423                 input_item_AddSubItem( p_current, p_input );
424                 vlc_gc_decref( p_input );
425             }
426             else
427             {
428                 msg_Err( p_demux, "unknown ref type=%4.4s FIXME (send a bug report)",
429                          (char*)&p_rdrf->data.p_rdrf->i_ref_type );
430             }
431             free( psz_ref );
432         }
433         vlc_object_release( p_input );
434     }
435
436     if( !(p_mvhd = MP4_BoxGet( p_sys->p_root, "/moov/mvhd" ) ) )
437     {
438         if( !p_rmra )
439         {
440             msg_Err( p_demux, "cannot find /moov/mvhd" );
441             goto error;
442         }
443         else
444         {
445             msg_Warn( p_demux, "cannot find /moov/mvhd (pure ref file)" );
446             p_demux->pf_demux = DemuxRef;
447             return VLC_SUCCESS;
448         }
449     }
450     else
451     {
452         p_sys->i_timescale = p_mvhd->data.p_mvhd->i_timescale;
453         if( p_sys->i_timescale == 0 )
454         {
455             msg_Err( p_this, "bad timescale" );
456             goto error;
457         }
458         p_sys->i_duration = p_mvhd->data.p_mvhd->i_duration;
459     }
460
461     if( !( p_sys->i_tracks = MP4_BoxCount( p_sys->p_root, "/moov/trak" ) ) )
462     {
463         msg_Err( p_demux, "cannot find any /moov/trak" );
464         goto error;
465     }
466     msg_Dbg( p_demux, "found %d track%c",
467                         p_sys->i_tracks,
468                         p_sys->i_tracks ? 's':' ' );
469
470     /* allocate memory */
471     p_sys->track = calloc( p_sys->i_tracks, sizeof( mp4_track_t ) );
472     if( p_sys->track == NULL )
473         goto error;
474     memset( p_sys->track, 0, p_sys->i_tracks * sizeof( mp4_track_t ) );
475
476     /* Search the first chap reference (like quicktime) and
477      * check that at least 1 stream is enabled */
478     p_sys->p_tref_chap = NULL;
479     b_enabled_es = false;
480     for( i = 0; i < p_sys->i_tracks; i++ )
481     {
482         MP4_Box_t *p_trak = MP4_BoxGet( p_sys->p_root, "/moov/trak[%d]", i );
483
484
485         MP4_Box_t *p_tkhd = MP4_BoxGet( p_trak, "tkhd" );
486         if( p_tkhd && (p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED) )
487             b_enabled_es = true;
488
489         MP4_Box_t *p_chap = MP4_BoxGet( p_trak, "tref/chap", i );
490         if( p_chap && p_chap->data.p_tref_generic->i_entry_count > 0 && !p_sys->p_tref_chap )
491             p_sys->p_tref_chap = p_chap;
492     }
493
494     /* now process each track and extract all usefull information */
495     for( i = 0; i < p_sys->i_tracks; i++ )
496     {
497         p_trak = MP4_BoxGet( p_sys->p_root, "/moov/trak[%d]", i );
498         MP4_TrackCreate( p_demux, &p_sys->track[i], p_trak, !b_enabled_es );
499
500         if( p_sys->track[i].b_ok && !p_sys->track[i].b_chapter )
501         {
502             const char *psz_cat;
503             switch( p_sys->track[i].fmt.i_cat )
504             {
505                 case( VIDEO_ES ):
506                     psz_cat = "video";
507                     break;
508                 case( AUDIO_ES ):
509                     psz_cat = "audio";
510                     break;
511                 case( SPU_ES ):
512                     psz_cat = "subtitle";
513                     break;
514
515                 default:
516                     psz_cat = "unknown";
517                     break;
518             }
519
520             msg_Dbg( p_demux, "adding track[Id 0x%x] %s (%s) language %s",
521                      p_sys->track[i].i_track_ID, psz_cat,
522                      p_sys->track[i].b_enable ? "enable":"disable",
523                      p_sys->track[i].fmt.psz_language ?
524                      p_sys->track[i].fmt.psz_language : "undef" );
525         }
526         else if( p_sys->track[i].b_ok && p_sys->track[i].b_chapter )
527         {
528             msg_Dbg( p_demux, "using track[Id 0x%x] for chapter language %s",
529                      p_sys->track[i].i_track_ID,
530                      p_sys->track[i].fmt.psz_language ?
531                      p_sys->track[i].fmt.psz_language : "undef" );
532         }
533         else
534         {
535             msg_Dbg( p_demux, "ignoring track[Id 0x%x]",
536                      p_sys->track[i].i_track_ID );
537         }
538     }
539
540     /* */
541     LoadChapter( p_demux );
542
543     return VLC_SUCCESS;
544
545 error:
546     if( p_sys->p_root )
547     {
548         MP4_BoxFree( p_demux->s, p_sys->p_root );
549     }
550     free( p_sys );
551     return VLC_EGENERIC;
552 }
553
554 /*****************************************************************************
555  * Demux: read packet and send them to decoders
556  *****************************************************************************
557  * TODO check for newly selected track (ie audio upt to now )
558  *****************************************************************************/
559 static int Demux( demux_t *p_demux )
560 {
561     demux_sys_t *p_sys = p_demux->p_sys;
562     unsigned int i_track;
563
564
565     unsigned int i_track_selected;
566
567     /* check for newly selected/unselected track */
568     for( i_track = 0, i_track_selected = 0; i_track < p_sys->i_tracks;
569          i_track++ )
570     {
571         mp4_track_t *tk = &p_sys->track[i_track];
572         bool b;
573
574         if( !tk->b_ok || tk->b_chapter ||
575             ( tk->b_selected && tk->i_sample >= tk->i_sample_count ) )
576         {
577             continue;
578         }
579
580         es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
581
582         if( tk->b_selected && !b )
583         {
584             MP4_TrackUnselect( p_demux, tk );
585         }
586         else if( !tk->b_selected && b)
587         {
588             MP4_TrackSelect( p_demux, tk, MP4_GetMoviePTS( p_sys ) );
589         }
590
591         if( tk->b_selected )
592         {
593             i_track_selected++;
594         }
595     }
596
597     if( i_track_selected <= 0 )
598     {
599         p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 );
600         if( p_sys->i_timescale > 0 )
601         {
602             int64_t i_length = (mtime_t)1000000 *
603                                (mtime_t)p_sys->i_duration /
604                                (mtime_t)p_sys->i_timescale;
605             if( MP4_GetMoviePTS( p_sys ) >= i_length )
606                 return 0;
607             return 1;
608         }
609
610         msg_Warn( p_demux, "no track selected, exiting..." );
611         return 0;
612     }
613
614     /* */
615     MP4_UpdateSeekpoint( p_demux );
616
617     /* first wait for the good time to read a packet */
618     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr + 1 );
619
620     p_sys->i_pcr = MP4_GetMoviePTS( p_sys );
621
622     /* we will read 100ms for each stream so ...*/
623     p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 );
624
625     for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
626     {
627         mp4_track_t *tk = &p_sys->track[i_track];
628
629         if( !tk->b_ok || tk->b_chapter || !tk->b_selected || tk->i_sample >= tk->i_sample_count )
630             continue;
631
632         while( MP4_TrackGetDTS( p_demux, tk ) < MP4_GetMoviePTS( p_sys ) )
633         {
634 #if 0
635             msg_Dbg( p_demux, "tk(%i)=%lld mv=%lld", i_track,
636                      MP4_TrackGetDTS( p_demux, tk ),
637                      MP4_GetMoviePTS( p_sys ) );
638 #endif
639
640             if( MP4_TrackSampleSize( tk ) > 0 )
641             {
642                 block_t *p_block;
643                 int64_t i_delta;
644
645                 /* go,go go ! */
646                 if( stream_Seek( p_demux->s, MP4_TrackGetPos( tk ) ) )
647                 {
648                     msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)",
649                               tk->i_track_ID );
650                     MP4_TrackUnselect( p_demux, tk );
651                     break;
652                 }
653
654                 /* now read pes */
655                 if( !(p_block =
656                          stream_Block( p_demux->s, MP4_TrackSampleSize(tk) )) )
657                 {
658                     msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)",
659                               tk->i_track_ID );
660                     MP4_TrackUnselect( p_demux, tk );
661                     break;
662                 }
663
664                 if( tk->b_drms && tk->p_drms )
665                 {
666                     drms_decrypt( tk->p_drms, (uint32_t*)p_block->p_buffer,
667                                   p_block->i_buffer );
668                 }
669                 else if( tk->fmt.i_cat == SPU_ES )
670                 {
671                     if( tk->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) &&
672                         p_block->i_buffer >= 2 )
673                     {
674                         uint16_t i_size = GetWBE( p_block->p_buffer );
675
676                         if( i_size + 2 <= p_block->i_buffer )
677                         {
678                             char *p;
679                             /* remove the length field, and append a '\0' */
680                             memmove( &p_block->p_buffer[0],
681                                      &p_block->p_buffer[2], i_size );
682                             p_block->p_buffer[i_size] = '\0';
683                             p_block->i_buffer = i_size + 1;
684
685                             /* convert \r -> \n */
686                             while( ( p = strchr((char *) p_block->p_buffer, '\r' ) ) )
687                             {
688                                 *p = '\n';
689                             }
690                         }
691                         else
692                         {
693                             /* Invalid */
694                             p_block->i_buffer = 0;
695                         }
696                     }
697                 }
698                 /* dts */
699                 p_block->i_dts = MP4_TrackGetDTS( p_demux, tk ) + 1;
700                 /* pts */
701                 i_delta = MP4_TrackGetPTSDelta( tk );
702                 if( i_delta != -1 )
703                     p_block->i_pts = p_block->i_dts + i_delta;
704                 else if( tk->fmt.i_cat != VIDEO_ES )
705                     p_block->i_pts = p_block->i_dts;
706                 else
707                     p_block->i_pts = 0;
708
709                 if( !tk->b_drms || ( tk->b_drms && tk->p_drms ) )
710                     es_out_Send( p_demux->out, tk->p_es, p_block );
711             }
712
713             /* Next sample */
714             if( MP4_TrackNextSample( p_demux, tk ) )
715                 break;
716         }
717     }
718
719     return 1;
720 }
721
722 static void MP4_UpdateSeekpoint( demux_t *p_demux )
723 {
724     demux_sys_t *p_sys = p_demux->p_sys;
725     int64_t i_time;
726     int i;
727     if( !p_sys->p_title )
728         return;
729     i_time = MP4_GetMoviePTS( p_sys );
730     for( i = 0; i < p_sys->p_title->i_seekpoint; i++ )
731     {
732         if( i_time < p_sys->p_title->seekpoint[i]->i_time_offset )
733             break;
734     }
735     i--;
736
737     if( i != p_demux->info.i_seekpoint && i >= 0 )
738     {
739         p_demux->info.i_seekpoint = i;
740         p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
741     }
742 }
743 /*****************************************************************************
744  * Seek: Got to i_date
745 ******************************************************************************/
746 static int Seek( demux_t *p_demux, mtime_t i_date )
747 {
748     demux_sys_t *p_sys = p_demux->p_sys;
749     unsigned int i_track;
750
751     /* First update update global time */
752     p_sys->i_time = i_date * p_sys->i_timescale / 1000000;
753     p_sys->i_pcr  = i_date;
754
755     /* Now for each stream try to go to this time */
756     for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
757     {
758         mp4_track_t *tk = &p_sys->track[i_track];
759         MP4_TrackSeek( p_demux, tk, i_date );
760     }
761     MP4_UpdateSeekpoint( p_demux );
762     return VLC_SUCCESS;
763 }
764
765 /*****************************************************************************
766  * Control:
767  *****************************************************************************/
768 static int Control( demux_t *p_demux, int i_query, va_list args )
769 {
770     demux_sys_t *p_sys = p_demux->p_sys;
771
772     double f, *pf;
773     int64_t i64, *pi64;
774
775     switch( i_query )
776     {
777         case DEMUX_GET_POSITION:
778             pf = (double*)va_arg( args, double * );
779             if( p_sys->i_duration > 0 )
780             {
781                 *pf = (double)p_sys->i_time / (double)p_sys->i_duration;
782             }
783             else
784             {
785                 *pf = 0.0;
786             }
787             return VLC_SUCCESS;
788
789         case DEMUX_SET_POSITION:
790             f = (double)va_arg( args, double );
791             if( p_sys->i_timescale > 0 )
792             {
793                 i64 = (int64_t)( f * (double)1000000 *
794                                  (double)p_sys->i_duration /
795                                  (double)p_sys->i_timescale );
796                 return Seek( p_demux, i64 );
797             }
798             else return VLC_SUCCESS;
799
800         case DEMUX_GET_TIME:
801             pi64 = (int64_t*)va_arg( args, int64_t * );
802             if( p_sys->i_timescale > 0 )
803             {
804                 *pi64 = (mtime_t)1000000 *
805                         (mtime_t)p_sys->i_time /
806                         (mtime_t)p_sys->i_timescale;
807             }
808             else *pi64 = 0;
809             return VLC_SUCCESS;
810
811         case DEMUX_SET_TIME:
812             i64 = (int64_t)va_arg( args, int64_t );
813             return Seek( p_demux, i64 );
814
815         case DEMUX_GET_LENGTH:
816             pi64 = (int64_t*)va_arg( args, int64_t * );
817             if( p_sys->i_timescale > 0 )
818             {
819                 *pi64 = (mtime_t)1000000 *
820                         (mtime_t)p_sys->i_duration /
821                         (mtime_t)p_sys->i_timescale;
822             }
823             else *pi64 = 0;
824             return VLC_SUCCESS;
825
826         case DEMUX_GET_FPS:
827             msg_Warn( p_demux, "DEMUX_GET_FPS unimplemented !!" );
828             return VLC_EGENERIC;
829
830         case DEMUX_GET_META:
831         {
832             vlc_meta_t *p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t*);
833             MP4_Box_t  *p_0xa9xxx;
834
835             MP4_Box_t  *p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta/meta/ilst" );
836             if( p_udta == NULL )
837             {
838                 p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta" );
839                 if( p_udta == NULL )
840                 {
841                     return VLC_EGENERIC;
842                 }
843             }
844
845             for( p_0xa9xxx = p_udta->p_first; p_0xa9xxx != NULL;
846                  p_0xa9xxx = p_0xa9xxx->p_next )
847             {
848
849                 if( !p_0xa9xxx || !p_0xa9xxx->data.p_0xa9xxx )
850                     continue;
851
852                 /* FIXME FIXME: should convert from whatever the character
853                  * encoding of MP4 meta data is to UTF-8. */
854 #define SET(fct) do { char *psz_utf = strdup( p_0xa9xxx->data.p_0xa9xxx->psz_text ? p_0xa9xxx->data.p_0xa9xxx->psz_text : "" ); \
855     if( psz_utf ) { EnsureUTF8( psz_utf );  \
856                     fct( p_meta, psz_utf ); free( psz_utf ); } } while(0)
857
858                 /* XXX Becarefull p_udta can have box that are not 0xa9xx */
859                 switch( p_0xa9xxx->i_type )
860                 {
861                 case FOURCC_0xa9nam: /* Full name */
862                     SET( vlc_meta_SetTitle );
863                     break;
864                 case FOURCC_0xa9aut:
865                     SET( vlc_meta_SetArtist );
866                     break;
867                 case FOURCC_0xa9ART:
868                     SET( vlc_meta_SetArtist );
869                     break;
870                 case FOURCC_0xa9cpy:
871                     SET( vlc_meta_SetCopyright );
872