📄 asf.c
字号:
if( i_payload_data_length < 0 || i_skip + i_payload_data_length > i_packet_size_left ) { break; }#if 0 msg_Dbg( p_demux, "payload(%d/%d) stream_number:%d media_object_number:%d media_object_offset:%d replicated_data_length:%d payload_data_length %d", i_payload + 1, i_payload_count, i_stream_number, i_media_object_number, i_media_object_offset, i_replicated_data_length, i_payload_data_length );#endif if( ( tk = p_sys->track[i_stream_number] ) == NULL ) { msg_Warn( p_demux, "undeclared stream[Id 0x%x]", i_stream_number ); i_skip += i_payload_data_length; continue; // over payload } if( !tk->p_es ) { i_skip += i_payload_data_length; continue; } for( i_payload_data_pos = 0; i_payload_data_pos < i_payload_data_length && i_packet_size_left > 0; i_payload_data_pos += i_sub_payload_data_length ) { block_t *p_frag; int i_read; // read sub payload length if( i_replicated_data_length == 1 ) { i_sub_payload_data_length = p_peek[i_skip]; i_skip++; i_payload_data_pos++; } else { i_sub_payload_data_length = i_payload_data_length; } /* FIXME I don't use i_media_object_number, sould I ? */ if( tk->p_frame && i_media_object_offset == 0 ) { /* send complete packet to decoder */ block_t *p_gather = block_ChainGather( tk->p_frame ); es_out_Send( p_demux->out, tk->p_es, p_gather ); tk->p_frame = NULL; } i_read = i_sub_payload_data_length + i_skip; if( ( p_frag = stream_Block( p_demux->s, i_read ) ) == NULL ) { msg_Warn( p_demux, "cannot read data" ); return 0; } i_packet_size_left -= i_read; p_frag->p_buffer += i_skip; p_frag->i_buffer -= i_skip; if( tk->p_frame == NULL ) { tk->i_time = ( (mtime_t)i_pts + i_payload * (mtime_t)i_pts_delta ); p_frag->i_pts = tk->i_time; if( tk->i_cat != VIDEO_ES ) p_frag->i_dts = p_frag->i_pts; else { p_frag->i_dts = p_frag->i_pts; p_frag->i_pts = 0; } } block_ChainAppend( &tk->p_frame, p_frag ); i_skip = 0; if( i_packet_size_left > 0 ) { if( stream_Peek( p_demux->s, &p_peek, i_packet_size_left ) < i_packet_size_left ) { msg_Warn( p_demux, "cannot peek, EOF ?" ); return 0; } } } } if( i_packet_size_left > 0 ) { if( stream_Read( p_demux->s, NULL, i_packet_size_left ) < i_packet_size_left ) { msg_Warn( p_demux, "cannot skip data, EOF ?" ); return 0; } } return 1;loop_error_recovery: msg_Warn( p_demux, "unsupported packet header" ); if( p_sys->p_fp->i_min_data_packet_size != p_sys->p_fp->i_max_data_packet_size ) { msg_Err( p_demux, "unsupported packet header, fatal error" ); return -1; } stream_Read( p_demux->s, NULL, i_data_packet_min ); return 1;}/***************************************************************************** * *****************************************************************************/static int DemuxInit( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; vlc_bool_t b_seekable; int i; unsigned int i_stream; asf_object_content_description_t *p_cd; /* init context */ p_sys->i_time = -1; p_sys->i_length = 0; p_sys->i_bitrate = 0; p_sys->p_root = NULL; p_sys->p_fp = NULL; p_sys->i_track = 0; for( i = 0; i < 128; i++ ) { p_sys->track[i] = NULL; } p_sys->i_data_begin = -1; p_sys->i_data_end = -1; p_sys->meta = NULL; /* Now load all object ( except raw data ) */ stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b_seekable ); if( (p_sys->p_root = ASF_ReadObjectRoot( p_demux->s, b_seekable )) == NULL ) { msg_Warn( p_demux, "ASF plugin discarded (not a valid file)" ); return VLC_EGENERIC; } p_sys->p_fp = p_sys->p_root->p_fp; if( p_sys->p_fp->i_min_data_packet_size != p_sys->p_fp->i_max_data_packet_size ) { msg_Warn( p_demux, "ASF plugin discarded (invalid file_properties object)" ); goto error; } p_sys->i_track = ASF_CountObject( p_sys->p_root->p_hdr, &asf_object_stream_properties_guid ); if( p_sys->i_track <= 0 ) { msg_Warn( p_demux, "ASF plugin discarded (cannot find any stream!)" ); goto error; } msg_Dbg( p_demux, "found %d streams", p_sys->i_track ); for( i_stream = 0; i_stream < p_sys->i_track; i_stream ++ ) { asf_track_t *tk; asf_object_stream_properties_t *p_sp; vlc_bool_t b_access_selected; p_sp = ASF_FindObject( p_sys->p_root->p_hdr, &asf_object_stream_properties_guid, i_stream ); tk = p_sys->track[p_sp->i_stream_number] = malloc( sizeof( asf_track_t ) ); memset( tk, 0, sizeof( asf_track_t ) ); tk->i_time = -1; tk->p_sp = p_sp; tk->p_es = NULL; tk->p_frame = NULL; /* Check (in case of mms) if this track is selected (ie will receive data) */ if( !stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, ACCESS_GET_PRIVATE_ID_STATE, p_sp->i_stream_number, &b_access_selected ) && !b_access_selected ) { tk->i_cat = UNKNOWN_ES; msg_Dbg( p_demux, "ignoring not selected stream(ID:%d) (by access)", p_sp->i_stream_number ); continue; } if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_audio ) && p_sp->i_type_specific_data_length >= sizeof( WAVEFORMATEX ) - 2 ) { es_format_t fmt; uint8_t *p_data = p_sp->p_type_specific_data; int i_format; es_format_Init( &fmt, AUDIO_ES, 0 ); i_format = GetWLE( &p_data[0] ); wf_tag_to_fourcc( i_format, &fmt.i_codec, NULL ); fmt.audio.i_channels = GetWLE( &p_data[2] ); fmt.audio.i_rate = GetDWLE( &p_data[4] ); fmt.i_bitrate = GetDWLE( &p_data[8] ) * 8; fmt.audio.i_blockalign = GetWLE( &p_data[12] ); fmt.audio.i_bitspersample = GetWLE( &p_data[14] ); if( p_sp->i_type_specific_data_length > sizeof( WAVEFORMATEX ) && i_format != WAVE_FORMAT_MPEGLAYER3 && i_format != WAVE_FORMAT_MPEG ) { fmt.i_extra = __MIN( GetWLE( &p_data[16] ), p_sp->i_type_specific_data_length - sizeof( WAVEFORMATEX ) ); fmt.p_extra = malloc( fmt.i_extra ); memcpy( fmt.p_extra, &p_data[sizeof( WAVEFORMATEX )], fmt.i_extra ); } tk->i_cat = AUDIO_ES; tk->p_es = es_out_Add( p_demux->out, &fmt ); es_format_Clean( &fmt ); msg_Dbg( p_demux, "added new audio stream(codec:0x%x,ID:%d)", GetWLE( p_data ), p_sp->i_stream_number ); } else if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_video ) && p_sp->i_type_specific_data_length >= 11 + sizeof( BITMAPINFOHEADER ) ) { es_format_t fmt; uint8_t *p_data = &p_sp->p_type_specific_data[11]; es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( p_data[16], p_data[17], p_data[18], p_data[19] ) ); fmt.video.i_width = GetDWLE( p_data + 4 ); fmt.video.i_height= GetDWLE( p_data + 8 ); if( p_sp->i_type_specific_data_length > 11 + sizeof( BITMAPINFOHEADER ) ) { fmt.i_extra = __MIN( GetDWLE( p_data ), p_sp->i_type_specific_data_length - 11 - sizeof( BITMAPINFOHEADER ) ); fmt.p_extra = malloc( fmt.i_extra ); memcpy( fmt.p_extra, &p_data[sizeof( BITMAPINFOHEADER )], fmt.i_extra ); } /* Look for an aspect ratio */ if( p_sys->p_root->p_metadata ) { asf_object_metadata_t *p_meta = p_sys->p_root->p_metadata; int i, i_aspect_x = 0, i_aspect_y = 0; for( i = 0; i < p_meta->i_record_entries_count; i++ ) { if( !strcmp( p_meta->record[i].psz_name, "AspectRatioX" ) ) { if( (!i_aspect_x && !p_meta->record[i].i_stream) || p_meta->record[i].i_stream == p_sp->i_stream_number ) i_aspect_x = p_meta->record[i].i_val; } if( !strcmp( p_meta->record[i].psz_name, "AspectRatioY" ) ) { if( (!i_aspect_y && !p_meta->record[i].i_stream) || p_meta->record[i].i_stream == p_sp->i_stream_number ) i_aspect_y = p_meta->record[i].i_val; } } if( i_aspect_x && i_aspect_y ) { fmt.video.i_aspect = i_aspect_x * (int64_t)fmt.video.i_width * VOUT_ASPECT_FACTOR / fmt.video.i_height / i_aspect_y; } } tk->i_cat = VIDEO_ES; tk->p_es = es_out_Add( p_demux->out, &fmt ); es_format_Clean( &fmt ); msg_Dbg( p_demux, "added new video stream(ID:%d)", p_sp->i_stream_number ); } else { tk->i_cat = UNKNOWN_ES; msg_Dbg( p_demux, "ignoring unknown stream(ID:%d)", p_sp->i_stream_number ); } } p_sys->i_data_begin = p_sys->p_root->p_data->i_object_pos + 50; if( p_sys->p_root->p_data->i_object_size != 0 ) { /* local file */ p_sys->i_data_end = p_sys->p_root->p_data->i_object_pos + p_sys->p_root->p_data->i_object_size; } else { /* live/broacast */ p_sys->i_data_end = -1; } /* go to first packet */ stream_Seek( p_demux->s, p_sys->i_data_begin ); /* try to calculate movie time */ if( p_sys->p_fp->i_data_packets_count > 0 ) { int64_t i_count; int64_t i_size = stream_Size( p_demux->s ); if( p_sys->i_data_end > 0 && i_size > p_sys->i_data_end ) { i_size = p_sys->i_data_end; } /* real number of packets */ i_count = ( i_size - p_sys->i_data_begin ) / p_sys->p_fp->i_min_data_packet_size; /* calculate the time duration in micro-s */ p_sys->i_length = (mtime_t)p_sys->p_fp->i_play_duration / 10 * (mtime_t)i_count / (mtime_t)p_sys->p_fp->i_data_packets_count; if( p_sys->i_length > 0 ) { p_sys->i_bitrate = 8 * i_size * (int64_t)1000000 / p_sys->i_length; } } /* Create meta information */ p_sys->meta = vlc_meta_New(); if( ( p_cd = ASF_FindObject( p_sys->p_root->p_hdr, &asf_object_content_description_guid, 0 ) ) ) { if( p_cd->psz_title && *p_cd->psz_title ) { vlc_meta_Add( p_sys->meta, VLC_META_TITLE, p_cd->psz_title ); } if( p_cd->psz_author && *p_cd->psz_author ) { vlc_meta_Add( p_sys->meta, VLC_META_AUTHOR, p_cd->psz_author ); } if( p_cd->psz_copyright && *p_cd->psz_copyright ) { vlc_meta_Add( p_sys->meta, VLC_META_COPYRIGHT, p_cd->psz_copyright ); } if( p_cd->psz_description && *p_cd->psz_description ) { vlc_meta_Add( p_sys->meta, VLC_META_DESCRIPTION, p_cd->psz_description ); } if( p_cd->psz_rating && *p_cd->psz_rating ) { vlc_meta_Add( p_sys->meta, VLC_META_RATING, p_cd->psz_rating ); } } for( i_stream = 0, i = 0; i < 128; i++ ) { asf_object_codec_list_t *p_cl = ASF_FindObject( p_sys->p_root->p_hdr, &asf_object_codec_list_guid, 0 ); if( p_sys->track[i] ) { vlc_meta_t *tk = vlc_meta_New(); TAB_APPEND( p_sys->meta->i_track, p_sys->meta->track, tk ); if( p_cl && i_stream < p_cl->i_codec_entries_count ) { if( p_cl->codec[i_stream].psz_name && *p_cl->codec[i_stream].psz_name ) { vlc_meta_Add( tk, VLC_META_CODEC_NAME, p_cl->codec[i_stream].psz_name ); } if( p_cl->codec[i_stream].psz_description && *p_cl->codec[i_stream].psz_description ) { vlc_meta_Add( tk, VLC_META_CODEC_DESCRIPTION, p_cl->codec[i_stream].psz_description ); } } i_stream++; } } es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); return VLC_SUCCESS;error: ASF_FreeObjectRoot( p_demux->s, p_sys->p_root ); return VLC_EGENERIC;}/***************************************************************************** * *****************************************************************************/static void DemuxEnd( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; int i; if( p_sys->p_root ) { ASF_FreeObjectRoot( p_demux->s, p_sys->p_root ); p_sys->p_root = NULL; } if( p_sys->meta ) { vlc_meta_Delete( p_sys->meta ); p_sys->meta = NULL; } for( i = 0; i < 128; i++ ) { asf_track_t *tk = p_sys->track[i]; if( tk ) { if( tk->p_frame ) { block_ChainRelease( tk->p_frame ); } if( tk->p_es ) { es_out_Del( p_demux->out, tk->p_es ); } free( tk ); } p_sys->track[i] = 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -