]> git.sesse.net Git - vlc/blobdiff - modules/mux/mp4.c
Fortuuuuune.
[vlc] / modules / mux / mp4.c
index 3b1ac0acba4bdd767b8b41d3529dab38dba74fa7..3611efc2334e7f898975af9065c1153365149737 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * mp4.c: mp4/mov muxer
  *****************************************************************************
- * Copyright (C) 2001, 2002, 2003 VideoLAN
+ * Copyright (C) 2001, 2002, 2003 the VideoLAN team
  * $Id$
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
@@ -54,12 +54,16 @@ static void Close  ( vlc_object_t * );
 
 vlc_module_begin();
     set_description( _("MP4/MOV muxer") );
+    set_category( CAT_SOUT );
+    set_subcategory( SUBCAT_SOUT_MUX );
+    set_shortname( "MP4" );
 
     add_bool( SOUT_CFG_PREFIX "faststart", 1, NULL, FASTSTART_TEXT, FASTSTART_LONGTEXT,
               VLC_TRUE );
     set_capability( "sout mux", 5 );
     add_shortcut( "mp4" );
     add_shortcut( "mov" );
+    add_shortcut( "3gp" );
     set_callbacks( Open, Close );
 vlc_module_end();
 
@@ -128,6 +132,7 @@ typedef struct
 struct sout_mux_sys_t
 {
     vlc_bool_t b_mov;
+    vlc_bool_t b_3gp;
     vlc_bool_t b_64_ext;
     vlc_bool_t b_fast_start;
 
@@ -200,6 +205,7 @@ static int Open( vlc_object_t *p_this )
     p_sys->pp_streams   = NULL;
     p_sys->i_mdat_pos   = 0;
     p_sys->b_mov        = p_mux->psz_mux && !strcmp( p_mux->psz_mux, "mov" );
+    p_sys->b_3gp        = p_mux->psz_mux && !strcmp( p_mux->psz_mux, "3gp" );
     p_sys->i_dts_start  = 0;
 
 
@@ -207,9 +213,11 @@ static int Open( vlc_object_t *p_this )
     {
         /* Now add ftyp header */
         box = box_new( "ftyp" );
-        bo_add_fourcc( box, "isom" );
+        if( p_sys->b_3gp ) bo_add_fourcc( box, "3gp4" );
+        else bo_add_fourcc( box, "isom" );
         bo_add_32be  ( box, 0 );
-        bo_add_fourcc( box, "mp41" );
+        if( p_sys->b_3gp ) bo_add_fourcc( box, "3gp4" );
+        else bo_add_fourcc( box, "mp41" );
         box_fix( box );
 
         p_sys->i_pos += box->i_buffer;
@@ -405,7 +413,10 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
         case VLC_FOURCC( 'm', 'j', 'p', 'b' ):
         case VLC_FOURCC( 'S', 'V', 'Q', '1' ):
         case VLC_FOURCC( 'S', 'V', 'Q', '3' ):
+        case VLC_FOURCC( 'H', '2', '6', '3' ):
         case VLC_FOURCC( 'h', '2', '6', '4' ):
+        case VLC_FOURCC( 's', 'a', 'm', 'r' ):
+        case VLC_FOURCC( 's', 'a', 'w', 'b' ):
             break;
         case VLC_FOURCC( 's', 'u', 'b', 't' ):
             msg_Warn( p_mux, "subtitle track added like in .mov (even when creating .mp4)" );
@@ -742,7 +753,30 @@ static bo_t *GetESDS( mp4_stream_t *p_stream )
     int  i_stream_type;
     int  i_object_type_indication;
     int  i_decoder_specific_info_size;
+    unsigned int i;
+    int64_t i_bitrate_avg = 0;
+    int64_t i_bitrate_max = 0;
 
+    /* Compute avg/max bitrate */
+    for( i = 0; i < p_stream->i_entry_count; i++ )
+    {
+        i_bitrate_avg += p_stream->entry[i].i_size;
+        if( p_stream->entry[i].i_length > 0)
+        {
+            int64_t i_bitrate = I64C(8000000) * p_stream->entry[i].i_size / p_stream->entry[i].i_length;
+            if( i_bitrate > i_bitrate_max )
+                i_bitrate_max = i_bitrate;
+        }
+    }
+
+    if( p_stream->i_duration > 0 )
+        i_bitrate_avg = I64C(8000000) * i_bitrate_avg / p_stream->i_duration;
+    else
+        i_bitrate_avg = 0;
+    if( i_bitrate_max <= 1 )
+        i_bitrate_max = 0x7fffffff;
+
+    /* */
     if( p_stream->fmt.i_extra > 0 )
     {
         i_decoder_specific_info_size =
@@ -791,8 +825,8 @@ static bo_t *GetESDS( mp4_stream_t *p_stream )
     bo_add_8   ( esds, i_object_type_indication );
     bo_add_8   ( esds, ( i_stream_type << 2 ) | 1 );
     bo_add_24be( esds, 1024 * 1024 );       // bufferSizeDB
-    bo_add_32be( esds, 0x7fffffff );        // maxBitrate
-    bo_add_32be( esds, 0 );                 // avgBitrate
+    bo_add_32be( esds, i_bitrate_max );     // maxBitrate
+    bo_add_32be( esds, i_bitrate_avg );     // avgBitrate
 
     if( p_stream->fmt.i_extra > 0 )
     {
@@ -851,6 +885,41 @@ static bo_t *GetWaveTag( mp4_stream_t *p_stream )
     return wave;
 }
 
+static bo_t *GetDamrTag( mp4_stream_t *p_stream )
+{
+    bo_t *damr;
+
+    damr = box_new( "damr" );
+
+    bo_add_fourcc( damr, "REFC" );
+    bo_add_8( damr, 0 );
+
+    if( p_stream->fmt.i_codec == VLC_FOURCC( 's', 'a', 'm', 'r' ) )
+        bo_add_16be( damr, 0x81ff ); /* Mode set (all modes for AMR_NB) */
+    else
+        bo_add_16be( damr, 0x83ff ); /* Mode set (all modes for AMR_WB) */
+    bo_add_16be( damr, 0x1 ); /* Mode change period (no restriction) */
+
+    box_fix( damr );
+
+    return damr;
+}
+
+static bo_t *GetD263Tag( mp4_stream_t *p_stream )
+{
+    bo_t *d263;
+
+    d263 = box_new( "d263" );
+
+    bo_add_fourcc( d263, "VLC " );
+    bo_add_16be( d263, 0xa );
+    bo_add_8( d263, 0 );
+
+    box_fix( d263 );
+
+    return d263;
+}
+
 static bo_t *GetAvcCTag( mp4_stream_t *p_stream )
 {
     bo_t *avcC;
@@ -1013,6 +1082,12 @@ static bo_t *GetSounBox( sout_mux_t *p_mux, mp4_stream_t *p_stream )
         b_descr = VLC_TRUE;
         break;
 
+    case VLC_FOURCC('s','a','m','r'):
+    case VLC_FOURCC('s','a','w','b'):
+        memcpy( fcc, (char*)&p_stream->fmt.i_codec, 4 );
+        b_descr = VLC_TRUE;
+        break;
+
     case VLC_FOURCC('m','p','g','a'):
         if( p_sys->b_mov )
             memcpy( fcc, ".mp3", 4 );
@@ -1079,6 +1154,10 @@ static bo_t *GetSounBox( sout_mux_t *p_mux, mp4_stream_t *p_stream )
         {
             box = GetWaveTag( p_stream );
         }
+        else if( p_stream->fmt.i_codec == VLC_FOURCC('s','a','m','r') )
+        {
+            box = GetDamrTag( p_stream );
+        }
         else
         {
             box = GetESDS( p_stream );
@@ -1118,6 +1197,10 @@ static bo_t *GetVideBox( sout_mux_t *p_mux, mp4_stream_t *p_stream )
         memcpy( fcc, "SVQ3", 4 );
         break;
 
+    case VLC_FOURCC('H','2','6','3'):
+        memcpy( fcc, "s263", 4 );
+        break;
+
     case VLC_FOURCC('h','2','6','4'):
         memcpy( fcc, "avc1", 4 );
         break;
@@ -1172,6 +1255,15 @@ static bo_t *GetVideBox( sout_mux_t *p_mux, mp4_stream_t *p_stream )
         }
         break;
 
+    case VLC_FOURCC('H','2','6','3'):
+        {
+            bo_t *d263 = GetD263Tag( p_stream );
+
+            box_fix( d263 );
+            box_gather( vide, d263 );
+        }
+        break;
+
     case VLC_FOURCC('S','V','Q','3'):
         {
             bo_t *esds = GetSVQ3Tag( p_stream );
@@ -1561,11 +1653,6 @@ static bo_t *GetMoovBox( sout_mux_t *p_mux )
                           ((int64_t)p_stream->fmt.video.i_height << 16) /
                           VOUT_ASPECT_FACTOR;
             }
-            fprintf( stderr, "%dx%d -> %dx%d a=%d/%d=%f\n",
-                     p_stream->fmt.video.i_width, p_stream->fmt.video.i_height,
-                     i_width, p_stream->fmt.video.i_height,
-                     p_stream->fmt.video.i_aspect, VOUT_ASPECT_FACTOR,
-                     (float)p_stream->fmt.video.i_aspect/(float)VOUT_ASPECT_FACTOR );
             // width (presentation)
             bo_add_32be( tkhd, i_width );
             // height(presentation)