avi.c
来自「VLC媒体播放程序」· C语言 代码 · 共 2,041 行 · 第 1/5 页
C
2,041 行
{ avi_track_t *tk = p_sys->track[i]; avi_chunk_list_t *p_strl; avi_chunk_strh_t *p_strh; avi_chunk_strf_auds_t *p_auds; if( tk->i_cat != AUDIO_ES ) { continue; } if( tk->i_idxnb < 1 || tk->i_scale != 1 || tk->i_samplesize != 0 ) { continue; } p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i ); p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 ); p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 ); if( p_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM && (unsigned int)tk->i_rate == p_auds->p_wf->nSamplesPerSec ) { int64_t i_track_length = tk->p_index[tk->i_idxnb-1].i_length + tk->p_index[tk->i_idxnb-1].i_lengthtotal; mtime_t i_length = (mtime_t)p_avih->i_totalframes * (mtime_t)p_avih->i_microsecperframe; if( i_length == 0 ) { msg_Warn( p_input, "track[%d] cannot be fixed (BeOS MediaKit generated)", i ); continue; } tk->i_samplesize = 1; tk->i_rate = i_track_length * (int64_t)1000000/ i_length; msg_Warn( p_input, "track[%d] fixed with rate=%d scale=%d (BeOS MediaKit generated)", i, tk->i_rate, tk->i_scale ); } } if( p_sys->i_length ) { p_input->stream.i_mux_rate = stream_Size( p_input->s ) / 50 / p_sys->i_length; } if( p_sys->b_seekable ) { /* we have read all chunk so go back to movi */ stream_Seek( p_input->s, p_movi->i_chunk_pos ); } /* Skip movi header */ stream_Read( p_input->s, NULL, 12 ); p_sys->i_movi_begin = p_movi->i_chunk_pos; return VLC_SUCCESS;error: if( p_sys->meta ) { vlc_meta_Delete( p_sys->meta ); } AVI_ChunkFreeRoot( p_input->s, &p_sys->ck_root ); free( p_sys ); return VLC_EGENERIC;}/***************************************************************************** * Close: frees unused data *****************************************************************************/static void Close ( vlc_object_t * p_this ){ input_thread_t * p_input = (input_thread_t *)p_this; unsigned int i; demux_sys_t *p_sys = p_input->p_demux_data ; for( i = 0; i < p_sys->i_track; i++ ) { if( p_sys->track[i] ) { FREE( p_sys->track[i]->p_index ); free( p_sys->track[i] ); } } FREE( p_sys->track ); AVI_ChunkFreeRoot( p_input->s, &p_sys->ck_root ); vlc_meta_Delete( p_sys->meta ); free( p_sys );}/***************************************************************************** * Demux_Seekable: reads and demuxes data packets for stream seekable ***************************************************************************** * AVIDemux: reads and demuxes data packets ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/typedef struct{ vlc_bool_t b_ok; int i_toread; off_t i_posf; /* where we will read : if i_idxposb == 0 : begining of chunk (+8 to acces data) else : point on data directly */} avi_track_toread_t;static int Demux_Seekable( input_thread_t *p_input ){ demux_sys_t *p_sys = p_input->p_demux_data; unsigned int i_track_count = 0; unsigned int i_track; vlc_bool_t b_stream; /* cannot be more than 100 stream (dcXX or wbXX) */ avi_track_toread_t toread[100]; /* detect new selected/unselected streams */ for( i_track = 0; i_track < p_sys->i_track; i_track++ ) { avi_track_t *tk = p_sys->track[i_track]; vlc_bool_t b; es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b ); if( b && !tk->b_activated ) { if( p_sys->b_seekable) { AVI_TrackSeek( p_input, i_track, p_sys->i_time ); } tk->b_activated = VLC_TRUE; } else if( !b && tk->b_activated ) { tk->b_activated = VLC_FALSE; } if( b ) { i_track_count++; } } if( i_track_count <= 0 ) { msg_Warn( p_input, "no track selected, exiting..." ); return( 0 ); } /* wait for the good time */ p_sys->i_pcr = p_sys->i_time * 9 / 100; input_ClockManageRef( p_input, p_input->stream.p_selected_program, p_sys->i_pcr ); p_sys->i_time += 25*1000; /* read 25ms */ /* init toread */ for( i_track = 0; i_track < p_sys->i_track; i_track++ ) { avi_track_t *tk = p_sys->track[i_track]; mtime_t i_dpts; toread[i_track].b_ok = tk->b_activated; if( tk->i_idxposc < tk->i_idxnb ) { toread[i_track].i_posf = tk->p_index[tk->i_idxposc].i_pos; if( tk->i_idxposb > 0 ) { toread[i_track].i_posf += 8 + tk->i_idxposb; } } else { toread[i_track].i_posf = -1; } i_dpts = p_sys->i_time - AVI_GetPTS( tk ); if( tk->i_samplesize ) { toread[i_track].i_toread = AVI_PTSToByte( tk, __ABS( i_dpts ) ); } else { toread[i_track].i_toread = AVI_PTSToChunk( tk, __ABS( i_dpts ) ); } if( i_dpts < 0 ) { toread[i_track].i_toread *= -1; } } b_stream = VLC_FALSE; for( ;; ) { avi_track_t *tk; vlc_bool_t b_done; block_t *p_frame; off_t i_pos; unsigned int i; size_t i_size; /* search for first chunk to be read */ for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_sys->i_track; i++ ) { if( !toread[i].b_ok || AVI_GetDPTS( p_sys->track[i], toread[i].i_toread ) <= -25 * 1000 ) { continue; } if( toread[i].i_toread > 0 ) { b_done = VLC_FALSE; /* not yet finished */ } if( toread[i].i_posf > 0 ) { if( i_pos == -1 || i_pos > toread[i_track].i_posf ) { i_track = i; i_pos = toread[i].i_posf; } } } if( b_done ) { return( 1 ); } if( i_pos == -1 ) { /* no valid index, we will parse directly the stream * in case we fail we will disable all finished stream */ if( p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 ) { stream_Seek( p_input->s, p_sys->i_movi_lastchunk_pos ); if( AVI_PacketNext( p_input ) ) { return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 ); } } else { stream_Seek( p_input->s, p_sys->i_movi_begin + 12 ); } for( ;; ) { avi_packet_t avi_pk; if( AVI_PacketGetHeader( p_input, &avi_pk ) ) { msg_Warn( p_input, "cannot get packet header, track disabled" ); return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 ); } if( avi_pk.i_stream >= p_sys->i_track || ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) ) { if( AVI_PacketNext( p_input ) ) { msg_Warn( p_input, "cannot skip packet, track disabled" ); return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 ); } continue; } else { /* add this chunk to the index */ AVIIndexEntry_t index; index.i_id = avi_pk.i_fourcc; index.i_flags = AVI_GetKeyFlag(p_sys->track[avi_pk.i_stream]->i_codec, avi_pk.i_peek); index.i_pos = avi_pk.i_pos; index.i_length = avi_pk.i_size; AVI_IndexAddEntry( p_sys, avi_pk.i_stream, &index ); i_track = avi_pk.i_stream; tk = p_sys->track[i_track]; /* do we will read this data ? */ if( AVI_GetDPTS( tk, toread[i_track].i_toread ) > -25*1000 ) { break; } else { if( AVI_PacketNext( p_input ) ) { msg_Warn( p_input, "cannot skip packet, track disabled" ); return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 ); } } } } } else { stream_Seek( p_input->s, i_pos ); } /* Set the track to use */ tk = p_sys->track[i_track]; /* read thoses data */ if( tk->i_samplesize ) { unsigned int i_toread; if( ( i_toread = toread[i_track].i_toread ) <= 0 ) { if( tk->i_samplesize > 1 ) { i_toread = tk->i_samplesize; } else { i_toread = __MAX( AVI_PTSToByte( tk, 20 * 1000 ), 100 ); } } i_size = __MIN( tk->p_index[tk->i_idxposc].i_length - tk->i_idxposb, i_toread ); } else { i_size = tk->p_index[tk->i_idxposc].i_length; } if( tk->i_idxposb == 0 ) { i_size += 8; /* need to read and skip header */ } if( ( p_frame = stream_Block( p_input->s, __EVEN( i_size ) ) )==NULL ) { msg_Warn( p_input, "failled reading data" ); tk->b_activated = VLC_FALSE; toread[i_track].b_ok = VLC_FALSE; continue; } if( i_size % 2 ) /* read was padded on word boundary */ { p_frame->i_buffer--; } /* skip header */ if( tk->i_idxposb == 0 ) { p_frame->p_buffer += 8; p_frame->i_buffer -= 8; } p_frame->i_pts = AVI_GetPTS( tk ); /* read data */ if( tk->i_samplesize ) { if( tk->i_idxposb == 0 ) { i_size -= 8; } toread[i_track].i_toread -= i_size; tk->i_idxposb += i_size; if( tk->i_idxposb >= tk->p_index[tk->i_idxposc].i_length ) { tk->i_idxposb = 0; tk->i_idxposc++; } } else { int i_length = tk->p_index[tk->i_idxposc].i_length; tk->i_idxposc++; if( tk->i_cat == AUDIO_ES ) { tk->i_blockno += tk->i_blocksize > 0 ? ( i_length + tk->i_blocksize - 1 ) / tk->i_blocksize : 1; } toread[i_track].i_toread--; } if( tk->i_idxposc < tk->i_idxnb) { toread[i_track].i_posf = tk->p_index[tk->i_idxposc].i_pos; if( tk->i_idxposb > 0 ) { toread[i_track].i_posf += 8 + tk->i_idxposb; } } else { toread[i_track].i_posf = -1; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?