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

📄 avi.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************** * avi.c : AVI file Stream input module for vlc ***************************************************************************** * Copyright (C) 2001-2004 VideoLAN * $Id: avi.c 10753 2005-04-20 14:55:46Z 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_meta.h"#include "codecs.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 so we can seek trough it more reliably." )static int  Open ( vlc_object_t * );static void Close( vlc_object_t * );vlc_module_begin();    set_shortname( "AVI" );    set_description( _("AVI demuxer") );    set_capability( "demux2", 212 );    set_category( CAT_INPUT );    set_subcategory( SUBCAT_INPUT_DEMUX );    add_bool( "avi-interleaved", 0, NULL,              INTERLEAVE_TEXT, INTERLEAVE_LONGTEXT, VLC_TRUE );    add_bool( "avi-index", 0, NULL,              INDEX_TEXT, INDEX_LONGTEXT, VLC_TRUE );    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 FREE( p ) if( p ) { free( p ); (p) = NULL; }#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{    vlc_bool_t      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_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 */    /* For VBR audio only */    unsigned int        i_blockno;    unsigned int        i_blocksize;} avi_track_t;struct demux_sys_t{    mtime_t i_time;    mtime_t i_length;    vlc_bool_t  b_seekable;    avi_chunk_t ck_root;    vlc_bool_t  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;    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;    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( &p_peek[0], "RIFF", 4 ) &&            !strncmp( &p_peek[8], "AVI ", 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   = VLC_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 = VLC_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_Add( p_sys->meta, VLC_META_SETTING, 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 ) );        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;        avi_chunk_strf_vids_t *p_vids;        es_format_t fmt;        tk->b_activated = VLC_FALSE;        tk->p_index     = 0;        tk->i_idxnb     = 0;        tk->i_idxmax    = 0;        tk->i_idxposc   = 0;        tk->i_idxposb   = 0;        tk->i_blockno   = 0;        tk->i_blocksize = 0;        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 );                if( ( tk->i_blocksize = p_auds->p_wf->nBlockAlign ) == 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;                    }                }                es_format_Init( &fmt, AUDIO_ES, tk->i_codec );                fmt.audio.i_channels        = p_auds->p_wf->nChannels;                fmt.audio.i_rate            = p_auds->p_wf->nSamplesPerSec;                fmt.i_bitrate               = p_auds->p_wf->nAvgBytesPerSec*8;                fmt.audio.i_blockalign      = p_auds->p_wf->nBlockAlign;                fmt.audio.i_bitspersample   = p_auds->p_wf->wBitsPerSample;                fmt.i_extra = __MIN( p_auds->p_wf->cbSize,                    p_auds->i_chunk_size - sizeof(WAVEFORMATEX) );                fmt.p_extra = &p_auds->p_wf[1];                msg_Dbg( p_demux, "stream[%d] audio(0x%x) %d channels %dHz %dbits",                         i, p_auds->p_wf->wFormatTag, p_auds->p_wf->nChannels,                         p_auds->p_wf->nSamplesPerSec, p_auds->p_wf->wBitsPerSample);                break;            case( AVIFOURCC_vids ):                tk->i_cat   = VIDEO_ES;                tk->i_codec = AVI_FourccGetCodec( VIDEO_ES,                                                  p_vids->p_bih->biCompression );                if( p_vids->p_bih->biCompression == 0x00 )                {                    switch( p_vids->p_bih->biBitCount )                    {                        case 32:                            tk->i_codec = VLC_FOURCC('R','V','3','2');                            break;                        case 24:                            tk->i_codec = VLC_FOURCC('R','V','2','4');                            break;                        case 16:                            /* tk->i_codec = VLC_FOURCC('R','V','1','6');*/                            /* break;*/                        case 15:                            tk->i_codec = VLC_FOURCC('R','V','1','5');                            break;                        case 9:                            tk->i_codec = VLC_FOURCC( 'Y', 'V', 'U', '9' ); /* <- TODO check that */                            break;                    }

⌨️ 快捷键说明

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