📄 asf.c
字号:
/***************************************************************************** * asf.c: asf muxer module for vlc ***************************************************************************** * Copyright (C) 2003-2004 VideoLAN * $Id: asf.c 10452 2005-03-27 17:49:24Z markfm $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * Gildas Bazin <gbazin@videolan.org> * * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h>#include <vlc/vlc.h>#include <vlc/input.h>#include <vlc/sout.h>#include "codecs.h"typedef GUID guid_t;#define MAX_ASF_TRACKS 128#define ASF_DATA_PACKET_SIZE 4096 // deprecated -- added sout-asf-packet-size/***************************************************************************** * Module descriptor *****************************************************************************/static int Open ( vlc_object_t * );static void Close ( vlc_object_t * );#define SOUT_CFG_PREFIX "sout-asf-"#define TITLE_TEXT N_("Title")#define TITLE_LONGTEXT N_("Allows you to define the title that will be put " \ "in ASF comments.")#define AUTHOR_TEXT N_("Author")#define AUTHOR_LONGTEXT N_("Allows you to define the author that will be put "\ "in ASF comments.")#define COPYRIGHT_TEXT N_("Copyright")#define COPYRIGHT_LONGTEXT N_("Allows you to define the copyright string " \ "that will be put in ASF comments.")#define COMMENT_TEXT N_("Comment")#define COMMENT_LONGTEXT N_("Allows you to define the comment that will be " \ "put in ASF comments.")#define RATING_TEXT N_("Rating")#define RATING_LONGTEXT N_("Allows you to define the \"rating\" that will " \ "be put in ASF comments.")#define PACKETSIZE_TEXT N_("Packet Size")#define PACKETSIZE_LONGTEXT N_("The ASF packet size -- default is 4096 bytes")vlc_module_begin(); set_description( _("ASF muxer") ); set_category( CAT_SOUT ); set_subcategory( SUBCAT_SOUT_MUX ); set_shortname( "ASF" ); set_capability( "sout mux", 5 ); add_shortcut( "asf" ); add_shortcut( "asfh" ); set_callbacks( Open, Close ); add_string( SOUT_CFG_PREFIX "title", "", NULL, TITLE_TEXT, TITLE_LONGTEXT, VLC_TRUE ); add_string( SOUT_CFG_PREFIX "author", "", NULL, AUTHOR_TEXT, AUTHOR_LONGTEXT, VLC_TRUE ); add_string( SOUT_CFG_PREFIX "copyright","", NULL, COPYRIGHT_TEXT, COPYRIGHT_LONGTEXT, VLC_TRUE ); add_string( SOUT_CFG_PREFIX "comment", "", NULL, COMMENT_TEXT, COMMENT_LONGTEXT, VLC_TRUE ); add_string( SOUT_CFG_PREFIX "rating", "", NULL, RATING_TEXT, RATING_LONGTEXT, VLC_TRUE ); add_integer( "sout-asf-packet-size", 4096, NULL, PACKETSIZE_TEXT, PACKETSIZE_LONGTEXT, VLC_TRUE );vlc_module_end();/***************************************************************************** * Locales prototypes *****************************************************************************/static const char *ppsz_sout_options[] = { "title", "author", "copyright", "comment", "rating", NULL};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 * );typedef struct{ int i_id; int i_cat; /* codec information */ uint16_t i_tag; /* for audio */ vlc_fourcc_t i_fourcc; /* for video */ char *psz_name; /* codec name */ int i_blockalign; /* for audio only */ vlc_bool_t b_audio_correction; int i_sequence; int i_extra; uint8_t *p_extra; es_format_t fmt;} 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; mtime_t i_dts_last; mtime_t i_preroll_time; int64_t i_bitrate; int i_track; asf_track_t track[MAX_ASF_TRACKS]; vlc_bool_t b_write_header; block_t *pk; int i_pk_used; int i_pk_frame; mtime_t i_pk_dts; vlc_bool_t b_asf_http; int i_seq; /* meta data */ char *psz_title; char *psz_author; char *psz_copyright; char *psz_comment; char *psz_rating;};static int MuxGetStream( sout_mux_t *, int *pi_stream, mtime_t *pi_dts );static block_t *asf_header_create( sout_mux_t *, vlc_bool_t );static block_t *asf_packet_create( sout_mux_t *, asf_track_t *, block_t * );static block_t *asf_stream_end_create( sout_mux_t *);static block_t *asf_packet_flush( sout_mux_t * );typedef struct{ int i_buffer_size; int i_buffer; uint8_t *p_buffer;} 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 );static void bo_addle_str16( bo_t *, char * );/***************************************************************************** * 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; vlc_value_t val; int i; msg_Dbg( p_mux, "Asf muxer opened" ); sout_CfgParse( p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg ); p_mux->pf_control = Control; 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 ) ); 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" ); } p_sys->pk = NULL; p_sys->i_pk_used = 0; p_sys->i_pk_frame = 0; p_sys->i_dts_first = -1; p_sys->i_dts_last = 0; p_sys->i_preroll_time = 2000; p_sys->i_bitrate = 0; p_sys->i_seq = 0; p_sys->b_write_header = VLC_TRUE; p_sys->i_track = 0; p_sys->i_packet_size = config_GetInt( p_mux, "sout-asf-packet-size" ); msg_Dbg( p_mux, "Packet size %d", p_sys->i_packet_size); p_sys->i_packet_count= 0; /* Generate a random fid */ srand( mdate() & 0xffffffff ); 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; for( i = 0; i < 8; i++ ) { p_sys->fid.Data4[i] = ( (uint64_t)rand() << 8 ) / RAND_MAX; } /* Meta data */ 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; msg_Dbg( p_mux, "meta data: title='%s' author='%s' copyright='%s' " "comment='%s' rating='%s'", p_sys->psz_title, p_sys->psz_author, p_sys->psz_copyright, p_sys->psz_comment, p_sys->psz_rating ); 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; block_t *out; int i; msg_Dbg( p_mux, "Asf muxer closed" ); /* Flush last packet if any */ if( (out = asf_packet_flush( p_mux ) ) ) { sout_AccessOutWrite( p_mux->p_access, out ); } if( ( out = asf_stream_end_create( p_mux ) ) ) { sout_AccessOutWrite( p_mux->p_access, out ); } /* rewrite header */ if( !sout_AccessOutSeek( p_mux->p_access, 0 ) ) { out = asf_header_create( p_mux, VLC_FALSE ); sout_AccessOutWrite( p_mux->p_access, out ); } for( i = 0; i < p_sys->i_track; i++ ) { free( p_sys->track[i].p_extra ); es_format_Clean( &p_sys->track[i].fmt ); } free( p_sys );}/***************************************************************************** * Capability: *****************************************************************************/static int Control( sout_mux_t *p_mux, int i_query, va_list args ){ sout_mux_sys_t *p_sys = p_mux->p_sys; vlc_bool_t *pb_bool; char **ppsz; switch( i_query ) { case MUX_CAN_ADD_STREAM_WHILE_MUXING: pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * ); if( p_sys->b_asf_http ) *pb_bool = VLC_TRUE; else *pb_bool = VLC_FALSE; return VLC_SUCCESS; case MUX_GET_ADD_STREAM_WAIT: pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * ); *pb_bool = VLC_TRUE; 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; default: return VLC_EGENERIC; }}/***************************************************************************** * 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" ); if( p_sys->i_track >= MAX_ASF_TRACKS ) { msg_Dbg( p_mux, "cannot add this track (too much track)" ); return VLC_EGENERIC; } tk = p_input->p_sys = &p_sys->track[p_sys->i_track]; tk->i_id = p_sys->i_track + 1; tk->i_cat = p_input->p_fmt->i_cat; tk->i_sequence = 0; tk->b_audio_correction = 0; switch( tk->i_cat ) { case AUDIO_ES: { int i_blockalign = p_input->p_fmt->audio.i_blockalign; int i_bitspersample = p_input->p_fmt->audio.i_bitspersample; int i_extra = 0; switch( p_input->p_fmt->i_codec ) { case VLC_FOURCC( 'a', '5', '2', ' ' ): tk->i_tag = WAVE_FORMAT_A52; tk->psz_name = "A/52"; i_bitspersample = 0; break; case VLC_FOURCC( 'm', 'p', 'g', 'a' ):#if 1 tk->psz_name = "MPEG Audio Layer 3"; tk->i_tag = WAVE_FORMAT_MPEGLAYER3; i_bitspersample = 0; i_blockalign = 1; i_extra = 12; break;#else tk->psz_name = "MPEG Audio Layer 1/2"; tk->i_tag = WAVE_FORMAT_MPEG; i_bitspersample = 0; i_blockalign = 1; i_extra = 22; break;#endif case VLC_FOURCC( 'w', 'm', 'a', '1' ): tk->psz_name = "Windows Media Audio v1"; tk->i_tag = WAVE_FORMAT_WMA1; tk->b_audio_correction = VLC_TRUE; break; case VLC_FOURCC( 'w', 'm', 'a', ' ' ): case VLC_FOURCC( 'w', 'm', 'a', '2' ): tk->psz_name= "Windows Media Audio (v2) 7, 8 and 9 Series"; tk->i_tag = WAVE_FORMAT_WMA2; tk->b_audio_correction = VLC_TRUE; break; case VLC_FOURCC( 'w', 'm', 'a', 'p' ): tk->psz_name = "Windows Media Audio 9 Professional"; tk->i_tag = WAVE_FORMAT_WMAP; tk->b_audio_correction = VLC_TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -