dshow.cpp

来自「VLC媒体播放程序」· C++ 代码 · 共 1,570 行 · 第 1/4 页

CPP
1,570
字号
/***************************************************************************** * dshow.cpp : DirectShow access module for vlc ***************************************************************************** * Copyright (C) 2002, 2003 VideoLAN * $Id: dshow.cpp,v 1.27 2004/01/29 17:04:01 gbazin Exp $ * * Author: Gildas Bazin <gbazin@netcourrier.com> * * 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>#include <stdio.h>#include <string.h>#include <vlc/vlc.h>#include <vlc/input.h>#include <vlc/vout.h>#include "filter.h"/***************************************************************************** * Access: local prototypes *****************************************************************************/static ssize_t Read          ( input_thread_t *, byte_t *, size_t );static ssize_t ReadCompressed( input_thread_t *, byte_t *, size_t );static int OpenDevice( input_thread_t *, string, vlc_bool_t );static IBaseFilter *FindCaptureDevice( vlc_object_t *, string *,                                       list<string> *, vlc_bool_t );static AM_MEDIA_TYPE EnumDeviceCaps( vlc_object_t *, IBaseFilter *,                                     int, int, int, int, int, int );static bool ConnectFilters( vlc_object_t *, IFilterGraph *,                            IBaseFilter *, IPin * );static int FindDevicesCallback( vlc_object_t *, char const *,                                vlc_value_t, vlc_value_t, void * );static int ConfigDevicesCallback( vlc_object_t *, char const *,                                  vlc_value_t, vlc_value_t, void * );static void PropertiesPage( vlc_object_t *, IBaseFilter * );#if 0    /* Debug only, use this to find out GUIDs */    unsigned char p_st[];    UuidToString( (IID *)&IID_IAMBufferNegotiation, &p_st );    msg_Err( p_input, "BufferNegotiation: %s" , p_st );#endif/* * header: *  fcc  ".dsh" *  u32    stream count *      fcc "auds"|"vids"       0 *      fcc codec               4 *      if vids *          u32 width           8 *          u32 height          12 *          u32 padding         16 *      if auds *          u32 channels        12 *          u32 samplerate      8 *          u32 samplesize      16 * * data: *  u32     stream number *  u32     data size *  u8      data */static void SetDWBE( uint8_t *p, uint32_t dw ){    p[0] = (dw >> 24)&0xff;    p[1] = (dw >> 16)&0xff;    p[2] = (dw >>  8)&0xff;    p[3] = (dw      )&0xff;}static void SetQWBE( uint8_t *p, uint64_t qw ){    SetDWBE( p, (qw >> 32)&0xffffffff );    SetDWBE( &p[4], qw&0xffffffff );}/***************************************************************************** * Module descriptor *****************************************************************************/static char *ppsz_vdev[] = { "", "none" };static char *ppsz_vdev_text[] = { N_("Default"), N_("None") };static char *ppsz_adev[] = { "", "none" };static char *ppsz_adev_text[] = { N_("Default"), N_("None") };#define CACHING_TEXT N_("Caching value in ms")#define CACHING_LONGTEXT N_( \    "Allows you to modify the default caching value for directshow streams. " \    "This value should be set in milliseconds units." )#define VDEV_TEXT N_("Video device name")#define VDEV_LONGTEXT N_( \    "You can specify the name of the video device that will be used by the " \    "DirectShow plugin. If you don't specify anything, the default device " \    "will be used.")#define ADEV_TEXT N_("Audio device name")#define ADEV_LONGTEXT N_( \    "You can specify the name of the audio device that will be used by the " \    "DirectShow plugin. If you don't specify anything, the default device " \    "will be used.")#define SIZE_TEXT N_("Video size")#define SIZE_LONGTEXT N_( \    "You can specify the size of the video that will be displayed by the " \    "DirectShow plugin. If you don't specify anything the default size for " \    "your device will be used.")#define CHROMA_TEXT N_("Video input chroma format")#define CHROMA_LONGTEXT N_( \    "Force the DirectShow video input to use a specific chroma format " \    "(eg. I420 (default), RV24, etc.)")#define CONFIG_TEXT N_("Device properties")#define CONFIG_LONGTEXT N_( \    "Show the properties dialog of the selected device.")static int  AccessOpen ( vlc_object_t * );static void AccessClose( vlc_object_t * );static int  DemuxOpen  ( vlc_object_t * );static void DemuxClose ( vlc_object_t * );vlc_module_begin();    set_description( _("DirectShow input") );    add_integer( "dshow-caching", (mtime_t)(0.2*CLOCK_FREQ) / 1000, NULL,                 CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );    add_string( "dshow-vdev", NULL, NULL, VDEV_TEXT, VDEV_LONGTEXT, VLC_FALSE);        change_string_list( ppsz_vdev, ppsz_vdev_text, FindDevicesCallback );        change_action_add( FindDevicesCallback, N_("Refresh list") );        change_action_add( ConfigDevicesCallback, N_("Configure") );    add_string( "dshow-adev", NULL, NULL, ADEV_TEXT, ADEV_LONGTEXT, VLC_FALSE);        change_string_list( ppsz_adev, ppsz_adev_text, FindDevicesCallback );        change_action_add( FindDevicesCallback, N_("Refresh list") );        change_action_add( ConfigDevicesCallback, N_("Configure") );    add_string( "dshow-size", NULL, NULL, SIZE_TEXT, SIZE_LONGTEXT, VLC_FALSE);    add_string( "dshow-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT,                VLC_TRUE );    add_bool( "dshow-config", VLC_FALSE, NULL, CONFIG_TEXT, CONFIG_LONGTEXT,              VLC_TRUE );    add_shortcut( "dshow" );    set_capability( "access", 0 );    set_callbacks( AccessOpen, AccessClose );    add_submodule();    set_description( _("DirectShow demuxer") );    add_shortcut( "dshow" );    set_capability( "demux", 200 );    set_callbacks( DemuxOpen, DemuxClose );vlc_module_end();/**************************************************************************** * DirectShow elementary stream descriptor ****************************************************************************/typedef struct dshow_stream_t{    string          devicename;    IBaseFilter     *p_device_filter;    CaptureFilter   *p_capture_filter;    AM_MEDIA_TYPE   mt;    int             i_fourcc;    vlc_bool_t      b_invert;    union    {      VIDEOINFOHEADER video;      WAVEFORMATEX    audio;    } header;    vlc_bool_t      b_pts;} dshow_stream_t;/**************************************************************************** * Access descriptor declaration ****************************************************************************/struct access_sys_t{    vlc_mutex_t lock;    vlc_cond_t  wait;    IFilterGraph  *p_graph;    IMediaControl *p_control;    /* header */    int     i_header_size;    int     i_header_pos;    uint8_t *p_header;    /* list of elementary streams */    dshow_stream_t **pp_streams;    int            i_streams;    int            i_current_stream;    /* misc properties */    int            i_width;    int            i_height;    int            i_chroma;    int            b_audio;};/***************************************************************************** * Open: open direct show device *****************************************************************************/static int AccessOpen( vlc_object_t *p_this ){    input_thread_t *p_input = (input_thread_t *)p_this;    access_sys_t   *p_sys;    vlc_value_t    val;    /* Get/parse options and open device(s) */    string vdevname, adevname;    int i_width = 0, i_height = 0, i_chroma = 0;    var_Create( p_input, "dshow-vdev", VLC_VAR_STRING | VLC_VAR_DOINHERIT);    var_Get( p_input, "dshow-vdev", &val );    if( val.psz_string ) vdevname = string( val.psz_string );    if( val.psz_string ) free( val.psz_string );    var_Create( p_input, "dshow-adev", VLC_VAR_STRING | VLC_VAR_DOINHERIT);    var_Get( p_input, "dshow-adev", &val );    if( val.psz_string ) adevname = string( val.psz_string );    if( val.psz_string ) free( val.psz_string );    var_Create( p_input, "dshow-size", VLC_VAR_STRING | VLC_VAR_DOINHERIT);    var_Get( p_input, "dshow-size", &val );    if( val.psz_string && *val.psz_string )    {        if( !strcmp( val.psz_string, "subqcif" ) )        {            i_width  = 128; i_height = 96;        }        else if( !strcmp( val.psz_string, "qsif" ) )        {            i_width  = 160; i_height = 120;        }        else if( !strcmp( val.psz_string, "qcif" ) )        {            i_width  = 176; i_height = 144;        }        else if( !strcmp( val.psz_string, "sif" ) )        {            i_width  = 320; i_height = 240;        }        else if( !strcmp( val.psz_string, "cif" ) )        {            i_width  = 352; i_height = 288;        }        else if( !strcmp( val.psz_string, "vga" ) )        {            i_width  = 640; i_height = 480;        }        else        {            /* Width x Height */            char *psz_parser;            i_width = strtol( val.psz_string, &psz_parser, 0 );            if( *psz_parser == 'x' || *psz_parser == 'X')            {                i_height = strtol( psz_parser + 1, &psz_parser, 0 );            }            msg_Dbg( p_input, "Width x Height %dx%d", i_width, i_height );        }    }    if( val.psz_string ) free( val.psz_string );    var_Create( p_input, "dshow-chroma", VLC_VAR_STRING | VLC_VAR_DOINHERIT);    var_Get( p_input, "dshow-chroma", &val );    if( val.psz_string && strlen( val.psz_string ) >= 4 )    {        i_chroma = VLC_FOURCC( val.psz_string[0], val.psz_string[1],                               val.psz_string[2], val.psz_string[3] );    }    if( val.psz_string ) free( val.psz_string );    p_input->pf_read        = Read;    p_input->pf_seek        = NULL;    p_input->pf_set_area    = NULL;    p_input->pf_set_program = NULL;    vlc_mutex_lock( &p_input->stream.stream_lock );    p_input->stream.b_pace_control = 0;    p_input->stream.b_seekable = 0;    p_input->stream.p_selected_area->i_size = 0;    p_input->stream.p_selected_area->i_tell = 0;    p_input->stream.i_method = INPUT_METHOD_FILE;    vlc_mutex_unlock( &p_input->stream.stream_lock );    var_Create( p_input, "dshow-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);    var_Get( p_input, "dshow-caching", &val );    p_input->i_pts_delay = val.i_int * 1000;    /* Initialize OLE/COM */    CoInitialize( 0 );    /* create access private data */    p_input->p_access_data = p_sys =        (access_sys_t *)malloc( sizeof( access_sys_t ) );    /* Initialize some data */    p_sys->i_streams = 0;    p_sys->pp_streams = (dshow_stream_t **)malloc( 1 );    p_sys->i_width = i_width;    p_sys->i_height = i_height;    p_sys->i_chroma = i_chroma;    p_sys->b_audio = VLC_TRUE;    /* Create header */    p_sys->i_header_size = 8;    p_sys->p_header      = (uint8_t *)malloc( p_sys->i_header_size );    memcpy(  &p_sys->p_header[0], ".dsh", 4 );    SetDWBE( &p_sys->p_header[4], 1 );    p_sys->i_header_pos = p_sys->i_header_size;    /* Build directshow graph */    CoCreateInstance( CLSID_FilterGraph, 0, CLSCTX_INPROC,                      (REFIID)IID_IFilterGraph, (void **)&p_sys->p_graph );    p_sys->p_graph->QueryInterface( IID_IMediaControl,                                    (void **)&p_sys->p_control );    if( OpenDevice( p_input, vdevname, 0 ) != VLC_SUCCESS )    {        msg_Err( p_input, "can't open video");    }    if( p_sys->b_audio && OpenDevice( p_input, adevname, 1 ) != VLC_SUCCESS )    {        msg_Err( p_input, "can't open audio");    }    if( !p_sys->i_streams )    {        /* Release directshow objects */        if( p_sys->p_control ) p_sys->p_control->Release();        p_sys->p_graph->Release();        /* Uninitialize OLE/COM */        CoUninitialize();        free( p_sys->p_header );        free( p_sys->pp_streams );        free( p_sys );        return VLC_EGENERIC;    }    /* Initialize some data */    p_sys->i_current_stream = 0;    p_input->i_mtu += p_sys->i_header_size + 16 /* data header size */;    vlc_mutex_init( p_input, &p_sys->lock );    vlc_cond_init( p_input, &p_sys->wait );    /* Everything is ready. Let's rock baby */    p_sys->p_control->Run();    return VLC_SUCCESS;}/***************************************************************************** * AccessClose: close device *****************************************************************************/static void AccessClose( vlc_object_t *p_this ){    input_thread_t *p_input = (input_thread_t *)p_this;    access_sys_t    *p_sys  = p_input->p_access_data;    /* Stop capturing stuff */

⌨️ 快捷键说明

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