/* * 从stream中,分离出一包包数据包,并投递给解码器。 * */ /***************************************************************************** * Demux: read packet and send them to decoders ***************************************************************************** * TODO check for newly selected track (ie audio upt to now ) *****************************************************************************/ static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; unsigned int i_track; unsigned int i_track_selected; /* check for newly selected/unselected track */ //检查每一条媒体轨道,找出可用的媒体轨道。 for( i_track = 0, i_track_selected = 0; i_track < p_sys->i_tracks; i_track++ ) { mp4_track_t *tk = &p_sys->track[i_track]; //媒体轨道德上下文。 bool b; if( !tk->b_ok || tk->b_chapter || ( tk->b_selected && tk->i_sample >= tk->i_sample_count ) ) //貌似这条轨道不太正常。 { continue; } es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b ); //看看解码器是否正常。 if( tk->b_selected && !b ) { MP4_TrackUnselect( p_demux, tk ); } else if( !tk->b_selected && b) { MP4_TrackSelect( p_demux, tk, MP4_GetMoviePTS( p_sys ) ); } if( tk->b_selected ) { i_track_selected++; } } if( i_track_selected <= 0 ) { p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 ); if( p_sys->i_timescale > 0 ) { int64_t i_length = CLOCK_FREQ * (mtime_t)p_sys->moovfragment.i_duration / (mtime_t)p_sys->i_timescale; if( MP4_GetMoviePTS( p_sys ) >= i_length ) return 0; return 1; } msg_Warn( p_demux, "no track selected, exiting..." ); return 0; } /* */ MP4_UpdateSeekpoint( p_demux ); /* first wait for the good time to read a packet */ p_sys->i_pcr = MP4_GetMoviePTS( p_sys ); bool b_data_sent = false; /* Find next track matching contiguous data */ mp4_track_t *tk = NULL; uint64_t i_candidate_pos = UINT64_MAX; mtime_t i_candidate_dts = INT64_MAX; for( i_track = 0; i_track < p_sys->i_tracks; i_track++ ) { mp4_track_t *tk_tmp = &p_sys->track[i_track]; if( !tk_tmp->b_ok || tk_tmp->b_chapter || !tk_tmp->b_selected || tk_tmp->i_sample >= tk_tmp->i_sample_count ) continue; if ( p_sys->b_seekmode ) { mtime_t i_dts = MP4_TrackGetDTS( p_demux, tk_tmp ); if ( i_dts <= i_candidate_dts ) { tk = tk_tmp; i_candidate_dts = i_dts; i_candidate_pos = MP4_TrackGetPos( tk_tmp ); } } else { /* Try to avoid seeking on non fastseekable. Will fail with non interleaved content */ uint64_t i_pos = MP4_TrackGetPos( tk_tmp ); if ( i_pos <= i_candidate_pos ) { i_candidate_pos = i_pos; tk = tk_tmp; } } } if ( !tk ) { msg_Dbg( p_demux, "Could not select track by data position" ); goto end; } else if ( p_sys->b_seekmode ) { if( stream_Seek( p_demux->s, i_candidate_pos ) ) { msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)", tk->i_track_ID ); MP4_TrackUnselect( p_demux, tk ); goto end; } } #if 0 msg_Dbg( p_demux, "tk(%i)=%"PRId64" mv=%"PRId64" pos=%"PRIu64, i_track, MP4_TrackGetDTS( p_demux, tk ), MP4_GetMoviePTS( p_sys ), i_candidate_pos ); #endif uint32_t i_nb_samples = 0; uint32_t i_samplessize = MP4_TrackGetReadSize( tk, &i_nb_samples ); if( i_samplessize > 0 ) { block_t *p_block; int64_t i_delta; uint64_t i_current_pos; /* go,go go ! */ if ( !MP4_stream_Tell( p_demux->s, &i_current_pos ) ) goto end; if( i_current_pos != i_candidate_pos ) { if( stream_Seek( p_demux->s, i_candidate_pos ) ) { msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)", tk->i_track_ID ); MP4_TrackUnselect( p_demux, tk ); goto end; } } /* now read pes */ if( !(p_block = stream_Block( p_demux->s, i_samplessize )) ) { msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)", tk->i_track_ID ); MP4_TrackUnselect( p_demux, tk ); goto end; } else if( tk->fmt.i_cat == SPU_ES ) { if ( tk->fmt.i_codec != VLC_CODEC_TX3G && tk->fmt.i_codec != VLC_CODEC_SPU ) p_block->i_buffer = 0; } /* dts */ p_block->i_dts = VLC_TS_0 + MP4_TrackGetDTS( p_demux, tk ); /* pts */ i_delta = MP4_TrackGetPTSDelta( p_demux, tk ); if( i_delta != -1 ) p_block->i_pts = p_block->i_dts + i_delta; else if( tk->fmt.i_cat != VIDEO_ES ) p_block->i_pts = p_block->i_dts; else p_block->i_pts = VLC_TS_INVALID; if ( !b_data_sent ) { es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_pcr ); b_data_sent = true; } es_out_Send( p_demux->out, tk->p_es, p_block ); } /* Next sample */ if ( i_nb_samples ) /* sample size could be 0, need to go fwd. see return */ MP4_TrackNextSample( p_demux, tk, i_nb_samples ); end: if ( b_data_sent ) { p_sys->i_pcr = INT64_MAX; for( i_track = 0; i_track < p_sys->i_tracks; i_track++ ) { mp4_track_t *tk = &p_sys->track[i_track]; if ( !tk->b_ok || !tk->b_selected || (tk->fmt.i_cat != AUDIO_ES && tk->fmt.i_cat != VIDEO_ES) ) continue; mtime_t i_dts = MP4_TrackGetDTS( p_demux, tk ); p_sys->i_pcr = __MIN( i_dts, p_sys->i_pcr ); if ( !p_sys->b_seekmode && i_dts > p_sys->i_pcr + 2*CLOCK_FREQ ) { msg_Dbg( p_demux, "that media doesn‘t look interleaved, will need to seek"); p_sys->b_seekmode = true; } p_sys->i_time = p_sys->i_pcr * p_sys->i_timescale / CLOCK_FREQ; } } return b_data_sent || ( i_samplessize == 0 && i_nb_samples ); }
时间: 2024-12-07 07:32:32