avi.c
来自「VLC媒体播放程序」· C语言 代码 · 共 2,041 行 · 第 1/5 页
C
2,041 行
b_stream = VLC_TRUE; /* at least one read succeed */ p_frame->i_pts = input_ClockGetTS( p_input, p_input->stream.p_selected_program, p_frame->i_pts * 9/100); if( tk->i_cat != VIDEO_ES ) p_frame->i_dts = p_frame->i_pts; else { p_frame->i_dts = p_frame->i_pts; p_frame->i_pts = 0; } //p_pes->i_rate = p_input->stream.control.i_rate; es_out_Send( p_input->p_es_out, tk->p_es, p_frame ); }}/***************************************************************************** * Demux_UnSeekable: reads and demuxes data packets for unseekable file ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/static int Demux_UnSeekable( input_thread_t *p_input ){ demux_sys_t *p_sys = p_input->p_demux_data; avi_track_t *p_stream_master = NULL; vlc_bool_t b_audio; unsigned int i_stream; unsigned int i_packet; /* Check if we need to send the audio data to decoder */ b_audio = !p_input->stream.control.b_mute; input_ClockManageRef( p_input, p_input->stream.p_selected_program, p_sys->i_pcr ); /* *** find master stream for data packet skipping algo *** */ /* *** -> first video, if any, or first audio ES *** */ for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ ) { avi_track_t *tk = p_sys->track[i_stream]; vlc_bool_t b; es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b ); if( b && tk->i_cat == VIDEO_ES ) { p_stream_master = tk; } else if( b ) { p_stream_master = tk; } } if( !p_stream_master ) { msg_Warn( p_input, "no more stream selected" ); return( 0 ); } p_sys->i_pcr = AVI_GetPTS( p_stream_master ) * 9 / 100; for( i_packet = 0; i_packet < 10; i_packet++) {#define p_stream p_sys->track[avi_pk.i_stream] avi_packet_t avi_pk; if( AVI_PacketGetHeader( p_input, &avi_pk ) ) { return( 0 ); } if( avi_pk.i_stream >= p_sys->i_track || ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) ) { /* we haven't found an audio or video packet: * - we have seek, found first next packet * - others packets could be found, skip them */ switch( avi_pk.i_fourcc ) { case AVIFOURCC_JUNK: case AVIFOURCC_LIST: case AVIFOURCC_RIFF: return( !AVI_PacketNext( p_input ) ? 1 : 0 ); case AVIFOURCC_idx1: if( p_sys->b_odml ) { return( !AVI_PacketNext( p_input ) ? 1 : 0 ); } return( 0 ); /* eof */ default: msg_Warn( p_input, "seems to have lost position, resync" ); if( AVI_PacketSearch( p_input ) ) { msg_Err( p_input, "resync failed" ); return( -1 ); } } } else { /* do will send this packet to decoder ? */ if( !b_audio && avi_pk.i_cat == AUDIO_ES ) { if( AVI_PacketNext( p_input ) ) { return( 0 ); } } else { /* it's a selected stream, check for time */ if( __ABS( AVI_GetPTS( p_stream ) - AVI_GetPTS( p_stream_master ) )< 600*1000 ) { /* load it and send to decoder */ block_t *p_frame; if( AVI_PacketRead( p_input, &avi_pk, &p_frame ) || p_frame == NULL ) { return( -1 ); } p_frame->i_pts = input_ClockGetTS( p_input, p_input->stream.p_selected_program, AVI_GetPTS( p_stream ) * 9/100); if( avi_pk.i_cat != VIDEO_ES ) p_frame->i_dts = p_frame->i_pts; else { p_frame->i_dts = p_frame->i_pts; p_frame->i_pts = 0; } //p_pes->i_rate = p_input->stream.control.i_rate; es_out_Send( p_input->p_es_out, p_stream->p_es, p_frame ); } else { if( AVI_PacketNext( p_input ) ) { return( 0 ); } } } /* *** update stream time position *** */ if( p_stream->i_samplesize ) { p_stream->i_idxposb += avi_pk.i_size; } else { if( p_stream->i_cat == AUDIO_ES ) { p_stream->i_blockno += p_stream->i_blocksize > 0 ? ( avi_pk.i_size + p_stream->i_blocksize - 1 ) / p_stream->i_blocksize : 1; } p_stream->i_idxposc++; } }#undef p_stream } return( 1 );}/***************************************************************************** * Seek: goto to i_date or i_percent ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/static int Seek( input_thread_t *p_input, mtime_t i_date, int i_percent ){ demux_sys_t *p_sys = p_input->p_demux_data; unsigned int i_stream; msg_Dbg( p_input, "seek requested: "I64Fd" secondes %d%%", i_date / 1000000, i_percent ); if( p_sys->b_seekable ) { if( !p_sys->i_length ) { avi_track_t *p_stream; int64_t i_pos; /* use i_percent to create a true i_date */ msg_Warn( p_input, "mmh, seeking without index at %d%%" " work only for interleaved file", i_percent ); if( i_percent >= 100 ) { msg_Warn( p_input, "cannot seek so far !" ); return( -1 ); } i_percent = __MAX( i_percent, 0 ); /* try to find chunk that is at i_percent or the file */ i_pos = __MAX( i_percent * stream_Size( p_input->s ) / 100, p_sys->i_movi_begin ); /* search first selected stream */ for( i_stream = 0, p_stream = NULL; i_stream < p_sys->i_track; i_stream++ ) { p_stream = p_sys->track[i_stream]; if( p_stream->b_activated ) { break; } } if( !p_stream || !p_stream->b_activated ) { msg_Warn( p_input, "cannot find any selected stream" ); return( -1 ); } /* be sure that the index exist */ if( AVI_StreamChunkSet( p_input, i_stream, 0 ) ) { msg_Warn( p_input, "cannot seek" ); return( -1 ); } while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos + p_stream->p_index[p_stream->i_idxposc].i_length + 8 ) { /* search after i_idxposc */ if( AVI_StreamChunkSet( p_input, i_stream, p_stream->i_idxposc + 1 ) ) { msg_Warn( p_input, "cannot seek" ); return( -1 ); } } i_date = AVI_GetPTS( p_stream ); /* TODO better support for i_samplesize != 0 */ msg_Dbg( p_input, "estimate date "I64Fd, i_date ); }#define p_stream p_sys->track[i_stream] p_sys->i_time = 0; /* seek for chunk based streams */ for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ ) { if( p_stream->b_activated && !p_stream->i_samplesize )/* if( p_stream->b_activated ) */ { AVI_TrackSeek( p_input, i_stream, i_date ); p_sys->i_time = __MAX( AVI_GetPTS( p_stream ), p_sys->i_time ); } }#if 1 if( p_sys->i_time ) { i_date = p_sys->i_time; } /* seek for bytes based streams */ for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ ) { if( p_stream->b_activated && p_stream->i_samplesize ) { AVI_TrackSeek( p_input, i_stream, i_date );/* p_sys->i_time = __MAX( AVI_GetPTS( p_stream ), p_sys->i_time );*/ } } msg_Dbg( p_input, "seek: "I64Fd" seconds", p_sys->i_time /1000000 ); /* set true movie time */#endif if( !p_sys->i_time ) { p_sys->i_time = i_date; }#undef p_stream return( 1 ); } else { msg_Err( p_input, "shouldn't yet be executed" ); return( -1 ); }}/***************************************************************************** * Control: ***************************************************************************** * *****************************************************************************/static double ControlGetPosition( input_thread_t *p_input ){ demux_sys_t *p_sys = p_input->p_demux_data; if( p_sys->i_length > 0 ) { return (double)p_sys->i_time / (double)( p_sys->i_length * (mtime_t)1000000 ); } else if( stream_Size( p_input->s ) > 0 ) { unsigned int i; int64_t i_tmp; int64_t i64 = 0; /* search the more advanced selected es */ for( i = 0; i < p_sys->i_track; i++ ) { avi_track_t *tk = p_sys->track[i]; if( tk->b_activated && tk->i_idxposc < tk->i_idxnb ) { i_tmp = tk->p_index[tk->i_idxposc].i_pos + tk->p_index[tk->i_idxposc].i_length + 8; if( i_tmp > i64 ) { i64 = i_tmp; } } } return (double)i64 / (double)stream_Size( p_input->s ); } return 0.0;}static int Control( input_thread_t *p_input, int i_query, va_list args ){ demux_sys_t *p_sys = p_input->p_demux_data; int i; double f, *pf; int64_t i64, *pi64; vlc_meta_t **pp_meta; switch( i_query ) { case DEMUX_GET_POSITION: pf = (double*)va_arg( args, double * ); *pf = ControlGetPosition( p_input ); return VLC_SUCCESS; case DEMUX_SET_POSITION: if( p_sys->b_seekable ) { f = (double)va_arg( args, double ); i64 = (mtime_t)(1000000.0 * p_sys->i_length * f ); return Seek( p_input, i64, (int)(f * 100) ) < 0 ? VLC_EGENERIC : VLC_SUCCESS; } return demux_vaControlDefault( p_input, i_query, args ); case DEMUX_GET_TIME: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = p_sys->i_time; return VLC_SUCCESS; case DEMUX_SET_TIME: { int i_percent = 0; i64 = (int64_t)va_arg( args, int64_t ); if( p_sys->i_length > 0 ) { i_percent = 100 * i64 / (p_sys->i_length*1000000); } else if( p_sys->i_time > 0 ) { i_percent = (int)( 100.0 * ControlGetPosition( p_input ) * (double)i64 / (double)p_sys->i_time ); } return Seek( p_input, i64, i_percent ); } case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = p_sys->i_length * (mtime_t)1000000; return VLC_SUCCESS; case DEMUX_GET_FPS: pf = (double*)va_arg( args, double * ); *pf = 0.0; for( i = 0; i < (int)p_sys->i_track; i++ ) { avi_track_t *tk = p_sys->track[i]; if( tk->i_cat == VIDEO_ES && tk->i_scale > 0) { *pf = (float)tk->i_rate / (float)tk->i_scale; break; } } return VLC_SUCCESS; case DEMUX_GET_META: pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); *pp_meta = vlc_meta_Duplicate( p_sys->meta ); return VLC_SUCCESS; default: return demux_vaControlDefault( p_input, i_query, args ); } return VLC_EGENERIC;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?