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

📄 mp4.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* First update update global time */    p_sys->i_time = i_date * p_sys->i_timescale / 1000000;    p_sys->i_pcr  = i_date;    /* Now for each stream try to go to this time */    for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )    {        mp4_track_t *tk = &p_sys->track[i_track];        MP4_TrackSeek( p_demux, tk, i_date );    }    MP4_UpdateSeekpoint( p_demux );    return VLC_SUCCESS;}/***************************************************************************** * Control: *****************************************************************************/static int Control( demux_t *p_demux, int i_query, va_list args ){    demux_sys_t *p_sys = p_demux->p_sys;    double f, *pf;    int64_t i64, *pi64;    switch( i_query )    {        case DEMUX_GET_POSITION:            pf = (double*)va_arg( args, double * );            if( p_sys->i_duration > 0 )            {                *pf = (double)p_sys->i_time / (double)p_sys->i_duration;            }            else            {                *pf = 0.0;            }            return VLC_SUCCESS;        case DEMUX_SET_POSITION:            f = (double)va_arg( args, double );            if( p_sys->i_timescale > 0 )            {                i64 = (int64_t)( f * (double)1000000 *                                 (double)p_sys->i_duration /                                 (double)p_sys->i_timescale );                return Seek( p_demux, i64 );            }            else return VLC_SUCCESS;        case DEMUX_GET_TIME:            pi64 = (int64_t*)va_arg( args, int64_t * );            if( p_sys->i_timescale > 0 )            {                *pi64 = (mtime_t)1000000 *                        (mtime_t)p_sys->i_time /                        (mtime_t)p_sys->i_timescale;            }            else *pi64 = 0;            return VLC_SUCCESS;        case DEMUX_SET_TIME:            i64 = (int64_t)va_arg( args, int64_t );            return Seek( p_demux, i64 );        case DEMUX_GET_LENGTH:            pi64 = (int64_t*)va_arg( args, int64_t * );            if( p_sys->i_timescale > 0 )            {                *pi64 = (mtime_t)1000000 *                        (mtime_t)p_sys->i_duration /                        (mtime_t)p_sys->i_timescale;            }            else *pi64 = 0;            return VLC_SUCCESS;        case DEMUX_GET_FPS:            msg_Warn( p_demux, "DEMUX_GET_FPS unimplemented !!" );            return VLC_EGENERIC;        case DEMUX_GET_META:        {            vlc_meta_t *p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t*);            MP4_Box_t  *p_0xa9xxx;            MP4_Box_t  *p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta/meta/ilst" );            if( p_udta == NULL )            {                p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta" );                if( p_udta == NULL )                {                    return VLC_EGENERIC;                }            }            for( p_0xa9xxx = p_udta->p_first; p_0xa9xxx != NULL;                 p_0xa9xxx = p_0xa9xxx->p_next )            {                if( !p_0xa9xxx || !p_0xa9xxx->data.p_0xa9xxx )                    continue;                /* FIXME FIXME: should convert from whatever the character                 * encoding of MP4 meta data is to UTF-8. */#define SET(fct) do { char *psz_utf = strdup( p_0xa9xxx->data.p_0xa9xxx->psz_text ? p_0xa9xxx->data.p_0xa9xxx->psz_text : "" ); \    if( psz_utf ) { EnsureUTF8( psz_utf );  \                    fct( p_meta, psz_utf ); free( psz_utf ); } } while(0)                /* XXX Becarefull p_udta can have box that are not 0xa9xx */                switch( p_0xa9xxx->i_type )                {                case FOURCC_0xa9nam: /* Full name */                    SET( vlc_meta_SetTitle );                    break;                case FOURCC_0xa9aut:                    SET( vlc_meta_SetArtist );                    break;                case FOURCC_0xa9ART:                    SET( vlc_meta_SetArtist );                    break;                case FOURCC_0xa9cpy:                    SET( vlc_meta_SetCopyright );                    break;                case FOURCC_0xa9day: /* Creation Date */                    SET( vlc_meta_SetDate );                    break;                case FOURCC_0xa9des: /* Description */                    SET( vlc_meta_SetDescription );                    break;                case FOURCC_0xa9gen: /* Genre */                    SET( vlc_meta_SetGenre );                    break;                case FOURCC_0xa9alb: /* Album */                    SET( vlc_meta_SetAlbum );                    break;                case FOURCC_0xa9trk: /* Track */                    SET( vlc_meta_SetTracknum );                    break;                case FOURCC_0xa9cmt: /* Commment */                    SET( vlc_meta_SetDescription );                    break;                case FOURCC_0xa9url: /* URL */                    SET( vlc_meta_SetURL );                    break;                case FOURCC_0xa9enc: /* Encoded By */                    SET( vlc_meta_SetEncodedBy );                    break;                                    case FOURCC_0xa9swr:                case FOURCC_0xa9inf: /* Information */                case FOURCC_0xa9dir: /* Director */                case FOURCC_0xa9dis: /* Disclaimer */                case FOURCC_0xa9req: /* Requirements */                case FOURCC_0xa9fmt: /* Original Format */                case FOURCC_0xa9dsa: /* Display Source As */                case FOURCC_0xa9hst: /* Host Computer */                case FOURCC_0xa9prd: /* Producer */                case FOURCC_0xa9prf: /* Performers */                case FOURCC_0xa9ope: /* Original Performer */                case FOURCC_0xa9src: /* Providers Source Content */                case FOURCC_0xa9wrt: /* Writer */                case FOURCC_0xa9com: /* Composer */                case FOURCC_WLOC:    /* Window Location */                    /* TODO one day, but they aren't really meaningfull */                    break;#undef SET                default:                    break;                }            }            return VLC_SUCCESS;        }        case DEMUX_GET_TITLE_INFO:        {            input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );            int *pi_int    = (int*)va_arg( args, int* );            int *pi_title_offset = (int*)va_arg( args, int* );            int *pi_seekpoint_offset = (int*)va_arg( args, int* );            if( !p_sys->p_title )                return VLC_EGENERIC;            *pi_int = 1;            *ppp_title = malloc( sizeof( input_title_t**) );            (*ppp_title)[0] = vlc_input_title_Duplicate( p_sys->p_title );            *pi_title_offset = 0;            *pi_seekpoint_offset = 0;            return VLC_SUCCESS;        }        case DEMUX_SET_TITLE:        {            const int i_title = (int)va_arg( args, int );            if( !p_sys->p_title || i_title != 0 )                return VLC_EGENERIC;            return VLC_SUCCESS;        }        case DEMUX_SET_SEEKPOINT:        {            const int i_seekpoint = (int)va_arg( args, int );            if( !p_sys->p_title )                return VLC_EGENERIC;            return Seek( p_demux, p_sys->p_title->seekpoint[i_seekpoint]->i_time_offset );        }        case DEMUX_SET_NEXT_DEMUX_TIME:        case DEMUX_SET_GROUP:        case DEMUX_HAS_UNSUPPORTED_META:        case DEMUX_GET_ATTACHMENTS:            return VLC_EGENERIC;        default:            msg_Warn( p_demux, "control query %u unimplemented", i_query );            return VLC_EGENERIC;    }}/***************************************************************************** * Close: frees unused data *****************************************************************************/static void Close ( vlc_object_t * p_this ){    demux_t *  p_demux = (demux_t *)p_this;    demux_sys_t *p_sys = p_demux->p_sys;    unsigned int i_track;    msg_Dbg( p_demux, "freeing all memory" );    MP4_BoxFree( p_demux->s, p_sys->p_root );    for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )    {        MP4_TrackDestroy(  &p_sys->track[i_track] );    }    FREENULL( p_sys->track );    if( p_sys->p_title )        vlc_input_title_Delete( p_sys->p_title );    free( p_sys );}/**************************************************************************** * Local functions, specific to vlc ****************************************************************************//* Chapters */static void LoadChapterGpac( demux_t  *p_demux, MP4_Box_t *p_chpl ){    demux_sys_t *p_sys = p_demux->p_sys;    int i;    p_sys->p_title = vlc_input_title_New();    for( i = 0; i < p_chpl->data.p_chpl->i_chapter; i++ )    {        seekpoint_t *s = vlc_seekpoint_New();        s->psz_name = strdup( p_chpl->data.p_chpl->chapter[i].psz_name );        EnsureUTF8( s->psz_name );        s->i_time_offset = p_chpl->data.p_chpl->chapter[i].i_start / 10;        TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );    }}static void LoadChapterApple( demux_t  *p_demux, mp4_track_t *tk ){    demux_sys_t *p_sys = p_demux->p_sys;    for( tk->i_sample = 0; tk->i_sample < tk->i_sample_count; tk->i_sample++ )    {        const int64_t i_dts = MP4_TrackGetDTS( p_demux, tk );        const int64_t i_pts_delta = MP4_TrackGetPTSDelta( tk );        const unsigned int i_size = MP4_TrackSampleSize( tk );        if( i_size > 0 && !stream_Seek( p_demux->s, MP4_TrackGetPos( tk ) ) )        {            char p_buffer[256];            const int i_read = stream_Read( p_demux->s, p_buffer, __MIN( sizeof(p_buffer), i_size ) );            const int i_len = __MIN( GetWBE(p_buffer), i_read-2 );            if( i_len > 0 )            {                seekpoint_t *s = vlc_seekpoint_New();                s->psz_name = strndup( &p_buffer[2], i_len );                EnsureUTF8( s->psz_name );                s->i_time_offset = i_dts + __MAX( i_pts_delta, 0 );                if( !p_sys->p_title )                    p_sys->p_title = vlc_input_title_New();                TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );            }        }        if( tk->i_sample+1 >= tk->chunk[tk->i_chunk].i_sample_first +                              tk->chunk[tk->i_chunk].i_sample_count )            tk->i_chunk++;    }}static void LoadChapter( demux_t  *p_demux ){    demux_sys_t *p_sys = p_demux->p_sys;    MP4_Box_t *p_chpl;    if( ( p_chpl = MP4_BoxGet( p_sys->p_root, "/moov/udta/chpl" ) ) && p_chpl->data.p_chpl->i_chapter > 0 )    {        LoadChapterGpac( p_demux, p_chpl );    }    else if( p_sys->p_tref_chap )    {        MP4_Box_data_tref_generic_t *p_chap = p_sys->p_tref_chap->data.p_tref_generic;        unsigned int i, j;        /* Load the first subtitle track like quicktime */        for( i = 0; i < p_chap->i_entry_count; i++ )        {            for( j = 0; j < p_sys->i_tracks; j++ )            {                mp4_track_t *tk = &p_sys->track[j];                if( tk->b_ok && tk->i_track_ID == p_chap->i_track_ID[i] &&                    tk->fmt.i_cat == SPU_ES && tk->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) )                    break;            }            if( j < p_sys->i_tracks )            {                LoadChapterApple( p_demux, &p_sys->track[j] );                break;            }        }    }}/* now create basic chunk data, the rest will be filled by MP4_CreateSamplesIndex */static int TrackCreateChunksIndex( demux_t *p_demux,                                   mp4_track_t *p_demux_track ){    MP4_Box_t *p_co64; /* give offset for each chunk, same for stco and co64 */    MP4_Box_t *p_stsc;    unsigned int i_chunk;    unsigned int i_index, i_last;    if( ( !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "stco" ) )&&          !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "co64" ) ) )||        ( !(p_stsc = MP4_BoxGet( p_demux_track->p_stbl, "stsc" ) ) ))    {        return( VLC_EGENERIC );    }    p_demux_track->i_chunk_count = p_co64->data.p_co64->i_entry_count;    if( !p_demux_track->i_chunk_count )    {        msg_Warn( p_demux, "no chunk defined" );        return( VLC_EGENERIC );    }    p_demux_track->chunk = calloc( p_demux_track->i_chunk_count,                                   sizeof( mp4_chunk_t ) );    if( p_demux_track->chunk == NULL )    {        return VLC_ENOMEM;    }    /* first we read chunk offset */    for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )    {        mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];        ck->i_offset = p_co64->data.p_co64->i_chunk_offset[i_chunk];        ck->i_first_dts = 0;        ck->p_sample_count_dts = NULL;

⌨️ 快捷键说明

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