/*****************************************************************************
* 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>
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();
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;
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;
{
/* 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;
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)" );
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 =
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 )
{
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;
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 );
{
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 );
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;
}
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 );
((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)