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