2003-08-24 18:38:38 +02:00
/*****************************************************************************
2004-08-18 14:04:03 +02:00
* asf . c : asf muxer module for vlc
2003-08-24 18:38:38 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2006-03-25 13:54:27 +01:00
* Copyright ( C ) 2003 - 2004 , 2006 the VideoLAN team
2004-03-11 18:37:50 +01:00
* $ Id $
2003-08-24 18:38:38 +02:00
*
* Authors : Laurent Aimar < fenrir @ via . ecp . fr >
2004-09-01 16:07:45 +02:00
* Gildas Bazin < gbazin @ videolan . org >
2003-08-24 18:38:38 +02:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2006-01-13 00:10:04 +01:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston MA 02110 - 1301 , USA .
2003-08-24 18:38:38 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*****************************************************************************
* Preamble
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-23 22:50:58 +01:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2008-05-31 20:49:57 +02:00
# include <vlc_common.h>
2008-05-08 17:30:33 +02:00
# include <vlc_plugin.h>
2006-11-26 15:20:34 +01:00
# include <vlc_sout.h>
# include <vlc_block.h>
# include <vlc_codecs.h>
2003-08-24 18:38:38 +02:00
2004-08-19 14:25:22 +02:00
typedef GUID guid_t ;
2003-08-24 18:38:38 +02:00
2004-08-27 22:44:39 +02:00
# define MAX_ASF_TRACKS 128
2005-03-27 19:49:24 +02:00
# define ASF_DATA_PACKET_SIZE 4096 // deprecated -- added sout-asf-packet-size
2004-08-27 22:44:39 +02:00
2003-08-24 18:38:38 +02:00
/*****************************************************************************
* Module descriptor
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int Open ( vlc_object_t * ) ;
static void Close ( vlc_object_t * ) ;
2004-04-24 01:33:04 +02:00
# define SOUT_CFG_PREFIX "sout-asf-"
2004-04-25 10:53:52 +02:00
# define TITLE_TEXT N_("Title")
2006-03-31 18:39:23 +02:00
# define TITLE_LONGTEXT N_("Title to put in ASF comments." )
2004-04-25 10:53:52 +02:00
# define AUTHOR_TEXT N_("Author")
2006-03-31 18:39:23 +02:00
# define AUTHOR_LONGTEXT N_("Author to put in ASF comments." )
2004-04-25 10:53:52 +02:00
# define COPYRIGHT_TEXT N_("Copyright")
2006-03-31 18:39:23 +02:00
# define COPYRIGHT_LONGTEXT N_("Copyright string to put in ASF comments." )
2004-04-25 10:53:52 +02:00
# define COMMENT_TEXT N_("Comment")
2006-03-31 18:39:23 +02:00
# define COMMENT_LONGTEXT N_("Comment to put in ASF comments." )
2004-04-25 10:53:52 +02:00
# define RATING_TEXT N_("Rating")
2006-03-31 18:39:23 +02:00
# define RATING_LONGTEXT N_("\"Rating\" to put in ASF comments." )
2005-03-27 19:49:24 +02:00
# define PACKETSIZE_TEXT N_("Packet Size")
2006-03-31 18:39:23 +02:00
# define PACKETSIZE_LONGTEXT N_("ASF packet size -- default is 4096 bytes")
2008-06-30 11:00:34 +02:00
# define BITRATE_TEXT N_("Bitrate override")
# define BITRATE_LONGTEXT N_("Do not try to guess ASF bitrate. Setting this, allows you to control how Windows Media Player will cache streamed content. Set to audio+video bitrate in bytes")
2004-04-25 10:53:52 +02:00
2008-10-29 20:59:01 +01:00
vlc_module_begin ( )
set_description ( N_ ( " ASF muxer " ) )
set_category ( CAT_SOUT )
set_subcategory ( SUBCAT_SOUT_MUX )
set_shortname ( " ASF " )
2004-12-11 15:45:46 +01:00
2008-10-29 20:59:01 +01:00
set_capability ( " sout mux " , 5 )
add_shortcut ( " asf " )
add_shortcut ( " asfh " )
set_callbacks ( Open , Close )
2004-04-24 01:33:04 +02:00
2004-04-25 10:53:52 +02:00
add_string ( SOUT_CFG_PREFIX " title " , " " , NULL , TITLE_TEXT , TITLE_LONGTEXT ,
2008-04-14 00:08:29 +02:00
true ) ;
2004-04-25 10:53:52 +02:00
add_string ( SOUT_CFG_PREFIX " author " , " " , NULL , AUTHOR_TEXT ,
2008-04-14 00:08:29 +02:00
AUTHOR_LONGTEXT , true ) ;
2004-04-25 10:53:52 +02:00
add_string ( SOUT_CFG_PREFIX " copyright " , " " , NULL , COPYRIGHT_TEXT ,
2008-04-14 00:08:29 +02:00
COPYRIGHT_LONGTEXT , true ) ;
2004-04-25 10:53:52 +02:00
add_string ( SOUT_CFG_PREFIX " comment " , " " , NULL , COMMENT_TEXT ,
2008-04-14 00:08:29 +02:00
COMMENT_LONGTEXT , true ) ;
2004-04-25 10:53:52 +02:00
add_string ( SOUT_CFG_PREFIX " rating " , " " , NULL , RATING_TEXT ,
2008-04-14 00:08:29 +02:00
RATING_LONGTEXT , true ) ;
2008-06-30 11:00:32 +02:00
add_integer ( SOUT_CFG_PREFIX " packet-size " , 4096 , NULL , PACKETSIZE_TEXT ,
2008-06-30 13:55:59 +02:00
PACKETSIZE_LONGTEXT , true ) ;
2008-06-30 11:00:34 +02:00
add_integer ( SOUT_CFG_PREFIX " bitrate-override " , 0 , NULL , BITRATE_TEXT ,
2008-06-30 13:55:59 +02:00
BITRATE_LONGTEXT , true ) ;
2005-03-27 19:49:24 +02:00
2008-10-29 20:59:01 +01:00
vlc_module_end ( )
2003-08-24 18:38:38 +02:00
/*****************************************************************************
* Locales prototypes
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-05-27 21:16:52 +02:00
static const char * const ppsz_sout_options [ ] = {
2004-04-24 01:33:04 +02:00
" title " , " author " , " copyright " , " comment " , " rating " , NULL
2004-07-10 19:20:11 +02:00
} ;
2004-04-24 01:33:04 +02:00
2004-07-10 19:20:11 +02:00
static int Control ( sout_mux_t * , int , va_list ) ;
static int AddStream ( sout_mux_t * , sout_input_t * ) ;
static int DelStream ( sout_mux_t * , sout_input_t * ) ;
static int Mux ( sout_mux_t * ) ;
2003-08-24 18:38:38 +02:00
typedef struct
{
2003-08-29 03:11:43 +02:00
int i_id ;
int i_cat ;
2003-08-24 18:38:38 +02:00
2004-07-16 13:29:21 +02:00
/* codec information */
2003-08-29 03:11:43 +02:00
uint16_t i_tag ; /* for audio */
vlc_fourcc_t i_fourcc ; /* for video */
2007-10-02 20:58:29 +02:00
const char * psz_name ; /* codec name */
2005-01-18 15:36:26 +01:00
int i_blockalign ; /* for audio only */
2008-04-14 00:08:29 +02:00
bool b_audio_correction ;
2003-08-29 03:11:43 +02:00
int i_sequence ;
int i_extra ;
2004-09-09 16:23:44 +02:00
uint8_t * p_extra ;
es_format_t fmt ;
2004-08-19 13:32:20 +02:00
2003-08-24 18:38:38 +02:00
} asf_track_t ;
struct sout_mux_sys_t
{
guid_t fid ; /* file id */
int i_packet_size ;
int64_t i_packet_count ;
mtime_t i_dts_first ;
2003-08-25 00:20:43 +02:00
mtime_t i_dts_last ;
2004-08-19 13:32:20 +02:00
mtime_t i_preroll_time ;
2003-08-25 00:20:43 +02:00
int64_t i_bitrate ;
2008-06-30 11:00:34 +02:00
int64_t i_bitrate_override ;
2003-08-24 18:38:38 +02:00
int i_track ;
2004-08-27 22:44:39 +02:00
asf_track_t track [ MAX_ASF_TRACKS ] ;
2003-08-24 18:38:38 +02:00
2008-04-14 00:08:29 +02:00
bool b_write_header ;
2003-08-24 18:38:38 +02:00
2004-08-18 14:04:03 +02:00
block_t * pk ;
2003-08-24 18:38:38 +02:00
int i_pk_used ;
int i_pk_frame ;
mtime_t i_pk_dts ;
2003-08-25 03:31:25 +02:00
2008-04-14 00:08:29 +02:00
bool b_asf_http ;
2003-08-25 03:31:25 +02:00
int i_seq ;
2003-08-29 21:49:33 +02:00
/* meta data */
char * psz_title ;
char * psz_author ;
char * psz_copyright ;
char * psz_comment ;
char * psz_rating ;
2003-08-24 18:38:38 +02:00
} ;
static int MuxGetStream ( sout_mux_t * , int * pi_stream , mtime_t * pi_dts ) ;
2008-04-14 00:08:29 +02:00
static block_t * asf_header_create ( sout_mux_t * , bool ) ;
2004-08-18 14:04:03 +02:00
static block_t * asf_packet_create ( sout_mux_t * , asf_track_t * , block_t * ) ;
2004-03-11 18:37:50 +01:00
static block_t * asf_stream_end_create ( sout_mux_t * ) ;
2004-08-27 22:10:21 +02:00
static block_t * asf_packet_flush ( sout_mux_t * ) ;
2003-08-24 18:38:38 +02:00
typedef struct
{
int i_buffer_size ;
int i_buffer ;
uint8_t * p_buffer ;
2004-08-19 14:25:22 +02:00
2003-08-24 18:38:38 +02:00
} bo_t ;
static void bo_init ( bo_t * , uint8_t * , int ) ;
static void bo_add_u8 ( bo_t * , uint8_t ) ;
static void bo_addle_u16 ( bo_t * , uint16_t ) ;
static void bo_addle_u32 ( bo_t * , uint32_t ) ;
static void bo_addle_u64 ( bo_t * , uint64_t ) ;
static void bo_add_mem ( bo_t * , uint8_t * , int ) ;
2007-10-02 20:58:29 +02:00
static void bo_addle_str16 ( bo_t * , const char * ) ;
2003-08-24 18:38:38 +02:00
/*****************************************************************************
* Open :
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int Open ( vlc_object_t * p_this )
{
sout_mux_t * p_mux = ( sout_mux_t * ) p_this ;
sout_mux_sys_t * p_sys ;
2004-04-24 01:33:04 +02:00
vlc_value_t val ;
2003-08-24 18:38:38 +02:00
int i ;
2006-03-25 13:54:27 +01:00
msg_Dbg ( p_mux , " asf muxer opened " ) ;
2006-10-01 18:08:37 +02:00
config_ChainParse ( p_mux , SOUT_CFG_PREFIX , ppsz_sout_options , p_mux - > p_cfg ) ;
2003-08-24 18:38:38 +02:00
2004-07-10 19:20:11 +02:00
p_mux - > pf_control = Control ;
2003-08-24 18:38:38 +02:00
p_mux - > pf_addstream = AddStream ;
p_mux - > pf_delstream = DelStream ;
p_mux - > pf_mux = Mux ;
p_mux - > p_sys = p_sys = malloc ( sizeof ( sout_mux_sys_t ) ) ;
2008-08-20 22:45:24 +02:00
if ( ! p_sys )
return VLC_ENOMEM ;
2003-08-25 03:31:25 +02:00
p_sys - > b_asf_http = p_mux - > psz_mux & & ! strcmp ( p_mux - > psz_mux , " asfh " ) ;
if ( p_sys - > b_asf_http )
{
msg_Dbg ( p_mux , " creating asf stream to be used with mmsh " ) ;
}
2003-08-24 18:38:38 +02:00
p_sys - > pk = NULL ;
2003-08-25 00:20:43 +02:00
p_sys - > i_pk_used = 0 ;
p_sys - > i_pk_frame = 0 ;
p_sys - > i_dts_first = - 1 ;
p_sys - > i_dts_last = 0 ;
2004-08-19 13:32:20 +02:00
p_sys - > i_preroll_time = 2000 ;
2003-08-25 00:20:43 +02:00
p_sys - > i_bitrate = 0 ;
2008-06-30 11:00:34 +02:00
p_sys - > i_bitrate_override = 0 ;
2003-08-25 03:31:25 +02:00
p_sys - > i_seq = 0 ;
2003-08-24 18:38:38 +02:00
2008-04-14 00:08:29 +02:00
p_sys - > b_write_header = true ;
2004-08-27 22:44:39 +02:00
p_sys - > i_track = 0 ;
2005-03-27 19:49:24 +02:00
p_sys - > i_packet_size = config_GetInt ( p_mux , " sout-asf-packet-size " ) ;
2008-06-30 11:00:34 +02:00
p_sys - > i_bitrate_override = config_GetInt ( p_mux , " sout-asf-bitrate-override " ) ;
2005-03-27 19:49:24 +02:00
msg_Dbg ( p_mux , " Packet size %d " , p_sys - > i_packet_size ) ;
2008-06-30 11:00:34 +02:00
if ( p_sys - > i_bitrate_override )
2008-07-03 20:19:21 +02:00
msg_Dbg ( p_mux , " Bitrate override % " PRId64 , p_sys - > i_bitrate_override ) ;
2003-08-24 18:38:38 +02:00
p_sys - > i_packet_count = 0 ;
2004-08-18 14:04:03 +02:00
/* Generate a random fid */
2003-08-24 18:38:38 +02:00
srand ( mdate ( ) & 0xffffffff ) ;
2004-08-19 14:25:22 +02:00
p_sys - > fid . Data1 = 0xbabac001 ;
p_sys - > fid . Data2 = ( ( uint64_t ) rand ( ) < < 16 ) / RAND_MAX ;
p_sys - > fid . Data3 = ( ( uint64_t ) rand ( ) < < 16 ) / RAND_MAX ;
2003-08-24 18:38:38 +02:00
for ( i = 0 ; i < 8 ; i + + )
{
2004-08-19 14:25:22 +02:00
p_sys - > fid . Data4 [ i ] = ( ( uint64_t ) rand ( ) < < 8 ) / RAND_MAX ;
2003-08-24 18:38:38 +02:00
}
2004-08-18 14:04:03 +02:00
/* Meta data */
2004-04-24 01:33:04 +02:00
var_Get ( p_mux , SOUT_CFG_PREFIX " title " , & val ) ;
p_sys - > psz_title = val . psz_string ;
var_Get ( p_mux , SOUT_CFG_PREFIX " author " , & val ) ;
p_sys - > psz_author = val . psz_string ;
var_Get ( p_mux , SOUT_CFG_PREFIX " copyright " , & val ) ;
p_sys - > psz_copyright = val . psz_string ;
var_Get ( p_mux , SOUT_CFG_PREFIX " comment " , & val ) ;
p_sys - > psz_comment = val . psz_string ;
var_Get ( p_mux , SOUT_CFG_PREFIX " rating " , & val ) ;
p_sys - > psz_rating = val . psz_string ;
2006-03-25 13:54:27 +01:00
msg_Dbg ( p_mux , " meta data: title='%s', author='%s', copyright='%s', "
" comment='%s', rating='%s' " ,
2003-08-29 21:49:33 +02:00
p_sys - > psz_title , p_sys - > psz_author , p_sys - > psz_copyright ,
p_sys - > psz_comment , p_sys - > psz_rating ) ;
2003-08-25 03:31:25 +02:00
2003-08-24 18:38:38 +02:00
return VLC_SUCCESS ;
}
/*****************************************************************************
* Close :
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void Close ( vlc_object_t * p_this )
{
sout_mux_t * p_mux = ( sout_mux_t * ) p_this ;
sout_mux_sys_t * p_sys = p_mux - > p_sys ;
2004-03-11 18:37:50 +01:00
block_t * out ;
2003-08-24 18:38:38 +02:00
int i ;
msg_Dbg ( p_mux , " Asf muxer closed " ) ;
2004-08-27 22:10:21 +02:00
/* Flush last packet if any */
if ( ( out = asf_packet_flush ( p_mux ) ) )
{
sout_AccessOutWrite ( p_mux - > p_access , out ) ;
}
2003-08-25 03:31:25 +02:00
if ( ( out = asf_stream_end_create ( p_mux ) ) )
{
sout_AccessOutWrite ( p_mux - > p_access , out ) ;
}
2003-08-24 18:38:38 +02:00
/* rewrite header */
2008-01-29 14:55:19 +01:00
if ( sout_AccessOutSeek ( p_mux - > p_access , 0 ) = = VLC_SUCCESS )
2003-08-24 18:38:38 +02:00
{
2008-04-14 00:08:29 +02:00
out = asf_header_create ( p_mux , false ) ;
2003-08-25 03:31:25 +02:00
sout_AccessOutWrite ( p_mux - > p_access , out ) ;
2003-08-24 18:38:38 +02:00
}
2004-08-27 22:44:39 +02:00
for ( i = 0 ; i < p_sys - > i_track ; i + + )
2003-08-24 18:38:38 +02:00
{
free ( p_sys - > track [ i ] . p_extra ) ;
2004-09-09 16:23:44 +02:00
es_format_Clean ( & p_sys - > track [ i ] . fmt ) ;
2003-08-24 18:38:38 +02:00
}
2008-08-12 22:21:52 +02:00
free ( p_sys - > psz_title ) ;
free ( p_sys - > psz_author ) ;
free ( p_sys - > psz_copyright ) ;
free ( p_sys - > psz_comment ) ;
free ( p_sys - > psz_rating ) ;
2003-08-24 18:38:38 +02:00
free ( p_sys ) ;
}
/*****************************************************************************
* Capability :
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-07-10 19:20:11 +02:00
static int Control ( sout_mux_t * p_mux , int i_query , va_list args )
2003-08-24 18:38:38 +02:00
{
2004-07-10 19:20:11 +02:00
sout_mux_sys_t * p_sys = p_mux - > p_sys ;
2008-04-14 00:08:29 +02:00
bool * pb_bool ;
2004-07-10 19:20:11 +02:00
char * * ppsz ;
2004-08-18 14:04:03 +02:00
switch ( i_query )
{
2004-07-10 19:20:11 +02:00
case MUX_CAN_ADD_STREAM_WHILE_MUXING :
2008-04-14 00:08:29 +02:00
pb_bool = ( bool * ) va_arg ( args , bool * ) ;
if ( p_sys - > b_asf_http ) * pb_bool = true ;
else * pb_bool = false ;
2004-07-10 19:20:11 +02:00
return VLC_SUCCESS ;
case MUX_GET_ADD_STREAM_WAIT :
2008-04-14 00:08:29 +02:00
pb_bool = ( bool * ) va_arg ( args , bool * ) ;
* pb_bool = true ;
2004-07-10 19:20:11 +02:00
return VLC_SUCCESS ;
case MUX_GET_MIME :
ppsz = ( char * * ) va_arg ( args , char * * ) ;
if ( p_sys - > b_asf_http )
* ppsz = strdup ( " video/x-ms-asf-stream " ) ;
else
* ppsz = strdup ( " video/x-ms-asf " ) ;
return VLC_SUCCESS ;
2003-08-24 18:38:38 +02:00
default :
2004-07-10 19:20:11 +02:00
return VLC_EGENERIC ;
2004-08-18 14:04:03 +02:00
}
2003-08-24 18:38:38 +02:00
}
/*****************************************************************************
* AddStream :
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int AddStream ( sout_mux_t * p_mux , sout_input_t * p_input )
{
sout_mux_sys_t * p_sys = p_mux - > p_sys ;
asf_track_t * tk ;
bo_t bo ;
msg_Dbg ( p_mux , " adding input " ) ;
2004-08-27 22:44:39 +02:00
if ( p_sys - > i_track > = MAX_ASF_TRACKS )
2003-08-24 18:38:38 +02:00
{
2006-03-25 13:54:27 +01:00
msg_Dbg ( p_mux , " cannot add this track (too much tracks) " ) ;
2003-08-24 18:38:38 +02:00
return VLC_EGENERIC ;
}
tk = p_input - > p_sys = & p_sys - > track [ p_sys - > i_track ] ;
2004-09-01 16:07:45 +02:00
tk - > i_id = p_sys - > i_track + 1 ;
2003-08-24 18:38:38 +02:00
tk - > i_cat = p_input - > p_fmt - > i_cat ;
tk - > i_sequence = 0 ;
2005-01-20 13:32:53 +01:00
tk - > b_audio_correction = 0 ;
2003-08-24 18:38:38 +02:00
switch ( tk - > i_cat )
{
case AUDIO_ES :
{
2004-08-18 14:04:03 +02:00
int i_blockalign = p_input - > p_fmt - > audio . i_blockalign ;
2005-01-18 15:36:26 +01:00
int i_bitspersample = p_input - > p_fmt - > audio . i_bitspersample ;
2004-08-18 14:04:03 +02:00
int i_extra = 0 ;
2003-08-24 18:38:38 +02:00
2003-11-21 16:32:09 +01:00
switch ( p_input - > p_fmt - > i_codec )
2003-08-24 18:38:38 +02:00
{
case VLC_FOURCC ( ' a ' , ' 5 ' , ' 2 ' , ' ' ) :
2003-08-29 03:11:43 +02:00
tk - > i_tag = WAVE_FORMAT_A52 ;
tk - > psz_name = " A/52 " ;
2005-01-21 11:53:29 +01:00
i_bitspersample = 0 ;
2003-08-24 18:38:38 +02:00
break ;
2006-06-01 01:12:09 +02:00
case VLC_FOURCC ( ' m ' , ' p ' , ' 4 ' , ' a ' ) :
tk - > i_tag = WAVE_FORMAT_AAC ;
tk - > psz_name = " MPEG-4 Audio " ;
i_bitspersample = 0 ;
break ;
2003-08-24 18:38:38 +02:00
case VLC_FOURCC ( ' m ' , ' p ' , ' g ' , ' a ' ) :
2003-08-27 01:14:11 +02:00
# if 1
2003-08-29 03:11:43 +02:00
tk - > psz_name = " MPEG Audio Layer 3 " ;
tk - > i_tag = WAVE_FORMAT_MPEGLAYER3 ;
2005-01-21 11:53:29 +01:00
i_bitspersample = 0 ;
2003-08-27 01:14:11 +02:00
i_blockalign = 1 ;
2003-08-25 03:31:25 +02:00
i_extra = 12 ;
2003-08-24 18:38:38 +02:00
break ;
2003-08-27 01:14:11 +02:00
# else
2003-08-29 03:11:43 +02:00
tk - > psz_name = " MPEG Audio Layer 1/2 " ;
tk - > i_tag = WAVE_FORMAT_MPEG ;
2005-01-21 11:53:29 +01:00
i_bitspersample = 0 ;
2003-08-27 01:14:11 +02:00
i_blockalign = 1 ;
i_extra = 22 ;
break ;
# endif
2003-08-24 18:38:38 +02:00
case VLC_FOURCC ( ' w ' , ' m ' , ' a ' , ' 1 ' ) :
2005-01-20 13:32:53 +01:00
tk - > psz_name = " Windows Media Audio v1 " ;
2003-08-29 03:11:43 +02:00
tk - > i_tag = WAVE_FORMAT_WMA1 ;
2008-04-14 00:08:29 +02:00
tk - > b_audio_correction = true ;
2003-08-24 18:38:38 +02:00
break ;
2005-01-20 13:32:53 +01:00
case VLC_FOURCC ( ' w ' , ' m ' , ' a ' , ' ' ) :
2003-08-24 18:38:38 +02:00
case VLC_FOURCC ( ' w ' , ' m ' , ' a ' , ' 2 ' ) :
2005-01-20 13:32:53 +01:00
tk - > psz_name = " Windows Media Audio (v2) 7, 8 and 9 Series " ;
2003-08-29 03:11:43 +02:00
tk - > i_tag = WAVE_FORMAT_WMA2 ;
2008-04-14 00:08:29 +02:00
tk - > b_audio_correction = true ;
2003-08-24 18:38:38 +02:00
break ;
2005-01-20 13:32:53 +01:00
case VLC_FOURCC ( ' w ' , ' m ' , ' a ' , ' p ' ) :
tk - > psz_name = " Windows Media Audio 9 Professional " ;
tk - > i_tag = WAVE_FORMAT_WMAP ;
2008-04-14 00:08:29 +02:00
tk - > b_audio_correction = true ;
2005-01-20 13:32:53 +01:00
break ;
case VLC_FOURCC ( ' w ' , ' m ' , ' a ' , ' l ' ) :
tk - > psz_name = " Windows Media Audio 9 Lossless " ;
tk - > i_tag = WAVE_FORMAT_WMAL ;
2008-04-14 00:08:29 +02:00
tk - > b_audio_correction = true ;
2003-08-24 18:38:38 +02:00
break ;
/* raw codec */
case VLC_FOURCC ( ' u ' , ' 8 ' , ' ' , ' ' ) :
2003-08-29 03:11:43 +02:00
tk - > psz_name = " Raw audio 8bits " ;
tk - > i_tag = WAVE_FORMAT_PCM ;
2003-11-21 16:32:09 +01:00
i_blockalign = p_input - > p_fmt - > audio . i_channels ;
2003-08-24 18:38:38 +02:00
i_bitspersample = 8 ;
break ;
case VLC_FOURCC ( ' s ' , ' 1 ' , ' 6 ' , ' l ' ) :
2003-08-29 03:11:43 +02:00
tk - > psz_name = " Raw audio 16bits " ;
tk - > i_tag = WAVE_FORMAT_PCM ;
2003-11-21 16:32:09 +01:00
i_blockalign = 2 * p_input - > p_fmt - > audio . i_channels ;
2003-08-24 18:38:38 +02:00
i_bitspersample = 16 ;
break ;
case VLC_FOURCC ( ' s ' , ' 2 ' , ' 4 ' , ' l ' ) :
2003-08-29 03:11:43 +02:00
tk - > psz_name = " Raw audio 24bits " ;
tk - > i_tag = WAVE_FORMAT_PCM ;
2003-11-21 16:32:09 +01:00
i_blockalign = 3 * p_input - > p_fmt - > audio . i_channels ;
2003-08-24 18:38:38 +02:00
i_bitspersample = 24 ;
break ;
case VLC_FOURCC ( ' s ' , ' 3 ' , ' 2 ' , ' l ' ) :
2003-08-29 03:11:43 +02:00
tk - > psz_name = " Raw audio 32bits " ;
tk - > i_tag = WAVE_FORMAT_PCM ;
2003-11-21 16:32:09 +01:00
i_blockalign = 4 * p_input - > p_fmt - > audio . i_channels ;
2003-08-24 18:38:38 +02:00
i_bitspersample = 32 ;
break ;
default :
return VLC_EGENERIC ;
}
2003-08-27 01:14:11 +02:00
tk - > i_extra = sizeof ( WAVEFORMATEX ) +
2003-11-21 16:32:09 +01:00
p_input - > p_fmt - > i_extra + i_extra ;
2003-08-24 18:38:38 +02:00
tk - > p_extra = malloc ( tk - > i_extra ) ;
2008-08-20 22:45:24 +02:00
if ( ! tk - > p_extra )
return VLC_ENOMEM ;
2003-08-24 18:38:38 +02:00
bo_init ( & bo , tk - > p_extra , tk - > i_extra ) ;
2003-08-29 03:11:43 +02:00
bo_addle_u16 ( & bo , tk - > i_tag ) ;
2003-11-21 16:32:09 +01:00
bo_addle_u16 ( & bo , p_input - > p_fmt - > audio . i_channels ) ;
bo_addle_u32 ( & bo , p_input - > p_fmt - > audio . i_rate ) ;
2003-08-24 18:38:38 +02:00
bo_addle_u32 ( & bo , p_input - > p_fmt - > i_bitrate / 8 ) ;
bo_addle_u16 ( & bo , i_blockalign ) ;
2005-01-18 15:36:26 +01:00
tk - > i_blockalign = i_blockalign ;
2003-08-24 18:38:38 +02:00
bo_addle_u16 ( & bo , i_bitspersample ) ;
2003-11-21 16:32:09 +01:00
if ( p_input - > p_fmt - > i_extra > 0 )
2003-08-25 00:20:43 +02:00
{
2003-11-21 16:32:09 +01:00
bo_addle_u16 ( & bo , p_input - > p_fmt - > i_extra ) ;
bo_add_mem ( & bo , p_input - > p_fmt - > p_extra ,
p_input - > p_fmt - > i_extra ) ;
2003-08-25 00:20:43 +02:00
}
2003-08-25 03:31:25 +02:00
else
{
bo_addle_u16 ( & bo , i_extra ) ;
2003-08-29 03:11:43 +02:00
if ( tk - > i_tag = = WAVE_FORMAT_MPEGLAYER3 )
2003-08-25 03:31:25 +02:00
{
2003-08-27 01:14:11 +02:00
msg_Dbg ( p_mux , " adding mp3 header " ) ;
2003-08-25 03:31:25 +02:00
bo_addle_u16 ( & bo , 1 ) ; /* wId */
bo_addle_u32 ( & bo , 2 ) ; /* fdwFlags */
bo_addle_u16 ( & bo , 1152 ) ; /* nBlockSize */
bo_addle_u16 ( & bo , 1 ) ; /* nFramesPerBlock */
bo_addle_u16 ( & bo , 1393 ) ; /* nCodecDelay */
}
2003-08-29 03:11:43 +02:00
else if ( tk - > i_tag = = WAVE_FORMAT_MPEG )
2003-08-27 01:14:11 +02:00
{
msg_Dbg ( p_mux , " adding mp2 header " ) ;
bo_addle_u16 ( & bo , 2 ) ; /* fwHeadLayer */
bo_addle_u32 ( & bo , p_input - > p_fmt - > i_bitrate ) ;
2003-11-21 16:32:09 +01:00
bo_addle_u16 ( & bo , p_input - > p_fmt - > audio . i_channels = = 2 ? 1 : 8 ) ;
2003-08-27 01:14:11 +02:00
bo_addle_u16 ( & bo , 0 ) ; /* fwHeadModeExt */
bo_addle_u16 ( & bo , 1 ) ; /* wHeadEmphasis */
bo_addle_u16 ( & bo , 16 ) ; /* fwHeadFlags */
bo_addle_u32 ( & bo , 0 ) ; /* dwPTSLow */
bo_addle_u32 ( & bo , 0 ) ; /* dwPTSHigh */
}
2003-08-25 03:31:25 +02:00
}
2003-08-25 00:20:43 +02:00
if ( p_input - > p_fmt - > i_bitrate > 24000 )
{
p_sys - > i_bitrate + = p_input - > p_fmt - > i_bitrate ;
}
else
{
2008-08-11 21:54:45 +02:00
p_sys - > i_bitrate + = 128000 ;
2003-08-25 00:20:43 +02:00
}
2008-06-30 11:00:34 +02:00
if ( p_sys - > i_bitrate_override )
p_sys - > i_bitrate = p_sys - > i_bitrate_override ;
2003-08-24 18:38:38 +02:00
break ;
}
case VIDEO_ES :
{
tk - > i_extra = 11 + sizeof ( BITMAPINFOHEADER ) +
2003-11-21 16:32:09 +01:00
p_input - > p_fmt - > i_extra ;
2003-08-24 18:38:38 +02:00
tk - > p_extra = malloc ( tk - > i_extra ) ;
2008-08-20 22:45:24 +02:00
if ( ! tk - > p_extra )
return VLC_ENOMEM ;
2003-08-24 18:38:38 +02:00
bo_init ( & bo , tk - > p_extra , tk - > i_extra ) ;
2003-11-21 16:32:09 +01:00
bo_addle_u32 ( & bo , p_input - > p_fmt - > video . i_width ) ;
bo_addle_u32 ( & bo , p_input - > p_fmt - > video . i_height ) ;
2003-08-24 18:38:38 +02:00
bo_add_u8 ( & bo , 0x02 ) ; /* flags */
bo_addle_u16 ( & bo , sizeof ( BITMAPINFOHEADER ) +
2003-11-21 16:32:09 +01:00
p_input - > p_fmt - > i_extra ) ;
2003-08-24 18:38:38 +02:00
bo_addle_u32 ( & bo , sizeof ( BITMAPINFOHEADER ) +
2003-11-21 16:32:09 +01:00
p_input - > p_fmt - > i_extra ) ;
bo_addle_u32 ( & bo , p_input - > p_fmt - > video . i_width ) ;
bo_addle_u32 ( & bo , p_input - > p_fmt - > video . i_height ) ;
2003-08-24 18:38:38 +02:00
bo_addle_u16 ( & bo , 1 ) ;
bo_addle_u16 ( & bo , 24 ) ;
2003-11-21 16:32:09 +01:00
if ( p_input - > p_fmt - > i_codec = = VLC_FOURCC ( ' m ' , ' p ' , ' 4 ' , ' v ' ) )
2003-08-24 18:38:38 +02:00
{
2003-08-29 03:11:43 +02:00
tk - > psz_name = " MPEG-4 Video " ;
tk - > i_fourcc = VLC_FOURCC ( ' M ' , ' P ' , ' 4 ' , ' S ' ) ;
2003-08-24 18:38:38 +02:00
}
2003-11-21 16:32:09 +01:00
else if ( p_input - > p_fmt - > i_codec = = VLC_FOURCC ( ' D ' , ' I ' , ' V ' , ' 3 ' ) )
2003-08-24 18:38:38 +02:00
{
2003-08-29 03:11:43 +02:00
tk - > psz_name = " MSMPEG-4 V3 Video " ;
tk - > i_fourcc = VLC_FOURCC ( ' M ' , ' P ' , ' 4 ' , ' 3 ' ) ;
2003-08-24 18:38:38 +02:00
}
2003-11-21 16:32:09 +01:00
else if ( p_input - > p_fmt - > i_codec = = VLC_FOURCC ( ' D ' , ' I ' , ' V ' , ' 2 ' ) )
2003-08-27 01:14:11 +02:00
{
2003-08-29 03:11:43 +02:00
tk - > psz_name = " MSMPEG-4 V2 Video " ;
tk - > i_fourcc = VLC_FOURCC ( ' M ' , ' P ' , ' 4 ' , ' 2 ' ) ;
2003-08-27 01:14:11 +02:00
}
2003-11-21 16:32:09 +01:00
else if ( p_input - > p_fmt - > i_codec = = VLC_FOURCC ( ' D ' , ' I ' , ' V ' , ' 1 ' ) )
2003-08-27 01:14:11 +02:00
{
2003-08-29 03:11:43 +02:00
tk - > psz_name = " MSMPEG-4 V1 Video " ;
tk - > i_fourcc = VLC_FOURCC ( ' M ' , ' P ' , ' G ' , ' 4 ' ) ;
}
2003-11-21 16:32:09 +01:00
else if ( p_input - > p_fmt - > i_codec = = VLC_FOURCC ( ' W ' , ' M ' , ' V ' , ' 1 ' ) )
2003-08-29 03:11:43 +02:00
{
2005-08-01 21:47:12 +02:00
tk - > psz_name = " Windows Media Video 7 " ;
2003-08-29 03:11:43 +02:00
tk - > i_fourcc = VLC_FOURCC ( ' W ' , ' M ' , ' V ' , ' 1 ' ) ;
}
2003-11-21 16:32:09 +01:00
else if ( p_input - > p_fmt - > i_codec = = VLC_FOURCC ( ' W ' , ' M ' , ' V ' , ' 2 ' ) )
2003-08-29 03:11:43 +02:00
{
2005-08-01 21:47:12 +02:00
tk - > psz_name = " Windows Media Video 8 " ;
2003-08-29 03:11:43 +02:00
tk - > i_fourcc = VLC_FOURCC ( ' W ' , ' M ' , ' V ' , ' 2 ' ) ;
2003-08-27 01:14:11 +02:00
}
2004-07-25 09:54:18 +02:00
else if ( p_input - > p_fmt - > i_codec = = VLC_FOURCC ( ' W ' , ' M ' , ' V ' , ' 3 ' ) )
{
2005-08-01 21:47:12 +02:00
tk - > psz_name = " Windows Media Video 9 " ;
2004-07-25 09:54:18 +02:00
tk - > i_fourcc = VLC_FOURCC ( ' W ' , ' M ' , ' V ' , ' 3 ' ) ;
}
2005-08-01 21:47:12 +02:00
else if ( p_input - > p_fmt - > i_codec = = VLC_FOURCC ( ' h ' , ' 2 ' , ' 6 ' , ' 4 ' ) )
{
tk - > psz_name = " H.264/MPEG-4 AVC " ;
tk - > i_fourcc = VLC_FOURCC ( ' h ' , ' 2 ' , ' 6 ' , ' 4 ' ) ;
}
2003-08-24 18:38:38 +02:00
else
{
2004-01-25 14:37:12 +01:00
tk - > psz_name = _ ( " Unknown Video " ) ;
2003-11-21 16:32:09 +01:00
tk - > i_fourcc = p_input - > p_fmt - > i_codec ;
2003-08-24 18:38:38 +02:00
}
2003-08-29 03:11:43 +02:00
bo_add_mem ( & bo , ( uint8_t * ) & tk - > i_fourcc , 4 ) ;
2003-08-24 18:38:38 +02:00
bo_addle_u32 ( & bo , 0 ) ;
bo_addle_u32 ( & bo , 0 ) ;
bo_addle_u32 ( & bo , 0 ) ;
bo_addle_u32 ( & bo , 0 ) ;
bo_addle_u32 ( & bo , 0 ) ;
2003-11-21 16:32:09 +01:00
if ( p_input - > p_fmt - > i_extra > 0 )
2003-08-25 00:20:43 +02:00
{
2003-11-21 16:32:09 +01:00
bo_add_mem ( & bo , p_input - > p_fmt - > p_extra ,
p_input - > p_fmt - > i_extra ) ;
2003-08-25 00:20:43 +02:00
}
2003-08-27 01:14:11 +02:00
if ( p_input - > p_fmt - > i_bitrate > 50000 )
{
p_sys - > i_bitrate + = p_input - > p_fmt - > i_bitrate ;
}
else
{
2008-08-11 21:54:45 +02:00
p_sys - > i_bitrate + = 512000 ;
2003-08-27 01:14:11 +02:00
}
2008-06-30 11:00:34 +02:00
if ( p_sys - > i_bitrate_override )
p_sys - > i_bitrate = p_sys - > i_bitrate_override ;
2003-08-24 18:38:38 +02:00
break ;
}
default :
msg_Err ( p_mux , " unhandled track type " ) ;
return VLC_EGENERIC ;
}
2004-09-09 16:23:44 +02:00
es_format_Copy ( & tk - > fmt , p_input - > p_fmt ) ;
2003-08-24 18:38:38 +02:00
p_sys - > i_track + + ;
return VLC_SUCCESS ;
}
/*****************************************************************************
* DelStream :
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int DelStream ( sout_mux_t * p_mux , sout_input_t * p_input )
{
2008-07-02 22:30:13 +02:00
/* if bitrate ain't defined in commanline, reduce it when tracks are deleted
*/
sout_mux_sys_t * p_sys = p_mux - > p_sys ;
asf_track_t * tk = p_input - > p_sys ;
if ( ! p_sys - > i_bitrate_override )
{
if ( tk - > i_cat = = AUDIO_ES )
{
if ( p_input - > p_fmt - > i_bitrate > 24000 )
p_sys - > i_bitrate - = p_input - > p_fmt - > i_bitrate ;
else
2008-08-11 21:54:45 +02:00
p_sys - > i_bitrate - = 128000 ;
2008-07-02 22:30:13 +02:00
}
else if ( tk - > i_cat = = VIDEO_ES )
{
if ( p_input - > p_fmt - > i_bitrate > 50000 )
p_sys - > i_bitrate - = p_input - > p_fmt - > i_bitrate ;
else
2008-08-11 21:54:45 +02:00
p_sys - > i_bitrate - = 512000 ;
2008-07-02 22:30:13 +02:00
}
}
2003-08-24 18:38:38 +02:00
msg_Dbg ( p_mux , " removing input " ) ;
return VLC_SUCCESS ;
}
/*****************************************************************************
* Mux :
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-08-18 14:04:03 +02:00
static int Mux ( sout_mux_t * p_mux )
2003-08-24 18:38:38 +02:00
{
sout_mux_sys_t * p_sys = p_mux - > p_sys ;
if ( p_sys - > b_write_header )
{
2008-04-14 00:08:29 +02:00
block_t * out = asf_header_create ( p_mux , true ) ;
2003-08-24 18:38:38 +02:00
2004-03-11 18:37:50 +01:00
out - > i_flags | = BLOCK_FLAG_HEADER ;
2003-08-24 18:38:38 +02:00
sout_AccessOutWrite ( p_mux - > p_access , out ) ;
2008-04-14 00:08:29 +02:00
p_sys - > b_write_header = false ;
2003-08-24 18:38:38 +02:00
}
for ( ; ; )
{
sout_input_t * p_input ;
asf_track_t * tk ;
int i_stream ;
mtime_t i_dts ;
2004-03-11 18:37:50 +01:00
block_t * data ;
block_t * pk ;
2003-08-24 18:38:38 +02:00
if ( MuxGetStream ( p_mux , & i_stream , & i_dts ) )
{
/* not enough data */
return VLC_SUCCESS ;
}
if ( p_sys - > i_dts_first < 0 )
{
p_sys - > i_dts_first = i_dts ;
}
2003-08-25 00:20:43 +02:00
if ( p_sys - > i_dts_last < i_dts )
{
p_sys - > i_dts_last = i_dts ;
}
2003-08-24 18:38:38 +02:00
p_input = p_mux - > pp_inputs [ i_stream ] ;
tk = ( asf_track_t * ) p_input - > p_sys ;
2004-03-11 18:37:50 +01:00
data = block_FifoGet ( p_input - > p_fifo ) ;
2003-08-24 18:38:38 +02:00
if ( ( pk = asf_packet_create ( p_mux , tk , data ) ) )
{
sout_AccessOutWrite ( p_mux - > p_access , pk ) ;
}
}
return VLC_SUCCESS ;
}
2004-08-18 14:04:03 +02:00
static int MuxGetStream ( sout_mux_t * p_mux , int * pi_stream , mtime_t * pi_dts )
2003-08-24 18:38:38 +02:00
{
mtime_t i_dts ;
int i_stream ;
int i ;
for ( i = 0 , i_dts = 0 , i_stream = - 1 ; i < p_mux - > i_nb_inputs ; i + + )
{
sout_input_t * p_input = p_mux - > pp_inputs [ i ] ;
2004-03-11 18:37:50 +01:00
block_t * p_data ;
2003-08-24 18:38:38 +02:00
2007-09-14 18:36:10 +02:00
if ( block_FifoCount ( p_input - > p_fifo ) < = 0 )
2003-08-24 18:38:38 +02:00
{
if ( p_input - > p_fmt - > i_cat = = AUDIO_ES | |
p_input - > p_fmt - > i_cat = = VIDEO_ES )
{
/* We need that audio+video fifo contain at least 1 packet */
return VLC_EGENERIC ;
}
/* SPU */
continue ;
}
2004-03-11 18:37:50 +01:00
p_data = block_FifoShow ( p_input - > p_fifo ) ;
2004-08-19 13:32:20 +02:00
if ( i_stream = = - 1 | | p_data - > i_dts < i_dts )
2003-08-24 18:38:38 +02:00
{
i_stream = i ;
i_dts = p_data - > i_dts ;
}
}
* pi_stream = i_stream ;
* pi_dts = i_dts ;
return VLC_SUCCESS ;
}
/****************************************************************************
* Asf header construction
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/****************************************************************************
* Buffer out
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void bo_init ( bo_t * p_bo , uint8_t * p_buffer , int i_size )
{
p_bo - > i_buffer_size = i_size ;
p_bo - > i_buffer = 0 ;
p_bo - > p_buffer = p_buffer ;
}
static void bo_add_u8 ( bo_t * p_bo , uint8_t i )
{
if ( p_bo - > i_buffer < p_bo - > i_buffer_size )
{
p_bo - > p_buffer [ p_bo - > i_buffer ] = i ;
}
p_bo - > i_buffer + + ;
}
static void bo_addle_u16 ( bo_t * p_bo , uint16_t i )
{
bo_add_u8 ( p_bo , i & 0xff ) ;
bo_add_u8 ( p_bo , ( ( i > > 8 ) & 0xff ) ) ;
}
static void bo_addle_u32 ( bo_t * p_bo , uint32_t i )
{
bo_addle_u16 ( p_bo , i & 0xffff ) ;
bo_addle_u16 ( p_bo , ( ( i > > 16 ) & 0xffff ) ) ;
}
static void bo_addle_u64 ( bo_t * p_bo , uint64_t i )
{
bo_addle_u32 ( p_bo , i & 0xffffffff ) ;
bo_addle_u32 ( p_bo , ( ( i > > 32 ) & 0xffffffff ) ) ;
}
static void bo_add_mem ( bo_t * p_bo , uint8_t * p_mem , int i_size )
{
int i_copy = __MIN ( i_size , p_bo - > i_buffer_size - p_bo - > i_buffer ) ;
if ( i_copy > 0 )
{
2004-08-18 14:04:03 +02:00
memcpy ( & p_bo - > p_buffer [ p_bo - > i_buffer ] , p_mem , i_copy ) ;
2003-08-24 18:38:38 +02:00
}
p_bo - > i_buffer + = i_size ;
}
2007-10-02 20:58:29 +02:00
static void bo_addle_str16 ( bo_t * bo , const char * str )
2003-08-29 03:11:43 +02:00
{
bo_addle_u16 ( bo , strlen ( str ) + 1 ) ;
for ( ; ; )
{
2004-08-18 14:04:03 +02:00
uint16_t c = ( uint8_t ) * str + + ;
2003-08-29 03:11:43 +02:00
bo_addle_u16 ( bo , c ) ;
2004-08-18 14:04:03 +02:00
if ( c = = ' \0 ' ) break ;
2003-08-29 03:11:43 +02:00
}
}
2007-10-02 20:58:29 +02:00
static void bo_addle_str16_nosize ( bo_t * bo , const char * str )
2003-08-29 21:49:33 +02:00
{
for ( ; ; )
{
2004-08-18 14:04:03 +02:00
uint16_t c = ( uint8_t ) * str + + ;
2003-08-29 21:49:33 +02:00
bo_addle_u16 ( bo , c ) ;
2004-08-18 14:04:03 +02:00
if ( c = = ' \0 ' ) break ;
2003-08-29 21:49:33 +02:00
}
}
2003-08-24 18:38:38 +02:00
/****************************************************************************
2004-08-19 14:25:22 +02:00
* GUID definitions
2003-08-24 18:38:38 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void bo_add_guid ( bo_t * p_bo , const guid_t * id )
{
int i ;
2004-08-19 14:25:22 +02:00
bo_addle_u32 ( p_bo , id - > Data1 ) ;
bo_addle_u16 ( p_bo , id - > Data2 ) ;
bo_addle_u16 ( p_bo , id - > Data3 ) ;
2003-08-24 18:38:38 +02:00
for ( i = 0 ; i < 8 ; i + + )
{
2004-08-19 14:25:22 +02:00
bo_add_u8 ( p_bo , id - > Data4 [ i ] ) ;
2003-08-24 18:38:38 +02:00
}
}
static const guid_t asf_object_header_guid =
2004-08-19 14:25:22 +02:00
{ 0x75B22630 , 0x668E , 0x11CF , { 0xA6 , 0xD9 , 0x00 , 0xAA , 0x00 , 0x62 , 0xCE , 0x6C } } ;
2003-08-24 18:38:38 +02:00
static const guid_t asf_object_data_guid =
2004-08-19 14:25:22 +02:00
{ 0x75B22636 , 0x668E , 0x11CF , { 0xA6 , 0xD9 , 0x00 , 0xAA , 0x00 , 0x62 , 0xCE , 0x6C } } ;
2003-08-24 18:38:38 +02:00
static const guid_t asf_object_file_properties_guid =
2004-08-19 14:25:22 +02:00
{ 0x8cabdca1 , 0xa947 , 0x11cf , { 0x8e , 0xe4 , 0x00 , 0xC0 , 0x0C , 0x20 , 0x53 , 0x65 } } ;
2003-08-24 18:38:38 +02:00
static const guid_t asf_object_stream_properties_guid =
2004-08-19 14:25:22 +02:00
{ 0xB7DC0791 , 0xA9B7 , 0x11CF , { 0x8E , 0xE6 , 0x00 , 0xC0 , 0x0C , 0x20 , 0x53 , 0x65 } } ;
2006-04-06 19:54:21 +02:00
static const guid_t asf_object_header_extension_guid =
2004-08-19 14:25:22 +02:00
{ 0x5FBF03B5 , 0xA92E , 0x11CF , { 0x8E , 0xE3 , 0x00 , 0xC0 , 0x0C , 0x20 , 0x53 , 0x65 } } ;
2003-08-24 18:38:38 +02:00
static const guid_t asf_object_stream_type_audio =
2004-08-19 14:25:22 +02:00
{ 0xF8699E40 , 0x5B4D , 0x11CF , { 0xA8 , 0xFD , 0x00 , 0x80 , 0x5F , 0x5C , 0x44 , 0x2B } } ;
2003-08-24 18:38:38 +02:00
static const guid_t asf_object_stream_type_video =
2004-08-19 14:25:22 +02:00
{ 0xbc19efc0 , 0x5B4D , 0x11CF , { 0xA8 , 0xFD , 0x00 , 0x80 , 0x5F , 0x5C , 0x44 , 0x2B } } ;
2003-08-24 18:38:38 +02:00
static const guid_t asf_guid_audio_conceal_none =
2004-08-19 14:25:22 +02:00
{ 0x20FB5700 , 0x5B55 , 0x11CF , { 0xA8 , 0xFD , 0x00 , 0x80 , 0x5F , 0x5C , 0x44 , 0x2B } } ;
2005-01-18 15:36:26 +01:00
static const guid_t asf_guid_audio_conceal_spread =
{ 0xBFC3CD50 , 0x618F , 0x11CF , { 0x8B , 0xB2 , 0x00 , 0xAA , 0x00 , 0xB4 , 0xE2 , 0x20 } } ;
2003-08-24 18:38:38 +02:00
static const guid_t asf_guid_video_conceal_none =
2004-08-19 14:25:22 +02:00
{ 0x20FB5700 , 0x5B55 , 0x11CF , { 0xA8 , 0xFD , 0x00 , 0x80 , 0x5F , 0x5C , 0x44 , 0x2B } } ;
2003-08-24 18:38:38 +02:00
static const guid_t asf_guid_reserved_1 =
2004-08-19 14:25:22 +02:00
{ 0xABD3D211 , 0xA9BA , 0x11cf , { 0x8E , 0xE6 , 0x00 , 0xC0 , 0x0C , 0x20 , 0x53 , 0x65 } } ;
2005-01-17 18:01:21 +01:00
static const guid_t asf_object_codec_list_guid =
2004-08-19 14:25:22 +02:00
{ 0x86D15240 , 0x311D , 0x11D0 , { 0xA3 , 0xA4 , 0x00 , 0xA0 , 0xC9 , 0x03 , 0x48 , 0xF6 } } ;
2005-01-17 18:01:21 +01:00
static const guid_t asf_object_codec_list_reserved_guid =
2004-08-19 14:25:22 +02:00
{ 0x86D15241 , 0x311D , 0x11D0 , { 0xA3 , 0xA4 , 0x00 , 0xA0 , 0xC9 , 0x03 , 0x48 , 0xF6 } } ;
2003-08-29 21:49:33 +02:00
static const guid_t asf_object_content_description_guid =
2004-08-19 14:25:22 +02:00
{ 0x75B22633 , 0x668E , 0x11CF , { 0xa6 , 0xd9 , 0x00 , 0xaa , 0x00 , 0x62 , 0xce , 0x6c } } ;
2004-08-19 17:11:32 +02:00
static const guid_t asf_object_index_guid =
{ 0x33000890 , 0xE5B1 , 0x11CF , { 0x89 , 0xF4 , 0x00 , 0xA0 , 0xC9 , 0x03 , 0x49 , 0xCB } } ;
2004-09-09 16:23:44 +02:00
static const guid_t asf_object_metadata_guid =
{ 0xC5F8CBEA , 0x5BAF , 0x4877 , { 0x84 , 0x67 , 0xAA , 0x8C , 0x44 , 0xFA , 0x4C , 0xCA } } ;
2003-08-24 18:38:38 +02:00
2004-08-19 14:25:22 +02:00
/****************************************************************************
* Misc
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-08-25 03:31:25 +02:00
static void asf_chunk_add ( bo_t * bo ,
int i_type , int i_len , int i_flags , int i_seq )
{
bo_addle_u16 ( bo , i_type ) ;
bo_addle_u16 ( bo , i_len + 8 ) ;
bo_addle_u32 ( bo , i_seq ) ;
bo_addle_u16 ( bo , i_flags ) ;
bo_addle_u16 ( bo , i_len + 8 ) ;
}
2008-04-14 00:08:29 +02:00
static block_t * asf_header_create ( sout_mux_t * p_mux , bool b_broadcast )
2003-08-24 18:38:38 +02:00
{
sout_mux_sys_t * p_sys = p_mux - > p_sys ;
asf_track_t * tk ;
2004-08-18 14:04:03 +02:00
mtime_t i_duration = 0 ;
2005-01-18 15:36:26 +01:00
int i_size , i_header_ext_size , i ;
2004-09-09 16:23:44 +02:00
int i_ci_size , i_cm_size = 0 , i_cd_size = 0 ;
2004-03-11 18:37:50 +01:00
block_t * out ;
2004-08-18 14:04:03 +02:00
bo_t bo ;
2003-08-24 18:38:38 +02:00
2004-08-18 17:46:01 +02:00
msg_Dbg ( p_mux , " Asf muxer creating header " ) ;
2003-08-25 00:20:43 +02:00
if ( p_sys - > i_dts_first > 0 )
{
i_duration = p_sys - > i_dts_last - p_sys - > i_dts_first ;
2004-08-18 14:04:03 +02:00
if ( i_duration < 0 ) i_duration = 0 ;
2003-08-25 00:20:43 +02:00
}
2003-08-24 18:38:38 +02:00
/* calculate header size */
2005-01-18 15:36:26 +01:00
i_size = 30 + 104 ;
2003-08-29 03:11:43 +02:00
i_ci_size = 44 ;
2004-08-27 22:44:39 +02:00
for ( i = 0 ; i < p_sys - > i_track ; i + + )
2003-08-24 18:38:38 +02:00
{
i_size + = 78 + p_sys - > track [ i ] . i_extra ;
2003-08-29 03:11:43 +02:00
i_ci_size + = 8 + 2 * strlen ( p_sys - > track [ i ] . psz_name ) ;
2005-01-20 13:32:53 +01:00
if ( p_sys - > track [ i ] . i_cat = = AUDIO_ES ) i_ci_size + = 4 ;
else if ( p_sys - > track [ i ] . i_cat = = VIDEO_ES ) i_ci_size + = 6 ;
2005-01-20 15:30:17 +01:00
/* Error correction data field */
if ( p_sys - > track [ i ] . b_audio_correction ) i_size + = 8 ;
2003-08-24 18:38:38 +02:00
}
2004-08-18 14:04:03 +02:00
2004-09-09 16:23:44 +02:00
/* size of the content description object */
2003-08-29 21:49:33 +02:00
if ( * p_sys - > psz_title | | * p_sys - > psz_author | | * p_sys - > psz_copyright | |
* p_sys - > psz_comment | | * p_sys - > psz_rating )
{
i_cd_size = 34 + 2 * ( strlen ( p_sys - > psz_title ) + 1 +
strlen ( p_sys - > psz_author ) + 1 +
strlen ( p_sys - > psz_copyright ) + 1 +
strlen ( p_sys - > psz_comment ) + 1 +
strlen ( p_sys - > psz_rating ) + 1 ) ;
}
2003-08-24 18:38:38 +02:00
2004-09-09 16:23:44 +02:00
/* size of the metadata object */
for ( i = 0 ; i < p_sys - > i_track ; i + + )
{
if ( p_sys - > track [ i ] . i_cat = = VIDEO_ES )
{
i_cm_size = 26 + 2 * ( 16 + 2 * sizeof ( " AspectRatio? " ) ) ;
break ;
}
}
2005-01-18 15:36:26 +01:00
i_header_ext_size = i_cm_size ? i_cm_size + 46 : 0 ;
i_size + = i_ci_size + i_cd_size + i_header_ext_size ;
2003-08-29 03:11:43 +02:00
2003-08-25 03:31:25 +02:00
if ( p_sys - > b_asf_http )
{
2004-03-11 18:37:50 +01:00
out = block_New ( p_mux , i_size + 50 + 12 ) ;
2003-08-25 03:31:25 +02:00
bo_init ( & bo , out - > p_buffer , i_size + 50 + 12 ) ;
asf_chunk_add ( & bo , 0x4824 , i_size + 50 , 0xc00 , p_sys - > i_seq + + ) ;
}
else
{
2004-03-11 18:37:50 +01:00
out = block_New ( p_mux , i_size + 50 ) ;
2003-08-25 03:31:25 +02:00
bo_init ( & bo , out - > p_buffer , i_size + 50 ) ;
}
2004-08-18 14:04:03 +02:00
2003-08-24 18:38:38 +02:00
/* header object */
bo_add_guid ( & bo , & asf_object_header_guid ) ;
bo_addle_u64 ( & bo , i_size ) ;
2004-12-07 15:27:06 +01:00
bo_addle_u32 ( & bo , 2 + p_sys - > i_track +
( i_cd_size ? 1 : 0 ) + ( i_cm_size ? 1 : 0 ) ) ;
2003-08-24 18:38:38 +02:00
bo_add_u8 ( & bo , 1 ) ;
bo_add_u8 ( & bo , 2 ) ;
/* sub object */
/* file properties */
bo_add_guid ( & bo , & asf_object_file_properties_guid ) ;
bo_addle_u64 ( & bo , 104 ) ;
bo_add_guid ( & bo , & p_sys - > fid ) ;
2003-08-26 01:39:20 +02:00
bo_addle_u64 ( & bo , i_size + 50 + p_sys - > i_packet_count *
2003-08-24 18:38:38 +02:00
p_sys - > i_packet_size ) ; /* file size */
2003-08-25 00:20:43 +02:00
bo_addle_u64 ( & bo , 0 ) ; /* creation date */
2003-08-26 01:39:20 +02:00
bo_addle_u64 ( & bo , b_broadcast ? 0xffffffffLL : p_sys - > i_packet_count ) ;
2003-08-25 00:20:43 +02:00
bo_addle_u64 ( & bo , i_duration * 10 ) ; /* play duration (100ns) */
bo_addle_u64 ( & bo , i_duration * 10 ) ; /* send duration (100ns) */
2004-08-19 13:32:20 +02:00
bo_addle_u64 ( & bo , p_sys - > i_preroll_time ) ; /* preroll duration (ms) */
2005-01-18 15:36:26 +01:00
bo_addle_u32 ( & bo , b_broadcast ? 0x01 : 0x02 /* seekable */ ) ; /* flags */
2003-08-24 18:38:38 +02:00
bo_addle_u32 ( & bo , p_sys - > i_packet_size ) ; /* packet size min */
bo_addle_u32 ( & bo , p_sys - > i_packet_size ) ; /* packet size max */
2003-08-25 00:20:43 +02:00
bo_addle_u32 ( & bo , p_sys - > i_bitrate ) ; /* maxbitrate */
2003-08-24 18:38:38 +02:00
2006-04-06 19:54:21 +02:00
/* header extension */
2005-01-18 15:36:26 +01:00
if ( i_header_ext_size )
{
2006-04-06 19:54:21 +02:00
bo_add_guid ( & bo , & asf_object_header_extension_guid ) ;
2005-01-18 15:36:26 +01:00
bo_addle_u64 ( & bo , i_header_ext_size ) ;
bo_add_guid ( & bo , & asf_guid_reserved_1 ) ;
bo_addle_u16 ( & bo , 6 ) ;
bo_addle_u32 ( & bo , i_header_ext_size - 46 ) ;
}
2004-09-09 16:23:44 +02:00
/* metadata object (part of header extension) */
if ( i_cm_size )
{
int64_t i_num , i_den ;
2005-09-28 20:49:52 +02:00
unsigned int i_dst_num , i_dst_den ;
2004-09-09 16:23:44 +02:00
2004-09-13 10:27:58 +02:00
for ( i = 0 ; i < p_sys - > i_track ; i + + )
if ( p_sys - > track [ i ] . i_cat = = VIDEO_ES ) break ;
2004-09-09 16:23:44 +02:00
i_num = p_sys - > track [ i ] . fmt . video . i_aspect *
( int64_t ) p_sys - > track [ i ] . fmt . video . i_height ;
i_den = VOUT_ASPECT_FACTOR * p_sys - > track [ i ] . fmt . video . i_width ;
2005-07-15 16:24:47 +02:00
vlc_ureduce ( & i_dst_num , & i_dst_den , i_num , i_den , 0 ) ;
2004-09-09 16:23:44 +02:00
2004-10-02 19:57:33 +02:00
msg_Dbg ( p_mux , " pixel aspect-ratio: %i/%i " , i_dst_num , i_dst_den ) ;
2004-09-09 16:23:44 +02:00
bo_add_guid ( & bo , & asf_object_metadata_guid ) ;
bo_addle_u64 ( & bo , i_cm_size ) ;
bo_addle_u16 ( & bo , 2 ) ; /* description records count */
/* 1st description record */
bo_addle_u16 ( & bo , 0 ) ; /* reserved */
bo_addle_u16 ( & bo , i + 1 ) ; /* stream number (0 for the whole file) */
bo_addle_u16 ( & bo , 2 * sizeof ( " AspectRatioX " ) ) ; /* name length */
bo_addle_u16 ( & bo , 0x3 /* DWORD */ ) ; /* data type */
bo_addle_u32 ( & bo , 4 ) ; /* data length */
bo_addle_str16_nosize ( & bo , " AspectRatioX " ) ;
bo_addle_u32 ( & bo , i_dst_num ) ; /* data */
/* 2nd description record */
bo_addle_u16 ( & bo , 0 ) ; /* reserved */
bo_addle_u16 ( & bo , i + 1 ) ; /* stream number (0 for the whole file) */
bo_addle_u16 ( & bo , 2 * sizeof ( " AspectRatioY " ) ) ; /* name length */
bo_addle_u16 ( & bo , 0x3 /* DWORD */ ) ; /* data type */
bo_addle_u32 ( & bo , 4 ) ; /* data length */
bo_addle_str16_nosize ( & bo , " AspectRatioY " ) ;
bo_addle_u32 ( & bo , i_dst_den ) ; /* data */
}
2003-08-24 18:38:38 +02:00
2003-08-29 21:49:33 +02:00
/* content description header */
if ( i_cd_size > 0 )
{
bo_add_guid ( & bo , & asf_object_content_description_guid ) ;
bo_addle_u64 ( & bo , i_cd_size ) ;
bo_addle_u16 ( & bo , 2 * strlen ( p_sys - > psz_title ) + 2 ) ;
bo_addle_u16 ( & bo , 2 * strlen ( p_sys - > psz_author ) + 2 ) ;
bo_addle_u16 ( & bo , 2 * strlen ( p_sys - > psz_copyright ) + 2 ) ;
bo_addle_u16 ( & bo , 2 * strlen ( p_sys - > psz_comment ) + 2 ) ;
bo_addle_u16 ( & bo , 2 * strlen ( p_sys - > psz_rating ) + 2 ) ;
bo_addle_str16_nosize ( & bo , p_sys - > psz_title ) ;
bo_addle_str16_nosize ( & bo , p_sys - > psz_author ) ;
bo_addle_str16_nosize ( & bo , p_sys - > psz_copyright ) ;
bo_addle_str16_nosize ( & bo , p_sys - > psz_comment ) ;
bo_addle_str16_nosize ( & bo , p_sys - > psz_rating ) ;
}
2003-08-24 18:38:38 +02:00
/* stream properties */
2004-08-27 22:44:39 +02:00
for ( i = 0 ; i < p_sys - > i_track ; i + + )
2003-08-24 18:38:38 +02:00
{
tk = & p_sys - > track [ i ] ;
bo_add_guid ( & bo , & asf_object_stream_properties_guid ) ;
2005-01-20 15:30:17 +01:00
bo_addle_u64 ( & bo , 78 + tk - > i_extra + ( tk - > b_audio_correction ? 8 : 0 ) ) ;
2005-01-18 15:36:26 +01:00
2003-08-24 18:38:38 +02:00
if ( tk - > i_cat = = AUDIO_ES )
{
bo_add_guid ( & bo , & asf_object_stream_type_audio ) ;
2005-01-20 13:32:53 +01:00
if ( tk - > b_audio_correction )
bo_add_guid ( & bo , & asf_guid_audio_conceal_spread ) ;
else
bo_add_guid ( & bo , & asf_guid_audio_conceal_none ) ;
2003-08-24 18:38:38 +02:00
}
else if ( tk - > i_cat = = VIDEO_ES )
{
bo_add_guid ( & bo , & asf_object_stream_type_video ) ;
bo_add_guid ( & bo , & asf_guid_video_conceal_none ) ;
}
bo_addle_u64 ( & bo , 0 ) ; /* time offset */
bo_addle_u32 ( & bo , tk - > i_extra ) ;
2005-01-20 13:32:53 +01:00
/* correction data length */
bo_addle_u32 ( & bo , tk - > b_audio_correction ? 8 : 0 ) ;
2003-08-24 18:38:38 +02:00
bo_addle_u16 ( & bo , tk - > i_id ) ; /* stream number */
bo_addle_u32 ( & bo , 0 ) ;
bo_add_mem ( & bo , tk - > p_extra , tk - > i_extra ) ;
2005-01-18 15:36:26 +01:00
/* Error correction data field */
2005-01-20 13:32:53 +01:00
if ( tk - > b_audio_correction )
2005-01-18 15:36:26 +01:00
{
bo_add_u8 ( & bo , 0x1 ) ; /* span */
bo_addle_u16 ( & bo , tk - > i_blockalign ) ; /* virtual packet length */
bo_addle_u16 ( & bo , tk - > i_blockalign ) ; /* virtual chunck length */
bo_addle_u16 ( & bo , 1 ) ; /* silence length */
bo_add_u8 ( & bo , 0x0 ) ; /* data */
}
2003-08-24 18:38:38 +02:00
}
2003-08-29 03:11:43 +02:00
/* Codec Infos */
2005-01-17 18:01:21 +01:00
bo_add_guid ( & bo , & asf_object_codec_list_guid ) ;
2003-08-29 03:11:43 +02:00
bo_addle_u64 ( & bo , i_ci_size ) ;
2005-01-17 18:01:21 +01:00
bo_add_guid ( & bo , & asf_object_codec_list_reserved_guid ) ;
2004-08-27 22:44:39 +02:00
bo_addle_u32 ( & bo , p_sys - > i_track ) ;
for ( i = 0 ; i < p_sys - > i_track ; i + + )
2003-08-29 03:11:43 +02:00
{
tk = & p_sys - > track [ i ] ;
2005-01-17 18:01:21 +01:00
if ( tk - > i_cat = = VIDEO_ES ) bo_addle_u16 ( & bo , 1 /* video */ ) ;
else if ( tk - > i_cat = = AUDIO_ES ) bo_addle_u16 ( & bo , 2 /* audio */ ) ;
else bo_addle_u16 ( & bo , 0xFFFF /* unknown */ ) ;
2003-08-29 03:11:43 +02:00
bo_addle_str16 ( & bo , tk - > psz_name ) ;
bo_addle_u16 ( & bo , 0 ) ;
if ( tk - > i_cat = = AUDIO_ES )
{
bo_addle_u16 ( & bo , 2 ) ;
bo_addle_u16 ( & bo , tk - > i_tag ) ;
}
else if ( tk - > i_cat = = VIDEO_ES )
{
bo_addle_u16 ( & bo , 4 ) ;
bo_add_mem ( & bo , ( uint8_t * ) & tk - > i_fourcc , 4 ) ;
}
}
2003-08-24 18:38:38 +02:00
/* data object */
bo_add_guid ( & bo , & asf_object_data_guid ) ;
bo_addle_u64 ( & bo , 50 + p_sys - > i_packet_count * p_sys - > i_packet_size ) ;
bo_add_guid ( & bo , & p_sys - > fid ) ;
bo_addle_u64 ( & bo , p_sys - > i_packet_count ) ;
bo_addle_u16 ( & bo , 0x101 ) ;
return out ;
}
/****************************************************************************
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-08-27 22:10:21 +02:00
static block_t * asf_packet_flush ( sout_mux_t * p_mux )
{
sout_mux_sys_t * p_sys = p_mux - > p_sys ;
int i_pad , i_preheader = p_sys - > b_asf_http ? 12 : 0 ;
block_t * pk ;
bo_t bo ;
if ( ! p_sys - > pk ) return 0 ;
i_pad = p_sys - > i_packet_size - p_sys - > i_pk_used ;
memset ( p_sys - > pk - > p_buffer + p_sys - > i_pk_used , 0 , i_pad ) ;
bo_init ( & bo , p_sys - > pk - > p_buffer , 14 + i_preheader ) ;
if ( p_sys - > b_asf_http )
asf_chunk_add ( & bo , 0x4424 , p_sys - > i_packet_size , 0x0 , p_sys - > i_seq + + ) ;
bo_add_u8 ( & bo , 0x82 ) ;
bo_addle_u16 ( & bo , 0 ) ;
bo_add_u8 ( & bo , 0x11 ) ;
bo_add_u8 ( & bo , 0x5d ) ;
bo_addle_u16 ( & bo , i_pad ) ;
bo_addle_u32 ( & bo , ( p_sys - > i_pk_dts - p_sys - > i_dts_first ) / 1000 +
p_sys - > i_preroll_time ) ;
bo_addle_u16 ( & bo , 0 /* data->i_length */ ) ;
bo_add_u8 ( & bo , 0x80 | p_sys - > i_pk_frame ) ;
pk = p_sys - > pk ;
p_sys - > pk = NULL ;
p_sys - > i_packet_count + + ;
return pk ;
}
2004-03-11 18:37:50 +01:00
static block_t * asf_packet_create ( sout_mux_t * p_mux ,
2004-08-18 14:04:03 +02:00
asf_track_t * tk , block_t * data )
2003-08-24 18:38:38 +02:00
{
sout_mux_sys_t * p_sys = p_mux - > p_sys ;
2004-03-11 18:37:50 +01:00
int i_data = data - > i_buffer ;
2003-08-24 18:38:38 +02:00
int i_pos = 0 ;
uint8_t * p_data = data - > p_buffer ;
2004-03-11 18:37:50 +01:00
block_t * first = NULL , * * last = & first ;
2003-08-25 03:31:25 +02:00
int i_preheader = p_sys - > b_asf_http ? 12 : 0 ;
2003-08-24 18:38:38 +02:00
while ( i_pos < i_data )
{
2004-08-18 14:04:03 +02:00
bo_t bo ;
int i_payload ;
2003-08-24 18:38:38 +02:00
if ( p_sys - > pk = = NULL )
{
2004-08-18 14:04:03 +02:00
p_sys - > pk = block_New ( p_mux , p_sys - > i_packet_size + i_preheader ) ;
2003-08-24 18:38:38 +02:00
/* reserve 14 bytes for the packet header */
2003-08-25 03:31:25 +02:00
p_sys - > i_pk_used = 14 + i_preheader ;
2003-08-24 18:38:38 +02:00
p_sys - > i_pk_frame = 0 ;
p_sys - > i_pk_dts = data - > i_dts ;
}
bo_init ( & bo , & p_sys - > pk - > p_buffer [ p_sys - > i_pk_used ] ,
2004-08-18 14:04:03 +02:00
p_sys - > i_packet_size - p_sys - > i_pk_used ) ;
2003-08-24 18:38:38 +02:00
/* add payload (header size = 17) */
i_payload = __MIN ( i_data - i_pos ,
p_sys - > i_packet_size - p_sys - > i_pk_used - 17 ) ;
2005-01-20 15:30:17 +01:00
if ( tk - > b_audio_correction & & p_sys - > i_pk_frame & & i_payload < i_data )
{
/* Don't know why yet but WMP doesn't like splitted WMA packets */
* last = asf_packet_flush ( p_mux ) ;
last = & ( * last ) - > p_next ;
continue ;
}
2004-08-19 17:11:32 +02:00
bo_add_u8 ( & bo , ! ( data - > i_flags & BLOCK_FLAG_TYPE_P | |
data - > i_flags & BLOCK_FLAG_TYPE_B ) ?
0x80 | tk - > i_id : tk - > i_id ) ;
2003-08-24 18:38:38 +02:00
bo_add_u8 ( & bo , tk - > i_sequence ) ;
bo_addle_u32 ( & bo , i_pos ) ;
bo_add_u8 ( & bo , 0x08 ) ; /* flags */
bo_addle_u32 ( & bo , i_data ) ;
2004-08-19 17:11:32 +02:00
bo_addle_u32 ( & bo , ( data - > i_dts - p_sys - > i_dts_first ) / 1000 +
2004-08-19 13:32:20 +02:00
p_sys - > i_preroll_time ) ;
2003-08-24 18:38:38 +02:00
bo_addle_u16 ( & bo , i_payload ) ;
bo_add_mem ( & bo , & p_data [ i_pos ] , i_payload ) ;
i_pos + = i_payload ;
p_sys - > i_pk_used + = 17 + i_payload ;
p_sys - > i_pk_frame + + ;
2003-08-29 03:11:43 +02:00
if ( p_sys - > i_pk_used + 17 > = p_sys - > i_packet_size )
2003-08-24 18:38:38 +02:00
{
2004-08-27 22:10:21 +02:00
/* Not enough data for another payload, flush the packet */
* last = asf_packet_flush ( p_mux ) ;
last = & ( * last ) - > p_next ;
2003-08-24 18:38:38 +02:00
}
}
tk - > i_sequence + + ;
2004-03-11 18:37:50 +01:00
block_Release ( data ) ;
2003-08-24 18:38:38 +02:00
return first ;
}
2004-03-11 18:37:50 +01:00
static block_t * asf_stream_end_create ( sout_mux_t * p_mux )
2003-08-25 03:31:25 +02:00
{
sout_mux_sys_t * p_sys = p_mux - > p_sys ;
2004-03-11 18:37:50 +01:00
block_t * out = NULL ;
2004-08-18 14:04:03 +02:00
bo_t bo ;
2003-08-24 18:38:38 +02:00
2003-08-25 03:31:25 +02:00
if ( p_sys - > b_asf_http )
{
2004-03-11 18:37:50 +01:00
out = block_New ( p_mux , 12 ) ;
2003-08-25 03:31:25 +02:00
bo_init ( & bo , out - > p_buffer , 12 ) ;
asf_chunk_add ( & bo , 0x4524 , 0 , 0x00 , p_sys - > i_seq + + ) ;
}
2004-08-19 17:11:32 +02:00
else
{
/* Create index */
out = block_New ( p_mux , 56 ) ;
bo_init ( & bo , out - > p_buffer , 56 ) ;
bo_add_guid ( & bo , & asf_object_index_guid ) ;
bo_addle_u64 ( & bo , 56 ) ;
bo_add_guid ( & bo , & p_sys - > fid ) ;
bo_addle_u64 ( & bo , 10000000 ) ;
bo_addle_u32 ( & bo , 5 ) ;
bo_addle_u32 ( & bo , 0 ) ;
}
2004-08-18 14:04:03 +02:00
2003-08-25 03:31:25 +02:00
return out ;
}