📄 avi.c
字号:
} else { stream_Seek( p_demux->s, p_sys->i_movi_begin + 12 ); } for( ;; ) { avi_packet_t avi_pk; if( AVI_PacketGetHeader( p_demux, &avi_pk ) ) { msg_Warn( p_demux, "cannot get packet header, track disabled" ); return( AVI_TrackStopFinishedStreams( p_demux ) ? 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_demux ) ) { msg_Warn( p_demux, "cannot skip packet, track disabled" ); return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 ); } /* Prevents from eating all the CPU with broken files. * This value should be low enough so that it doesn't * affect the reading speed too much. */ if( !(++i_loop_count % 1024) ) { if( p_demux->b_die ) return -1; msleep( 10000 ); if( !(i_loop_count % (1024 * 10)) ) msg_Warn( p_demux, "don't seem to find any data..." ); } continue; } else { /* add this chunk to the index */ avi_entry_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_demux ) ) { msg_Warn( p_demux, "cannot skip packet, track disabled" ); return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 ); } } } } } else { stream_Seek( p_demux->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 = AVI_PTSToByte( tk, 20 * 1000 ); i_toread = __MAX( i_toread, 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_demux->s, __EVEN( i_size ) ) )==NULL ) { msg_Warn( p_demux, "failed 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 ) + 1; if( tk->p_index[tk->i_idxposc].i_flags&AVIIF_KEYFRAME ) { p_frame->i_flags = BLOCK_FLAG_TYPE_I; } else { p_frame->i_flags = BLOCK_FLAG_TYPE_PB; } /* 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; } b_stream = VLC_TRUE; /* at least one read succeed */ 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_demux->stream.control.i_rate; es_out_Send( p_demux->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( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; avi_track_t *p_stream_master = NULL; unsigned int i_stream; unsigned int i_packet; es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time + 1 ); /* *** 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_demux->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_demux, "no more stream selected" ); return( 0 ); } p_sys->i_time = AVI_GetPTS( p_stream_master ); 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_demux, &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_demux ) ? 1 : 0 ); case AVIFOURCC_idx1: if( p_sys->b_odml ) { return( !AVI_PacketNext( p_demux ) ? 1 : 0 ); } return( 0 ); /* eof */ default: msg_Warn( p_demux, "seems to have lost position, resync" ); if( AVI_PacketSearch( p_demux ) ) { msg_Err( p_demux, "resync failed" ); return( -1 ); } } } else { /* 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_demux, &avi_pk, &p_frame ) || p_frame == NULL ) { return( -1 ); } p_frame->i_pts = AVI_GetPTS( p_stream ) + 1; 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_demux->stream.control.i_rate; es_out_Send( p_demux->out, p_stream->p_es, p_frame ); } else { if( AVI_PacketNext( p_demux ) ) { 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 *****************************************************************************/static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent ){ demux_sys_t *p_sys = p_demux->p_sys; unsigned int i_stream; msg_Dbg( p_demux, "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_demux, "seeking without index at %d%%" " only works for interleaved files", i_percent ); if( i_percent >= 100 ) { msg_Warn( p_demux, "cannot seek so far !" ); return VLC_EGENERIC; } 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_demux->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_demux, "cannot find any selected stream" ); return VLC_EGENERIC; } /* be sure that the index exist */ if( AVI_StreamChunkSet( p_demux, i_stream, 0 ) ) { msg_Warn( p_demux, "cannot seek" ); return VLC_EGENERIC; } 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_demux, i_stream, p_stream->i_idxposc + 1 ) ) { msg_Warn( p_demux, "cannot seek" ); return VLC_EGENERIC; } } i_date = AVI_GetPTS( p_stream ); /* TODO better support for i_samplesize != 0 */ msg_Dbg( p_demux, "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_demux, i_stream, i_date );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -