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

📄 mp4.c

📁 VLC媒体播放程序
💻 C
📖 第 1 页 / 共 4 页
字号:
    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_input, "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;        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;        int i;        msg_Warn( p_input, "elst box found" );        for( i = 0; i < elst->i_entry_count; i++ )        {            msg_Dbg( p_input, "   - [%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 ?                        elst->i_media_time[i] * 1000 / p_track->i_timescale : -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 );    }    /* fxi i_timescale for AUDIO_ES with i_qt_version == 0 */    if( p_track->fmt.i_cat == AUDIO_ES ) //&& p_track->i_sample_size == 1 )    {        MP4_Box_t *p_sample;        p_sample = MP4_BoxGet(  p_track->p_stsd, "[0]" );        if( p_sample && p_sample->data.p_sample_soun)        {            MP4_Box_data_sample_soun_t *p_soun = p_sample->data.p_sample_soun;            if( p_soun->i_qt_version == 0 &&                p_track->i_timescale != p_soun->i_sampleratehi )            {                msg_Warn( p_input,                          "i_timescale ("I64Fu") != i_sampleratehi (%u) with "                          "qt_version == 0\n"                          "Making both equal. (report any problem)",                          p_track->i_timescale, p_soun->i_sampleratehi );                if( p_soun->i_sampleratehi )                    p_track->i_timescale = p_soun->i_sampleratehi;                else                    p_soun->i_sampleratehi = p_track->i_timescale;            }        }    }    /* Create chunk index table and sample index table */    if( TrackCreateChunksIndex( p_input,p_track  ) ||        TrackCreateSamplesIndex( p_input, p_track ) )    {        return; /* cannot create chunks index */    }    p_track->i_chunk  = 0;    p_track->i_sample = 0;    /* now create es */    if( TrackCreateES( p_input,                       p_track, p_track->i_chunk,                       &p_track->p_es ) )    {        msg_Err( p_input, "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( input_thread_t *p_input,                              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_Init( &p_track->fmt, UNKNOWN_ES, 0 );    for( i_chunk = 0; i_chunk < p_track->i_chunk_count; i_chunk++ )    {        if( p_track->chunk )        {           FREE(p_track->chunk[i_chunk].p_sample_count_dts);           FREE(p_track->chunk[i_chunk].p_sample_delta_dts );        }    }    FREE( p_track->chunk );    if( !p_track->i_sample_size )    {        FREE( p_track->p_sample_size );    }}static int  MP4_TrackSelect ( input_thread_t    *p_input,                              mp4_track_t  *p_track,                              mtime_t           i_start ){    if( !p_track->b_ok )    {        return VLC_EGENERIC;    }    if( p_track->b_selected )    {        msg_Warn( p_input,                  "track[Id 0x%x] already selected",                  p_track->i_track_ID );        return VLC_SUCCESS;    }    return MP4_TrackSeek( p_input, p_track, i_start );}static void MP4_TrackUnselect(input_thread_t    *p_input,                              mp4_track_t  *p_track ){    if( !p_track->b_ok )    {        return;    }    if( !p_track->b_selected )    {        msg_Warn( p_input,                  "track[Id 0x%x] already unselected",                  p_track->i_track_ID );        return;    }    if( p_track->p_es )    {        es_out_Control( p_input->p_es_out, ES_OUT_SET_ES_STATE, p_track->p_es, VLC_FALSE );    }    p_track->b_selected = VLC_FALSE;}static int  MP4_TrackSeek   ( input_thread_t    *p_input,                              mp4_track_t  *p_track,                              mtime_t           i_start ){    uint32_t i_chunk;    uint32_t i_sample;    if( !p_track->b_ok )    {        return( VLC_EGENERIC );    }    if( TrackTimeToSampleChunk( p_input,                                p_track, i_start,                                &i_chunk, &i_sample ) )    {        msg_Warn( p_input,                  "cannot select track[Id 0x%x]",                  p_track->i_track_ID );        return( VLC_EGENERIC );    }    p_track->b_selected = VLC_TRUE;    if( TrackGotoChunkSample( p_input, p_track, i_chunk, i_sample ) )    {        p_track->b_selected = VLC_FALSE;    }    return( p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC );}/* * 3 types: for audio *  */#define QT_V0_MAX_SAMPLES    1500static int  MP4_TrackSampleSize( mp4_track_t   *p_track ){    int i_size;    MP4_Box_data_sample_soun_t *p_soun;    if( p_track->i_sample_size == 0 )    {        /* most simple case */        return( p_track->p_sample_size[p_track->i_sample] );    }    if( p_track->fmt.i_cat != AUDIO_ES )    {        return( p_track->i_sample_size );    }    if( p_track->i_sample_size != 1 )    {        //msg_Warn( p_input, "SampleSize != 1" );        return( p_track->i_sample_size );    }    p_soun = p_track->p_sample->data.p_sample_soun;    if( p_soun->i_qt_version == 1 )    {        i_size = p_track->chunk[p_track->i_chunk].i_sample_count / p_soun->i_sample_per_packet * p_soun->i_bytes_per_frame;    }    else    {        /* FIXME */        int i_samples = p_track->chunk[p_track->i_chunk].i_sample_count -                ( p_track->i_sample - p_track->chunk[p_track->i_chunk].i_sample_first );        if( i_samples > QT_V0_MAX_SAMPLES )        {            i_samples = QT_V0_MAX_SAMPLES;        }        i_size = i_samples * p_soun->i_channelcount * p_soun->i_samplesize / 8;    }    //fprintf( stderr, "size=%d\n", i_size );    return( i_size );}static uint64_t MP4_TrackGetPos( mp4_track_t *p_track ){    unsigned int i_sample;    uint64_t i_pos;    i_pos = p_track->chunk[p_track->i_chunk].i_offset;    if( p_track->i_sample_size )    {        MP4_Box_data_sample_soun_t *p_soun = p_track->p_sample->data.p_sample_soun;        if( p_soun->i_qt_version == 0 )        {            i_pos += ( p_track->i_sample - p_track->chunk[p_track->i_chunk].i_sample_first ) *                        p_soun->i_channelcount * p_soun->i_samplesize / 8;        }        else        {            /* we read chunk by chunk */            i_pos += 0;        }    }    else    {        for( i_sample = p_track->chunk[p_track->i_chunk].i_sample_first;                i_sample < p_track->i_sample; i_sample++ )        {            i_pos += p_track->p_sample_size[i_sample];        }    }    return( i_pos );}static int  MP4_TrackNextSample( input_thread_t     *p_input,                                 mp4_track_t   *p_track ){    if( p_track->fmt.i_cat == AUDIO_ES &&        p_track->i_sample_size != 0 )    {        MP4_Box_data_sample_soun_t *p_soun;        p_soun = p_track->p_sample->data.p_sample_soun;        if( p_soun->i_qt_version == 1 )        {            /* chunk by chunk */            p_track->i_sample =                p_track->chunk[p_track->i_chunk].i_sample_first +                p_track->chunk[p_track->i_chunk].i_sample_count;        }        else        {            /* FIXME */            p_track->i_sample += QT_V0_MAX_SAMPLES;            if( p_track->i_sample > p_track->chunk[p_track->i_chunk].i_sample_first + p_track->chunk[p_track->i_chunk].i_sample_count )            {                p_track->i_sample =                    p_track->chunk[p_track->i_chunk].i_sample_first +                    p_track->chunk[p_track->i_chunk].i_sample_count;            }        }    }    else    {        p_track->i_sample++;    }    if( p_track->i_sample >= p_track->i_sample_count )    {        /* we have reach end of the track so free decoder stuff */        msg_Warn( p_input, "track[0x%x] will be disabled", p_track->i_track_ID );        MP4_TrackUnselect( p_input, p_track );        return VLC_EGENERIC;    }    /* Have we changed chunk ? */    if( p_track->i_sample >=            p_track->chunk[p_track->i_chunk].i_sample_first +            p_track->chunk[p_track->i_chunk].i_sample_count )    {        if( TrackGotoChunkSample( p_input,                                  p_track,                                  p_track->i_chunk + 1,                                  p_track->i_sample ) )        {            msg_Warn( p_input, "track[0x%x] will be disabled (cannot restart decoder)", p_track->i_track_ID );            MP4_TrackUnselect( p_input, p_track );            return VLC_EGENERIC;        }    }    /* Have we changed elst */    if( p_track->p_elst && p_track->p_elst->data.p_elst->i_entry_count > 0 )    {        demux_sys_t *p_sys = p_input->p_demux_data;        MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;        int64_t i_mvt = MP4_TrackGetPTS( p_input, p_track ) * p_sys->i_timescale / (int64_t)1000000;        if( p_track->i_elst < elst->i_entry_count &&            i_mvt >= p_track->i_elst_time + elst->i_segment_duration[p_track->i_elst] )        {            MP4_TrackSetELST( p_input, p_track, MP4_TrackGetPTS( p_input, p_track ) );        }    }    return VLC_SUCCESS;}static void MP4_TrackSetELST( input_thread_t *p_input, mp4_track_t *tk, int64_t i_time ){    demux_sys_t *p_sys = p_input->p_demux_data;    int         i_elst_last = tk->i_elst;    /* handle elst (find the correct one) */    tk->i_elst      = 0;    tk->i_elst_time = 0;    if( tk->p_elst && tk->p_elst->data.p_elst->i_entry_count > 0 )    {        MP4_Box_data_elst_t *elst = tk->p_elst->data.p_elst;        int64_t i_mvt= i_time * p_sys->i_timescale / (int64_t)1000000;        for( tk->i_elst = 0; tk->i_elst < elst->i_entry_count; tk->i_elst++ )        {            mtime_t i_dur = elst->i_segment_duration[tk->i_elst];            if( tk->i_elst_time <= i_mvt && i_mvt < tk->i_elst_time + i_dur )            {                break;            }            tk->i_elst_time += i_dur;        }        if( tk->i_elst >= elst->i_entry_count )        {            /* msg_Dbg( p_input, "invalid number of entry in elst" ); */            tk->i_elst = elst->i_entry_count - 1;            tk->i_elst_time -= elst->i_segment_duration[tk->i_elst];        }        if( elst->i_media_time[tk->i_elst] < 0 )        {            /* track offset */            tk->i_elst_time += elst->i_segment_duration[tk->i_elst];        }    }    if( i_elst_last != tk->i_elst )    {        msg_Warn( p_input, "elst old=%d new=%d", i_elst_last, tk->i_elst );    }}

⌨️ 快捷键说明

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