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

📄 mp4.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************** * mp4.c : MP4 file input module for vlc ***************************************************************************** * Copyright (C) 2001-2004 the VideoLAN team * $Id$ * Authors: Laurent Aimar <fenrir@via.ecp.fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_demux.h>#include <vlc_md5.h>#include <vlc_charset.h>#include <vlc_iso_lang.h>#include <vlc_meta.h>#include <vlc_input.h>#include "libmp4.h"#include "drms.h"#ifdef UNDER_CE#define uint64_t int64_t#endif/***************************************************************************** * Module descriptor *****************************************************************************/static int  Open ( vlc_object_t * );static void Close( vlc_object_t * );vlc_module_begin();    set_category( CAT_INPUT );    set_subcategory( SUBCAT_INPUT_DEMUX );    set_description( N_("MP4 stream demuxer") );    set_capability( "demux", 242 );    set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Local prototypes *****************************************************************************/static int   Demux   ( demux_t * );static int   DemuxRef( demux_t *p_demux ){ (void)p_demux; return 0;}static int   Seek    ( demux_t *, mtime_t );static int   Control ( demux_t *, int, va_list );/* Contain all information about a chunk */typedef struct{    uint64_t     i_offset; /* absolute position of this chunk in the file */    uint32_t     i_sample_description_index; /* index for SampleEntry to use */    uint32_t     i_sample_count; /* how many samples in this chunk */    uint32_t     i_sample_first; /* index of the first sample in this chunk */    /* now provide way to calculate pts, dts, and offset without to        much memory and with fast acces */    /* with this we can calculate dts/pts without waste memory */    uint64_t     i_first_dts;    uint32_t     *p_sample_count_dts;    uint32_t     *p_sample_delta_dts;   /* dts delta */    uint32_t     *p_sample_count_pts;    int32_t      *p_sample_offset_pts;  /* pts-dts */    /* TODO if needed add pts        but quickly *add* support for edts and seeking */} mp4_chunk_t; /* Contain all needed information for read all track with vlc */typedef struct{    unsigned int i_track_ID;/* this should be unique */    int b_ok;               /* The track is usable */    int b_enable;           /* is the trak enable by default */    bool b_selected;  /* is the trak being played */    bool b_chapter;   /* True when used for chapter only */    bool b_mac_encoding;    es_format_t fmt;    es_out_id_t *p_es;    /* display size only ! */    int i_width;    int i_height;    /* more internal data */    uint64_t        i_timescale;    /* time scale for this track only */    /* elst */    int             i_elst;         /* current elst */    int64_t         i_elst_time;    /* current elst start time (in movie time scale)*/    MP4_Box_t       *p_elst;        /* elst (could be NULL) */    /* give the next sample to read, i_chunk is to find quickly where      the sample is located */    uint32_t         i_sample;       /* next sample to read */    uint32_t         i_chunk;        /* chunk where next sample is stored */    /* total count of chunk and sample */    uint32_t         i_chunk_count;    uint32_t         i_sample_count;    mp4_chunk_t    *chunk; /* always defined  for each chunk */    /* sample size, p_sample_size defined only if i_sample_size == 0        else i_sample_size is size for all sample */    uint32_t         i_sample_size;    uint32_t         *p_sample_size; /* XXX perhaps add file offset if take                                    too much time to do sumations each time*/    MP4_Box_t *p_stbl;  /* will contain all timing information */    MP4_Box_t *p_stsd;  /* will contain all data to initialize decoder */    MP4_Box_t *p_sample;/* point on actual sdsd */    bool b_drms;    void      *p_drms;} mp4_track_t;struct demux_sys_t{    MP4_Box_t    *p_root;      /* container for the whole file */    mtime_t      i_pcr;    uint64_t     i_time;         /* time position of the presentation                                  * in movie timescale */    uint64_t     i_timescale;    /* movie time scale */    uint64_t     i_duration;     /* movie duration */    unsigned int i_tracks;       /* number of tracks */    mp4_track_t  *track;         /* array of track */    /* */    MP4_Box_t    *p_tref_chap;    /* */    input_title_t *p_title;};/***************************************************************************** * Declaration of local function *****************************************************************************/static void MP4_TrackCreate ( demux_t *, mp4_track_t *, MP4_Box_t  *, bool b_force_enable );static void MP4_TrackDestroy(  mp4_track_t * );static int  MP4_TrackSelect ( demux_t *, mp4_track_t *, mtime_t );static void MP4_TrackUnselect(demux_t *, mp4_track_t * );static int  MP4_TrackSeek   ( demux_t *, mp4_track_t *, mtime_t );static uint64_t MP4_TrackGetPos    ( mp4_track_t * );static int      MP4_TrackSampleSize( mp4_track_t * );static int      MP4_TrackNextSample( demux_t *, mp4_track_t * );static void     MP4_TrackSetELST( demux_t *, mp4_track_t *, int64_t );static void     MP4_UpdateSeekpoint( demux_t * );static const char *MP4_ConvertMacCode( uint16_t );/* Return time in s of a track */static inline int64_t MP4_TrackGetDTS( demux_t *p_demux, mp4_track_t *p_track ){#define chunk p_track->chunk[p_track->i_chunk]    unsigned int i_index = 0;    unsigned int i_sample = p_track->i_sample - chunk.i_sample_first;    int64_t i_dts = chunk.i_first_dts;    while( i_sample > 0 )    {        if( i_sample > chunk.p_sample_count_dts[i_index] )        {            i_dts += chunk.p_sample_count_dts[i_index] *                chunk.p_sample_delta_dts[i_index];            i_sample -= chunk.p_sample_count_dts[i_index];            i_index++;        }        else        {            i_dts += i_sample * chunk.p_sample_delta_dts[i_index];            i_sample = 0;            break;        }    }#undef chunk    /* now handle elst */    if( p_track->p_elst )    {        demux_sys_t         *p_sys = p_demux->p_sys;        MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;        /* convert to offset */        if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||              elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&            elst->i_media_time[p_track->i_elst] > 0 )        {            i_dts -= elst->i_media_time[p_track->i_elst];        }        /* add i_elst_time */        i_dts += p_track->i_elst_time * p_track->i_timescale /            p_sys->i_timescale;        if( i_dts < 0 ) i_dts = 0;    }    return INT64_C(1000000) * i_dts / p_track->i_timescale;}static inline int64_t MP4_TrackGetPTSDelta( mp4_track_t *p_track ){    mp4_chunk_t *ck = &p_track->chunk[p_track->i_chunk];    unsigned int i_index = 0;    unsigned int i_sample = p_track->i_sample - ck->i_sample_first;    if( ck->p_sample_count_pts == NULL || ck->p_sample_offset_pts == NULL )        return -1;    for( i_index = 0;; i_index++ )    {        if( i_sample < ck->p_sample_count_pts[i_index] )            return ck->p_sample_offset_pts[i_index] * INT64_C(1000000) /                   (int64_t)p_track->i_timescale;        i_sample -= ck->p_sample_count_pts[i_index];    }}static inline int64_t MP4_GetMoviePTS(demux_sys_t *p_sys ){    return INT64_C(1000000) * p_sys->i_time / p_sys->i_timescale;}static void LoadChapter( demux_t  *p_demux );/***************************************************************************** * Open: check file and initializes MP4 structures *****************************************************************************/static int Open( vlc_object_t * p_this ){    demux_t  *p_demux = (demux_t *)p_this;    demux_sys_t     *p_sys;    const uint8_t   *p_peek;    MP4_Box_t       *p_ftyp;    MP4_Box_t       *p_rmra;    MP4_Box_t       *p_mvhd;    MP4_Box_t       *p_trak;    unsigned int    i;    bool      b_seekable;    bool      b_enabled_es;    /* A little test to see if it could be a mp4 */    if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 ) return VLC_EGENERIC;    switch( VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] ) )    {        case FOURCC_ftyp:        case FOURCC_moov:        case FOURCC_foov:        case FOURCC_moof:        case FOURCC_mdat:        case FOURCC_udta:        case FOURCC_free:        case FOURCC_skip:        case FOURCC_wide:        case VLC_FOURCC( 'p', 'n', 'o', 't' ):            break;         default:            return VLC_EGENERIC;    }    /* I need to seek */    stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_seekable );    if( !b_seekable )    {        msg_Warn( p_demux, "MP4 plugin discarded (unseekable)" );        return VLC_EGENERIC;    }    /*Set exported functions */    p_demux->pf_demux = Demux;    p_demux->pf_control = Control;    /* create our structure that will contains all data */    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );    memset( p_sys, 0, sizeof( demux_sys_t ) );    /* Now load all boxes ( except raw data ) */    if( ( p_sys->p_root = MP4_BoxGetRoot( p_demux->s ) ) == NULL )    {        msg_Warn( p_demux, "MP4 plugin discarded (not a valid file)" );        goto error;    }    MP4_BoxDumpStructure( p_demux->s, p_sys->p_root );    if( ( p_ftyp = MP4_BoxGet( p_sys->p_root, "/ftyp" ) ) )    {        switch( p_ftyp->data.p_ftyp->i_major_brand )        {            case( FOURCC_isom ):                msg_Dbg( p_demux,                         "ISO Media file (isom) version %d.",                         p_ftyp->data.p_ftyp->i_minor_version );                break;            default:                msg_Dbg( p_demux,                         "unrecognized major file specification (%4.4s).",                          (char*)&p_ftyp->data.p_ftyp->i_major_brand );                break;        }    }    else    {        msg_Dbg( p_demux, "file type box missing (assuming ISO Media file)" );    }    /* the file need to have one moov box */    if( MP4_BoxCount( p_sys->p_root, "/moov" ) <= 0 )    {        MP4_Box_t *p_foov = MP4_BoxGet( p_sys->p_root, "/foov" );        if( !p_foov )        {            msg_Err( p_demux, "MP4 plugin discarded (no moov box)" );            goto error;        }        /* we have a free box as a moov, rename it */        p_foov->i_type = FOURCC_moov;    }    if( ( p_rmra = MP4_BoxGet( p_sys->p_root,  "/moov/rmra" ) ) )    {        int        i_count = MP4_BoxCount( p_rmra, "rmda" );        int        i;        msg_Dbg( p_demux, "detected playlist mov file (%d ref)", i_count );        input_thread_t * p_input = vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );        input_item_t * p_current = input_GetItem( p_input );        p_current->i_type = ITEM_TYPE_PLAYLIST;        for( i = 0; i < i_count; i++ )

⌨️ 快捷键说明

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