📄 asf.c
字号:
{0x33000890, 0xE5B1, 0x11CF, {0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB}};static const guid_t asf_object_metadata_guid ={0xC5F8CBEA, 0x5BAF, 0x4877, {0x84, 0x67, 0xAA, 0x8C, 0x44, 0xFA, 0x4C, 0xCA}};/**************************************************************************** * Misc ****************************************************************************/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 );}static block_t *asf_header_create( sout_mux_t *p_mux, vlc_bool_t b_broadcast ){ sout_mux_sys_t *p_sys = p_mux->p_sys; asf_track_t *tk; mtime_t i_duration = 0; int i_size, i_header_ext_size, i; int i_ci_size, i_cm_size = 0, i_cd_size = 0; block_t *out; bo_t bo; msg_Dbg( p_mux, "Asf muxer creating header" ); if( p_sys->i_dts_first > 0 ) { i_duration = p_sys->i_dts_last - p_sys->i_dts_first; if( i_duration < 0 ) i_duration = 0; } /* calculate header size */ i_size = 30 + 104; i_ci_size = 44; for( i = 0; i < p_sys->i_track; i++ ) { i_size += 78 + p_sys->track[i].i_extra; i_ci_size += 8 + 2 * strlen( p_sys->track[i].psz_name ); 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; /* Error correction data field */ if( p_sys->track[i].b_audio_correction ) i_size += 8; } /* size of the content description object */ 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 ); } /* 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; } } i_header_ext_size = i_cm_size ? i_cm_size + 46 : 0; i_size += i_ci_size + i_cd_size + i_header_ext_size ; if( p_sys->b_asf_http ) { out = block_New( p_mux, i_size + 50 + 12 ); bo_init( &bo, out->p_buffer, i_size + 50 + 12 ); asf_chunk_add( &bo, 0x4824, i_size + 50, 0xc00, p_sys->i_seq++ ); } else { out = block_New( p_mux, i_size + 50 ); bo_init( &bo, out->p_buffer, i_size + 50 ); } /* header object */ bo_add_guid ( &bo, &asf_object_header_guid ); bo_addle_u64( &bo, i_size ); bo_addle_u32( &bo, 2 + p_sys->i_track + (i_cd_size ? 1 : 0) + (i_cm_size ? 1 : 0) ); 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 ); bo_addle_u64( &bo, i_size + 50 + p_sys->i_packet_count * p_sys->i_packet_size ); /* file size */ bo_addle_u64( &bo, 0 ); /* creation date */ bo_addle_u64( &bo, b_broadcast ? 0xffffffffLL : p_sys->i_packet_count ); bo_addle_u64( &bo, i_duration * 10 ); /* play duration (100ns) */ bo_addle_u64( &bo, i_duration * 10 ); /* send duration (100ns) */ bo_addle_u64( &bo, p_sys->i_preroll_time ); /* preroll duration (ms) */ bo_addle_u32( &bo, b_broadcast ? 0x01 : 0x02 /* seekable */ ); /* flags */ bo_addle_u32( &bo, p_sys->i_packet_size ); /* packet size min */ bo_addle_u32( &bo, p_sys->i_packet_size ); /* packet size max */ bo_addle_u32( &bo, p_sys->i_bitrate ); /* maxbitrate */ /* header extention */ if( i_header_ext_size ) { bo_add_guid ( &bo, &asf_object_header_extention_guid ); 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 ); } /* metadata object (part of header extension) */ if( i_cm_size ) { int64_t i_num, i_den; int i_dst_num, i_dst_den; for( i = 0; i < p_sys->i_track; i++ ) if( p_sys->track[i].i_cat == VIDEO_ES ) break; 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; vlc_reduce( &i_dst_num, &i_dst_den, i_num, i_den, 0 ); msg_Dbg( p_mux, "pixel aspect-ratio: %i/%i", i_dst_num, i_dst_den ); 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 */ } /* 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 ); } /* stream properties */ for( i = 0; i < p_sys->i_track; i++ ) { tk = &p_sys->track[i]; bo_add_guid ( &bo, &asf_object_stream_properties_guid ); bo_addle_u64( &bo, 78 + tk->i_extra + (tk->b_audio_correction ? 8:0) ); if( tk->i_cat == AUDIO_ES ) { bo_add_guid( &bo, &asf_object_stream_type_audio ); if( tk->b_audio_correction ) bo_add_guid( &bo, &asf_guid_audio_conceal_spread ); else bo_add_guid( &bo, &asf_guid_audio_conceal_none ); } 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 ); /* correction data length */ bo_addle_u32( &bo, tk->b_audio_correction ? 8 : 0 ); bo_addle_u16( &bo, tk->i_id ); /* stream number */ bo_addle_u32( &bo, 0 ); bo_add_mem ( &bo, tk->p_extra, tk->i_extra ); /* Error correction data field */ if( tk->b_audio_correction ) { 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 */ } } /* Codec Infos */ bo_add_guid ( &bo, &asf_object_codec_list_guid ); bo_addle_u64( &bo, i_ci_size ); bo_add_guid ( &bo, &asf_object_codec_list_reserved_guid ); bo_addle_u32( &bo, p_sys->i_track ); for( i = 0; i < p_sys->i_track; i++ ) { tk = &p_sys->track[i]; 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 */ ); 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 ); } } /* 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;}/**************************************************************************** * ****************************************************************************/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;}static block_t *asf_packet_create( sout_mux_t *p_mux, asf_track_t *tk, block_t *data ){ sout_mux_sys_t *p_sys = p_mux->p_sys; int i_data = data->i_buffer; int i_pos = 0; uint8_t *p_data= data->p_buffer; block_t *first = NULL, **last = &first; int i_preheader = p_sys->b_asf_http ? 12 : 0; while( i_pos < i_data ) { bo_t bo; int i_payload; if( p_sys->pk == NULL ) { p_sys->pk = block_New( p_mux, p_sys->i_packet_size + i_preheader ); /* reserve 14 bytes for the packet header */ p_sys->i_pk_used = 14 + i_preheader; 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], p_sys->i_packet_size - p_sys->i_pk_used ); /* add payload (header size = 17) */ i_payload = __MIN( i_data - i_pos, p_sys->i_packet_size - p_sys->i_pk_used - 17 ); 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; } 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 ); 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 ); bo_addle_u32( &bo, (data->i_dts - p_sys->i_dts_first) / 1000 + p_sys->i_preroll_time ); 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++; if( p_sys->i_pk_used + 17 >= p_sys->i_packet_size ) { /* Not enough data for another payload, flush the packet */ *last = asf_packet_flush( p_mux ); last = &(*last)->p_next; } } tk->i_sequence++; block_Release( data ); return first;}static block_t *asf_stream_end_create( sout_mux_t *p_mux ){ sout_mux_sys_t *p_sys = p_mux->p_sys; block_t *out = NULL; bo_t bo; if( p_sys->b_asf_http ) { out = block_New( p_mux, 12 ); bo_init( &bo, out->p_buffer, 12 ); asf_chunk_add( &bo, 0x4524, 0, 0x00, p_sys->i_seq++ ); } 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 ); } return out;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -