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

📄 mp4.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************** * mp4.c : MP4 file input module for vlc ***************************************************************************** * Copyright (C) 2001-2004 VideoLAN * $Id: mp4.c 11515 2005-06-24 20:39:26Z gbazin $ * 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., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h>                                      /* malloc(), free() */#include <vlc/vlc.h>#include <vlc/input.h>#include <vlc_playlist.h>#include "iso_lang.h"#include "vlc_meta.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( _("MP4 stream demuxer") );    set_capability( "demux2", 242 );    set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Local prototypes *****************************************************************************/static int   Demux   ( demux_t * );static int   DemuxRef( demux_t *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{    int i_track_ID;     /* this should be unique */    int b_ok;           /* The track is usable */    int b_enable;       /* is the trak enable by default */    vlc_bool_t b_selected;     /* is the trak being played */    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 */    vlc_bool_t 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 */};/***************************************************************************** * Declaration of local function *****************************************************************************/static void MP4_TrackCreate ( demux_t *, mp4_track_t *, MP4_Box_t  *);static void MP4_TrackDestroy( demux_t *, 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 );/* Return time in 祍 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 I64C(1000000) * i_dts / p_track->i_timescale;}static inline int64_t MP4_TrackGetPTSDelta( demux_t *p_demux, 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] * I64C(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 I64C(1000000) * p_sys->i_time / p_sys->i_timescale;}#define FREE( p ) if( p ) { free( p ); (p) = NULL;}/***************************************************************************** * 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;    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;    vlc_bool_t      b_seekable;    /* 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" ) ) )    {        playlist_t *p_playlist;        playlist_item_t *p_item;        int        i_count = MP4_BoxCount( p_rmra, "rmda" );        int        i;        vlc_bool_t b_play = VLC_FALSE;        msg_Dbg( p_demux, "detected playlist mov file (%d ref)", i_count );        p_playlist =            (playlist_t *)vlc_object_find( p_demux,                                           VLC_OBJECT_PLAYLIST,                                           FIND_ANYWHERE );        if( p_playlist )        {            p_item = playlist_LockItemGetByInput( p_playlist,                      ((input_thread_t *)p_demux->p_parent)->input.p_item );            playlist_ItemToNode( p_playlist, p_item );            for( i = 0; i < i_count; i++ )            {                MP4_Box_t *p_rdrf = MP4_BoxGet( p_rmra, "rmda[%d]/rdrf", i );                char      *psz_ref;                uint32_t  i_ref_type;                if( !p_rdrf || !( psz_ref = p_rdrf->data.p_rdrf->psz_ref ) )                {                    continue;                }                i_ref_type = p_rdrf->data.p_rdrf->i_ref_type;                msg_Dbg( p_demux, "new ref=`%s' type=%4.4s",                         psz_ref, (char*)&i_ref_type );                if( i_ref_type == VLC_FOURCC( 'u', 'r', 'l', ' ' ) )                {                    if( strstr( psz_ref, "qt5gateQT" ) )                    {                        msg_Dbg( p_demux, "ignoring pseudo ref =`%s'", psz_ref );

⌨️ 快捷键说明

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