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

📄 mp4.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
        ck->p_sample_delta_dts = NULL;        ck->p_sample_count_pts = NULL;        ck->p_sample_offset_pts = NULL;    }    /* now we read index for SampleEntry( soun vide mp4a mp4v ...)        to be used for the sample XXX begin to 1        We construct it begining at the end */    i_last = p_demux_track->i_chunk_count; /* last chunk proceded */    i_index = p_stsc->data.p_stsc->i_entry_count;    if( !i_index )    {        msg_Warn( p_demux, "cannot read chunk table or table empty" );        return( VLC_EGENERIC );    }    while( i_index-- )    {        for( i_chunk = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;             i_chunk < i_last; i_chunk++ )        {            if( i_chunk >= p_demux_track->i_chunk_count )            {                msg_Warn( p_demux, "corrupted chunk table" );                return VLC_EGENERIC;            }            p_demux_track->chunk[i_chunk].i_sample_description_index =                    p_stsc->data.p_stsc->i_sample_description_index[i_index];            p_demux_track->chunk[i_chunk].i_sample_count =                    p_stsc->data.p_stsc->i_samples_per_chunk[i_index];        }        i_last = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;    }    p_demux_track->chunk[0].i_sample_first = 0;    for( i_chunk = 1; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )    {        p_demux_track->chunk[i_chunk].i_sample_first =            p_demux_track->chunk[i_chunk-1].i_sample_first +                p_demux_track->chunk[i_chunk-1].i_sample_count;    }    msg_Dbg( p_demux, "track[Id 0x%x] read %d chunk",             p_demux_track->i_track_ID, p_demux_track->i_chunk_count );    return VLC_SUCCESS;}static int TrackCreateSamplesIndex( demux_t *p_demux,                                    mp4_track_t *p_demux_track ){    MP4_Box_t *p_box;    MP4_Box_data_stsz_t *stsz;    MP4_Box_data_stts_t *stts;    /* TODO use also stss and stsh table for seeking */    /* FIXME use edit table */    int64_t i_sample;    int64_t i_chunk;    int64_t i_index;    int64_t i_index_sample_used;    int64_t i_last_dts;    /* Find stsz     *  Gives the sample size for each samples. There is also a stz2 table     *  (compressed form) that we need to implement TODO */    p_box = MP4_BoxGet( p_demux_track->p_stbl, "stsz" );    if( !p_box )    {        /* FIXME and stz2 */        msg_Warn( p_demux, "cannot find STSZ box" );        return VLC_EGENERIC;    }    stsz = p_box->data.p_stsz;    /* Find stts     *  Gives mapping between sample and decoding time     */    p_box = MP4_BoxGet( p_demux_track->p_stbl, "stts" );    if( !p_box )    {        msg_Warn( p_demux, "cannot find STTS box" );        return VLC_EGENERIC;    }    stts = p_box->data.p_stts;    /* Use stsz table to create a sample number -> sample size table */    p_demux_track->i_sample_count = stsz->i_sample_count;    if( stsz->i_sample_size )    {        /* 1: all sample have the same size, so no need to construct a table */        p_demux_track->i_sample_size = stsz->i_sample_size;        p_demux_track->p_sample_size = NULL;    }    else    {        /* 2: each sample can have a different size */        p_demux_track->i_sample_size = 0;        p_demux_track->p_sample_size =            calloc( p_demux_track->i_sample_count, sizeof( uint32_t ) );        if( p_demux_track->p_sample_size == NULL )            return VLC_ENOMEM;        for( i_sample = 0; i_sample < p_demux_track->i_sample_count; i_sample++ )        {            p_demux_track->p_sample_size[i_sample] =                    stsz->i_entry_size[i_sample];        }    }    /* Use stts table to create a sample number -> dts table.     * XXX: if we don't want to waste too much memory, we can't expand     *  the box! so each chunk will contain an "extract" of this table     *  for fast research (problem with raw stream where a sample is sometime     *  just channels*bits_per_sample/8 */    i_last_dts = 0;    i_index = 0; i_index_sample_used = 0;    for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )    {        mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];        int64_t i_entry, i_sample_count, i;        /* save last dts */        ck->i_first_dts = i_last_dts;        /* count how many entries are needed for this chunk         * for p_sample_delta_dts and p_sample_count_dts */        i_sample_count = ck->i_sample_count;        i_entry = 0;        while( i_sample_count > 0 )        {            i_sample_count -= stts->i_sample_count[i_index+i_entry];            /* don't count already used sample in this entry */            if( i_entry == 0 )                i_sample_count += i_index_sample_used;            i_entry++;        }        /* allocate them */        ck->p_sample_count_dts = calloc( i_entry, sizeof( uint32_t ) );        ck->p_sample_delta_dts = calloc( i_entry, sizeof( uint32_t ) );        if( !ck->p_sample_count_dts || !ck->p_sample_delta_dts )            return VLC_ENOMEM;        /* now copy */        i_sample_count = ck->i_sample_count;        for( i = 0; i < i_entry; i++ )        {            int64_t i_used;            int64_t i_rest;            i_rest = stts->i_sample_count[i_index] - i_index_sample_used;            i_used = __MIN( i_rest, i_sample_count );            i_index_sample_used += i_used;            i_sample_count -= i_used;            ck->p_sample_count_dts[i] = i_used;            ck->p_sample_delta_dts[i] = stts->i_sample_delta[i_index];            i_last_dts += i_used * ck->p_sample_delta_dts[i];            if( i_index_sample_used >= stts->i_sample_count[i_index] )            {                i_index++;                i_index_sample_used = 0;            }        }    }    /* Find ctts     *  Gives the delta between decoding time (dts) and composition table (pts)     */    p_box = MP4_BoxGet( p_demux_track->p_stbl, "ctts" );    if( p_box )    {        MP4_Box_data_ctts_t *ctts = p_box->data.p_ctts;        msg_Warn( p_demux, "CTTS table" );        /* Create pts-dts table per chunk */        i_index = 0; i_index_sample_used = 0;        for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )        {            mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];            int64_t i_entry, i_sample_count, i;            /* count how many entries are needed for this chunk             * for p_sample_delta_dts and p_sample_count_dts */            i_sample_count = ck->i_sample_count;            i_entry = 0;            while( i_sample_count > 0 )            {                i_sample_count -= ctts->i_sample_count[i_index+i_entry];                /* don't count already used sample in this entry */                if( i_entry == 0 )                    i_sample_count += i_index_sample_used;                i_entry++;            }            /* allocate them */            ck->p_sample_count_pts = calloc( i_entry, sizeof( uint32_t ) );            ck->p_sample_offset_pts = calloc( i_entry, sizeof( int32_t ) );            if( !ck->p_sample_count_pts || !ck->p_sample_offset_pts )                return VLC_ENOMEM;            /* now copy */            i_sample_count = ck->i_sample_count;            for( i = 0; i < i_entry; i++ )            {                int64_t i_used;                int64_t i_rest;                i_rest = ctts->i_sample_count[i_index] -                    i_index_sample_used;                i_used = __MIN( i_rest, i_sample_count );                i_index_sample_used += i_used;                i_sample_count -= i_used;                ck->p_sample_count_pts[i] = i_used;                ck->p_sample_offset_pts[i] = ctts->i_sample_offset[i_index];                if( i_index_sample_used >= ctts->i_sample_count[i_index] )                {                    i_index++;                    i_index_sample_used = 0;                }            }        }    }    msg_Dbg( p_demux, "track[Id 0x%x] read %d samples length:%"PRId64"s",             p_demux_track->i_track_ID, p_demux_track->i_sample_count,             i_last_dts / p_demux_track->i_timescale );    return VLC_SUCCESS;}/* * TrackCreateES: * Create ES and PES to init decoder if needed, for a track starting at i_chunk */static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,                          unsigned int i_chunk, es_out_id_t **pp_es ){    MP4_Box_t   *p_sample;    MP4_Box_t   *p_esds;    MP4_Box_t   *p_box;    if( pp_es )        *pp_es = NULL;    if( !p_track->chunk[i_chunk].i_sample_description_index )    {        msg_Warn( p_demux, "invalid SampleEntry index (track[Id 0x%x])",                  p_track->i_track_ID );        return VLC_EGENERIC;    }    p_sample = MP4_BoxGet(  p_track->p_stsd, "[%d]",                p_track->chunk[i_chunk].i_sample_description_index - 1 );    if( !p_sample ||        ( !p_sample->data.p_data && p_track->fmt.i_cat != SPU_ES ) )    {        msg_Warn( p_demux, "cannot find SampleEntry (track[Id 0x%x])",                  p_track->i_track_ID );        return VLC_EGENERIC;    }    p_track->p_sample = p_sample;    if( p_track->fmt.i_cat == AUDIO_ES && ( p_track->i_sample_size == 1 || p_track->i_sample_size == 2 ) )    {        MP4_Box_data_sample_soun_t *p_soun;        p_soun = p_sample->data.p_sample_soun;        if( p_soun->i_qt_version == 0 )        {            switch( p_sample->i_type )            {                case VLC_FOURCC( 'i', 'm', 'a', '4' ):                    p_soun->i_qt_version = 1;                    p_soun->i_sample_per_packet = 64;                    p_soun->i_bytes_per_packet  = 34;                    p_soun->i_bytes_per_frame   = 34 * p_soun->i_channelcount;                    p_soun->i_bytes_per_sample  = 2;                    break;                case VLC_FOURCC( 'M', 'A', 'C', '3' ):                    p_soun->i_qt_version = 1;                    p_soun->i_sample_per_packet = 6;                    p_soun->i_bytes_per_packet  = 2;                    p_soun->i_bytes_per_frame   = 2 * p_soun->i_channelcount;                    p_soun->i_bytes_per_sample  = 2;                    break;                case VLC_FOURCC( 'M', 'A', 'C', '6' ):                    p_soun->i_qt_version = 1;                    p_soun->i_sample_per_packet = 12;                    p_soun->i_bytes_per_packet  = 2;                    p_soun->i_bytes_per_frame   = 2 * p_soun->i_channelcount;                    p_soun->i_bytes_per_sample  = 2;                    break;                case VLC_FOURCC( 'a', 'l', 'a', 'w' ):                case VLC_FOURCC( 'u', 'l', 'a', 'w' ):                    p_soun->i_samplesize = 8;                    break;                case VLC_FOURCC( 'N', 'O', 'N', 'E' ):                case VLC_FOURCC( 'r', 'a', 'w', ' ' ):                case VLC_FOURCC( 't', 'w', 'o', 's' ):                case VLC_FOURCC( 's', 'o', 'w', 't' ):                    /* What would be the fun if you could trust the .mov */                    p_track->i_sample_size = ((p_soun->i_samplesize+7)/8) * p_soun->i_channelcount;                    break;                default:                    break;            }        }        else if( p_soun->i_qt_version == 1 && p_soun->i_sample_per_packet <= 0 )        {            p_soun->i_qt_version = 0;        }    }    /* It's a little ugly but .. there are special cases */    switch( p_sample->i_type )    {        case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):        case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):        {            MP4_Box_data_sample_soun_t *p_soun = p_sample->data.p_sample_soun;            p_track->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );            if( p_track->i_sample_size > 1 )                p_soun->i_qt_version = 0;            break;        }        case( VLC_FOURCC( 'r', 'a', 'w', ' ' ) ):        case( VLC_FOURCC( 'N', 'O', 'N', 'E' ) ):        {            MP4_Box_data_sample_soun_t *p_soun = p_sample->data.p_sample_soun;            if(p_soun && (p_soun->i_samplesize+7)/8 == 1 )                p_track->fmt.i_codec = VLC_FOURCC( 'u', '8', ' ', ' ' );            else                p_track->fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );            /* Buggy files workaround */            if( p_sample->data.p_sample_soun && (p_track->i_timescale !=                p_sample->data.p_sample_soun->i_sampleratehi) )            {                MP4_Box_data_sample_soun_t *p_soun =                    p_sample->data.p_sample_soun;                msg_Warn( p_demux, "i_timescale (%"PRIu64") != i_sampleratehi "                          "(%u), 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;

⌨️ 快捷键说明

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