]> git.sesse.net Git - vlc/blob - modules/mux/mp4.c
* modules/gui/wxwindows/preferences.cpp: fixes some alignment issues in the config...
[vlc] / modules / mux / mp4.c
1 /*****************************************************************************
2  * mp4.c: mp4/mov muxer
3  *****************************************************************************
4  * Copyright (C) 2001, 2002, 2003 VideoLAN
5  * $Id: mp4.c,v 1.6 2003/10/17 16:40:08 gbazin Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/input.h>
33 #include <vlc/sout.h>
34
35 #ifdef HAVE_TIME_H
36 #include <time.h>
37 #endif
38
39 #include "codecs.h"
40
41 /*****************************************************************************
42  * Exported prototypes
43  *****************************************************************************/
44 static int     Open   ( vlc_object_t * );
45 static void    Close  ( vlc_object_t * );
46
47 static int Capability(sout_mux_t *, int, void *, void * );
48 static int AddStream( sout_mux_t *, sout_input_t * );
49 static int DelStream( sout_mux_t *, sout_input_t * );
50 static int Mux      ( sout_mux_t * );
51
52 /*****************************************************************************
53  * Module descriptor
54  *****************************************************************************/
55 vlc_module_begin();
56     set_description( _("MP4/MOV muxer") );
57     set_capability( "sout mux", 5 );
58     add_shortcut( "mp4" );
59     add_shortcut( "mov" );
60     set_callbacks( Open, Close );
61 vlc_module_end();
62
63 typedef struct
64 {
65     uint64_t i_pos;
66     int      i_size;
67
68     mtime_t  i_pts;
69     mtime_t  i_dts;
70     mtime_t  i_length;
71
72 } mp4_entry_t;
73
74 typedef struct
75 {
76     sout_format_t *p_fmt;
77     int           i_track_id;
78
79     /* index */
80     unsigned int i_entry_count;
81     unsigned int i_entry_max;
82     mp4_entry_t  *entry;
83
84     /* stats */
85     mtime_t      i_duration;
86 } mp4_stream_t;
87
88 struct sout_mux_sys_t
89 {
90     vlc_bool_t b_mov;
91
92     uint64_t i_mdat_pos;
93     uint64_t i_pos;
94
95     mtime_t  i_start_dts;
96
97     int          i_nb_streams;
98     mp4_stream_t **pp_streams;
99 };
100
101
102 typedef struct bo_t bo_t;
103 struct bo_t
104 {
105     vlc_bool_t b_grow;
106
107     int        i_buffer_size;
108     int        i_buffer;
109     uint8_t    *p_buffer;
110
111 };
112
113 static void bo_init     ( bo_t *, int , uint8_t *, vlc_bool_t  );
114 static void bo_add_8    ( bo_t *, uint8_t );
115 static void bo_add_16be ( bo_t *, uint16_t );
116 static void bo_add_24be ( bo_t *, uint32_t );
117 static void bo_add_32be ( bo_t *, uint32_t );
118 static void bo_add_64be ( bo_t *, uint64_t );
119 static void bo_add_fourcc(bo_t *, char * );
120 static void bo_add_bo   ( bo_t *, bo_t * );
121 static void bo_add_mem  ( bo_t *, int , uint8_t * );
122 static void bo_add_descr ( bo_t *, uint8_t , uint32_t );
123
124 static void bo_fix_32be ( bo_t *, int , uint32_t );
125
126 static bo_t *box_new     ( char *fcc );
127 static bo_t *box_full_new( char *fcc, uint8_t v, uint32_t f );
128 static void  box_fix     ( bo_t *box );
129 static void  box_free    ( bo_t *box );
130 static void  box_gather  ( bo_t *box, bo_t *box2 );
131
132 static void box_send( sout_mux_t *p_mux,  bo_t *box );
133
134 static int64_t get_timestamp();
135
136 static sout_buffer_t * bo_to_sout( sout_instance_t *p_sout,  bo_t *box );
137
138 /*****************************************************************************
139  * Open:
140  *****************************************************************************/
141 static int Open( vlc_object_t *p_this )
142 {
143     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
144     sout_mux_sys_t  *p_sys;
145     bo_t            *box;
146
147     p_sys = malloc( sizeof( sout_mux_sys_t ) );
148     p_sys->i_pos        = 0;
149     p_sys->i_nb_streams = 0;
150     p_sys->pp_streams   = NULL;
151     p_sys->i_mdat_pos   = 0;
152     p_sys->b_mov        = p_mux->psz_mux && !strcmp( p_mux->psz_mux, "mov" );
153     p_sys->i_start_dts  = 0;
154
155     msg_Info( p_mux, "Open" );
156
157     p_mux->pf_capacity  = Capability;
158     p_mux->pf_addstream = AddStream;
159     p_mux->pf_delstream = DelStream;
160     p_mux->pf_mux       = Mux;
161     p_mux->p_sys        = p_sys;
162
163     if( !p_sys->b_mov )
164     {
165         /* Now add ftyp header */
166         box = box_new( "ftyp" );
167         bo_add_fourcc( box, "isom" );
168         bo_add_32be  ( box, 0 );
169         bo_add_fourcc( box, "mp41" );
170         box_fix( box );
171
172         p_sys->i_pos += box->i_buffer;
173         p_sys->i_mdat_pos = p_sys->i_pos;
174
175         box_send( p_mux, box );
176
177         /* FIXME FIXME
178          * Quicktime actually doesn't like the 64 bits extensions !!! */
179         p_sys->b_mov = VLC_TRUE;
180     }
181
182     /* Now add mdat header */
183     box = box_new( "mdat" );
184     bo_add_64be  ( box, 0 ); // enough to store an extended size
185
186     p_sys->i_pos += box->i_buffer;
187
188     box_send( p_mux, box );
189
190     return VLC_SUCCESS;
191 }
192
193 static int GetDescrLength( int i_size )
194 {
195     if( i_size < 0x00000080 )
196         return 2 + i_size;
197     else if( i_size < 0x00004000 )
198         return 3 + i_size;
199     else if( i_size < 0x00200000 )
200         return 4 + i_size;
201     else
202         return 5 + i_size;
203 }
204
205 static bo_t *GetESDS( mp4_stream_t *p_stream )
206 {
207     bo_t *esds;
208     int  i_stream_type;
209     int  i_object_type_indication;
210     int  i_decoder_specific_info_size;
211
212     if( p_stream->p_fmt->i_extra_data > 0 )
213     {
214         i_decoder_specific_info_size =
215             GetDescrLength( p_stream->p_fmt->i_extra_data );
216     }
217     else
218     {
219         i_decoder_specific_info_size = 0;
220     }
221
222     esds = box_full_new( "esds", 0, 0 );
223
224     /* ES_Descr */
225     bo_add_descr( esds, 0x03, 3 +
226                   GetDescrLength( 13 + i_decoder_specific_info_size ) +
227                   GetDescrLength( 1 ) );
228     bo_add_16be( esds, p_stream->i_track_id );
229     bo_add_8   ( esds, 0x1f );      // flags=0|streamPriority=0x1f
230
231     /* DecoderConfigDescr */
232     bo_add_descr( esds, 0x04, 13 + i_decoder_specific_info_size );
233
234     switch( p_stream->p_fmt->i_fourcc )
235     {
236         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
237             i_object_type_indication = 0x20;
238             break;
239         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
240             /* FIXME MPEG-I=0x6b, MPEG-II = 0x60 -> 0x65 */
241             i_object_type_indication = 0x60;
242             break;
243         case VLC_FOURCC( 'm', 'p', '4', 'a' ):
244             /* FIXME for mpeg2-aac == 0x66->0x68 */
245             i_object_type_indication = 0x40;
246             break;
247         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
248             i_object_type_indication =
249                 p_stream->p_fmt->i_sample_rate < 32000 ? 0x69 : 0x6b;
250             break;
251         default:
252             i_object_type_indication = 0x00;
253             break;
254     }
255     i_stream_type = p_stream->p_fmt->i_cat == VIDEO_ES ? 0x04 : 0x05;
256
257     bo_add_8   ( esds, i_object_type_indication );
258     bo_add_8   ( esds, ( i_stream_type << 2 ) | 1 );
259     bo_add_24be( esds, 1024 * 1024 );       // bufferSizeDB
260     bo_add_32be( esds, 0x7fffffff );        // maxBitrate
261     bo_add_32be( esds, 0 );                 // avgBitrate
262
263     if( p_stream->p_fmt->i_extra_data > 0 )
264     {
265         int i;
266
267         /* DecoderSpecificInfo */
268         bo_add_descr( esds, 0x05, p_stream->p_fmt->i_extra_data );
269
270         for( i = 0; i < p_stream->p_fmt->i_extra_data; i++ )
271         {
272             bo_add_8( esds, p_stream->p_fmt->p_extra_data[i] );
273         }
274     }
275
276     /* SL_Descr mandatory */
277     bo_add_descr( esds, 0x06, 1 );
278     bo_add_8    ( esds, 0x02 );  // sl_predefined
279
280     box_fix( esds );
281
282     return esds;
283 }
284
285 /*****************************************************************************
286  * Close:
287  *****************************************************************************/
288 static uint32_t mvhd_matrix[9] =
289     { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 };
290
291 static void Close( vlc_object_t * p_this )
292 {
293     sout_mux_t *p_mux = (sout_mux_t*)p_this;
294     sout_mux_sys_t  *p_sys = p_mux->p_sys;
295     sout_buffer_t   *p_hdr;
296     bo_t            bo;
297     bo_t            *moov, *mvhd;
298     unsigned int    i;
299     int             i_trak, i_index;
300
301     uint32_t        i_movie_timescale = 90000;
302     int64_t         i_movie_duration  = 0;
303     msg_Info( p_mux, "Close" );
304
305     /* create general info */
306     for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
307     {
308         mp4_stream_t *p_stream;
309
310         p_stream = p_sys->pp_streams[i_trak];
311
312         i_movie_duration = __MAX( i_movie_duration, p_stream->i_duration );
313     }
314     msg_Dbg( p_mux, "movie duration %ds",
315              (uint32_t)( i_movie_duration / (mtime_t)1000000 ) );
316
317     i_movie_duration = i_movie_duration *
318                        (int64_t)i_movie_timescale / (int64_t)1000000;
319
320     /* *** update mdat size *** */
321     bo_init      ( &bo, 0, NULL, VLC_TRUE );
322     if( p_sys->i_pos - p_sys->i_mdat_pos >= (((uint64_t)1)<<32) )
323     {
324         /* Extended size */
325         bo_add_32be  ( &bo, 1 );
326         bo_add_fourcc( &bo, "mdat" );
327         bo_add_64be  ( &bo, p_sys->i_pos - p_sys->i_mdat_pos );
328     }
329     else
330     {
331         bo_add_32be  ( &bo, 8 );
332         bo_add_fourcc( &bo, "wide" );
333         bo_add_32be  ( &bo, p_sys->i_pos - p_sys->i_mdat_pos - 8 );
334         bo_add_fourcc( &bo, "mdat" );
335     }
336
337     p_hdr = bo_to_sout( p_mux->p_sout, &bo );
338     free( bo.p_buffer );
339
340     /* seek to mdat */
341     sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos );
342     sout_AccessOutWrite( p_mux->p_access, p_hdr );
343
344     /* Now create header */
345     sout_AccessOutSeek( p_mux->p_access, p_sys->i_pos );
346
347     moov = box_new( "moov" );
348
349     /* *** add /moov/mvhd *** */
350     if( p_sys->b_mov )
351     {
352         mvhd = box_full_new( "mvhd", 0, 0 );
353         bo_add_32be( mvhd, get_timestamp() );   // creation time
354         bo_add_32be( mvhd, get_timestamp() );   // modification time
355         bo_add_32be( mvhd, i_movie_timescale);  // timescale
356         bo_add_32be( mvhd, i_movie_duration );  // duration
357     }
358     else
359     {
360         mvhd = box_full_new( "mvhd", 1, 0 );
361         bo_add_64be( mvhd, get_timestamp() );   // creation time
362         bo_add_64be( mvhd, get_timestamp() );   // modification time
363         bo_add_32be( mvhd, i_movie_timescale);  // timescale
364         bo_add_64be( mvhd, i_movie_duration );  // duration
365     }
366     bo_add_32be( mvhd, 0x10000 );           // rate
367     bo_add_16be( mvhd, 0x100 );             // volume
368     bo_add_16be( mvhd, 0 );                 // reserved
369     for( i = 0; i < 2; i++ )
370     {
371         bo_add_32be( mvhd, 0 );             // reserved
372     }
373     for( i = 0; i < 9; i++ )
374     {
375         bo_add_32be( mvhd, mvhd_matrix[i] );// matrix
376     }
377     for( i = 0; i < 6; i++ )
378     {
379         bo_add_32be( mvhd, 0 );             // pre-defined
380     }
381
382     /* Find the 1st track id */
383     for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
384     {
385         mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
386
387         if( p_stream->p_fmt->i_cat == AUDIO_ES ||
388             p_stream->p_fmt->i_cat == VIDEO_ES )
389         {
390             /* Found it */
391             bo_add_32be( mvhd, p_stream->i_track_id ); // next-track-id
392             break;
393         }
394     }
395     if( i_trak == p_sys->i_nb_streams ) /* Just for sanity reasons */
396         bo_add_32be( mvhd, 0xffffffff );
397
398     box_fix( mvhd );
399     box_gather( moov, mvhd );
400
401     for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
402     {
403         mp4_stream_t *p_stream;
404         uint32_t     i_timescale;
405         uint32_t     i_chunk_count;
406
407         bo_t *trak;
408         bo_t *tkhd;
409         bo_t *mdia;
410         bo_t *mdhd, *hdlr;
411         bo_t *minf;
412         bo_t *dinf;
413         bo_t *dref;
414         bo_t *url;
415         bo_t *stbl;
416         bo_t *stsd;
417         bo_t *stts;
418         bo_t *stsz;
419
420         p_stream = p_sys->pp_streams[i_trak];
421
422         if( p_stream->p_fmt->i_cat != AUDIO_ES &&
423             p_stream->p_fmt->i_cat != VIDEO_ES )
424         {
425             msg_Err( p_mux, "FIXME ignoring trak (noaudio&&novideo)" );
426             continue;
427         }
428         if( p_stream->p_fmt->i_cat == AUDIO_ES )
429         {
430             i_timescale = p_stream->p_fmt->i_sample_rate;
431         }
432         else
433         {
434             i_timescale = 1001;
435         }
436
437         /* *** add /moov/trak *** */
438         trak = box_new( "trak" );
439
440         /* *** add /moov/trak/tkhd *** */
441         if( p_sys->b_mov )
442         {
443             tkhd = box_full_new( "tkhd", 0, 1 );
444             bo_add_32be( tkhd, get_timestamp() );       // creation time
445             bo_add_32be( tkhd, get_timestamp() );       // modification time
446             bo_add_32be( tkhd, p_stream->i_track_id );
447             bo_add_32be( tkhd, 0 );                     // reserved 0
448             bo_add_32be( tkhd, p_stream->i_duration *
449                          (int64_t)i_movie_timescale /
450                          (mtime_t)1000000 );            // duration
451         }
452         else
453         {
454             tkhd = box_full_new( "tkhd", 1, 1 );
455             bo_add_64be( tkhd, get_timestamp() );       // creation time
456             bo_add_64be( tkhd, get_timestamp() );       // modification time
457             bo_add_32be( tkhd, p_stream->i_track_id );
458             bo_add_32be( tkhd, 0 );                     // reserved 0
459             bo_add_64be( tkhd, p_stream->i_duration *
460                          (int64_t)i_movie_timescale /
461                          (mtime_t)1000000 );            // duration
462         }
463
464         for( i = 0; i < 2; i++ )
465         {
466             bo_add_32be( tkhd, 0 );                 // reserved
467         }
468         bo_add_16be( tkhd, 0 );                     // layer
469         bo_add_16be( tkhd, 0 );                     // pre-defined
470         bo_add_16be( tkhd, p_stream->p_fmt->i_cat == AUDIO_ES ? 0x100 : 0 ); // volume
471         bo_add_16be( tkhd, 0 );                     // reserved
472         for( i = 0; i < 9; i++ )
473         {
474             bo_add_32be( tkhd, mvhd_matrix[i] );    // matrix
475         }
476         if( p_stream->p_fmt->i_cat == AUDIO_ES )
477         {
478             bo_add_32be( tkhd, 0 );                 // width (presentation)
479             bo_add_32be( tkhd, 0 );                 // height(presentation)
480         }
481         else
482         {
483             bo_add_32be( tkhd, p_stream->p_fmt->i_width  << 16 );     // width (presentation)
484             bo_add_32be( tkhd, p_stream->p_fmt->i_height << 16 );     // height(presentation)
485         }
486         box_fix( tkhd );
487         box_gather( trak, tkhd );
488
489         /* *** add /moov/trak/mdia *** */
490         mdia = box_new( "mdia" );
491
492         /* media header */
493         if( p_sys->b_mov )
494         {
495             mdhd = box_full_new( "mdhd", 0, 0 );
496             bo_add_32be( mdhd, get_timestamp() );   // creation time
497             bo_add_32be( mdhd, get_timestamp() );   // modification time
498             bo_add_32be( mdhd, i_timescale);        // timescale
499             bo_add_32be( mdhd, p_stream->i_duration * (int64_t)i_timescale /
500                                (mtime_t)1000000 );  // duration
501         }
502         else
503         {
504             mdhd = box_full_new( "mdhd", 1, 0 );
505             bo_add_64be( mdhd, get_timestamp() );   // creation time
506             bo_add_64be( mdhd, get_timestamp() );   // modification time
507             bo_add_32be( mdhd, i_timescale);        // timescale
508             bo_add_64be( mdhd, p_stream->i_duration * (int64_t)i_timescale /
509                                (mtime_t)1000000 );  // duration
510         }
511
512         bo_add_16be( mdhd, 0    );              // language   FIXME
513         bo_add_16be( mdhd, 0    );              // predefined
514         box_fix( mdhd );
515         box_gather( mdia, mdhd );
516
517         /* handler reference */
518         hdlr = box_full_new( "hdlr", 0, 0 );
519
520         bo_add_fourcc( hdlr, "mhlr" );         // media handler
521         if( p_stream->p_fmt->i_cat == AUDIO_ES )
522         {
523             bo_add_fourcc( hdlr, "soun" );
524         }
525         else
526         {
527             bo_add_fourcc( hdlr, "vide" );
528         }
529
530         bo_add_32be( hdlr, 0 );         // reserved
531         bo_add_32be( hdlr, 0 );         // reserved
532         bo_add_32be( hdlr, 0 );         // reserved
533
534         if( p_stream->p_fmt->i_cat == AUDIO_ES )
535         {
536             bo_add_mem( hdlr, 13, "SoundHandler" );
537         }
538         else
539         {
540             bo_add_mem( hdlr, 13, "VideoHandler" );
541         }
542
543         box_fix( hdlr );
544         box_gather( mdia, hdlr );
545
546         /* minf*/
547         minf = box_new( "minf" );
548
549         /* add smhd|vmhd */
550         if( p_stream->p_fmt->i_cat == AUDIO_ES )
551         {
552             bo_t *smhd;
553
554             smhd = box_full_new( "smhd", 0, 0 );
555             bo_add_16be( smhd, 0 );     // balance
556             bo_add_16be( smhd, 0 );     // reserved
557             box_fix( smhd );
558
559             box_gather( minf, smhd );
560         }
561         else if( p_stream->p_fmt->i_cat == VIDEO_ES )
562         {
563             bo_t *vmhd;
564
565             vmhd = box_full_new( "vmhd", 0, 1 );
566             bo_add_16be( vmhd, 0 );     // graphicsmode
567             for( i = 0; i < 3; i++ )
568             {
569                 bo_add_16be( vmhd, 0 ); // opcolor
570             }
571             box_fix( vmhd );
572
573             box_gather( minf, vmhd );
574         }
575
576         /* dinf */
577         dinf = box_new( "dinf" );
578         dref = box_full_new( "dref", 0, 0 );
579         bo_add_32be( dref, 1 );
580         url = box_full_new( "url ", 0, 0x01 );
581         box_fix( url );
582         box_gather( dref, url );
583         box_fix( dref );
584         box_gather( dinf, dref );
585
586         /* append dinf to mdia */
587         box_fix( dinf );
588         box_gather( minf, dinf );
589
590         /* add stbl */
591         stbl = box_new( "stbl" );
592         stsd = box_full_new( "stsd", 0, 0 );
593         bo_add_32be( stsd, 1 );
594
595         if( p_stream->p_fmt->i_cat == AUDIO_ES )
596         {
597             bo_t *soun;
598             char fcc[4] = "    ";
599             int  i;
600             vlc_bool_t b_mpeg4_hdr;
601
602             switch( p_stream->p_fmt->i_fourcc )
603             {
604                 case VLC_FOURCC( 'm', 'p', '4', 'a' ):
605                     memcpy( fcc, "mp4a", 4 );
606                     b_mpeg4_hdr = VLC_TRUE;
607                     break;
608
609                 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
610                     if( p_sys->b_mov )
611                         memcpy( fcc, ".mp3 ", 4 );
612                     else
613                         memcpy( fcc, "mp4a", 4 );
614                     b_mpeg4_hdr = VLC_FALSE;
615                     break;
616
617                 default:
618                     memcpy( fcc, (char*)&p_stream->p_fmt->i_fourcc, 4 );
619                     b_mpeg4_hdr = VLC_FALSE;
620                     break;
621             }
622
623             soun = box_new( fcc );
624             for( i = 0; i < 6; i++ )
625             {
626                 bo_add_8( soun, 0 );        // reserved;
627             }
628             bo_add_16be( soun, 1 );         // data-reference-index
629
630             /* SoundDescription */
631             bo_add_16be( soun, 0 );         // version;
632             bo_add_16be( soun, 0 );         // revision level (0)
633             bo_add_32be( soun, 0 );         // vendor
634             bo_add_16be( soun, p_stream->p_fmt->i_channels );   // channel-count
635             bo_add_16be( soun, 16);         // FIXME sample size
636             bo_add_16be( soun, -2 );        // compression id
637             bo_add_16be( soun, 0 );         // packet size (0)
638             bo_add_16be( soun, p_stream->p_fmt->i_sample_rate ); // sampleratehi
639             bo_add_16be( soun, 0 );                              // sampleratelo
640
641             /* add an ES Descriptor */
642             if( b_mpeg4_hdr )
643             {
644                 bo_t *esds;
645
646                 esds = GetESDS( p_stream );
647
648                 box_fix( esds );
649                 box_gather( soun, esds );
650             }
651
652             box_fix( soun );
653             box_gather( stsd, soun );
654         }
655         else if( p_stream->p_fmt->i_cat == VIDEO_ES )
656         {
657             bo_t *vide;
658             char fcc[4] = "    ";
659             int  i;
660             vlc_bool_t b_mpeg4_hdr;
661
662             switch( p_stream->p_fmt->i_fourcc )
663             {
664                 case VLC_FOURCC( 'm', 'p', '4', 'v' ):
665                 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
666                     memcpy( fcc, "mp4v", 4 );
667                     b_mpeg4_hdr = VLC_TRUE;
668                     break;
669
670                 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
671                     memcpy( fcc, "mjpa", 4 );
672                     b_mpeg4_hdr = VLC_FALSE;
673                     break;
674
675                 default:
676                     memcpy( fcc, (char*)&p_stream->p_fmt->i_fourcc, 4 );
677                     b_mpeg4_hdr = VLC_FALSE;
678                     break;
679             }
680
681             vide = box_new( fcc );
682             for( i = 0; i < 6; i++ )
683             {
684                 bo_add_8( vide, 0 );        // reserved;
685             }
686             bo_add_16be( vide, 1 );         // data-reference-index
687
688             bo_add_16be( vide, 0 );         // predefined;
689             bo_add_16be( vide, 0 );         // reserved;
690             for( i = 0; i < 3; i++ )
691             {
692                 bo_add_32be( vide, 0 );     // predefined;
693             }
694
695             bo_add_16be( vide, p_stream->p_fmt->i_width );  // i_width
696             bo_add_16be( vide, p_stream->p_fmt->i_height ); // i_height
697
698             bo_add_32be( vide, 0x00480000 );                // h 72dpi
699             bo_add_32be( vide, 0x00480000 );                // v 72dpi
700
701             bo_add_32be( vide, 0 );         // data size, always 0
702             bo_add_16be( vide, 1 );         // frames count per sample
703
704             // compressor name;
705             for( i = 0; i < 32; i++ )
706             {
707                 bo_add_8( vide, 0 );
708             }
709
710             bo_add_16be( vide, 0x18 );      // depth
711             bo_add_16be( vide, 0xffff );    // predefined
712
713             /* add an ES Descriptor */
714             if( b_mpeg4_hdr )
715             {
716                 bo_t *esds;
717
718                 esds = GetESDS( p_stream );
719
720                 box_fix( esds );
721                 box_gather( vide, esds );
722             }
723
724             box_fix( vide );
725             box_gather( stsd, vide );
726         }
727
728         /* append stsd to stbl */
729         box_fix( stsd );
730         box_gather( stbl, stsd );
731
732         /* we will create chunk table and stsc table FIXME optim stsc table FIXME */
733         i_chunk_count = 0;
734         for( i = 0; i < p_stream->i_entry_count; )
735         {
736             while( i < p_stream->i_entry_count )
737             {
738                 if( i + 1 < p_stream->i_entry_count &&
739                     p_stream->entry[i].i_pos +
740                     p_stream->entry[i].i_size != p_stream->entry[i + 1].i_pos )
741                 {
742                     i++;
743                     break;
744                 }
745
746                 i++;
747             }
748             i_chunk_count++;
749         }
750
751         /* chunk offset table */
752         if( p_sys->i_pos >= (((uint64_t)0x1) << 32) )
753         {
754             /* 64 bits version */
755             bo_t *co64;
756             bo_t *stsc;
757
758             unsigned int  i_chunk;
759
760             msg_Dbg( p_mux, "creating %d chunk (co64)", i_chunk_count );
761
762             co64 = box_full_new( "co64", 0, 0 );
763             bo_add_32be( co64, i_chunk_count );
764
765             stsc = box_full_new( "stsc", 0, 0 );
766             bo_add_32be( stsc, i_chunk_count );     // entry-count
767             for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ )
768             {
769                 int i_first;
770                 bo_add_64be( co64, p_stream->entry[i].i_pos );
771
772                 i_first = i;
773
774                 while( i < p_stream->i_entry_count )
775                 {
776                     if( i + 1 < p_stream->i_entry_count &&
777                         p_stream->entry[i].i_pos + p_stream->entry[i].i_size
778                         != p_stream->entry[i + 1].i_pos )
779                     {
780                         i++;
781                         break;
782                     }
783
784                     i++;
785                 }
786                 bo_add_32be( stsc, 1 + i_chunk );   // first-chunk
787                 bo_add_32be( stsc, i - i_first ) ;  // samples-per-chunk
788                 bo_add_32be( stsc, 1 );             // sample-descr-index
789             }
790             /* append co64 to stbl */
791             box_fix( co64 );
792             box_gather( stbl, co64 );
793
794             /* append stsc to stbl */
795             box_fix( stsc );
796             box_gather( stbl, stsc );
797         }
798         else
799         {
800             /* 32 bits version */
801             bo_t *stco;
802             bo_t *stsc;
803
804             unsigned int  i_chunk;
805
806             msg_Dbg( p_mux, "creating %d chunk (stco)", i_chunk_count );
807
808             stco = box_full_new( "stco", 0, 0 );
809             bo_add_32be( stco, i_chunk_count );
810
811             stsc = box_full_new( "stsc", 0, 0 );
812             bo_add_32be( stsc, i_chunk_count );     // entry-count
813             for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ )
814             {
815                 int i_first;
816                 bo_add_32be( stco, p_stream->entry[i].i_pos );
817
818                 i_first = i;
819
820                 while( i < p_stream->i_entry_count )
821                 {
822                     if( i + 1 < p_stream->i_entry_count &&
823                         p_stream->entry[i].i_pos + p_stream->entry[i].i_size
824                         != p_stream->entry[i + 1].i_pos )
825                     {
826                         i++;
827                         break;
828                     }
829
830                     i++;
831                 }
832                 bo_add_32be( stsc, 1 + i_chunk );   // first-chunk
833                 bo_add_32be( stsc, i - i_first ) ;  // samples-per-chunk
834                 bo_add_32be( stsc, 1 );             // sample-descr-index
835             }
836             /* append stco to stbl */
837             box_fix( stco );
838             box_gather( stbl, stco );
839
840             /* append stsc to stbl */
841             box_fix( stsc );
842             box_gather( stbl, stsc );
843         }
844
845
846         /* add stts */
847         stts = box_full_new( "stts", 0, 0 );
848         bo_add_32be( stts, 0 );     // fixed latter
849         for( i = 0, i_index = 0; i < p_stream->i_entry_count; i_index++)
850         {
851             int64_t i_delta;
852             int     i_first;
853
854             i_first = i;
855             i_delta = p_stream->entry[i].i_length;
856
857             while( i < p_stream->i_entry_count )
858             {
859                 if( i + 1 < p_stream->i_entry_count &&
860                     p_stream->entry[i + 1].i_length != i_delta )
861                 {
862                     i++;
863                     break;
864                 }
865
866                 i++;
867             }
868
869             bo_add_32be( stts, i - i_first );           // sample-count
870             bo_add_32be( stts, i_delta * (int64_t)i_timescale /
871                                (int64_t)1000000 );      // sample-delta
872         }
873         bo_fix_32be( stts, 12, i_index );
874
875         /* append stts to stbl */
876         box_fix( stts );
877         box_gather( stbl, stts );
878
879         /* FIXME add ctts ?? FIXME */
880
881         stsz = box_full_new( "stsz", 0, 0 );
882         bo_add_32be( stsz, 0 );                             // sample-size
883         bo_add_32be( stsz, p_stream->i_entry_count );       // sample-count
884         for( i = 0; i < p_stream->i_entry_count; i++ )
885         {
886             bo_add_32be( stsz, p_stream->entry[i].i_size ); // sample-size
887         }
888         /* append stsz to stbl */
889         box_fix( stsz );
890         box_gather( stbl, stsz );
891
892         /* append stbl to minf */
893         box_fix( stbl );
894         box_gather( minf, stbl );
895
896         /* append minf to mdia */
897         box_fix( minf );
898         box_gather( mdia, minf );
899
900         /* append mdia to trak */
901         box_fix( mdia );
902         box_gather( trak, mdia );
903
904         /* append trak to moov */
905         box_fix( trak );
906         box_gather( moov, trak );
907     }
908
909     box_fix( moov );
910     box_send( p_mux, moov );
911
912     /* *** release memory *** */
913     for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
914     {
915         mp4_stream_t *p_stream;
916
917         p_stream = p_sys->pp_streams[i_trak];
918
919         if( p_stream->p_fmt->p_extra_data )
920         {
921             free( p_stream->p_fmt->p_extra_data );
922         }
923         free( p_stream->p_fmt );
924         free( p_stream->entry );
925         free( p_stream );
926     }
927     free( p_sys );
928 }
929
930 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args,
931                        void *p_answer )
932 {
933    switch( i_query )
934    {
935         case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
936             *(vlc_bool_t*)p_answer = VLC_FALSE;
937             return( SOUT_MUX_CAP_ERR_OK );
938         default:
939             return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
940    }
941 }
942
943 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
944 {
945     sout_mux_sys_t  *p_sys = p_mux->p_sys;
946     mp4_stream_t    *p_stream;
947
948     switch( p_input->p_fmt->i_fourcc )
949     {
950         case VLC_FOURCC( 'm', 'p', '4', 'a' ):
951         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
952         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
953         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
954         case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
955         case VLC_FOURCC( 'm', 'j', 'p', 'b' ):
956             break;
957         default:
958             msg_Err( p_mux, "unsupported codec %4.4s in mp4",
959                      (char*)&p_input->p_fmt->i_fourcc );
960             return VLC_EGENERIC;
961     }
962
963     p_stream                = malloc( sizeof( mp4_stream_t ) );
964     p_stream->p_fmt         = malloc( sizeof( sout_format_t ) );
965     memcpy( p_stream->p_fmt, p_input->p_fmt, sizeof( sout_format_t ) );
966     if( p_stream->p_fmt->i_extra_data )
967     {
968         p_stream->p_fmt->p_extra_data =
969             malloc( p_stream->p_fmt->i_extra_data );
970         memcpy( p_stream->p_fmt->p_extra_data,
971                 p_input->p_fmt->p_extra_data,
972                 p_input->p_fmt->i_extra_data );
973     }
974     p_stream->i_track_id    = p_sys->i_nb_streams + 1;
975     p_stream->i_entry_count = 0;
976     p_stream->i_entry_max   = 1000;
977     p_stream->entry         =
978         calloc( p_stream->i_entry_max, sizeof( mp4_entry_t ) );
979     p_stream->i_duration    = 0;
980
981     p_input->p_sys          = p_stream;
982
983     msg_Dbg( p_mux, "adding input" );
984
985     TAB_APPEND( p_sys->i_nb_streams, p_sys->pp_streams, p_stream );
986     return( VLC_SUCCESS );
987 }
988
989 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
990 {
991     msg_Dbg( p_mux, "removing input" );
992     return( 0 );
993 }
994
995 /****************************************************************************/
996
997 static int MuxGetStream( sout_mux_t *p_mux, int *pi_stream, mtime_t *pi_dts )
998 {
999     mtime_t i_dts;
1000     int     i_stream;
1001     int     i;
1002
1003     for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
1004     {
1005         sout_fifo_t  *p_fifo;
1006
1007         p_fifo = p_mux->pp_inputs[i]->p_fifo;
1008
1009         if( p_fifo->i_depth > 1 )
1010         {
1011             sout_buffer_t *p_buf;
1012
1013             p_buf = sout_FifoShow( p_fifo );
1014             if( i_stream < 0 || p_buf->i_dts < i_dts )
1015             {
1016                 i_dts = p_buf->i_dts;
1017                 i_stream = i;
1018             }
1019         }
1020         else
1021         {
1022             return( -1 ); // wait that all fifo have at least 2 packets
1023         }
1024     }
1025     if( pi_stream )
1026     {
1027         *pi_stream = i_stream;
1028     }
1029     if( pi_dts )
1030     {
1031         *pi_dts = i_dts;
1032     }
1033     return( i_stream );
1034 }
1035
1036 static int Mux( sout_mux_t *p_mux )
1037 {
1038     sout_mux_sys_t  *p_sys = p_mux->p_sys;
1039
1040     for( ;; )
1041     {
1042         sout_input_t    *p_input;
1043         int             i_stream;
1044         mp4_stream_t    *p_stream;
1045         sout_buffer_t   *p_data;
1046         mtime_t         i_dts;
1047
1048         if( MuxGetStream( p_mux, &i_stream, &i_dts) < 0 )
1049         {
1050             return( VLC_SUCCESS );
1051         }
1052
1053         if( !p_sys->i_start_dts )
1054             p_sys->i_start_dts = i_dts;
1055
1056         p_input  = p_mux->pp_inputs[i_stream];
1057         p_stream = (mp4_stream_t*)p_input->p_sys;
1058
1059         p_data  = sout_FifoGet( p_input->p_fifo );
1060         //msg_Dbg( p_mux, "stream=%d size=%6d pos=%8lld", i_stream, p_data->i_size, p_sys->i_pos );
1061
1062         /* add index entry */
1063         p_stream->entry[p_stream->i_entry_count].i_pos   = p_sys->i_pos;
1064         p_stream->entry[p_stream->i_entry_count].i_size  = p_data->i_size;
1065         p_stream->entry[p_stream->i_entry_count].i_pts   = p_data->i_pts;
1066         p_stream->entry[p_stream->i_entry_count].i_dts   = p_data->i_dts;
1067         p_stream->entry[p_stream->i_entry_count].i_length=
1068             __MAX( p_data->i_length, 0 );
1069
1070         if( p_stream->i_entry_count == 0 )
1071         {
1072             /* Here is another bad hack.
1073              * To make sure audio/video are in sync, we report a corrected
1074              * length for the 1st sample. */
1075             p_stream->entry[p_stream->i_entry_count].i_length =
1076                 __MAX( p_data->i_length, 0 ) +
1077                 p_data->i_pts - p_sys->i_start_dts;
1078         }
1079
1080         p_stream->i_entry_count++;
1081         if( p_stream->i_entry_count >= p_stream->i_entry_max )
1082         {
1083             p_stream->i_entry_max += 1000;
1084             p_stream->entry =
1085                 realloc( p_stream->entry,
1086                          p_stream->i_entry_max * sizeof( mp4_entry_t ) );
1087         }
1088
1089         /* update */
1090         p_stream->i_duration += __MAX( p_data->i_length, 0 );
1091         p_sys->i_pos += p_data->i_size;
1092
1093         /* write data */
1094         sout_AccessOutWrite( p_mux->p_access, p_data );
1095     }
1096
1097     return( VLC_SUCCESS );
1098 }
1099
1100
1101 /****************************************************************************/
1102
1103 static void bo_init( bo_t *p_bo, int i_size, uint8_t *p_buffer,
1104                      vlc_bool_t b_grow )
1105 {
1106     if( !p_buffer )
1107     {
1108         p_bo->i_buffer_size = __MAX( i_size, 1024 );
1109         p_bo->p_buffer = malloc( p_bo->i_buffer_size );
1110     }
1111     else
1112     {
1113         p_bo->i_buffer_size = i_size;
1114         p_bo->p_buffer = p_buffer;
1115     }
1116
1117     p_bo->b_grow = b_grow;
1118     p_bo->i_buffer = 0;
1119 }
1120
1121 static void bo_add_8( bo_t *p_bo, uint8_t i )
1122 {
1123     if( p_bo->i_buffer < p_bo->i_buffer_size )
1124     {
1125         p_bo->p_buffer[p_bo->i_buffer] = i;
1126     }
1127     else if( p_bo->b_grow )
1128     {
1129         p_bo->i_buffer_size += 1024;
1130         p_bo->p_buffer = realloc( p_bo->p_buffer, p_bo->i_buffer_size );
1131
1132         p_bo->p_buffer[p_bo->i_buffer] = i;
1133     }
1134
1135     p_bo->i_buffer++;
1136 }
1137
1138 static void bo_add_16be( bo_t *p_bo, uint16_t i )
1139 {
1140     bo_add_8( p_bo, ( ( i >> 8) &0xff ) );
1141     bo_add_8( p_bo, i &0xff );
1142 }
1143
1144 static void bo_add_24be( bo_t *p_bo, uint32_t i )
1145 {
1146     bo_add_8( p_bo, ( ( i >> 16) &0xff ) );
1147     bo_add_8( p_bo, ( ( i >> 8) &0xff ) );
1148     bo_add_8( p_bo, (   i &0xff ) );
1149 }
1150 static void bo_add_32be( bo_t *p_bo, uint32_t i )
1151 {
1152     bo_add_16be( p_bo, ( ( i >> 16) &0xffff ) );
1153     bo_add_16be( p_bo, i &0xffff );
1154 }
1155
1156 static void bo_fix_32be ( bo_t *p_bo, int i_pos, uint32_t i)
1157 {
1158     p_bo->p_buffer[i_pos    ] = ( i >> 24 )&0xff;
1159     p_bo->p_buffer[i_pos + 1] = ( i >> 16 )&0xff;
1160     p_bo->p_buffer[i_pos + 2] = ( i >>  8 )&0xff;
1161     p_bo->p_buffer[i_pos + 3] = ( i       )&0xff;
1162 }
1163
1164 static void bo_add_64be( bo_t *p_bo, uint64_t i )
1165 {
1166     bo_add_32be( p_bo, ( ( i >> 32) &0xffffffff ) );
1167     bo_add_32be( p_bo, i &0xffffffff );
1168 }
1169
1170 static void bo_add_fourcc( bo_t *p_bo, char *fcc )
1171 {
1172     bo_add_8( p_bo, fcc[0] );
1173     bo_add_8( p_bo, fcc[1] );
1174     bo_add_8( p_bo, fcc[2] );
1175     bo_add_8( p_bo, fcc[3] );
1176 }
1177
1178 static void bo_add_mem( bo_t *p_bo, int i_size, uint8_t *p_mem )
1179 {
1180     int i;
1181
1182     for( i = 0; i < i_size; i++ )
1183     {
1184         bo_add_8( p_bo, p_mem[i] );
1185     }
1186 }
1187
1188 static void bo_add_descr( bo_t *p_bo, uint8_t tag, uint32_t i_size )
1189 {
1190     uint32_t i_length;
1191     uint8_t  vals[4];
1192
1193     i_length = i_size;
1194     vals[3] = (unsigned char)(i_length & 0x7f);
1195     i_length >>= 7;
1196     vals[2] = (unsigned char)((i_length & 0x7f) | 0x80); 
1197     i_length >>= 7;
1198     vals[1] = (unsigned char)((i_length & 0x7f) | 0x80); 
1199     i_length >>= 7;
1200     vals[0] = (unsigned char)((i_length & 0x7f) | 0x80);
1201
1202     bo_add_8( p_bo, tag );
1203
1204     if( i_size < 0x00000080 )
1205     {
1206         bo_add_8( p_bo, vals[3] );
1207     }
1208     else if( i_size < 0x00004000 )
1209     {
1210         bo_add_8( p_bo, vals[2] );
1211         bo_add_8( p_bo, vals[3] );
1212     }
1213     else if( i_size < 0x00200000 )
1214     {
1215         bo_add_8( p_bo, vals[1] );
1216         bo_add_8( p_bo, vals[2] );
1217         bo_add_8( p_bo, vals[3] );
1218     }
1219     else if( i_size < 0x10000000 )
1220     {
1221         bo_add_8( p_bo, vals[0] );
1222         bo_add_8( p_bo, vals[1] );
1223         bo_add_8( p_bo, vals[2] );
1224         bo_add_8( p_bo, vals[3] );
1225     }
1226 }
1227
1228 static void bo_add_bo( bo_t *p_bo, bo_t *p_bo2 )
1229 {
1230     int i;
1231
1232     for( i = 0; i < p_bo2->i_buffer; i++ )
1233     {
1234         bo_add_8( p_bo, p_bo2->p_buffer[i] );
1235     }
1236 }
1237
1238 static bo_t * box_new( char *fcc )
1239 {
1240     bo_t *box;
1241
1242     if( ( box = malloc( sizeof( bo_t ) ) ) )
1243     {
1244         bo_init( box, 0, NULL, VLC_TRUE );
1245
1246         bo_add_32be  ( box, 0 );
1247         bo_add_fourcc( box, fcc );
1248     }
1249
1250     return box;
1251 }
1252
1253 static bo_t * box_full_new( char *fcc, uint8_t v, uint32_t f )
1254 {
1255     bo_t *box;
1256
1257     if( ( box = malloc( sizeof( bo_t ) ) ) )
1258     {
1259         bo_init( box, 0, NULL, VLC_TRUE );
1260
1261         bo_add_32be  ( box, 0 );
1262         bo_add_fourcc( box, fcc );
1263         bo_add_8     ( box, v );
1264         bo_add_24be  ( box, f );
1265     }
1266
1267     return box;
1268 }
1269
1270 static void box_fix( bo_t *box )
1271 {
1272     bo_t box_tmp;
1273
1274     memcpy( &box_tmp, box, sizeof( bo_t ) );
1275
1276     box_tmp.i_buffer = 0;
1277     bo_add_32be( &box_tmp, box->i_buffer );
1278 }
1279
1280 static void box_free( bo_t *box )
1281 {
1282     if( box->p_buffer )
1283     {
1284         free( box->p_buffer );
1285     }
1286
1287     free( box );
1288 }
1289
1290 static void box_gather ( bo_t *box, bo_t *box2 )
1291 {
1292     bo_add_bo( box, box2 );
1293     box_free( box2 );
1294 }
1295
1296
1297 static sout_buffer_t * bo_to_sout( sout_instance_t *p_sout,  bo_t *box )
1298 {
1299     sout_buffer_t *p_buf;
1300
1301     p_buf = sout_BufferNew( p_sout, box->i_buffer );
1302     if( box->i_buffer > 0 )
1303     {
1304         memcpy( p_buf->p_buffer, box->p_buffer, box->i_buffer );
1305     }
1306
1307     p_buf->i_size = box->i_buffer;
1308
1309     return p_buf;
1310 }
1311
1312 static void box_send( sout_mux_t *p_mux,  bo_t *box )
1313 {
1314     sout_buffer_t *p_buf;
1315
1316     p_buf = bo_to_sout( p_mux->p_sout, box );
1317     box_free( box );
1318
1319     sout_AccessOutWrite( p_mux->p_access, p_buf );
1320 }
1321
1322 static int64_t get_timestamp()
1323 {
1324     int64_t i_timestamp = 0;
1325
1326 #ifdef HAVE_TIME_H
1327     i_timestamp = time(NULL);
1328     i_timestamp += 2082844800; // MOV/MP4 start date is 1/1/1904
1329     // 208284480 is (((1970 - 1904) * 365) + 17) * 24 * 60 * 60
1330 #endif
1331
1332     return i_timestamp;
1333 }