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

📄 avi.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************** * avi.c : AVI file Stream input module for vlc ***************************************************************************** * Copyright (C) 2001-2004 the VideoLAN team * $Id: 2d8975cd286cc6850615b639ad862f2cf4a66970 $ * 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_interface.h>#include <vlc_meta.h>#include <vlc_codecs.h>#include <vlc_charset.h>#include "libavi.h"/***************************************************************************** * Module descriptor *****************************************************************************/#define INTERLEAVE_TEXT N_("Force interleaved method" )#define INTERLEAVE_LONGTEXT N_( "Force interleaved method." )#define INDEX_TEXT N_("Force index creation")#define INDEX_LONGTEXT N_( \    "Recreate a index for the AVI file. Use this if your AVI file is damaged "\    "or incomplete (not seekable)." )static int  Open ( vlc_object_t * );static void Close( vlc_object_t * );static const int pi_index[] = {0,1,2};static const char *const ppsz_indexes[] = { N_("Ask"), N_("Always fix"),                                N_("Never fix") };vlc_module_begin();    set_shortname( "AVI" );    set_description( N_("AVI demuxer") );    set_capability( "demux", 212 );    set_category( CAT_INPUT );    set_subcategory( SUBCAT_INPUT_DEMUX );    add_bool( "avi-interleaved", 0, NULL,              INTERLEAVE_TEXT, INTERLEAVE_LONGTEXT, true );    add_integer( "avi-index", 0, NULL,              INDEX_TEXT, INDEX_LONGTEXT, false );        change_integer_list( pi_index, ppsz_indexes, NULL );    set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Local prototypes *****************************************************************************/static int Control         ( demux_t *, int, va_list );static int Seek            ( demux_t *, mtime_t, int );static int Demux_Seekable  ( demux_t * );static int Demux_UnSeekable( demux_t * );#define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )typedef struct{    vlc_fourcc_t i_fourcc;    off_t        i_pos;    uint32_t     i_size;    vlc_fourcc_t i_type;     /* only for AVIFOURCC_LIST */    uint8_t      i_peek[8];  /* first 8 bytes */    unsigned int i_stream;    unsigned int i_cat;} avi_packet_t;typedef struct{    vlc_fourcc_t i_id;    uint32_t     i_flags;    off_t        i_pos;    uint32_t     i_length;    uint32_t     i_lengthtotal;} avi_entry_t;typedef struct{    bool      b_activated;    unsigned int    i_cat; /* AUDIO_ES, VIDEO_ES */    vlc_fourcc_t    i_codec;    int             i_rate;    int             i_scale;    int             i_samplesize;    es_out_id_t     *p_es;    /* Avi Index */    avi_entry_t     *p_index;    unsigned int    i_idxnb;    unsigned int    i_idxmax;    unsigned int    i_idxposc;  /* numero of chunk */    unsigned int    i_idxposb;  /* byte in the current chunk */    /* extra information given to the decoder */    void            *p_extra;    /* For VBR audio only */    unsigned int    i_blockno;    unsigned int    i_blocksize;    /* For muxed streams */    stream_t        *p_out_muxed;} avi_track_t;struct demux_sys_t{    mtime_t i_time;    mtime_t i_length;    bool  b_seekable;    bool  b_muxed;    avi_chunk_t ck_root;    bool  b_odml;    off_t   i_movi_begin;    off_t   i_movi_lastchunk_pos;   /* XXX position of last valid chunk */    /* number of streams and information */    unsigned int i_track;    avi_track_t  **track;    /* meta */    vlc_meta_t  *meta;};static inline off_t __EVEN( off_t i ){    return (i & 1) ? i + 1 : i;}static mtime_t AVI_PTSToChunk( avi_track_t *, mtime_t i_pts );static mtime_t AVI_PTSToByte ( avi_track_t *, mtime_t i_pts );static mtime_t AVI_GetDPTS   ( avi_track_t *, int64_t i_count );static mtime_t AVI_GetPTS    ( avi_track_t * );static int AVI_StreamChunkFind( demux_t *, unsigned int i_stream );static int AVI_StreamChunkSet ( demux_t *,                                unsigned int i_stream, unsigned int i_ck );static int AVI_StreamBytesSet ( demux_t *,                                unsigned int i_stream, off_t   i_byte );vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t );static int   AVI_GetKeyFlag    ( vlc_fourcc_t , uint8_t * );static int AVI_PacketGetHeader( demux_t *, avi_packet_t *p_pk );static int AVI_PacketNext     ( demux_t * );static int AVI_PacketRead     ( demux_t *, avi_packet_t *, block_t **);static int AVI_PacketSearch   ( demux_t * );static void AVI_IndexLoad    ( demux_t * );static void AVI_IndexCreate  ( demux_t * );static void AVI_IndexAddEntry( demux_sys_t *, int, avi_entry_t * );static mtime_t  AVI_MovieGetLength( demux_t * );/***************************************************************************** * Stream management *****************************************************************************/static int        AVI_TrackSeek  ( demux_t *, int, mtime_t );static int        AVI_TrackStopFinishedStreams( demux_t *);/* Remarks: - For VBR mp3 stream:    count blocks by rounded-up chunksizes instead of chunks    we need full emulation of dshow avi demuxer bugs :(    fixes silly nandub-style a-v delaying in avi with vbr mp3...    (from mplayer 2002/08/02) - to complete.... *//***************************************************************************** * Open: check file and initializes AVI structures *****************************************************************************/static int Open( vlc_object_t * p_this ){    demux_t  *p_demux = (demux_t *)p_this;    demux_sys_t     *p_sys;    bool       b_index = false;    int              i_do_index;    avi_chunk_t         ck_riff;    avi_chunk_list_t    *p_riff = (avi_chunk_list_t*)&ck_riff;    avi_chunk_list_t    *p_hdrl, *p_movi;    avi_chunk_avih_t    *p_avih;    unsigned int i_track;    unsigned int i, i_peeker;    const uint8_t *p_peek;    /* Is it an avi file ? */    if( stream_Peek( p_demux->s, &p_peek, 200 ) < 200 ) return VLC_EGENERIC;    for( i_peeker = 0; i_peeker < 188; i_peeker++ )    {        if( !strncmp( (char *)&p_peek[0], "RIFF", 4 ) && !strncmp( (char *)&p_peek[8], "AVI ", 4 ) )            break;        if( !strncmp( (char *)&p_peek[0], "ON2 ", 4 ) && !strncmp( (char *)&p_peek[8], "ON2f", 4 ) )            break;        p_peek++;    }    if( i_peeker == 188 )    {        return VLC_EGENERIC;    }    /* Initialize input  structures. */    p_sys = p_demux->p_sys = malloc( sizeof(demux_sys_t) );    memset( p_sys, 0, sizeof( demux_sys_t ) );    p_sys->i_time   = 0;    p_sys->i_length = 0;    p_sys->i_movi_lastchunk_pos = 0;    p_sys->b_odml   = false;    p_sys->b_muxed  = false;    p_sys->i_track  = 0;    p_sys->track    = NULL;    p_sys->meta     = NULL;    stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &p_sys->b_seekable );    p_demux->pf_control = Control;    p_demux->pf_demux = Demux_Seekable;    /* For unseekable stream, automaticaly use Demux_UnSeekable */    if( !p_sys->b_seekable || config_GetInt( p_demux, "avi-interleaved" ) )    {        p_demux->pf_demux = Demux_UnSeekable;    }    if( i_peeker > 0 )    {        stream_Read( p_demux->s, NULL, i_peeker );    }    if( AVI_ChunkReadRoot( p_demux->s, &p_sys->ck_root ) )    {        msg_Err( p_demux, "avi module discarded (invalid file)" );        return VLC_EGENERIC;    }    if( AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF ) > 1 )    {        unsigned int i_count =            AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF );        msg_Warn( p_demux, "multiple riff -> OpenDML ?" );        for( i = 1; i < i_count; i++ )        {            avi_chunk_list_t *p_sysx;            p_sysx = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, i );            if( p_sysx->i_type == AVIFOURCC_AVIX )            {                msg_Warn( p_demux, "detected OpenDML file" );                p_sys->b_odml = true;                break;            }        }    }    p_riff  = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0 );    p_hdrl  = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );    p_movi  = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0 );    if( !p_hdrl || !p_movi )    {        msg_Err( p_demux, "avi module discarded (invalid file)" );        goto error;    }    if( !( p_avih = AVI_ChunkFind( p_hdrl, AVIFOURCC_avih, 0 ) ) )    {        msg_Err( p_demux, "cannot find avih chunk" );        goto error;    }    i_track = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl );    if( p_avih->i_streams != i_track )    {        msg_Warn( p_demux,                  "found %d stream but %d are declared",                  i_track, p_avih->i_streams );    }    if( i_track == 0 )    {        msg_Err( p_demux, "no stream defined!" );        goto error;    }    /* print information on streams */    msg_Dbg( p_demux, "AVIH: %d stream, flags %s%s%s%s ",             i_track,             p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",             p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",             p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",             p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );    if( ( p_sys->meta = vlc_meta_New() ) )    {        char buffer[200];        sprintf( buffer, "%s%s%s%s",                 p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",                 p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",                 p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",                 p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );        vlc_meta_SetSetting( p_sys->meta, buffer );    }    /* now read info on each stream and create ES */    for( i = 0 ; i < i_track; i++ )    {        avi_track_t           *tk     = malloc( sizeof( avi_track_t ) );        if( !tk )            goto error;        avi_chunk_list_t      *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );        avi_chunk_strh_t      *p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );        avi_chunk_STRING_t    *p_strn = AVI_ChunkFind( p_strl, AVIFOURCC_strn, 0 );        avi_chunk_strf_auds_t *p_auds = NULL;        avi_chunk_strf_vids_t *p_vids = NULL;        es_format_t fmt;        memset( tk, 0, sizeof( avi_track_t ) );        p_vids = (avi_chunk_strf_vids_t*)AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );        p_auds = (avi_chunk_strf_auds_t*)AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );        if( p_strl == NULL || p_strh == NULL || p_auds == NULL || p_vids == NULL )        {            msg_Warn( p_demux, "stream[%d] incomplete", i );            continue;        }        tk->i_rate  = p_strh->i_rate;        tk->i_scale = p_strh->i_scale;        tk->i_samplesize = p_strh->i_samplesize;        msg_Dbg( p_demux, "stream[%d] rate:%d scale:%d samplesize:%d",                 i, tk->i_rate, tk->i_scale, tk->i_samplesize );        switch( p_strh->i_type )        {            case( AVIFOURCC_auds ):                tk->i_cat   = AUDIO_ES;                tk->i_codec = AVI_FourccGetCodec( AUDIO_ES,                                                  p_auds->p_wf->wFormatTag );                tk->i_blocksize = p_auds->p_wf->nBlockAlign;                if( tk->i_blocksize == 0 )                {                    if( p_auds->p_wf->wFormatTag == 1 )                        tk->i_blocksize = p_auds->p_wf->nChannels * (p_auds->p_wf->wBitsPerSample/8);                    else                        tk->i_blocksize = 1;                }                else if( tk->i_samplesize != 0 && tk->i_samplesize != tk->i_blocksize )                {                    msg_Warn( p_demux, "track[%d] samplesize=%d and blocksize=%d are not equal."                                       "Using blocksize as a workaround.",

⌨️ 快捷键说明

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