⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp4.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        {            i_start += elst->i_media_time[p_track->i_elst];        }        msg_Dbg( p_demux, "elst (%d) gives "I64Fd"ms (movie)-> "I64Fd                 "ms (track)", p_track->i_elst,                 i_mvt * 1000 / p_sys->i_timescale,                 i_start * 1000 / p_track->i_timescale );    }    else    {        /* convert absolute time to in timescale unit */        i_start = i_start * p_track->i_timescale / (int64_t)1000000;    }    /* we start from sample 0/chunk 0, hope it won't take too much time */    /* *** find good chunk *** */    for( i_chunk = 0; ; i_chunk++ )    {        if( i_chunk + 1 >= p_track->i_chunk_count )        {            /* at the end and can't check if i_start in this chunk,               it will be check while searching i_sample */            i_chunk = p_track->i_chunk_count - 1;            break;        }        if( (uint64_t)i_start >= p_track->chunk[i_chunk].i_first_dts &&            (uint64_t)i_start <  p_track->chunk[i_chunk + 1].i_first_dts )        {            break;        }    }    /* *** find sample in the chunk *** */    i_sample = p_track->chunk[i_chunk].i_sample_first;    i_dts    = p_track->chunk[i_chunk].i_first_dts;    for( i_index = 0; i_sample < p_track->chunk[i_chunk].i_sample_count; )    {        if( i_dts +            p_track->chunk[i_chunk].p_sample_count_dts[i_index] *            p_track->chunk[i_chunk].p_sample_delta_dts[i_index] < (uint64_t)i_start )        {            i_dts    +=                p_track->chunk[i_chunk].p_sample_count_dts[i_index] *                p_track->chunk[i_chunk].p_sample_delta_dts[i_index];            i_sample += p_track->chunk[i_chunk].p_sample_count_dts[i_index];            i_index++;        }        else        {            if( p_track->chunk[i_chunk].p_sample_delta_dts[i_index] <= 0 )            {                break;            }            i_sample += ( i_start - i_dts ) /                p_track->chunk[i_chunk].p_sample_delta_dts[i_index];            break;        }    }    if( i_sample >= p_track->i_sample_count )    {        msg_Warn( p_demux, "track[Id 0x%x] will be disabled "                  "(seeking too far) chunk=%d sample=%d",                  p_track->i_track_ID, i_chunk, i_sample );        return( VLC_EGENERIC );    }    /* *** Try to find nearest sync points *** */    if( ( p_stss = MP4_BoxGet( p_track->p_stbl, "stss" ) ) )    {        unsigned int i_index;        msg_Dbg( p_demux,                    "track[Id 0x%x] using Sync Sample Box (stss)",                    p_track->i_track_ID );        for( i_index = 0; i_index < p_stss->data.p_stss->i_entry_count; i_index++ )        {            if( p_stss->data.p_stss->i_sample_number[i_index] >= i_sample )            {                if( i_index > 0 )                {                    msg_Dbg( p_demux, "stts gives %d --> %d (sample number)",                            i_sample,                            p_stss->data.p_stss->i_sample_number[i_index-1] );                    i_sample = p_stss->data.p_stss->i_sample_number[i_index-1];                    /* new i_sample is less than old so i_chunk can only decreased */                    while( i_chunk > 0 &&                            i_sample < p_track->chunk[i_chunk].i_sample_first )                    {                        i_chunk--;                    }                }                else                {                    msg_Dbg( p_demux, "stts gives %d --> %d (sample number)",                            i_sample,                            p_stss->data.p_stss->i_sample_number[i_index] );                    i_sample = p_stss->data.p_stss->i_sample_number[i_index];                    /* new i_sample is more than old so i_chunk can only increased */                    while( i_chunk < p_track->i_chunk_count - 1 &&                           i_sample >= p_track->chunk[i_chunk].i_sample_first +                             p_track->chunk[i_chunk].i_sample_count )                    {                        i_chunk++;                    }                }                break;            }        }    }    else    {        msg_Dbg( p_demux, "track[Id 0x%x] does not provide Sync "                 "Sample Box (stss)", p_track->i_track_ID );    }    *pi_chunk  = i_chunk;    *pi_sample = i_sample;    return VLC_SUCCESS;}static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,                                 unsigned int i_chunk, unsigned int i_sample ){    vlc_bool_t b_reselect = VLC_FALSE;    /* now see if actual es is ok */    if( p_track->i_chunk < 0 ||        p_track->i_chunk >= p_track->i_chunk_count - 1 ||        p_track->chunk[p_track->i_chunk].i_sample_description_index !=            p_track->chunk[i_chunk].i_sample_description_index )    {        msg_Warn( p_demux, "recreate ES for track[Id 0x%x]",                  p_track->i_track_ID );        es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,                        p_track->p_es, &b_reselect );        es_out_Del( p_demux->out, p_track->p_es );        p_track->p_es = NULL;        if( TrackCreateES( p_demux, p_track, i_chunk, &p_track->p_es ) )        {            msg_Err( p_demux, "cannot create es for track[Id 0x%x]",                     p_track->i_track_ID );            p_track->b_ok       = VLC_FALSE;            p_track->b_selected = VLC_FALSE;            return VLC_EGENERIC;        }    }    /* select again the new decoder */    if( b_reselect )    {        es_out_Control( p_demux->out, ES_OUT_SET_ES, p_track->p_es );    }    p_track->i_chunk    = i_chunk;    p_track->i_sample   = i_sample;    return p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC;}/**************************************************************************** * MP4_TrackCreate: **************************************************************************** * Parse track information and create all needed data to run a track * If it succeed b_ok is set to 1 else to 0 ****************************************************************************/static void MP4_TrackCreate( demux_t *p_demux, mp4_track_t *p_track,                             MP4_Box_t *p_box_trak ){    demux_sys_t *p_sys = p_demux->p_sys;    MP4_Box_t *p_tkhd = MP4_BoxGet( p_box_trak, "tkhd" );    MP4_Box_t *p_tref = MP4_BoxGet( p_box_trak, "tref" );    MP4_Box_t *p_elst;    MP4_Box_t *p_mdhd;    MP4_Box_t *p_udta;    MP4_Box_t *p_hdlr;    MP4_Box_t *p_vmhd;    MP4_Box_t *p_smhd;    MP4_Box_t *p_drms;    unsigned int i;    char language[4];    /* hint track unsupported */    /* set default value (-> track unusable) */    p_track->b_ok       = VLC_FALSE;    p_track->b_enable   = VLC_FALSE;    p_track->b_selected = VLC_FALSE;    es_format_Init( &p_track->fmt, UNKNOWN_ES, 0 );    if( !p_tkhd )    {        return;    }    /* do we launch this track by default ? */    p_track->b_enable =        ( ( p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED ) != 0 );    p_track->i_track_ID = p_tkhd->data.p_tkhd->i_track_ID;    p_track->i_width = p_tkhd->data.p_tkhd->i_width / 65536;    p_track->i_height = p_tkhd->data.p_tkhd->i_height / 65536;    if( p_tref )    {/*        msg_Warn( p_demux, "unhandled box: tref --> FIXME" ); */    }    p_mdhd = MP4_BoxGet( p_box_trak, "mdia/mdhd" );    p_hdlr = MP4_BoxGet( p_box_trak, "mdia/hdlr" );    if( ( !p_mdhd )||( !p_hdlr ) )    {        return;    }    p_track->i_timescale = p_mdhd->data.p_mdhd->i_timescale;    for( i = 0; i < 3; i++ )    {        language[i] = p_mdhd->data.p_mdhd->i_language[i];    }    language[3] = '\0';    switch( p_hdlr->data.p_hdlr->i_handler_type )    {        case( FOURCC_soun ):            if( !( p_smhd = MP4_BoxGet( p_box_trak, "mdia/minf/smhd" ) ) )            {                return;            }            p_track->fmt.i_cat = AUDIO_ES;            break;        case( FOURCC_vide ):            if( !( p_vmhd = MP4_BoxGet( p_box_trak, "mdia/minf/vmhd" ) ) )            {                return;            }            p_track->fmt.i_cat = VIDEO_ES;            break;        case( FOURCC_text ):        case( FOURCC_subp ):        case( FOURCC_tx3g ):            p_track->fmt.i_cat = SPU_ES;            break;        default:            return;    }    p_track->i_elst = 0;    p_track->i_elst_time = 0;    if( ( p_track->p_elst = p_elst = MP4_BoxGet( p_box_trak, "edts/elst" ) ) )    {        MP4_Box_data_elst_t *elst = p_elst->data.p_elst;        unsigned int i;        msg_Warn( p_demux, "elst box found" );        for( i = 0; i < elst->i_entry_count; i++ )        {            msg_Dbg( p_demux, "   - [%d] duration="I64Fd"ms media time="I64Fd                     "ms) rate=%d.%d", i,                     elst->i_segment_duration[i] * 1000 / p_sys->i_timescale,                     elst->i_media_time[i] >= 0 ?                     (int64_t)(elst->i_media_time[i] * 1000 / p_track->i_timescale) :                     I64C(-1),                     elst->i_media_rate_integer[i],                     elst->i_media_rate_fraction[i] );        }    }/*  TODO    add support for:    p_dinf = MP4_BoxGet( p_minf, "dinf" );*/    if( !( p_track->p_stbl = MP4_BoxGet( p_box_trak,"mdia/minf/stbl" ) ) ||        !( p_track->p_stsd = MP4_BoxGet( p_box_trak,"mdia/minf/stbl/stsd") ) )    {        return;    }    p_drms = MP4_BoxGet( p_track->p_stsd, "drms" );    p_track->b_drms = p_drms != NULL;    p_track->p_drms = p_track->b_drms ?        p_drms->data.p_sample_soun->p_drms : NULL;    /* Set language */    if( strcmp( language, "```" ) && strcmp( language, "und" ) )    {        p_track->fmt.psz_language = strdup( language );    }    p_udta = MP4_BoxGet( p_box_trak, "udta" );    if( p_udta )    {        MP4_Box_t *p_0xa9xxx;        for( p_0xa9xxx = p_udta->p_first; p_0xa9xxx != NULL;                 p_0xa9xxx = p_0xa9xxx->p_next )        {            switch( p_0xa9xxx->i_type )            {                case FOURCC_0xa9nam:                    p_track->fmt.psz_description =                        strdup( p_0xa9xxx->data.p_0xa9xxx->psz_text );                    break;            }        }    }    /* Create chunk index table and sample index table */    if( TrackCreateChunksIndex( p_demux,p_track  ) ||        TrackCreateSamplesIndex( p_demux, p_track ) )    {        return; /* cannot create chunks index */    }    p_track->i_chunk  = 0;    p_track->i_sample = 0;    /* now create es */    if( TrackCreateES( p_demux,                       p_track, p_track->i_chunk,                       &p_track->p_es ) )    {        msg_Err( p_demux, "cannot create es for track[Id 0x%x]",                 p_track->i_track_ID );        return;    }#if 0    {        int i;        for( i = 0; i < p_track->i_chunk_count; i++ )        {            fprintf( stderr, "%-5d sample_count=%d pts=%lld\n",                     i, p_track->chunk[i].i_sample_count,                     p_track->chunk[i].i_first_dts );        }    }#endif    p_track->b_ok = VLC_TRUE;}/**************************************************************************** * MP4_TrackDestroy: **************************************************************************** * Destroy a track created by MP4_TrackCreate. ****************************************************************************/static void MP4_TrackDestroy( demux_t *p_demux, mp4_track_t *p_track ){    unsigned int i_chunk;    p_track->b_ok = VLC_FALSE;    p_track->b_enable   = VLC_FALSE;    p_track->b_selected = VLC_FALSE;    es_format_Clean( &p_track->fmt );    for( i_chunk = 0; i_chunk < p_track->i_chunk_count; i_chunk++ )    {        if( p_track->chunk )        {           FREE(p_track

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -