首页 > 代码库 > vlc的MP4的Demux函数分析

vlc的MP4的Demux函数分析

/* * 从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 );}

 

vlc的MP4的Demux函数分析