summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-08-12 15:30:21 +0200
committerwm4 <wm4@nowhere>2012-08-16 17:16:33 +0200
commitaebfbbf2bdda8e18beef90c16da97bd335f7d3b0 (patch)
treea7362bf3ef6f2d80a47b2e539a2ea4efe5e2e079 /stream
parentc6b03ffef6250096373c4a81a489dae9fbff9087 (diff)
downloadmpv-aebfbbf2bdda8e18beef90c16da97bd335f7d3b0.tar.bz2
mpv-aebfbbf2bdda8e18beef90c16da97bd335f7d3b0.tar.xz
Remove win32/qt/xanim/real binary codecs loading
Remove the win32 loader - the win32 emulation layer, as well as the code for using DirectShow/DMO/VFW codecs. Remove loading of xanim, QuickTime, and RealMedia codecs. The win32 emulation layer is based on a very old version of wine. Apparently, wine code was copied and hacked until it was somehow able to load a limited collection of binary codecs. It poked around in the code segment of some known binary codecs to disable unsupported win32 API calls to make them work. Example from module.c: for (i=0;i<5;i++) RVA(0x19e842)[i]=0x90; // make_new_region ? for (i=0;i<28;i++) RVA(0x19e86d)[i]=0x90; // call__call_CreateCompatibleDC ? for (i=0;i<5;i++) RVA(0x19e898)[i]=0x90; // jmp_to_call_loadbitmap ? for (i=0;i<9;i++) RVA(0x19e8ac)[i]=0x90; // call__calls_OLE_shit ? for (i=0;i<106;i++) RVA(0x261b10)[i]=0x90; // disable threads Just to show how utterly insane this code is. You wouldn't want even your worst enemy to have to maintain this. In fact, it seems nobody made major changes to this code ever since it was committed. Most formats can be decoded by libavcodecs these days, and the loader couldn't be used on 64 bit platforms anyway. The same is (probably) true for the other binary codecs. General note about how support for win32 codecs could be added back: It's not possible to replace the win32 loader code by using wine as library, because modern wine can not be linked with native Linux programs for certain reasons. It would be possible to to move DirectShow video decoding into a separate process linked with wine, like the CoreAVC-for-Linux patches do. There is also the mplayer-ww fork, which uses the dshownative library to use DirectShow codecs on Windows.
Diffstat (limited to 'stream')
-rw-r--r--stream/tvi_dshow.c3514
-rw-r--r--stream/tvi_dshow.h728
2 files changed, 0 insertions, 4242 deletions
diff --git a/stream/tvi_dshow.c b/stream/tvi_dshow.c
deleted file mode 100644
index db3004b5ba..0000000000
--- a/stream/tvi_dshow.c
+++ /dev/null
@@ -1,3514 +0,0 @@
-/*
- * TV support under Win32
- *
- * (C) 2007 Vladimir Voroshilov <voroshil@gmail.com>
- *
- * Based on tvi_dummy.c with help of tv.c, tvi_v4l2.c code.
- *
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/*
- * WARNING: This is alpha code!
- *
- * Abilities:
- * * Watching TV under Win32 using WDM Capture driver and DirectShow
- * * Grabbing synchronized audio/video with mencoder (synchronization is beeing done by DirectShow)
- * * If device driver provides IAMStreamConfig interface, user can choose width/height with "-tv height=<h>:width=<w>"
- * * Adjusting BRIGHTNESS,HUE,SATURATION,CONTRAST if supported by device
- * * Selecting Tuner,S-Video,... as media source
- * * User can select used video capture device, passing -tv device=<dev#>
- * * User can select used audio input, passing -tv audioid=<input#>
- *
- * options which will not be implemented (probably sometime in future, if possible):
- * * alsa
- * * mjpeg
- * * decimation=<1|2|4>
- * * quality=<0\-100>
- * * forceaudio
- * * forcechan=<1\-2>
- * * [volume|bass|treble|balance]
- *
- * Works with:
- * - LifeView FlyTV Prime 34FM (SAA7134 based) with driver from Ivan Uskov
- * Partially works with:
- * - ATI 9200 VIVO based card
- * - ATI AIW 7500
- * - nVidia Ti-4400
- *
- * Known bugs:
- * * stream goes with 24.93 FPS (NTSC), while reporting 25 FPS (PAL) ?!
- * * direct set frequency call does not work ('Insufficient Buffer' error)
- * * audio stream goes with about 1 sample/sec rate when capturing sound from audio card
- *
- * TODO:
- * * check audio with small buffer on vivo !!!
- * * norm for IAMVideoDecoder and for IAMTVtuner - differs !!
- * * check how to change TVFormat on VIVO card without tuner
- * * Flip image upside-down for RGB formats.
- * *
- * * remove debug sleep()
- * * Add some notes to methods' parameters
- * * refactor console messages
- * * check using header files and keep only needed
- * * add additional comments to methods' bodies
- *
- */
-
-
-/// \ingroup tvi_dshow
-
-#include "config.h"
-
-#include <stdio.h>
-#include "libmpcodecs/img_format.h"
-#include "libaf/af_format.h"
-#include "osdep/timer.h"
-
-
-#include "tv.h"
-#include "mp_msg.h"
-#include "frequencies.h"
-
-
-#include "tvi_dshow.h"
-
-#ifndef STDCALL
-// mingw64 needs this
-#define STDCALL __stdcall
-#endif
-
-static tvi_handle_t *tvi_init_dshow(tv_param_t* tv_param);
-
-/*
-*---------------------------------------------------------------------------------------
-*
-* Data structures
-*
-*---------------------------------------------------------------------------------------
-*/
-/**
- information about this file
-*/
-const tvi_info_t tvi_info_dshow = {
- tvi_init_dshow,
- "DirectShow TV",
- "dshow",
- "Vladimir Voroshilov",
- "Very experimental!! Use with caution"
-};
-
-
-/**
-ringbuffer related info
-*/
-typedef struct {
- CRITICAL_SECTION *pMutex; ///< pointer to critical section (mutex)
- char **ringbuffer; ///< ringbuffer array
- double*dpts; ///< samples' timestamps
-
- int buffersize; ///< size of buffer in blocks
- int blocksize; ///< size of individual block
- int head; ///< index of first valid sample
- int tail; ///< index of last valid sample
- int count; ///< count of valid samples in ringbuffer
- double tStart; ///< pts of first sample (first sample should have pts 0)
-} grabber_ringbuffer_t;
-
-typedef enum { unknown, video, audio, vbi } stream_type;
-
-/**
- CSampleGrabberCD definition
-*/
-typedef struct CSampleGrabberCB {
- ISampleGrabberCBVtbl *lpVtbl;
- int refcount;
- GUID interfaces[2];
- grabber_ringbuffer_t *pbuf;
-} CSampleGrabberCB;
-
-/**
- Chain related structure
- */
-typedef struct {
- stream_type type; ///< stream type
- const GUID* majortype; ///< GUID of major mediatype (video/audio/vbi)
- const GUID* pin_category; ///< pin category (pointer to one of PIN_CATEGORY_*)
-
- IBaseFilter *pCaptureFilter; ///< capture device filter
- IAMStreamConfig *pStreamConfig; ///< for configuring stream
- ISampleGrabber *pSG; ///< ISampleGrabber interface of SampleGrabber filter
- IBaseFilter *pSGF; ///< IBaseFilter interface of SampleGrabber filter
- IPin *pCapturePin; ///< output capture pin
- IPin *pSGIn; ///< input pin of SampleGrabber filter
-
- grabber_ringbuffer_t *rbuf; ///< sample frabber data
- CSampleGrabberCB* pCSGCB; ///< callback object
-
- AM_MEDIA_TYPE *pmt; ///< stream properties.
- int nFormatUsed; ///< index of used format
- AM_MEDIA_TYPE **arpmt; ///< available formats
- void** arStreamCaps; ///< VIDEO_STREAM_CONFIG_CAPS or AUDIO_STREAM_CONFIG_CAPS
-} chain_t;
-
-typedef struct tt_stream_props_s{
- int sampling_rate;
- int samples_per_line;
- int offset;
- int count[2]; ///< number of lines in first and second fields
- int interlaced; ///< vbi data are interlaced
- int bufsize; ///< required buffer size
-} tt_stream_props;
-
-typedef struct priv {
- int dev_index; ///< capture device index in device list (defaul: 0, first available device)
- int adev_index; ///< audio capture device index in device list (default: -1, not used)
- int immediate_mode; ///< immediate mode (no sound capture)
- int state; ///< state: 1-filter graph running, 0-filter graph stopped
- int direct_setfreq_call; ///< 0-find nearest channels from system channel list(workaround),1-direct call to set frequency
- int direct_getfreq_call; ///< 0-find frequncy from frequency table (workaround),1-direct call to get frequency
-
- int fcc; ///< used video format code (FourCC)
- int width; ///< picture width (default: auto)
- int height; ///< picture height (default: auto)
-
- int channels; ///< number of audio channels (default: auto)
- int samplerate; ///< audio samplerate (default: auto)
-
- long *freq_table; ///< frequency table (in Hz)
- int freq_table_len; ///< length of freq table
- int first_channel; ///< channel number of first entry in freq table
- int input; ///< used input
-
- chain_t* chains[3]; ///< chains' data (0-video, 1-audio, 2-vbi)
-
- IAMTVTuner *pTVTuner; ///< interface for tuner device
- IGraphBuilder *pGraph; ///< filter graph
- ICaptureGraphBuilder2 *pBuilder; ///< graph builder
- IMediaControl *pMediaControl; ///< interface for controlling graph (start, stop,...)
- IAMVideoProcAmp *pVideoProcAmp; ///< for adjusting hue,saturation,etc
- IAMCrossbar *pCrossbar; ///< for selecting input (Tuner,Composite,S-Video,...)
- DWORD dwRegister; ///< allow graphedit to connect to our graph
- void *priv_vbi; ///< private VBI data structure
- tt_stream_props tsp; ///< data for VBI initialization
-
- tv_param_t* tv_param; ///< TV parameters
-} priv_t;
-
-#include "tvi_def.h"
-
-/**
- country table entry structure (for loading freq table stored in kstvtuner.ax
-
- \note
- structure have to be 2-byte aligned and have 10-byte length!!
-*/
-typedef struct __attribute__((__packed__)) {
- WORD CountryCode; ///< Country code
- WORD CableFreqTable; ///< index of resource with frequencies for cable channels
- WORD BroadcastFreqTable; ///< index of resource with frequencies for broadcast channels
- DWORD VideoStandard; ///< used video standard
-} TRCCountryList;
-/**
- information about image formats
-*/
-typedef struct {
- uint32_t fmt; ///< FourCC
- const GUID *subtype; ///< DirectShow's subtype
- int nBits; ///< number of bits
- int nCompression; ///< complression
- int tail; ///< number of additional bytes followed VIDEOINFOHEADER structure
-} img_fmt;
-
-/*
-*---------------------------------------------------------------------------------------
-*
-* Methods forward declaration
-*
-*---------------------------------------------------------------------------------------
-*/
-static HRESULT init_ringbuffer(grabber_ringbuffer_t * rb, int buffersize,
- int blocksize);
-static HRESULT show_filter_info(IBaseFilter * pFilter);
-#if 0
-//defined in current MinGW release
-HRESULT STDCALL GetRunningObjectTable(DWORD, IRunningObjectTable **);
-HRESULT STDCALL CreateItemMoniker(LPCOLESTR, LPCOLESTR, IMoniker **);
-#endif
-static CSampleGrabberCB *CSampleGrabberCB_Create(grabber_ringbuffer_t *
- pbuf);
-static int set_crossbar_input(priv_t * priv, int input);
-static int subtype2imgfmt(const GUID * subtype);
-
-/*
-*---------------------------------------------------------------------------------------
-*
-* Global constants and variables
-*
-*---------------------------------------------------------------------------------------
-*/
-/**
- lookup tables for physical connector types
- */
-static const struct {
- long type;
- char *name;
-} tv_physcon_types[]={
- {PhysConn_Video_Tuner, "Tuner" },
- {PhysConn_Video_Composite, "Composite" },
- {PhysConn_Video_SVideo, "S-Video" },
- {PhysConn_Video_RGB, "RGB" },
- {PhysConn_Video_YRYBY, "YRYBY" },
- {PhysConn_Video_SerialDigital, "SerialDigital" },
- {PhysConn_Video_ParallelDigital, "ParallelDigital"},
- {PhysConn_Video_VideoDecoder, "VideoDecoder" },
- {PhysConn_Video_VideoEncoder, "VideoEncoder" },
- {PhysConn_Video_SCART, "SCART" },
- {PhysConn_Video_Black, "Blaack" },
- {PhysConn_Audio_Tuner, "Tuner" },
- {PhysConn_Audio_Line, "Line" },
- {PhysConn_Audio_Mic, "Mic" },
- {PhysConn_Audio_AESDigital, "AESDiital" },
- {PhysConn_Audio_SPDIFDigital, "SPDIFDigital" },
- {PhysConn_Audio_AudioDecoder, "AudioDecoder" },
- {PhysConn_Audio_SCSI, "SCSI" },
- {PhysConn_Video_SCSI, "SCSI" },
- {PhysConn_Audio_AUX, "AUX" },
- {PhysConn_Video_AUX, "AUX" },
- {PhysConn_Audio_1394, "1394" },
- {PhysConn_Video_1394, "1394" },
- {PhysConn_Audio_USB, "USB" },
- {PhysConn_Video_USB, "USB" },
- {-1, NULL }
-};
-
-static const struct {
- char *chanlist_name;
- int country_code;
-} tv_chanlist2country[]={
- {"us-bcast", 1},
- {"russia", 7},
- {"argentina", 54},
- {"japan-bcast", 81},
- {"china-bcast", 86},
- {"southafrica", 27},
- {"australia", 61},
- {"ireland", 353},
- {"france", 33},
- {"italy", 39},
- {"newzealand", 64},
- //directshow table uses eastern europe freq table for russia
- {"europe-east", 7},
- //directshow table uses western europe freq table for germany
- {"europe-west", 49},
- /* cable channels */
- {"us-cable", 1},
- {"us-cable-hrc", 1},
- {"japan-cable", 81},
- //default is USA
- {NULL, 1}
-};
-
-/**
- array, contains information about various supported (i hope) image formats
-*/
-static const img_fmt img_fmt_list[] = {
- {IMGFMT_YUY2, &MEDIASUBTYPE_YUY2, 16, IMGFMT_YUY2, 0},
- {IMGFMT_YV12, &MEDIASUBTYPE_YV12, 12, IMGFMT_YV12, 0},
- {IMGFMT_IYUV, &MEDIASUBTYPE_IYUV, 12, IMGFMT_IYUV, 0},
- {IMGFMT_I420, &MEDIASUBTYPE_I420, 12, IMGFMT_I420, 0},
- {IMGFMT_UYVY, &MEDIASUBTYPE_UYVY, 16, IMGFMT_UYVY, 0},
- {IMGFMT_YVYU, &MEDIASUBTYPE_YVYU, 16, IMGFMT_YVYU, 0},
- {IMGFMT_YVU9, &MEDIASUBTYPE_YVU9, 9, IMGFMT_YVU9, 0},
- {IMGFMT_BGR32, &MEDIASUBTYPE_RGB32, 32, 0, 0},
- {IMGFMT_BGR24, &MEDIASUBTYPE_RGB24, 24, 0, 0},
- {IMGFMT_BGR16, &MEDIASUBTYPE_RGB565, 16, 3, 12},
- {IMGFMT_BGR15, &MEDIASUBTYPE_RGB555, 16, 3, 12},
- {0, &GUID_NULL, 0, 0, 0}
-};
-
-#define TV_NORMS_COUNT 19
-static const struct {
- long index;
- char *name;
-} tv_norms[TV_NORMS_COUNT] = {
- {
- AnalogVideo_NTSC_M, "ntsc-m"}, {
- AnalogVideo_NTSC_M_J, "ntsc-mj"}, {
- AnalogVideo_NTSC_433, "ntsc-433"}, {
- AnalogVideo_PAL_B, "pal-b"}, {
- AnalogVideo_PAL_D, "pal-d"}, {
- AnalogVideo_PAL_G, "pal-g"}, {
- AnalogVideo_PAL_H, "pal-h"}, {
- AnalogVideo_PAL_I, "pal-i"}, {
- AnalogVideo_PAL_M, "pal-m"}, {
- AnalogVideo_PAL_N, "pal-n"}, {
- AnalogVideo_PAL_60, "pal-60"}, {
- AnalogVideo_SECAM_B, "secam-b"}, {
- AnalogVideo_SECAM_D, "secam-d"}, {
- AnalogVideo_SECAM_G, "secam-g"}, {
- AnalogVideo_SECAM_H, "secam-h"}, {
- AnalogVideo_SECAM_K, "secam-k"}, {
- AnalogVideo_SECAM_K1, "secam-k1"}, {
- AnalogVideo_SECAM_L, "secam-l"}, {
- AnalogVideo_SECAM_L1, "secam-l1"}
-};
-static long tv_available_norms[TV_NORMS_COUNT];
-static int tv_available_norms_count = 0;
-
-
-static long *tv_available_inputs;
-static int tv_available_inputs_count = 0;
-
-/*
-*---------------------------------------------------------------------------------------
-*
-* Various GUID definitions
-*
-*---------------------------------------------------------------------------------------
-*/
-// selectany can not be used with "static", fixes compilation with mingw-w64
-#undef DECLSPEC_SELECTANY
-#define DECLSPEC_SELECTANY
-/// CLSID definitions (used for CoCreateInstance call)
-#define CLSID_SampleGrabber MP_CLSID_SampleGrabber
-static DEFINE_GUID(CLSID_SampleGrabber, 0xC1F400A0, 0x3F08, 0x11d3, 0x9F, 0x0B,
- 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37);
-#define CLSID_NullRenderer MP_CLSID_NullRenderer
-static DEFINE_GUID(CLSID_NullRenderer, 0xC1F400A4, 0x3F08, 0x11d3, 0x9F, 0x0B,
- 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37);
-#define CLSID_SystemDeviceEnum MP_CLSID_SystemDeviceEnum
-static DEFINE_GUID(CLSID_SystemDeviceEnum, 0x62BE5D10, 0x60EB, 0x11d0, 0xBD, 0x3B,
- 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
-#define CLSID_CaptureGraphBuilder2 MP_CLSID_CaptureGraphBuilder2
-static DEFINE_GUID(CLSID_CaptureGraphBuilder2, 0xBF87B6E1, 0x8C27, 0x11d0, 0xB3,
- 0xF0, 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5);
-#define CLSID_VideoInputDeviceCategory MP_CLSID_VideoInputDeviceCategory
-static DEFINE_GUID(CLSID_VideoInputDeviceCategory, 0x860BB310, 0x5D01, 0x11d0,
- 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
-#define CLSID_AudioInputDeviceCategory MP_CLSID_AudioInputDeviceCategory
-static DEFINE_GUID(CLSID_AudioInputDeviceCategory, 0x33d9a762, 0x90c8, 0x11d0,
- 0xbd, 0x43, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86);
-#define CLSID_FilterGraph MP_CLSID_FilterGraph
-static DEFINE_GUID(CLSID_FilterGraph, 0xe436ebb3, 0x524f, 0x11ce, 0x9f, 0x53,
- 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
-#define CLSID_SystemClock MP_CLSID_SystemClock
-static DEFINE_GUID(CLSID_SystemClock, 0xe436ebb1, 0x524f, 0x11ce, 0x9f, 0x53,
- 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
-#ifdef NOT_USED
-#define CLSID_CaptureGraphBuilder MP_CLSID_CaptureGraphBuilder
-static DEFINE_GUID(CLSID_CaptureGraphBuilder, 0xBF87B6E0, 0x8C27, 0x11d0, 0xB3,
- 0xF0, 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5);
-#define CLSID_VideoPortManager MP_CLSID_VideoPortManager
-static DEFINE_GUID(CLSID_VideoPortManager, 0x6f26a6cd, 0x967b, 0x47fd, 0x87, 0x4a,
- 0x7a, 0xed, 0x2c, 0x9d, 0x25, 0xa2);
-#define IID_IPin MP_IID_IPin
-static DEFINE_GUID(IID_IPin, 0x56a86891, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20,
- 0xaf, 0x0b, 0xa7, 0x70);
-#define IID_ICaptureGraphBuilder MP_IID_ICaptureGraphBuilder
-static DEFINE_GUID(IID_ICaptureGraphBuilder, 0xbf87b6e0, 0x8c27, 0x11d0, 0xb3,
- 0xf0, 0x00, 0xaa, 0x00, 0x37, 0x61, 0xc5);
-#define IID_IFilterGraph MP_IID_IFilterGraph
-static DEFINE_GUID(IID_IFilterGraph, 0x56a8689f, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00,
- 0x20, 0xaf, 0x0b, 0xa7, 0x70);
-#define PIN_CATEGORY_PREVIEW MP_PIN_CATEGORY_PREVIEW
-static DEFINE_GUID(PIN_CATEGORY_PREVIEW, 0xfb6c4282, 0x0353, 0x11d1, 0x90, 0x5f,
- 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba);
-#endif
-
-/// IID definitions (used for QueryInterface call)
-#define IID_IReferenceClock MP_IID_IReferenceClock
-static DEFINE_GUID(IID_IReferenceClock, 0x56a86897, 0x0ad4, 0x11ce, 0xb0, 0x3a,
- 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
-#define IID_IAMBufferNegotiation MP_IID_IAMBufferNegotiation
-static DEFINE_GUID(IID_IAMBufferNegotiation, 0x56ED71A0, 0xAF5F, 0x11D0, 0xB3, 0xF0,
- 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5);
-#define IID_IKsPropertySet MP_IID_IKsPropertySet
-static DEFINE_GUID(IID_IKsPropertySet, 0x31efac30, 0x515c, 0x11d0, 0xa9, 0xaa,
- 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93);
-#define IID_ISampleGrabber MP_IID_ISampleGrabber
-static DEFINE_GUID(IID_ISampleGrabber, 0x6B652FFF, 0x11FE, 0x4fce, 0x92, 0xAD,
- 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F);
-#define IID_ISampleGrabberCB MP_IID_ISampleGrabberCB
-static DEFINE_GUID(IID_ISampleGrabberCB, 0x0579154A, 0x2B53, 0x4994, 0xB0, 0xD0,
- 0xE7, 0x73, 0x14, 0x8E, 0xFF, 0x85);
-#define IID_ICaptureGraphBuilder2 MP_IID_ICaptureGraphBuilder2
-static DEFINE_GUID(IID_ICaptureGraphBuilder2, 0x93e5a4e0, 0x2d50, 0x11d2, 0xab,
- 0xfa, 0x00, 0xa0, 0xc9, 0xc6, 0xe3, 0x8d);
-#define IID_ICreateDevEnum MP_IID_ICreateDevEnum
-static DEFINE_GUID(IID_ICreateDevEnum, 0x29840822, 0x5b84, 0x11d0, 0xbd, 0x3b,
- 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86);
-#define IID_IGraphBuilder MP_IID_IGraphBuilder
-static DEFINE_GUID(IID_IGraphBuilder, 0x56a868a9, 0x0ad4, 0x11ce, 0xb0, 0x3a,
- 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
-#define IID_IAMVideoProcAmp MP_IID_IAMVideoProcAmp
-static DEFINE_GUID(IID_IAMVideoProcAmp, 0xC6E13360, 0x30AC, 0x11d0, 0xA1, 0x8C,
- 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56);
-#define IID_IVideoWindow MP_IID_IVideoWindow
-static DEFINE_GUID(IID_IVideoWindow, 0x56a868b4, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00,
- 0x20, 0xaf, 0x0b, 0xa7, 0x70);
-#define IID_IMediaControl MP_IID_IMediaControl
-static DEFINE_GUID(IID_IMediaControl, 0x56a868b1, 0x0ad4, 0x11ce, 0xb0, 0x3a,
- 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
-#define IID_IAMTVTuner MP_IID_IAMTVTuner
-static DEFINE_GUID(IID_IAMTVTuner, 0x211A8766, 0x03AC, 0x11d1, 0x8D, 0x13, 0x00,
- 0xAA, 0x00, 0xBD, 0x83, 0x39);
-#define IID_IAMCrossbar MP_IID_IAMCrossbar
-static DEFINE_GUID(IID_IAMCrossbar, 0xc6e13380, 0x30ac, 0x11d0, 0xa1, 0x8c, 0x00,
- 0xa0, 0xc9, 0x11, 0x89, 0x56);
-#define IID_IAMStreamConfig MP_IID_IAMStreamConfig
-static DEFINE_GUID(IID_IAMStreamConfig, 0xc6e13340, 0x30ac, 0x11d0, 0xa1, 0x8c,
- 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56);
-#define IID_IAMAudioInputMixer MP_IID_IAMAudioInputMixer
-static DEFINE_GUID(IID_IAMAudioInputMixer, 0x54C39221, 0x8380, 0x11d0, 0xB3, 0xF0,
- 0x00, 0xAA, 0x00, 0x37, 0x61, 0xC5);
-#define IID_IAMTVAudio MP_IID_IAMTVAudio
-static DEFINE_GUID(IID_IAMTVAudio, 0x83EC1C30, 0x23D1, 0x11d1, 0x99, 0xE6, 0x00,
- 0xA0, 0xC9, 0x56, 0x02, 0x66);
-#define IID_IAMAnalogVideoDecoder MP_IID_IAMAnalogVideoDecoder
-static DEFINE_GUID(IID_IAMAnalogVideoDecoder, 0xC6E13350, 0x30AC, 0x11d0, 0xA1,
- 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56);
-#define IID_IPropertyBag MP_IID_IPropertyBag
-static DEFINE_GUID(IID_IPropertyBag, 0x55272a00, 0x42cb, 0x11ce, 0x81, 0x35, 0x00,
- 0xaa, 0x00, 0x4b, 0xb8, 0x51);
-#define PIN_CATEGORY_CAPTURE MP_PIN_CATEGORY_CAPTURE
-static DEFINE_GUID(PIN_CATEGORY_CAPTURE, 0xfb6c4281, 0x0353, 0x11d1, 0x90, 0x5f,
- 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba);
-#define PIN_CATEGORY_VIDEOPORT MP_PIN_CATEGORY_VIDEOPORT
-static DEFINE_GUID(PIN_CATEGORY_VIDEOPORT, 0xfb6c4285, 0x0353, 0x11d1, 0x90, 0x5f,
- 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba);
-#define PIN_CATEGORY_PREVIEW MP_PIN_CATEGORY_PREVIEW
-static DEFINE_GUID(PIN_CATEGORY_PREVIEW, 0xfb6c4282, 0x0353, 0x11d1, 0x90, 0x5f,
- 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba);
-#define PIN_CATEGORY_VBI MP_PIN_CATEGORY_VBI
-static DEFINE_GUID(PIN_CATEGORY_VBI, 0xfb6c4284, 0x0353, 0x11d1, 0x90, 0x5f,
- 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba);
-#define PROPSETID_TUNER MP_PROPSETID_TUNER
-static DEFINE_GUID(PROPSETID_TUNER, 0x6a2e0605, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00,
- 0xa0, 0xc9, 0x11, 0x89, 0x56);
-#define MEDIATYPE_VBI MP_MEDIATYPE_VBI
-static DEFINE_GUID(MEDIATYPE_VBI, 0xf72a76e1, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00,
- 0x00, 0xc0, 0xcc, 0x16, 0xba);
-
-#define INSTANCEDATA_OF_PROPERTY_PTR(x) (((KSPROPERTY*)(x)) + 1)
-#define INSTANCEDATA_OF_PROPERTY_SIZE(x) (sizeof((x)) - sizeof(KSPROPERTY))
-
-#define DEVICE_NAME_MAX_LEN 2000
-
-/*---------------------------------------------------------------------------------------
-* Methods, called only from this file
-*---------------------------------------------------------------------------------------*/
-
-static void set_buffer_preference(int nDiv, WAVEFORMATEX *pWF,
- IPin *pOutPin, IPin *pInPin)
-{
- ALLOCATOR_PROPERTIES prop;
- IAMBufferNegotiation* pBN;
- HRESULT hr;
-
- prop.cbAlign = -1;
- prop.cbBuffer = pWF->nAvgBytesPerSec/nDiv;
- if (!prop.cbBuffer)
- prop.cbBuffer = 1;
- prop.cbBuffer += pWF->nBlockAlign - 1;
- prop.cbBuffer -= prop.cbBuffer % pWF->nBlockAlign;
- prop.cbPrefix = -1;
- prop.cBuffers = -1;
-
- hr=OLE_QUERYINTERFACE(pOutPin,IID_IAMBufferNegotiation,pBN);
- if(FAILED(hr))
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: pOutPin->QueryInterface(IID_IAMBufferNegotiation) Error: 0x%x\n",(unsigned int)hr);
- else{
- hr=OLE_CALL_ARGS(pBN,SuggestAllocatorProperties,&prop);
- if(FAILED(hr))
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow:pOutPin->SuggestAllocatorProperties Error:0x%x\n",(unsigned int)hr);
- OLE_RELEASE_SAFE(pBN);
- }
- hr=OLE_QUERYINTERFACE(pInPin,IID_IAMBufferNegotiation,pBN);
- if(FAILED(hr))
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: pInPin->QueryInterface(IID_IAMBufferNegotiation) Error: 0x%x",(unsigned int)hr);
- else{
- hr=OLE_CALL_ARGS(pBN,SuggestAllocatorProperties,&prop);
- if(FAILED(hr))
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: pInPit->SuggestAllocatorProperties Error:0x%x\n",(unsigned int)hr);
- OLE_RELEASE_SAFE(pBN);
- }
-}
-/*
-*---------------------------------------------------------------------------------------
-*
-* CSampleGrabberCD class. Used for receiving samples from DirectShow.
-*
-*---------------------------------------------------------------------------------------
-*/
-/// CSampleGrabberCD destructor
-static void CSampleGrabberCB_Destroy(CSampleGrabberCB * This)
-{
- free(This->lpVtbl);
- free(This);
-}
-
-/// CSampleGrabberCD IUnknown interface methods implementation
-static long STDCALL CSampleGrabberCB_QueryInterface(ISampleGrabberCB *
- This,
- const GUID * riid,
- void **ppvObject)
-{
- CSampleGrabberCB *me = (CSampleGrabberCB *) This;
- GUID *r;
- unsigned int i = 0;
- Debug printf("CSampleGrabberCB_QueryInterface(%p) called\n", This);
- if (!ppvObject)
- return E_POINTER;
- for (r = me->interfaces;
- i < sizeof(me->interfaces) / sizeof(me->interfaces[0]); r++, i++)
- if (!memcmp(r, riid, sizeof(*r))) {
- OLE_CALL(This, AddRef);
- *ppvObject = This;
- return 0;
- }
- Debug printf("Query failed! (GUID: 0x%x)\n", *(unsigned int *) riid);
- return E_NOINTERFACE;
-}
-
-static long STDCALL CSampleGrabberCB_AddRef(ISampleGrabberCB * This)
-{
- CSampleGrabberCB *me = (CSampleGrabberCB *) This;
- Debug printf("CSampleGrabberCB_AddRef(%p) called (ref:%d)\n", This,
- me->refcount);
- return ++(me->refcount);
-}
-
-static long STDCALL CSampleGrabberCB_Release(ISampleGrabberCB * This)
-{
- CSampleGrabberCB *me = (CSampleGrabberCB *) This;
- Debug printf("CSampleGrabberCB_Release(%p) called (new ref:%d)\n",
- This, me->refcount - 1);
- if (--(me->refcount) == 0)
- CSampleGrabberCB_Destroy(me);
- return 0;
-}
-
-
-static HRESULT STDCALL CSampleGrabberCB_BufferCB(ISampleGrabberCB *This,
- double SampleTime,
- BYTE *pBuffer,
- long lBufferLen)
-{
- CSampleGrabberCB *this = (CSampleGrabberCB *) This;
- grabber_ringbuffer_t *rb = this->pbuf;
-
- if (!lBufferLen)
- return E_FAIL;
-
- if (!rb->ringbuffer) {
- rb->buffersize /= lBufferLen;
- if (init_ringbuffer(rb, rb->buffersize, lBufferLen) != S_OK)
- return E_FAIL;
- }
- mp_msg(MSGT_TV, MSGL_DBG4,
- "tvi_dshow: BufferCB(%p): len=%ld ts=%f\n", This, lBufferLen, SampleTime);
- EnterCriticalSection(rb->pMutex);
- if (rb->count >= rb->buffersize) {
- rb->head = (rb->head + 1) % rb->buffersize;
- rb->count--;
- }
-
- memcpy(rb->ringbuffer[rb->tail], pBuffer,
- lBufferLen < rb->blocksize ? lBufferLen : rb->blocksize);
- rb->dpts[rb->tail] = SampleTime;
- rb->tail = (rb->tail + 1) % rb->buffersize;
- rb->count++;
- LeaveCriticalSection(rb->pMutex);
-
- return S_OK;
-}
-
-/// wrapper. directshow does the same when BufferCB callback is requested
-static HRESULT STDCALL CSampleGrabberCB_SampleCB(ISampleGrabberCB *This,
- double SampleTime,
- LPMEDIASAMPLE pSample)
-{
- char* buf;
- long len;
- long long tStart,tEnd;
- HRESULT hr;
- grabber_ringbuffer_t *rb = ((CSampleGrabberCB*)This)->pbuf;
-
- len=OLE_CALL(pSample,GetSize);
- tStart=tEnd=0;
- hr=OLE_CALL_ARGS(pSample,GetTime,&tStart,&tEnd);
- if(FAILED(hr)){
- return hr;
- }
- mp_msg(MSGT_TV, MSGL_DBG4,"tvi_dshow: SampleCB(%p): %d/%d %f\n", This,rb->count,rb->buffersize,1e-7*tStart);
- hr=OLE_CALL_ARGS(pSample,GetPointer,(void*)&buf);
- if(FAILED(hr)){
- return hr;
- }
- hr=CSampleGrabberCB_BufferCB(This,1e-7*tStart,buf,len);
- return hr;
-
-}
-
-/// main grabbing routine
-static CSampleGrabberCB *CSampleGrabberCB_Create(grabber_ringbuffer_t *
- pbuf)
-{
- CSampleGrabberCB *This = malloc(sizeof(CSampleGrabberCB));
- if (!This)
- return NULL;
-
- This->lpVtbl = malloc(sizeof(ISampleGrabberVtbl));
- if (!This->lpVtbl) {
- CSampleGrabberCB_Destroy(This);
- return NULL;
- }
- This->refcount = 1;
- This->lpVtbl->QueryInterface = CSampleGrabberCB_QueryInterface;
- This->lpVtbl->AddRef = CSampleGrabberCB_AddRef;
- This->lpVtbl->Release = CSampleGrabberCB_Release;
- This->lpVtbl->SampleCB = CSampleGrabberCB_SampleCB;
- This->lpVtbl->BufferCB = CSampleGrabberCB_BufferCB;
-
- This->interfaces[0] = IID_IUnknown;
- This->interfaces[1] = IID_ISampleGrabberCB;
-
- This->pbuf = pbuf;
-
- return This;
-}
-
-/*
-*---------------------------------------------------------------------------------------
-*
-* ROT related methods (register, unregister)
-*
-*---------------------------------------------------------------------------------------
-*/
-/**
-Registering graph in ROT. User will be able to connect to graph from GraphEdit.
-*/
-static HRESULT AddToRot(IUnknown * pUnkGraph, DWORD * pdwRegister)
-{
- IMoniker *pMoniker;
- IRunningObjectTable *pROT;
- WCHAR wsz[256];
- HRESULT hr;
-
- if (FAILED(GetRunningObjectTable(0, &pROT))) {
- return E_FAIL;
- }
- wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR) pUnkGraph,
- GetCurrentProcessId());
- hr = CreateItemMoniker(L"!", wsz, &pMoniker);
- if (SUCCEEDED(hr)) {
- hr = OLE_CALL_ARGS(pROT, Register, ROTFLAGS_REGISTRATIONKEEPSALIVE,
- pUnkGraph, pMoniker, pdwRegister);
- OLE_RELEASE_SAFE(pMoniker);
- }
- OLE_RELEASE_SAFE(pROT);
- return hr;
-}
-
-/// Unregistering graph in ROT
-static void RemoveFromRot(DWORD dwRegister)
-{
- IRunningObjectTable *pROT;
- if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
- OLE_CALL_ARGS(pROT, Revoke, dwRegister);
- OLE_RELEASE_SAFE(pROT);
- }
-}
-
-/*
-*---------------------------------------------------------------------------------------
-*
-* ringbuffer related methods (init, destroy)
-*
-*---------------------------------------------------------------------------------------
-*/
-/**
- * \brief ringbuffer destroying routine
- *
- * \param rb pointer to empty (just allocated) ringbuffer structure
- *
- * \note routine does not frees memory, allocated for grabber_rinbuffer_s structure
- */
-static void destroy_ringbuffer(grabber_ringbuffer_t * rb)
-{
- int i;
-
- if (!rb)
- return;
-
- if (rb->ringbuffer) {
- for (i = 0; i < rb->buffersize; i++)
- free(rb->ringbuffer[i]);
- free(rb->ringbuffer);
- rb->ringbuffer = NULL;
- }
- free(rb->dpts);
- rb->dpts = NULL;
- if (rb->pMutex) {
- DeleteCriticalSection(rb->pMutex);
- free(rb->pMutex);
- rb->pMutex = NULL;
- }
-
- rb->blocksize = 0;
- rb->buffersize = 0;
- rb->head = 0;
- rb->tail = 0;
- rb->count = 0;
-}
-
-/**
- * \brief ringbuffer initialization
- *
- * \param rb pointer to empty (just allocated) ringbuffer structure
- * \param buffersize size of buffer in blocks
- * \param blocksize size of buffer's block
- *
- * \return S_OK if success
- * \return E_OUTOFMEMORY not enough memory
- *
- * \note routine does not allocates memory for grabber_rinbuffer_s structure
- */
-static HRESULT init_ringbuffer(grabber_ringbuffer_t * rb, int buffersize,
- int blocksize)
-{
- int i;
-
- if (!rb)
- return E_OUTOFMEMORY;
-
- rb->buffersize = buffersize < 2 ? 2 : buffersize;
- rb->blocksize = blocksize;
-
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Capture buffer: %d blocks of %d bytes.\n",
- rb->buffersize, rb->blocksize);
-
- rb->ringbuffer = malloc(rb->buffersize * sizeof(char *));
- if (!rb)
- return E_POINTER;
- memset(rb->ringbuffer, 0, rb->buffersize * sizeof(char *));
-
- for (i = 0; i < rb->buffersize; i++) {
- rb->ringbuffer[i] = malloc(rb->blocksize * sizeof(char));
- if (!rb->ringbuffer[i]) {
- destroy_ringbuffer(rb);
- return E_OUTOFMEMORY;
- }
- }
- rb->dpts = malloc(rb->buffersize * sizeof(double));
- if (!rb->dpts) {
- destroy_ringbuffer(rb);
- return E_OUTOFMEMORY;
- }
- rb->head = 0;
- rb->tail = 0;
- rb->count = 0;
- rb->tStart = -1;
- rb->pMutex = malloc(sizeof(CRITICAL_SECTION));
- if (!rb->pMutex) {
- destroy_ringbuffer(rb);
- return E_OUTOFMEMORY;
- }
- InitializeCriticalSection(rb->pMutex);
- return S_OK;
-}
-
-/*
-*---------------------------------------------------------------------------------------
-*
-* Tuner related methods (frequency, capabilities, etc
-*
-*---------------------------------------------------------------------------------------
-*/
-/**
- * \brief returns string with name for givend PsysCon_* constant
- *
- * \param lPhysicalType constant from PhysicalConnectorType enumeration
- *
- * \return pointer to string with apropriate name
- *
- * \note
- * Caller should not free returned pointer
- */
-static char *physcon2str(const long lPhysicalType)
-{
- int i;
- for(i=0; tv_physcon_types[i].name; i++)
- if(tv_physcon_types[i].type==lPhysicalType)
- return tv_physcon_types[i].name;
- return "Unknown";
-};
-
-/**
- * \brief converts MPlayer's chanlist to system country code.
- *
- * \param chanlist MPlayer's chanlist name
- *
- * \return system country code
- *
- * \remarks
- * After call to IAMTVTuner::put_CountryCode with returned value tuner switches to frequency table used in specified
- * country (which is usually larger then MPlayer's one, so workaround will work fine).
- *
- * \todo
- * Resolve trouble with cable channels (DirectShow's tuners must be switched between broadcast and cable channels modes.
- */
-static int chanlist2country(char *chanlist)
-{
- int i;
- for(i=0; tv_chanlist2country[i].chanlist_name; i++)
- if (!strcmp(chanlist, tv_chanlist2country[i].chanlist_name))
- break;
- return tv_chanlist2country[i].country_code;
-}
-
-/**
- * \brief loads specified resource from module and return pointer to it
- *
- * \param hDLL valid module desriptor
- * \param index index of resource. resource with name "#<index>" will be loaded
- *
- * \return pointer to loader resource or NULL if error occured
- */
-static void *GetRC(HMODULE hDLL, int index)
-{
- char szRCDATA[10];
- char szName[10];
- HRSRC hRes;
- HGLOBAL hTable;
-
- snprintf(szRCDATA, 10, "#%d", (int)RT_RCDATA);
- snprintf(szName, 10, "#%d", index);
-
- hRes = FindResource(hDLL, szName, szRCDATA);
- if (!hRes) {
- return NULL;
- }
- hTable = LoadResource(hDLL, hRes);
- if (!hTable) {
- return NULL;
- }
- return LockResource(hTable);
-}
-
-/**
- * \brief loads frequency table for given country from kstvtune.ax
- *
- * \param[in] nCountry - country code
- * \param[in] nInputType (TunerInputCable or TunerInputAntenna)
- * \param[out] pplFreqTable - address of variable that receives pointer to array, containing frequencies
- * \param[out] pnLen length of array
- * \param[out] pnFirst - channel number of first entry in array (nChannelMax)
- *
- * \return S_OK if success
- * \return E_POINTER pplFreqTable==NULL || plFirst==NULL || pnLen==NULL
- * \return E_FAIL error occured during load
- *
- * \remarks
- * - array must be freed by caller
- * - MSDN says that it is not neccessery to unlock or free resource. It will be done after unloading DLL
- */
-static HRESULT load_freq_table(int nCountry, int nInputType,
- long **pplFreqTable, int *pnLen,
- int *pnFirst)
-{
- HMODULE hDLL;
- long *plFreqTable;
- TRCCountryList *pCountryList;
- int i, index;
-
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: load_freq_table called %d (%s)\n",nCountry,nInputType == TunerInputAntenna ? "broadcast" : "cable");
- /* ASSERT(sizeof(TRCCountryList)==10); // need properly aligned structure */
-
- if (!pplFreqTable || !pnFirst || !pnLen)
- return E_POINTER;
- if (!nCountry)
- return E_FAIL;
-
- hDLL = LoadLibrary("kstvtune.ax");
- if (!hDLL) {
- return E_FAIL;
- }
- pCountryList = GetRC(hDLL, 9999);
- if (!pCountryList) {
- FreeLibrary(hDLL);
- return E_FAIL;
- }
- for (i = 0; pCountryList[i].CountryCode != 0; i++)
- if (pCountryList[i].CountryCode == nCountry)
- break;
- if (pCountryList[i].CountryCode == 0) {
- FreeLibrary(hDLL);
- return E_FAIL;
- }
- if (nInputType == TunerInputCable)
- index = pCountryList[i].CableFreqTable;
- else
- index = pCountryList[i].BroadcastFreqTable;
-
- plFreqTable = GetRC(hDLL, index); //First element is number of first channel, second - number of last channel
- if (!plFreqTable) {
- FreeLibrary(hDLL);
- return E_FAIL;
- }
- *pnFirst = plFreqTable[0];
- *pnLen = (int) (plFreqTable[1] - plFreqTable[0] + 1);
- *pplFreqTable = malloc((*pnLen) * sizeof(long));
- if (!*pplFreqTable) {
- FreeLibrary(hDLL);
- return E_FAIL;
- }
- for (i = 0; i < *pnLen; i++) {
- (*pplFreqTable)[i] = plFreqTable[i + 2];
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: load_freq_table #%d => (%ld)\n",i+*pnFirst,(*pplFreqTable)[i]);
- }
- FreeLibrary(hDLL);
- return S_OK;
-}
-
-/**
- * \brief tunes to given frequency through IKsPropertySet call
- *
- * \param pTVTuner IAMTVTuner interface of capture device
- * \param lFreq frequency to tune (in Hz)
- *
- * \return S_OK success
- * \return apropriate error code otherwise
- *
- * \note
- * Due to either bug in driver or error in following code calll to IKsProperty::Set
- * in this methods always fail with error 0x8007007a.
- *
- * \todo test code on other machines and an error
- */
-static HRESULT set_frequency_direct(IAMTVTuner * pTVTuner, long lFreq)
-{
- HRESULT hr;
- DWORD dwSupported = 0;
- DWORD cbBytes = 0;
- KSPROPERTY_TUNER_MODE_CAPS_S mode_caps;
- KSPROPERTY_TUNER_FREQUENCY_S frequency;
- IKsPropertySet *pKSProp;
-
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: set_frequency_direct called\n");
-
- memset(&mode_caps, 0, sizeof(mode_caps));
- memset(&frequency, 0, sizeof(frequency));
-
- hr = OLE_QUERYINTERFACE(pTVTuner, IID_IKsPropertySet, pKSProp);
- if (FAILED(hr))
- return hr; //no IKsPropertySet interface
-
- mode_caps.Mode = AMTUNER_MODE_TV;
- hr = OLE_CALL_ARGS(pKSProp, QuerySupported, &PROPSETID_TUNER,
- KSPROPERTY_TUNER_MODE_CAPS, &dwSupported);
- if (FAILED(hr)) {
- OLE_RELEASE_SAFE(pKSProp);
- return hr;
- }
-
- if (!dwSupported & KSPROPERTY_SUPPORT_GET) {
- OLE_RELEASE_SAFE(pKSProp);
- return E_FAIL; //PROPSETID_TINER not supported
- }
-
- hr = OLE_CALL_ARGS(pKSProp, Get, &PROPSETID_TUNER,
- KSPROPERTY_TUNER_MODE_CAPS,
- INSTANCEDATA_OF_PROPERTY_PTR(&mode_caps),
- INSTANCEDATA_OF_PROPERTY_SIZE(mode_caps),
- &mode_caps, sizeof(mode_caps), &cbBytes);
-
- frequency.Frequency = lFreq;
-
- if (mode_caps.Strategy == KS_TUNER_STRATEGY_DRIVER_TUNES)
- frequency.TuningFlags = KS_TUNER_TUNING_FINE;
- else
- frequency.TuningFlags = KS_TUNER_TUNING_EXACT;
-
- if (lFreq < mode_caps.MinFrequency || lFreq > mode_caps.MaxFrequency) {
- OLE_RELEASE_SAFE(pKSProp);
- return E_FAIL;
- }
-
- hr = OLE_CALL_ARGS(pKSProp, Set, &PROPSETID_TUNER,
- KSPROPERTY_TUNER_FREQUENCY,
- INSTANCEDATA_OF_PROPERTY_PTR(&frequency),
- INSTANCEDATA_OF_PROPERTY_SIZE(frequency),
- &frequency, sizeof(frequency));
- if (FAILED(hr)) {
- OLE_RELEASE_SAFE(pKSProp);
- return hr;
- }
-
- OLE_RELEASE_SAFE(pKSProp);
-
- return S_OK;
-}
-
-/**
- * \brief find channel with nearest frequency and set it
- *
- * \param priv driver's private data
- * \param lFreq frequency in Hz
- *
- * \return S_OK if success
- * \return E_FAIL if error occured
- */
-static HRESULT set_nearest_freq(priv_t * priv, long lFreq)
-{
- HRESULT hr;
- int i;
- long lFreqDiff=-1;
- int nChannel;
- TunerInputType tunerInput;
- long lInput;
-
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: set_nearest_freq called: %ld\n", lFreq);
- if(priv->freq_table_len == -1 && !priv->freq_table) {
-
- hr = OLE_CALL_ARGS(priv->pTVTuner, get_ConnectInput, &lInput);
- if(FAILED(hr)){ //Falling back to 0
- lInput=0;
- }
-
- hr = OLE_CALL_ARGS(priv->pTVTuner, get_InputType, lInput, &tunerInput);
-
- if (load_freq_table(chanlist2country(priv->tv_param->chanlist), tunerInput, &(priv->freq_table), &(priv->freq_table_len), &(priv->first_channel)) != S_OK) {//FIXME
- priv->freq_table_len=0;
- priv->freq_table=NULL;
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Unable to load frequency table from kstvtune.ax\n");
- return E_FAIL;
- };
- mp_tmsg(MSGT_TV, MSGL_V, "tvi_dshow: loaded system (%s) frequency table for country id=%d (channels:%d).\n", tunerInput == TunerInputAntenna ? "broadcast" : "cable",
- chanlist2country(priv->tv_param->chanlist), priv->freq_table_len);
- }
-
- if (priv->freq_table_len <= 0)
- return E_FAIL;
-
- //FIXME: rewrite search algo
- nChannel = -1;
- for (i = 0; i < priv->freq_table_len; i++) {
- if (nChannel == -1 || labs(lFreq - priv->freq_table[i]) < lFreqDiff) {
- nChannel = priv->first_channel + i;
- lFreqDiff = labs(lFreq - priv->freq_table[i]);
- }
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: set_nearest_freq #%d (%ld) => %d (%ld)\n",i+priv->first_channel,priv->freq_table[i], nChannel,lFreqDiff);
- }
- if (nChannel == -1) {
- mp_tmsg(MSGT_TV,MSGL_ERR, "tvi_dshow: Unable to find nearest channel in system frequency table\n");
- return E_FAIL;
- }
- mp_msg(MSGT_TV, MSGL_V, "tvi_dshow: set_nearest_freq #%d (%ld)\n",nChannel,priv->freq_table[nChannel - priv->first_channel]);
- hr = OLE_CALL_ARGS(priv->pTVTuner, put_Channel, nChannel,
- AMTUNER_SUBCHAN_DEFAULT, AMTUNER_SUBCHAN_DEFAULT);
- if (FAILED(hr)) {
- mp_tmsg(MSGT_TV,MSGL_ERR,"tvi_dshow: Unable to switch to nearest channel from system frequency table. Error:0x%x\n", (unsigned int)hr);
- return E_FAIL;
- }
- return S_OK;
-}
-
-/**
- * \brief setting frequency. decides whether use direct call/workaround
- *
- * \param priv driver's private data
- * \param lFreq frequency in Hz
- *
- * \return TVI_CONTROL_TRUE if success
- * \return TVI_CONTROL_FALSE if error occured
- *
- * \todo check for freq boundary
- */
-static int set_frequency(priv_t * priv, long lFreq)
-{
- HRESULT hr;
-
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: set_frequency called: %ld\n", lFreq);
- if (!priv->pTVTuner)
- return TVI_CONTROL_FALSE;
- if (priv->direct_setfreq_call) { //using direct call to set frequency
- hr = set_frequency_direct(priv->pTVTuner, lFreq);
- if (FAILED(hr)) {
- mp_tmsg(MSGT_TV, MSGL_V, "tvi_dshow: Unable to set frequency directly. OS built-in channels table will be used.\n");
- priv->direct_setfreq_call = 0;
- }
- }
- if (!priv->direct_setfreq_call) {
- hr = set_nearest_freq(priv, lFreq);
- }
- if (FAILED(hr))
- return TVI_CONTROL_FALSE;
-#ifdef DEPRECATED
- priv->pGrabber->ClearBuffer(priv->pGrabber);
-#endif
- return TVI_CONTROL_TRUE;
-}
-
-/**
- * \brief return current frequency from tuner (in Hz)
- *
- * \param pTVTuner IAMTVTuner interface of tuner
- * \param plFreq address of variable that receives current frequency
- *
- * \return S_OK success
- * \return E_POINTER pTVTuner==NULL || plFreq==NULL
- * \return apropriate error code otherwise
- */
-static HRESULT get_frequency_direct(IAMTVTuner * pTVTuner, long *plFreq)
-{
- HRESULT hr;
- KSPROPERTY_TUNER_STATUS_S TunerStatus;
- DWORD cbBytes;
- IKsPropertySet *pKSProp;
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: get_frequency_direct called\n");
-
- if (!plFreq)
- return E_POINTER;
-
- hr = OLE_QUERYINTERFACE(pTVTuner, IID_IKsPropertySet, pKSProp);
- if (FAILED(hr)) {
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Get freq QueryInterface failed\n");
- return hr;
- }
-
- hr = OLE_CALL_ARGS(pKSProp, Get, &PROPSETID_TUNER,
- KSPROPERTY_TUNER_STATUS,
- INSTANCEDATA_OF_PROPERTY_PTR(&TunerStatus),
- INSTANCEDATA_OF_PROPERTY_SIZE(TunerStatus),
- &TunerStatus, sizeof(TunerStatus), &cbBytes);
- if (FAILED(hr)) {
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Get freq Get failure\n");
- return hr;
- }
- *plFreq = TunerStatus.CurrentFrequency;
- return S_OK;
-}
-
-/**
- * \brief gets current frequency
- *
- * \param priv driver's private data structure
- * \param plFreq - pointer to long int to store frequency to (in Hz)
- *
- * \return TVI_CONTROL_TRUE if success, TVI_CONTROL_FALSE otherwise
- */
-static int get_frequency(priv_t * priv, long *plFreq)
-{
- HRESULT hr;
-
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: get_frequency called\n");
-
- if (!plFreq || !priv->pTVTuner)
- return TVI_CONTROL_FALSE;
-
- if (priv->direct_getfreq_call) { //using direct call to get frequency
- hr = get_frequency_direct(priv->pTVTuner, plFreq);
- if (FAILED(hr)) {
- mp_tmsg(MSGT_TV, MSGL_INFO, "tvi_dshow: Unable to get frequency directly. OS built-in channels table will be used.\n");
- priv->direct_getfreq_call = 0;
- }
- }
- if (!priv->direct_getfreq_call) {
- hr=OLE_CALL_ARGS(priv->pTVTuner, get_VideoFrequency, plFreq);
- if (FAILED(hr))
- return TVI_CONTROL_FALSE;
-
- }
- return TVI_CONTROL_TRUE;
-}
-
-/**
- * \brief get tuner capabilities
- *
- * \param priv driver's private data
- */
-static void get_capabilities(priv_t * priv)
-{
- long lAvailableFormats;
- HRESULT hr;
- int i;
- long lInputPins, lOutputPins, lRelated, lPhysicalType;
- IEnumPins *pEnum;
- char tmp[200];
- IPin *pPin = 0;
- PIN_DIRECTION ThisPinDir;
- PIN_INFO pi;
- IAMAudioInputMixer *pIAMixer;
-
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: get_capabilities called\n");
- if (priv->pTVTuner) {
-
- mp_tmsg(MSGT_TV, MSGL_V, "tvi_dshow: supported norms:");
- hr = OLE_CALL_ARGS(priv->pTVTuner, get_AvailableTVFormats,
- &lAvailableFormats);
- if (FAILED(hr))
- tv_available_norms_count = 0;
- else {
- for (i = 0; i < TV_NORMS_COUNT; i++) {
- if (lAvailableFormats & tv_norms[i].index) {
- tv_available_norms[tv_available_norms_count] = i;
- mp_msg(MSGT_TV, MSGL_V, " %d=%s;",
- tv_available_norms_count + 1, tv_norms[i].name);
- tv_available_norms_count++;
- }
- }
- }
- mp_msg(MSGT_TV, MSGL_INFO, "\n");
- }
- if (priv->pCrossbar) {
- OLE_CALL_ARGS(priv->pCrossbar, get_PinCounts, &lOutputPins,
- &lInputPins);
-
- tv_available_inputs = malloc(sizeof(long) * lInputPins);
- tv_available_inputs_count = 0;
-
- mp_tmsg(MSGT_TV, MSGL_V, "tvi_dshow: available video inputs:");
- for (i = 0; i < lInputPins; i++) {
- OLE_CALL_ARGS(priv->pCrossbar, get_CrossbarPinInfo, 1, i,
- &lRelated, &lPhysicalType);
-
- if (lPhysicalType < 0x1000) {
- tv_available_inputs[tv_available_inputs_count++] = i;
- mp_msg(MSGT_TV, MSGL_V, " %d=%s;",
- tv_available_inputs_count - 1,
- physcon2str(lPhysicalType));
- }
- }
- mp_msg(MSGT_TV, MSGL_INFO, "\n");
-
- set_crossbar_input(priv, 0);
- }
-
- if (priv->adev_index != -1) {
- hr = OLE_CALL_ARGS(priv->chains[1]->pCaptureFilter, EnumPins, &pEnum);
- if (FAILED(hr))
- return;
- mp_tmsg(MSGT_TV, MSGL_V, "tvi_dshow: available audio inputs:");
- i = 0;
- while (OLE_CALL_ARGS(pEnum, Next, 1, &pPin, NULL) == S_OK) {
- memset(&pi, 0, sizeof(pi));
- memset(tmp, 0, 200);
- OLE_CALL_ARGS(pPin, QueryDirection, &ThisPinDir);
- if (ThisPinDir == PINDIR_INPUT) {
- OLE_CALL_ARGS(pPin, QueryPinInfo, &pi);
- wtoa(pi.achName, tmp, 200);
- OLE_RELEASE_SAFE(pi.pFilter);
- mp_msg(MSGT_TV, MSGL_V, " %d=%s", i, tmp);
- mp_msg(MSGT_TV, MSGL_DBG3, " (%p)", pPin);
- hr = OLE_QUERYINTERFACE(pPin, IID_IAMAudioInputMixer,pIAMixer);
- if (SUCCEEDED(hr)) {
- if (i == priv->tv_param->audio_id) {
- OLE_CALL_ARGS(pIAMixer, put_Enable, TRUE);
- if(priv->tv_param->volume>0)
- OLE_CALL_ARGS(pIAMixer, put_MixLevel, 0.01 * priv->tv_param->volume);
-#if 0
- else
- OLE_CALL_ARGS(pIAMixer, put_MixLevel, 1.0);
-#endif
- mp_tmsg(MSGT_TV, MSGL_V, "(selected)");
- } else {
- OLE_CALL_ARGS(pIAMixer, put_Enable, FALSE);
-#if 0
- OLE_CALL_ARGS(pIAMixer, put_MixLevel, 0.0);
-#endif
- }
- OLE_RELEASE_SAFE(pIAMixer);
- }
- mp_msg(MSGT_TV, MSGL_V, ";");
- OLE_RELEASE_SAFE(pPin);
- i++;
- }
- }
- mp_msg(MSGT_TV, MSGL_INFO, "\n");
- OLE_RELEASE_SAFE(pEnum);
- }
-}
-
-/*
-*---------------------------------------------------------------------------------------
-*
-* Filter related methods
-*
-*---------------------------------------------------------------------------------------
-*/
-/**
- * \brief building in graph audio/video capture chain
- *
- * \param priv driver's private data
- * \param pCaptureFilter pointer to capture device's IBaseFilter interface
- * \param pbuf ringbuffer data structure
- * \param pmt media type for chain (AM_MEDIA_TYPE)
- *
- * \note routine does not frees memory, allocated for grabber_rinbuffer_s structure
- */
-static HRESULT build_sub_graph(priv_t * priv, chain_t * chain, const GUID* ppin_category)
-{
- HRESULT hr;
- int nFormatProbed = 0;
-
- IPin *pSGOut;
- IPin *pNRIn=NULL;
-
- IBaseFilter *pNR = NULL;
-
- hr=S_OK;
-
- //No supported formats
- if(!chain->arpmt[0])
- return E_FAIL;
-
- do{
- hr = OLE_CALL_ARGS(priv->pBuilder, FindPin,
- (IUnknown *) chain->pCaptureFilter,
- PINDIR_OUTPUT, ppin_category,
- chain->majortype, FALSE, 0, &chain->pCapturePin);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: FindPin(pCapturePin) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- /* Addinf SampleGrabber filter for video stream */
- hr = CoCreateInstance((GUID *) & CLSID_SampleGrabber, NULL,CLSCTX_INPROC_SERVER, &IID_IBaseFilter,(void *) &chain->pSGF);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: CoCreateInstance(SampleGrabber) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- hr = OLE_CALL_ARGS(priv->pGraph, AddFilter, chain->pSGF, L"Sample Grabber");
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: AddFilter(SampleGrabber) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- hr = OLE_CALL_ARGS(priv->pBuilder, FindPin, (IUnknown *) chain->pSGF,PINDIR_INPUT, NULL, NULL, FALSE, 0, &chain->pSGIn);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: FindPin(pSGIn) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- hr = OLE_CALL_ARGS(priv->pBuilder, FindPin, (IUnknown *) chain->pSGF,PINDIR_OUTPUT, NULL, NULL, FALSE, 0, &pSGOut);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: FindPin(pSGOut) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
-
- /* creating ringbuffer for video samples */
- chain->pCSGCB = CSampleGrabberCB_Create(chain->rbuf);
- if(!chain->pCSGCB){
- mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: CSampleGrabberCB_Create(pbuf) call failed. Error:0x%x\n", (unsigned int)E_OUTOFMEMORY);
- break;
- }
-
- /* initializing SampleGrabber filter */
- hr = OLE_QUERYINTERFACE(chain->pSGF, IID_ISampleGrabber, chain->pSG);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: QueryInterface(IID_ISampleGrabber) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- // hr = OLE_CALL_ARGS(pSG, SetCallback, (ISampleGrabberCB *) pCSGCB, 1); //we want to receive copy of sample's data
- hr = OLE_CALL_ARGS(chain->pSG, SetCallback, (ISampleGrabberCB *) chain->pCSGCB, 0); //we want to receive sample
-
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: SetCallback(pSG) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- hr = OLE_CALL_ARGS(chain->pSG, SetOneShot, FALSE); //... for all frames
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: SetOneShot(pSG) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- hr = OLE_CALL_ARGS(chain->pSG, SetBufferSamples, FALSE); //... do not buffer samples in sample grabber
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: SetBufferSamples(pSG) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
-
- if(priv->tv_param->normalize_audio_chunks && chain->type==audio){
- set_buffer_preference(20,(WAVEFORMATEX*)(chain->arpmt[nFormatProbed]->pbFormat),chain->pCapturePin,chain->pSGIn);
- }
-
- for(nFormatProbed=0; chain->arpmt[nFormatProbed]; nFormatProbed++)
- {
- DisplayMediaType("Probing format", chain->arpmt[nFormatProbed]);
- hr = OLE_CALL_ARGS(chain->pSG, SetMediaType, chain->arpmt[nFormatProbed]); //set desired mediatype
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: SetMediaType(pSG) call failed. Error:0x%x\n", (unsigned int)hr);
- continue;
- }
- /* connecting filters together: VideoCapture --> SampleGrabber */
- hr = OLE_CALL_ARGS(priv->pGraph, Connect, chain->pCapturePin, chain->pSGIn);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: Unable to create pCapturePin<->pSGIn connection. Error:0x%x\n", (unsigned int)hr);
- continue;
- }
- break;
- }
-
- if(!chain->arpmt[nFormatProbed])
- {
- mp_msg(MSGT_TV, MSGL_WARN, "tvi_dshow: Unable to negotiate media format\n");
- hr = E_FAIL;
- break;
- }
-
- hr = OLE_CALL_ARGS(chain->pCapturePin, ConnectionMediaType, chain->pmt);
- if(FAILED(hr))
- {
- mp_tmsg(MSGT_TV, MSGL_WARN, "tvi_dshow: Unable to get actual mediatype (Error:0x%x). Assuming equal to requested.\n", (unsigned int)hr);
- }
-
- if(priv->tv_param->hidden_video_renderer){
- IEnumFilters* pEnum;
- IBaseFilter* pFilter;
-
- hr=OLE_CALL_ARGS(priv->pBuilder,RenderStream,NULL,NULL,(IUnknown*)chain->pCapturePin,NULL,NULL);
-
- OLE_CALL_ARGS(priv->pGraph, EnumFilters, &pEnum);
- while (OLE_CALL_ARGS(pEnum, Next, 1, &pFilter, NULL) == S_OK) {
- LPVIDEOWINDOW pVideoWindow;
- hr = OLE_QUERYINTERFACE(pFilter, IID_IVideoWindow, pVideoWindow);
- if (SUCCEEDED(hr))
- {
- OLE_CALL_ARGS(pVideoWindow,put_Visible,/* OAFALSE*/ 0);
- OLE_CALL_ARGS(pVideoWindow,put_AutoShow,/* OAFALSE*/ 0);
- OLE_RELEASE_SAFE(pVideoWindow);
- }
- OLE_RELEASE_SAFE(pFilter);
- }
- OLE_RELEASE_SAFE(pEnum);
- }else
- {
-#if 0
- /*
- Code below is disabled, because terminating chain with NullRenderer leads to jerky video.
- Perhaps, this happens because NullRenderer filter discards each received
- frame while discarded frames causes live source filter to dramatically reduce frame rate.
- */
- /* adding sink for video stream */
- hr = CoCreateInstance((GUID *) & CLSID_NullRenderer, NULL,CLSCTX_INPROC_SERVER, &IID_IBaseFilter,(void *) &pNR);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: CoCreateInstance(NullRenderer) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- hr = OLE_CALL_ARGS(priv->pGraph, AddFilter, pNR, L"Null Renderer");
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: AddFilter(NullRenderer) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- hr = OLE_CALL_ARGS(priv->pBuilder, FindPin, (IUnknown *) pNR,PINDIR_INPUT, NULL, NULL, FALSE, 0, &pNRIn);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: FindPin(pNRIn) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- /*
- Prevent ending VBI chain with NullRenderer filter, because this causes VBI pin disconnection
- */
- if(memcmp(&(arpmt[nFormatProbed]->majortype),&MEDIATYPE_VBI,16)){
- /* connecting filters together: SampleGrabber --> NullRenderer */
- hr = OLE_CALL_ARGS(priv->pGraph, Connect, pSGOut, pNRIn);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: Unable to create pSGOut<->pNRIn connection. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- }
-#endif
- }
-
- hr = S_OK;
- } while(0);
-
- OLE_RELEASE_SAFE(pSGOut);
- OLE_RELEASE_SAFE(pNR);
- OLE_RELEASE_SAFE(pNRIn);
-
- return hr;
-}
-
-/**
- * \brief configures crossbar for grabbing video stream from given input
- *
- * \param priv driver's private data
- * \param input index of available video input to get data from
- *
- * \return TVI_CONTROL_TRUE success
- * \return TVI_CONTROL_FALSE error
- */
-static int set_crossbar_input(priv_t * priv, int input)
-{
- HRESULT hr;
- int i, nVideoDecoder, nAudioDecoder;
- long lInput, lInputRelated, lRelated, lPhysicalType, lOutputPins,
- lInputPins;
-
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: Configuring crossbar\n");
- if (!priv->pCrossbar || input < 0
- || input >= tv_available_inputs_count)
- return TVI_CONTROL_FALSE;
-
- OLE_CALL_ARGS(priv->pCrossbar, get_PinCounts, &lOutputPins, &lInputPins);
-
- lInput = tv_available_inputs[input];
-
- if (lInput < 0 || lInput >= lInputPins)
- return TVI_CONTROL_FALSE;
-
- OLE_CALL_ARGS(priv->pCrossbar, get_CrossbarPinInfo, 1 /* input */ , lInput,
- &lInputRelated, &lPhysicalType);
-
- nVideoDecoder = nAudioDecoder = -1;
- for (i = 0; i < lOutputPins; i++) {
- OLE_CALL_ARGS(priv->pCrossbar, get_CrossbarPinInfo, 0 /*output */ , i,
- &lRelated, &lPhysicalType);
- if (lPhysicalType == PhysConn_Video_VideoDecoder)
- nVideoDecoder = i;
- if (lPhysicalType == PhysConn_Audio_AudioDecoder)
- nAudioDecoder = i;
- }
- if (nVideoDecoder >= 0) {
- //connecting given input with video decoder
- hr = OLE_CALL_ARGS(priv->pCrossbar, Route, nVideoDecoder, lInput);
- if (hr != S_OK) {
- mp_tmsg(MSGT_TV,MSGL_ERR,"Unable to connect given input to video decoder. Error:0x%x\n", (unsigned int)hr);
- return TVI_CONTROL_FALSE;
- }
- }
- if (nAudioDecoder >= 0 && lInputRelated >= 0) {
- hr = OLE_CALL_ARGS(priv->pCrossbar, Route, nAudioDecoder,
- lInputRelated);
- if (hr != S_OK) {
- mp_tmsg(MSGT_TV,MSGL_ERR,"Unable to connect given input to audio decoder. Error:0x%x\n", (unsigned int)hr);
- return TVI_CONTROL_FALSE;
- }
- }
- return TVI_CONTROL_TRUE;
-}
-
-/**
- * \brief adjusts video control (hue,saturation,contrast,brightess)
- *
- * \param priv driver's private data
- * \param control which control to adjust
- * \param value new value for control (0-100)
- *
- * \return TVI_CONTROL_TRUE success
- * \return TVI_CONTROL_FALSE error
- */
-static int set_control(priv_t * priv, int control, int value)
-{
- long lMin, lMax, lStepping, lDefault, lFlags, lValue;
- HRESULT hr;
-
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: set_control called\n");
- if (value < -100 || value > 100 || !priv->pVideoProcAmp)
- return TVI_CONTROL_FALSE;
-
- hr = OLE_CALL_ARGS(priv->pVideoProcAmp, GetRange, control,
- &lMin, &lMax, &lStepping, &lDefault, &lFlags);
- if (FAILED(hr) || lFlags != VideoProcAmp_Flags_Manual)
- return TVI_CONTROL_FALSE;
-
- lValue = lMin + (value + 100) * (lMax - lMin) / 200;
- /*
- Workaround for ATI AIW 7500. The driver reports: max=255, stepping=256
- */
- if (lStepping > lMax) {
- mp_msg(MSGT_TV, MSGL_DBG3,
- "tvi_dshow: Stepping (%ld) is bigger than max value (%ld) for control %d. Assuming 1\n",
- lStepping, lMax,control);
- lStepping = 1;
- }
- lValue -= lValue % lStepping;
- hr = OLE_CALL_ARGS(priv->pVideoProcAmp, Set, control, lValue,
- VideoProcAmp_Flags_Manual);
- if (FAILED(hr))
- return TVI_CONTROL_FALSE;
-
- return TVI_CONTROL_TRUE;
-}
-
-/**
- * \brief get current value of video control (hue,saturation,contrast,brightess)
- *
- * \param priv driver's private data
- * \param control which control to adjust
- * \param pvalue address of variable thar receives current value
- *
- * \return TVI_CONTROL_TRUE success
- * \return TVI_CONTROL_FALSE error
- */
-static int get_control(priv_t * priv, int control, int *pvalue)
-{
- long lMin, lMax, lStepping, lDefault, lFlags, lValue;
- HRESULT hr;
-
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: get_control called\n");
- if (!pvalue || !priv->pVideoProcAmp)
- return TVI_CONTROL_FALSE;
-
- hr = OLE_CALL_ARGS(priv->pVideoProcAmp, GetRange, control,
- &lMin, &lMax, &lStepping, &lDefault, &lFlags);
- if (FAILED(hr))
- return TVI_CONTROL_FALSE;
- if (lMin == lMax) {
- *pvalue = lMin;
- return TVI_CONTROL_TRUE;
- }
-
- hr = OLE_CALL_ARGS(priv->pVideoProcAmp, Get, control, &lValue, &lFlags);
- if (FAILED(hr))
- return TVI_CONTROL_FALSE;
-
- *pvalue = 200 * (lValue - lMin) / (lMax - lMin) - 100;
-
- return TVI_CONTROL_TRUE;
-}
-
-/**
- * \brief create AM_MEDIA_TYPE structure, corresponding to given FourCC code and width/height/fps
- * \param fcc FourCC code for video format
- * \param width picture width
- * \param height pciture height
- * \param fps frames per second (required for bitrate calculation)
- *
- * \return pointer to AM_MEDIA_TYPE structure if success, NULL - otherwise
- */
-static AM_MEDIA_TYPE* create_video_format(int fcc, int width, int height, int fps)
-{
- int i;
- AM_MEDIA_TYPE mt;
- VIDEOINFOHEADER vHdr;
-
- /* Check given fcc in lookup table*/
- for(i=0; img_fmt_list[i].fmt && img_fmt_list[i].fmt!=fcc; i++) /* NOTHING */;
- if(!img_fmt_list[i].fmt)
- return NULL;
-
- memset(&mt, 0, sizeof(AM_MEDIA_TYPE));
- memset(&vHdr, 0, sizeof(VIDEOINFOHEADER));
-
- vHdr.bmiHeader.biSize = sizeof(vHdr.bmiHeader);
- vHdr.bmiHeader.biWidth = width;
- vHdr.bmiHeader.biHeight = height;
- //FIXME: is biPlanes required too?
- //vHdr.bmiHeader.biPlanes = img_fmt_list[i].nPlanes;
- vHdr.bmiHeader.biBitCount = img_fmt_list[i].nBits;
- vHdr.bmiHeader.biCompression = img_fmt_list[i].nCompression;
- vHdr.bmiHeader.biSizeImage = width * height * img_fmt_list[i].nBits / 8;
- vHdr.dwBitRate = vHdr.bmiHeader.biSizeImage * 8 * fps;
-
- mt.pbFormat = (char*)&vHdr;
- mt.cbFormat = sizeof(vHdr);
-
- mt.majortype = MEDIATYPE_Video;
- mt.subtype = *img_fmt_list[i].subtype;
- mt.formattype = FORMAT_VideoInfo;
-
- mt.bFixedSizeSamples = 1;
- mt.bTemporalCompression = 0;
- mt.lSampleSize = vHdr.bmiHeader.biSizeImage;
-
- return CreateMediaType(&mt);
-}
-
-/**
- * \brief extracts fcc,width,height from AM_MEDIA_TYPE
- *
- * \param pmt pointer to AM_MEDIA_TYPE to extract data from
- * \param pfcc address of variable that receives FourCC
- * \param pwidth address of variable that receives width
- * \param pheight address of variable that recevies height
- *
- * \return 1 if data extracted successfully, 0 - otherwise
- */
-static int extract_video_format(AM_MEDIA_TYPE * pmt, int *pfcc,
- int *pwidth, int *pheight)
-{
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: extract_video_format called\n");
- if (!pmt)
- return 0;
- if (!pmt->pbFormat)
- return 0;
- if (memcmp(&(pmt->formattype), &FORMAT_VideoInfo, 16) != 0)
- return 0;
- if (pfcc)
- *pfcc = subtype2imgfmt(&(pmt->subtype));
- if (pwidth)
- *pwidth = ((VIDEOINFOHEADER *) pmt->pbFormat)->bmiHeader.biWidth;
- if (pheight)
- *pheight = ((VIDEOINFOHEADER *) pmt->pbFormat)->bmiHeader.biHeight;
- return 1;
-}
-
-/**
- * \brief extracts samplerate,bits,channels from AM_MEDIA_TYPE
- *
- * \param pmt pointer to AM_MEDIA_TYPE to extract data from
- * \param pfcc address of variable that receives samplerate
- * \param pwidth address of variable that receives number of bits per sample
- * \param pheight address of variable that recevies number of channels
- *
- * \return 1 if data extracted successfully, 0 - otherwise
- */
-static int extract_audio_format(AM_MEDIA_TYPE * pmt, int *psamplerate,
- int *pbits, int *pchannels)
-{
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: extract_audio_format called\n");
- if (!pmt)
- return 0;
- if (!pmt->pbFormat)
- return 0;
- if (memcmp(&(pmt->formattype), &FORMAT_WaveFormatEx, 16) != 0)
- return 0;
- if (psamplerate)
- *psamplerate = ((WAVEFORMATEX *) pmt->pbFormat)->nSamplesPerSec;
- if (pbits)
- *pbits = ((WAVEFORMATEX *) pmt->pbFormat)->wBitsPerSample;
- if (pchannels)
- *pchannels = ((WAVEFORMATEX *) pmt->pbFormat)->nChannels;
- return 1;
-}
-
-/**
- * \brief checks if AM_MEDIA_TYPE compatible with given samplerate,bits,channels
- *
- * \param pmt pointer to AM_MEDIA_TYPE for check
- * \param samplerate audio samplerate
- * \param bits bits per sample
- * \param channels number of audio channels
- *
- * \return 1 if AM_MEDIA_TYPE compatible
- * \return 0 if not
- */
-static int check_audio_format(AM_MEDIA_TYPE * pmt, int samplerate,
- int bits, int channels)
-{
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: check_audio_format called\n");
- if (!pmt)
- return 0;
- if (memcmp(&(pmt->majortype), &MEDIATYPE_Audio, 16) != 0)
- return 0;
- if (memcmp(&(pmt->subtype), &MEDIASUBTYPE_PCM, 16) != 0)
- return 0;
- if (memcmp(&(pmt->formattype), &FORMAT_WaveFormatEx, 16) != 0)
- return 0;
- if (!pmt->pbFormat)
- return 0;
- if (((WAVEFORMATEX *) pmt->pbFormat)->nSamplesPerSec != samplerate)
- return 0;
- if (((WAVEFORMATEX *) pmt->pbFormat)->wBitsPerSample != bits)
- return 0;
- if (channels > 0
- && ((WAVEFORMATEX *) pmt->pbFormat)->nChannels != channels)
- return 0;
-
- return 1;
-}
-
-/**
- * \brief checks if AM_MEDIA_TYPE compatible with given fcc,width,height
- *
- * \param pmt pointer to AM_MEDIA_TYPE for check
- * \param fcc FourCC (compression)
- * \param width width of picture
- * \param height height of picture
- *
- * \return 1 if AM_MEDIA_TYPE compatible
- & \return 0 if not
- *
- * \note
- * width and height are currently not used
- *
- * \todo
- * add width/height check
- */
-static int check_video_format(AM_MEDIA_TYPE * pmt, int fcc, int width,
- int height)
-{
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: check_video_format called\n");
- if (!pmt)
- return 0;
- if (memcmp(&(pmt->majortype), &MEDIATYPE_Video, 16) != 0)
- return 0;
- if (subtype2imgfmt(&(pmt->subtype)) != fcc)
- return 0;
- return 1;
-}
-
-/**
- * \brief converts DirectShow subtype to MPlayer's IMGFMT
- *
- * \param subtype DirectShow subtype for video format
- *
- * \return MPlayer's IMGFMT or 0 if error occured
- */
-static int subtype2imgfmt(const GUID * subtype)
-{
- int i;
- for (i = 0; img_fmt_list[i].fmt; i++) {
- if (memcmp(subtype, img_fmt_list[i].subtype, 16) == 0)
- return img_fmt_list[i].fmt;
- }
- return 0;
-}
-
-/**
- * \brief prints filter name and it pins
- *
- * \param pFilter - IBaseFilter to get data from
- *
- * \return S_OK if success, error code otherwise
- */
-static HRESULT show_filter_info(IBaseFilter * pFilter)
-{
- char tmp[200];
- FILTER_INFO fi;
- LPENUMPINS pEnum = 0;
- IPin *pPin = 0;
- PIN_DIRECTION ThisPinDir;
- PIN_INFO pi;
- HRESULT hr;
- int i;
-
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: show_filter_info called\n");
- memset(&fi, 0, sizeof(fi));
- memset(tmp, 0, 200);
-
- OLE_CALL_ARGS(pFilter, QueryFilterInfo, &fi);
- OLE_RELEASE_SAFE(fi.pGraph);
- wtoa(fi.achName, tmp, 200);
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: BaseFilter (%p): Name=%s, Graph=%p output pins:",
- pFilter, tmp, fi.pGraph);
- hr = OLE_CALL_ARGS(pFilter, EnumPins, &pEnum);
- if (FAILED(hr))
- return hr;
- i = 0;
- while (OLE_CALL_ARGS(pEnum, Next, 1, &pPin, NULL) == S_OK) {
- memset(&pi, 0, sizeof(pi));
- memset(tmp, 0, 200);
- OLE_CALL_ARGS(pPin, QueryDirection, &ThisPinDir);
- if (ThisPinDir == PINDIR_OUTPUT) {
- OLE_CALL_ARGS(pPin, QueryPinInfo, &pi);
- wtoa(pi.achName, tmp, 200);
- OLE_RELEASE_SAFE(pi.pFilter);
- mp_msg(MSGT_TV, MSGL_DBG2, " %d=%s", i, tmp);
- mp_msg(MSGT_TV, MSGL_DBG3, " (%p)", pPin);
- mp_msg(MSGT_TV, MSGL_DBG2, ";");
- OLE_RELEASE_SAFE(pPin);
- i++;
- }
- }
- mp_msg(MSGT_TV, MSGL_DBG2, "\n");
- OLE_RELEASE_SAFE(pEnum);
- return S_OK;
-}
-
-/**
- * \brief gets device's frendly in ANSI encoding
- *
- * \param pM IMoniker interface, got in enumeration process
- * \param category device category
- *
- * \return TVI_CONTROL_TRUE if operation succeded, TVI_CONTROL_FALSE - otherwise
- */
-static int get_device_name(IMoniker * pM, char *pBuf, int nLen)
-{
- HRESULT hr;
- VARIANT var;
- IPropertyBag *pPropBag;
- hr = OLE_CALL_ARGS(pM, BindToStorage, 0, 0, &IID_IPropertyBag,(void *) &pPropBag);
- if (FAILED(hr)) {
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Call to BindToStorage failed\n");
- return TVI_CONTROL_FALSE;
- }
- var.vt = VT_BSTR;
- hr = OLE_CALL_ARGS(pPropBag, Read, L"Description", (LPVARIANT) & var,
- NULL);
- if (FAILED(hr)) {
- hr = OLE_CALL_ARGS(pPropBag, Read, L"FriendlyName", (LPVARIANT) & var,
- NULL);
- }
- OLE_RELEASE_SAFE(pPropBag);
- if (SUCCEEDED(hr)) {
- wtoa(var.bstrVal, pBuf, nLen);
- return TVI_CONTROL_TRUE;
- }
- return TVI_CONTROL_FALSE;
-}
-
-/**
- * \brief find capture device at given index
- *
- * \param index device index to search for (-1 mean only print available)
- * \param category device category
- *
- * \return IBaseFilter interface for capture device with given index
- *
- * Sample values for category:
- * CLSID_VideoInputDeviceCategory - Video Capture Sources
- * CLSID_AudioInputDeviceCategory - Audio Capture Sources
- * See DirectShow SDK documentation for other possible values
- */
-static IBaseFilter *find_capture_device(int index, REFCLSID category)
-{
- IBaseFilter *pFilter = NULL;
- ICreateDevEnum *pDevEnum = NULL;
- IEnumMoniker *pClassEnum = NULL;
- IMoniker *pM;
- HRESULT hr;
- ULONG cFetched;
- int i;
- char tmp[DEVICE_NAME_MAX_LEN + 1];
- hr = CoCreateInstance((GUID *) & CLSID_SystemDeviceEnum, NULL,
- CLSCTX_INPROC_SERVER, &IID_ICreateDevEnum,
- (void *) &pDevEnum);
- if (FAILED(hr)) {
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Unable to create device enumerator\n");
- return NULL;
- }
-
- hr = OLE_CALL_ARGS(pDevEnum, CreateClassEnumerator, category, &pClassEnum, 0);
- OLE_RELEASE_SAFE(pDevEnum);
- if (FAILED(hr)) {
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Unable to create class enumerator\n");
- return NULL;
- }
- if (hr == S_FALSE) {
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: No capture devices found\n");
- return NULL;
- }
-
- OLE_CALL(pClassEnum,Reset);
- for (i = 0; OLE_CALL_ARGS(pClassEnum, Next, 1, &pM, &cFetched) == S_OK; i++) {
- if(get_device_name(pM, tmp, DEVICE_NAME_MAX_LEN)!=TVI_CONTROL_TRUE)
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Unable to get name for device #%d\n", i);
- else
- mp_tmsg(MSGT_TV, MSGL_V, "tvi_dshow: Device #%d: %s\n", i, tmp);
- if (index != -1 && i == index) {
- mp_tmsg(MSGT_TV, MSGL_INFO, "tvi_dshow: Using device #%d: %s\n", index, tmp);
- hr = OLE_CALL_ARGS(pM, BindToObject, 0, 0, &IID_IBaseFilter,(void *) &pFilter);
- if (FAILED(hr))
- pFilter = NULL;
- }
- OLE_RELEASE_SAFE(pM);
- }
- if (index != -1 && !pFilter) {
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Device #%d not found\n",
- index);
- }
- OLE_RELEASE_SAFE(pClassEnum);
-
- return pFilter;
-}
-
-/**
- * \brief get array of available formats through call to IAMStreamConfig::GetStreamCaps
- *
- * \praram[in] chain chain data structure
- *
- * \return S_OK success
- * \return E_POINTER one of parameters is NULL
- * \return E_FAIL required size of buffer is unknown for given media type
- * \return E_OUTOFMEMORY not enough memory
- * \return other error code from called methods
- *
- * \remarks
- * last items of chain->arpmt and chain->arStreamCaps will be NULL
- */
-static HRESULT get_available_formats_stream(chain_t *chain)
-{
- AM_MEDIA_TYPE **arpmt;
- void **pBuf=NULL;
-
- HRESULT hr;
- int i, count, size;
- int done;
-
- mp_msg(MSGT_TV, MSGL_DBG4,
- "tvi_dshow: get_available_formats_stream called\n");
-
- if (!chain->pStreamConfig)
- return E_POINTER;
-
- hr=OLE_CALL_ARGS(chain->pStreamConfig, GetNumberOfCapabilities, &count, &size);
- if (FAILED(hr)) {
- mp_msg(MSGT_TV, MSGL_DBG4,
- "tvi_dshow: Call to GetNumberOfCapabilities failed (get_available_formats_stream)\n");
- return hr;
- }
- if (chain->type == video){
- if (size != sizeof(VIDEO_STREAM_CONFIG_CAPS)) {
- mp_msg(MSGT_TV, MSGL_DBG4,
- "tvi_dshow: Wrong video structure size for GetNumberOfCapabilities (get_available_formats_stream)\n");
- return E_FAIL;
- }
- } else if (chain->type == audio){
- if (size != sizeof(AUDIO_STREAM_CONFIG_CAPS)) {
- mp_msg(MSGT_TV, MSGL_DBG4,
- "tvi_dshow: Wrong audio structure size for GetNumberOfCapabilities (get_available_formats_stream)\n");
- return E_FAIL;
- }
- } else {
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Unsupported media type passed to %s\n","get_available_formats_stream");
- return E_FAIL;
- }
- done = 0;
-
- arpmt = malloc((count + 1) * sizeof(AM_MEDIA_TYPE *));
- if (arpmt) {
- memset(arpmt, 0, (count + 1) * sizeof(AM_MEDIA_TYPE *));
-
- pBuf = malloc((count + 1) * sizeof(void *));
- if (pBuf) {
- memset(pBuf, 0, (count + 1) * sizeof(void *));
-
- for (i = 0; i < count; i++) {
- pBuf[i] = malloc(size);
-
- if (!pBuf[i])
- break;
-
- hr = OLE_CALL_ARGS(chain->pStreamConfig, GetStreamCaps, i,
- &(arpmt[i]), pBuf[i]);
- if (FAILED(hr))
- break;
- }
- if (i == count) {
- chain->arpmt = arpmt;
- chain->arStreamCaps = pBuf;
- done = 1;
- }
- }
- }
- if (!done) {
- for (i = 0; i < count; i++) {
- if (pBuf)
- free(pBuf[i]);
- if (arpmt && arpmt[i])
- DeleteMediaType(arpmt[i]);
- }
- free(pBuf);
- free(arpmt);
- if (hr != S_OK) {
- mp_msg(MSGT_TV, MSGL_DBG4, "tvi_dshow: Call to GetStreamCaps failed (get_available_formats_stream)\n");
- return hr;
- } else
- return E_OUTOFMEMORY;
- }
- return S_OK;
-}
-
-/**
- * \brief returns allocates an array and store available media formats for given pin type to it
- *
- * \param pBuilder ICaptureGraphBuilder2 interface of graph builder
- * \param chain chain data structure
- *
- * \return S_OK success
- * \return E_POINTER one of given pointers is null
- * \return apropriate error code otherwise
- */
-static HRESULT get_available_formats_pin(ICaptureGraphBuilder2 * pBuilder,
- chain_t *chain)
-{
- IEnumMediaTypes *pEnum;
- int i, count, size;
- ULONG cFetched;
- AM_MEDIA_TYPE *pmt;
- HRESULT hr;
- void **pBuf;
- AM_MEDIA_TYPE **arpmt; //This will be real array
- VIDEO_STREAM_CONFIG_CAPS *pVideoCaps;
- AUDIO_STREAM_CONFIG_CAPS *pAudioCaps;
- int p1, p2, p3;
-
- mp_msg(MSGT_TV, MSGL_DBG4,
- "tvi_dshow: get_available_formats_pin called\n");
- if (!pBuilder || !chain->pCaptureFilter)
- return E_POINTER;
-
- if (!chain->pCapturePin)
- {
- hr = OLE_CALL_ARGS(pBuilder, FindPin,
- (IUnknown *) chain->pCaptureFilter,
- PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE,
- chain->majortype, FALSE, 0, &chain->pCapturePin);
-
- if (!chain->pCapturePin)
- return E_POINTER;
- }
- if (chain->type == video) {
- size = sizeof(VIDEO_STREAM_CONFIG_CAPS);
- } else if (chain->type == audio) {
- size = sizeof(AUDIO_STREAM_CONFIG_CAPS);
- } else {
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Unsupported media type passed to %s\n","get_available_formats_pin");
- return E_FAIL;
- }
-
- hr = OLE_CALL_ARGS(chain->pCapturePin, EnumMediaTypes, &pEnum);
- if (FAILED(hr)) {
- mp_msg(MSGT_TV, MSGL_DBG4,
- "tvi_dshow: Call to EnumMediaTypes failed (get_available_formats_pin)\n");
- return hr;
- }
- for (i = 0; OLE_CALL_ARGS(pEnum, Next, 1, &pmt, &cFetched) == S_OK; i++) {
- if (!pmt)
- break;
- }
- OLE_CALL(pEnum,Reset);
-
- count = i;
- arpmt = malloc((count + 1) * sizeof(AM_MEDIA_TYPE *));
- if (!arpmt)
- return E_OUTOFMEMORY;
- memset(arpmt, 0, (count + 1) * sizeof(AM_MEDIA_TYPE *));
-
- for (i = 0;
- i < count
- && OLE_CALL_ARGS(pEnum, Next, 1, &(arpmt[i]), &cFetched) == S_OK;
- i++);
-
- OLE_RELEASE_SAFE(pEnum);
-
-
- pBuf = malloc((count + 1) * sizeof(void *));
- if (!pBuf) {
- for (i = 0; i < count; i++)
- if (arpmt[i])
- DeleteMediaType(arpmt[i]);
- free(arpmt);
- return E_OUTOFMEMORY;
- }
- memset(pBuf, 0, (count + 1) * sizeof(void *));
-
- for (i = 0; i < count; i++) {
- pBuf[i] = malloc(size);
- if (!pBuf[i])
- break;
- memset(pBuf[i], 0, size);
-
- if (chain->type == video) {
- pVideoCaps = (VIDEO_STREAM_CONFIG_CAPS *) pBuf[i];
- extract_video_format(arpmt[i], NULL, &p1, &p2);
- pVideoCaps->MaxOutputSize.cx = pVideoCaps->MinOutputSize.cx =
- p1;
- pVideoCaps->MaxOutputSize.cy = pVideoCaps->MinOutputSize.cy =
- p2;
- } else {
- pAudioCaps = (AUDIO_STREAM_CONFIG_CAPS *) pBuf[i];
- extract_audio_format(arpmt[i], &p1, &p2, &p3);
- pAudioCaps->MaximumSampleFrequency =
- pAudioCaps->MinimumSampleFrequency = p1;
- pAudioCaps->MaximumBitsPerSample =
- pAudioCaps->MinimumBitsPerSample = p2;
- pAudioCaps->MaximumChannels = pAudioCaps->MinimumChannels = p3;
- }
-
- }
- if (i != count) {
- for (i = 0; i < count; i++) {
- if (arpmt[i])
- DeleteMediaType(arpmt[i]);
- free(pBuf[i]);
- }
- free(arpmt);
- free(pBuf);
- return E_OUTOFMEMORY;
- }
- chain->arpmt = arpmt;
- chain->arStreamCaps = pBuf;
-
- return S_OK;
-}
-
-/*
-*---------------------------------------------------------------------------------------
-*
-* Public methods
-*
-*---------------------------------------------------------------------------------------
-*/
-/**
- * \brief fills given buffer with audio data (usually one block)
- *
- * \param priv driver's private data structure
- * \param buffer buffer to store data to
- * \param len buffer's size in bytes (usually one block size)
- *
- * \return audio pts if audio present, 1 - otherwise
- */
-static double grab_audio_frame(priv_t * priv, char *buffer, int len)
-{
- int bytes = 0;
- int i;
- double pts;
- grabber_ringbuffer_t *rb = priv->chains[1]->rbuf;
- grabber_ringbuffer_t *vrb = priv->chains[0]->rbuf;
-
- if (!rb || !rb->ringbuffer)
- return 1;
-
- if(vrb && vrb->tStart<0){
- memset(buffer,0,len);
- return 0;
- }
- if(vrb && rb->tStart<0)
- rb->tStart=vrb->tStart;
-
- if (len < rb->blocksize)
- bytes = len;
- else
- bytes = rb->blocksize;
-
- mp_msg(MSGT_TV, MSGL_DBG3,"tvi_dshow: FillBuffer (audio) called. %d blocks in buffer, %d bytes requested\n",
- rb->count, len);
- if(!rb->count){
- mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: waiting for frame\n");
- for(i=0;i<1000 && !rb->count;i++) usec_sleep(1000);
- if(!rb->count){
- mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: waiting timeout\n");
- return 0;
- }
- mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: got frame!\n");
- }
-
- EnterCriticalSection(rb->pMutex);
- pts=rb->dpts[rb->head]-rb->tStart;
- memcpy(buffer, rb->ringbuffer[rb->head], bytes);
- rb->head = (rb->head + 1) % rb->buffersize;
- rb->count--;
- LeaveCriticalSection(rb->pMutex);
- return pts;
-}
-
-/**
- * \brief returns audio frame size
- *
- * \param priv driver's private data structure
- *
- * \return audio block size if audio enabled and 1 - otherwise
- */
-static int get_audio_framesize(priv_t * priv)
-{
- if (!priv->chains[1]->rbuf)
- return 1; //no audio
- mp_msg(MSGT_TV,MSGL_DBG3,"get_audio_framesize: %d\n",priv->chains[1]->rbuf->blocksize);
- return priv->chains[1]->rbuf->blocksize;
-}
-
-static int vbi_get_props(priv_t* priv,tt_stream_props* ptsp)
-{
- if(!priv || !ptsp)
- return TVI_CONTROL_FALSE;
-
-//STUBS!!!
- ptsp->interlaced=0;
- ptsp->offset=256;
-
- ptsp->sampling_rate=27e6;
- ptsp->samples_per_line=720;
-
- ptsp->count[0]=16;
- ptsp->count[1]=16;
-//END STUBS!!!
- ptsp->bufsize = ptsp->samples_per_line * (ptsp->count[0] + ptsp->count[1]);
-
- mp_msg(MSGT_TV,MSGL_V,"vbi_get_props: sampling_rate=%d,offset:%d,samples_per_line: %d\n interlaced:%s, count=[%d,%d]\n",
- ptsp->sampling_rate,
- ptsp->offset,
- ptsp->samples_per_line,
- ptsp->interlaced?"Yes":"No",
- ptsp->count[0],
- ptsp->count[1]);
-
- return TVI_CONTROL_TRUE;
-}
-
-static void vbi_grabber(priv_t* priv)
-{
- grabber_ringbuffer_t *rb = priv->chains[2]->rbuf;
- int i;
- unsigned char* buf;
- if (!rb || !rb->ringbuffer)
- return;
-
- buf=calloc(1,rb->blocksize);
- for(i=0; i<23 && rb->count; i++){
- memcpy(buf,rb->ringbuffer[rb->head],rb->blocksize);
- rb->head = (rb->head + 1) % rb->buffersize;
- rb->count--;
- }
- free(buf);
-}
-
-/**
- * \brief fills given buffer with video data (usually one frame)
- *
- * \param priv driver's private data structure
- * \param buffer buffer to store data to
- * \param len buffer's size in bytes (usually one frame size)
- *
- * \return frame size if video present, 0 - otherwise
- */
-static double grab_video_frame(priv_t * priv, char *buffer, int len)
-{
- int bytes = 0;
- int i;
- double pts;
- grabber_ringbuffer_t *rb = priv->chains[0]->rbuf;
-
- if (!rb || !rb->ringbuffer)
- return 1;
- if (len < rb->blocksize)
- bytes = len;
- else
- bytes = rb->blocksize;
-
- mp_msg(MSGT_TV, MSGL_DBG3,"tvi_dshow: FillBuffer (video) called. %d blocks in buffer, %d bytes requested\n",
- rb->count, len);
- if(!rb->count){
- mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: waiting for frame\n");
- for(i=0;i<1000 && !rb->count;i++) usec_sleep(1000);
- if(!rb->count){
- mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: waiting timeout\n");
- return 0;
- }
- mp_msg(MSGT_TV,MSGL_DBG4,"tvi_dshow: got frame!\n");
- }
- EnterCriticalSection(rb->pMutex);
- if(rb->tStart<0)
- rb->tStart=rb->dpts[rb->head];
- pts=rb->dpts[rb->head]-rb->tStart;
- memcpy(buffer, rb->ringbuffer[rb->head], bytes);
- rb->head = (rb->head + 1) % rb->buffersize;
- rb->count--;
- LeaveCriticalSection(rb->pMutex);
-
- vbi_grabber(priv);
- return pts;
-}
-
-/**
- * \brief returns frame size
- *
- * \param priv driver's private data structure
- *
- * \return frame size if video present, 0 - otherwise
- */
-static int get_video_framesize(priv_t * priv)
-{
-// if(!priv->pmtVideo) return 1; //no video
-// return priv->pmtVideo->lSampleSize;
- if (!priv->chains[0]->rbuf)
- return 1; //no video
-mp_msg(MSGT_TV,MSGL_DBG3,"geT_video_framesize: %d\n",priv->chains[0]->rbuf->blocksize);
- return priv->chains[0]->rbuf->blocksize;
-}
-
-/**
- * \brief calculate audio buffer size
- * \param video_buf_size size of video buffer in bytes
- * \param video_bitrate video bit rate
- * \param audio_bitrate audio bit rate
- * \return audio buffer isze in bytes
- *
- * \remarks length of video buffer and resulted audio buffer calculated in
- * seconds will be the same.
- */
-static inline int audio_buf_size_from_video(int video_buf_size, int video_bitrate, int audio_bitrate)
-{
- int audio_buf_size = audio_bitrate * (video_buf_size / video_bitrate);
- mp_msg(MSGT_TV,MSGL_DBG2,"tvi_dshow: Audio capture buffer: %d * %d / %d = %d\n",
- audio_bitrate,video_buf_size,video_bitrate,audio_buf_size);
- return audio_buf_size;
-}
-
-/**
- * \brief common chain initialization routine
- * \param chain chain data structure
- *
- * \note pCaptureFilter member should be initialized before call to this routine
- */
-static HRESULT init_chain_common(ICaptureGraphBuilder2 *pBuilder, chain_t *chain)
-{
- HRESULT hr;
- int i;
-
- if(!chain->pCaptureFilter)
- return E_POINTER;
-
- show_filter_info(chain->pCaptureFilter);
-
- hr = OLE_CALL_ARGS(pBuilder, FindPin,
- (IUnknown *) chain->pCaptureFilter,
- PINDIR_OUTPUT, chain->pin_category,
- chain->majortype, FALSE, 0, &chain->pCapturePin);
-
- if (FAILED(hr)) {
- mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: FindPin(pCapturePin) call failed. Error:0x%x\n", (unsigned int)hr);
- return hr;
- }
-
- hr = OLE_CALL_ARGS(pBuilder, FindInterface,
- chain->pin_category,
- chain->majortype,
- chain->pCaptureFilter,
- &IID_IAMStreamConfig,
- (void **) &(chain->pStreamConfig));
- if (FAILED(hr))
- chain->pStreamConfig = NULL;
-
- /*
- Getting available video formats (last pointer in array will be NULL)
- First tryin to call IAMStreamConfig::GetStreamCaos. this will give us additional information such as
- min/max picture dimensions, etc. If this call fails trying IPIn::EnumMediaTypes with default
- min/max values.
- */
- hr = get_available_formats_stream(chain);
- if (FAILED(hr)) {
- mp_msg(MSGT_TV, MSGL_DBG2, "Unable to use IAMStreamConfig for retriving available formats (Error:0x%x). Using EnumMediaTypes instead\n", (unsigned int)hr);
- hr = get_available_formats_pin(pBuilder, chain);
- if(FAILED(hr)){
- return hr;
- }
- }
- chain->nFormatUsed = 0;
-
- //If argument to CreateMediaType is NULL then result will be NULL too.
- chain->pmt = CreateMediaType(chain->arpmt[0]);
-
- for (i = 0; chain->arpmt[i]; i++)
- DisplayMediaType("Available format", chain->arpmt[i]);
-
- return S_OK;
-}
-/**
- * \brief build video stream chain in graph
- * \param priv private data structure
- *
- * \return S_OK if chain was built successfully, apropriate error code otherwise
- */
-static HRESULT build_video_chain(priv_t *priv)
-{
- HRESULT hr;
-
- if(priv->chains[0]->rbuf)
- return S_OK;
-
- if (priv->chains[0]->pStreamConfig) {
- hr = OLE_CALL_ARGS(priv->chains[0]->pStreamConfig, SetFormat, priv->chains[0]->pmt);
- if (FAILED(hr)) {
- mp_tmsg(MSGT_TV,MSGL_ERR,"tvi_dshow: Unable to select video format. Error:0x%x\n", (unsigned int)hr);
- }
- }
-
- priv->chains[0]->rbuf=calloc(1,sizeof(grabber_ringbuffer_t));
- if(!priv->chains[0]->rbuf)
- return E_OUTOFMEMORY;
-
- if (priv->tv_param->buffer_size >= 0) {
- priv->chains[0]->rbuf->buffersize = priv->tv_param->buffer_size;
- } else {
- priv->chains[0]->rbuf->buffersize = 16;
- }
-
- priv->chains[0]->rbuf->buffersize *= 1024 * 1024;
- hr=build_sub_graph(priv, priv->chains[0], &PIN_CATEGORY_CAPTURE);
- if(FAILED(hr)){
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Unable to build video chain of capture graph. Error:0x%x\n",(unsigned int)hr);
- return hr;
- }
- return S_OK;
-}
-
-/**
- * \brief build audio stream chain in graph
- * \param priv private data structure
- *
- * \return S_OK if chain was built successfully, apropriate error code otherwise
- */
-static HRESULT build_audio_chain(priv_t *priv)
-{
- HRESULT hr;
-
- if(priv->chains[1]->rbuf)
- return S_OK;
-
- if(priv->immediate_mode)
- return S_OK;
-
- if (priv->chains[1]->pStreamConfig) {
- hr = OLE_CALL_ARGS(priv->chains[1]->pStreamConfig, SetFormat,
- priv->chains[1]->pmt);
- if (FAILED(hr)) {
- mp_tmsg(MSGT_TV,MSGL_ERR,"tvi_dshow: Unable to select audio format. Error:0x%x\n", (unsigned int)hr);
- }
- }
-
- if(priv->chains[1]->pmt){
- priv->chains[1]->rbuf=calloc(1,sizeof(grabber_ringbuffer_t));
- if(!priv->chains[1]->rbuf)
- return E_OUTOFMEMORY;
-
- /* let the audio buffer be the same size (in seconds) than video one */
- priv->chains[1]->rbuf->buffersize=audio_buf_size_from_video(
- priv->chains[0]->rbuf->buffersize,
- (((VIDEOINFOHEADER *) priv->chains[0]->pmt->pbFormat)->dwBitRate),
- (((WAVEFORMATEX *) (priv->chains[1]->pmt->pbFormat))->nAvgBytesPerSec));
-
- hr=build_sub_graph(priv, priv->chains[1],&PIN_CATEGORY_CAPTURE);
- if(FAILED(hr)){
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Unable to build audio chain of capture graph. Error:0x%x\n",(unsigned int)hr);
- return 0;
- }
- }
- return S_OK;
-}
-
-/**
- * \brief build VBI stream chain in graph
- * \param priv private data structure
- *
- * \return S_OK if chain was built successfully, apropriate error code otherwise
- */
-static HRESULT build_vbi_chain(priv_t *priv)
-{
- HRESULT hr;
-
- if(priv->chains[2]->rbuf)
- return S_OK;
-
- return S_OK;
-}
-
-/**
- * \brief playback/capture real start
- *
- * \param priv driver's private data structure
- *
- * \return 1 if success, 0 - otherwise
- *
- * TODO: move some code from init() here
- */
-static int start(priv_t * priv)
-{
- HRESULT hr;
-
- hr = build_video_chain(priv);
- if(FAILED(hr))
- return 0;
-
- hr = build_audio_chain(priv);
- if(FAILED(hr))
- return 0;
-
- hr = build_vbi_chain(priv);
- if(FAILED(hr))
- return 0;
-
- /*
- Graph is ready to capture. Starting graph.
- */
- if (mp_msg_test(MSGT_TV, MSGL_DBG2)) {
- mp_msg(MSGT_TV, MSGL_DBG2, "Debug pause 10sec\n");
- usec_sleep(10000000);
- mp_msg(MSGT_TV, MSGL_DBG2, "Debug pause end\n");
- }
- if (!priv->pMediaControl) {
- mp_tmsg(MSGT_TV,MSGL_ERR,"tvi_dshow: Unable to get IMediaControl interface. Error:0x%x\n",(unsigned int)E_POINTER);
- return 0;
- }
- hr = OLE_CALL(priv->pMediaControl, Run);
- if (FAILED(hr)) {
- mp_tmsg(MSGT_TV,MSGL_ERR,"tvi_dshow: Unable to start graph! Error:0x%x\n", (unsigned int)hr);
- return 0;
- }
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Graph is started.\n");
- priv->state = 1;
-
- return 1;
-}
-
-/**
- * \brief driver initialization
- *
- * \param priv driver's private data structure
- *
- * \return 1 if success, 0 - otherwise
- */
-static int init(priv_t * priv)
-{
- HRESULT hr;
- int result = 0;
- long lInput, lTunerInput;
- IEnumFilters *pEnum;
- IBaseFilter *pFilter;
- IPin *pVPOutPin;
- int i;
-
- priv->state=0;
-
- CoInitialize(NULL);
-
- for(i=0; i<3;i++)
- priv->chains[i] = calloc(1, sizeof(chain_t));
-
- priv->chains[0]->type=video;
- priv->chains[0]->majortype=&MEDIATYPE_Video;
- priv->chains[0]->pin_category=&PIN_CATEGORY_CAPTURE;
- priv->chains[1]->type=audio;
- priv->chains[1]->majortype=&MEDIATYPE_Audio;
- priv->chains[1]->pin_category=&PIN_CATEGORY_CAPTURE;
- priv->chains[2]->type=vbi;
- priv->chains[2]->majortype=&MEDIATYPE_VBI;
- priv->chains[2]->pin_category=&PIN_CATEGORY_VBI;
-
- do{
- hr = CoCreateInstance((GUID *) & CLSID_FilterGraph, NULL,
- CLSCTX_INPROC_SERVER, &IID_IGraphBuilder,
- (void **) &priv->pGraph);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: CoCreateInstance(FilterGraph) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- //Debug
- if (mp_msg_test(MSGT_TV, MSGL_DBG2)) {
- AddToRot((IUnknown *) priv->pGraph, &(priv->dwRegister));
- }
-
- hr = CoCreateInstance((GUID *) & CLSID_CaptureGraphBuilder2, NULL,
- CLSCTX_INPROC_SERVER, &IID_ICaptureGraphBuilder2,
- (void **) &priv->pBuilder);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: CoCreateInstance(CaptureGraphBuilder) call failed. Error:0x%x\n", (unsigned int)hr);
- break;
- }
-
- hr = OLE_CALL_ARGS(priv->pBuilder, SetFiltergraph, priv->pGraph);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_ERR, "tvi_dshow: SetFiltergraph call failed. Error:0x%x\n",(unsigned int)hr);
- break;
- }
-
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Searching for available video capture devices\n");
- priv->chains[0]->pCaptureFilter = find_capture_device(priv->dev_index, &CLSID_VideoInputDeviceCategory);
- if(!priv->chains[0]->pCaptureFilter){
- mp_tmsg(MSGT_TV,MSGL_ERR, "tvi_dshow: Unable to find video capture device\n");
- break;
- }
- hr = OLE_CALL_ARGS(priv->pGraph, AddFilter, priv->chains[0]->pCaptureFilter, NULL);
- if(FAILED(hr)){
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Unable to add video capture device to Directshow graph. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Searching for available audio capture devices\n");
- if (priv->adev_index != -1) {
- priv->chains[1]->pCaptureFilter = find_capture_device(priv->adev_index, &CLSID_AudioInputDeviceCategory); //output available audio edevices
- if(!priv->chains[1]->pCaptureFilter){
- mp_tmsg(MSGT_TV,MSGL_ERR, "tvi_dshow: Unable to find audio capture device\n");
- break;
- }
-
- hr = OLE_CALL_ARGS(priv->pGraph, AddFilter, priv->chains[1]->pCaptureFilter, NULL);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: Unable to add audio capture device to Directshow graph. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- } else
- hr = OLE_QUERYINTERFACE(priv->chains[0]->pCaptureFilter, IID_IBaseFilter, priv->chains[1]->pCaptureFilter);
-
- /* increase refrence counter for capture filter ad store pointer into vbi chain structure too */
- hr = OLE_QUERYINTERFACE(priv->chains[0]->pCaptureFilter, IID_IBaseFilter, priv->chains[2]->pCaptureFilter);
-
- hr = OLE_QUERYINTERFACE(priv->chains[0]->pCaptureFilter, IID_IAMVideoProcAmp,priv->pVideoProcAmp);
- if (FAILED(hr) && hr != E_NOINTERFACE)
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Get IID_IAMVideoProcAmp failed (0x%x).\n", (unsigned int)hr);
-
- if (hr != S_OK) {
- mp_tmsg(MSGT_TV, MSGL_INFO, "tvi_dshow: Adjusting of brightness/hue/saturation/contrast is not supported by device\n");
- priv->pVideoProcAmp = NULL;
- }
-
- hr = OLE_CALL_ARGS(priv->pBuilder, FindInterface,
- &PIN_CATEGORY_CAPTURE,
- priv->chains[0]->majortype,
- priv->chains[0]->pCaptureFilter,
- &IID_IAMCrossbar, (void **) &(priv->pCrossbar));
- if (FAILED(hr)) {
- mp_tmsg(MSGT_TV, MSGL_INFO, "tvi_dshow: Selection of capture source is not supported by device\n");
- priv->pCrossbar = NULL;
- }
-
- if (priv->tv_param->amode >= 0) {
- IAMTVAudio *pTVAudio;
- hr = OLE_CALL_ARGS(priv->pBuilder, FindInterface, NULL, NULL,priv->chains[0]->pCaptureFilter,&IID_IAMTVAudio, (void *) &pTVAudio);
- if (hr == S_OK) {
- switch (priv->tv_param->amode) {
- case 0:
- hr = OLE_CALL_ARGS(pTVAudio, put_TVAudioMode, AMTVAUDIO_MODE_MONO);
- break;
- case 1:
- hr = OLE_CALL_ARGS(pTVAudio, put_TVAudioMode, AMTVAUDIO_MODE_STEREO);
- break;
- case 2:
- hr = OLE_CALL_ARGS(pTVAudio, put_TVAudioMode,
- AMTVAUDIO_MODE_LANG_A);
- break;
- case 3:
- hr = OLE_CALL_ARGS(pTVAudio, put_TVAudioMode,
- AMTVAUDIO_MODE_LANG_B);
- break;
- }
- OLE_RELEASE_SAFE(pTVAudio);
- if (FAILED(hr))
- mp_tmsg(MSGT_TV, MSGL_WARN, "tvi_dshow: Unable to set audio mode %d. Error:0x%x\n", priv->tv_param->amode,(unsigned int)hr);
- }
- }
-
- // Video chain initialization
- hr = init_chain_common(priv->pBuilder, priv->chains[0]);
- if(FAILED(hr))
- break;
-
- /*
- Audio chain initialization
- Since absent audio stream is not fatal,
- at least one NULL pointer should be kept in format arrays
- (to avoid another additional check everywhere for array presence).
- */
- hr = init_chain_common(priv->pBuilder, priv->chains[1]);
- if(FAILED(hr))
- {
- mp_msg(MSGT_TV, MSGL_V,
- "tvi_dshow: Unable to initialize audio chain (Error:0x%lx). Audio disabled\n",
- (unsigned long)hr);
- priv->chains[1]->arpmt=calloc(1, sizeof(AM_MEDIA_TYPE*));
- priv->chains[1]->arStreamCaps=calloc(1, sizeof(void*));
- }
-
- /*
- VBI chain initialization
- Since absent VBI stream is not fatal,
- at least one NULL pointer should be kept in format arrays
- (to avoid another additional check everywhere for array presence).
- */
- hr = init_chain_common(priv->pBuilder, priv->chains[2]);
- if(FAILED(hr))
- {
- mp_msg(MSGT_TV, MSGL_V,
- "tvi_dshow: Unable to initialize VBI chain (Error:0x%lx). Teletext disabled\n",
- (unsigned long)hr);
- priv->chains[2]->arpmt=calloc(1, sizeof(AM_MEDIA_TYPE*));
- priv->chains[2]->arStreamCaps=calloc(1, sizeof(void*));
- }
-
- if (!priv->chains[0]->pStreamConfig)
- mp_tmsg(MSGT_TV, MSGL_INFO, "tvi_dshow: Changing video width/height is not supported by device.\n");
-
- if (!priv->chains[0]->arpmt[priv->chains[0]->nFormatUsed]
- || !extract_video_format(priv->chains[0]->arpmt[priv->chains[0]->nFormatUsed],
- &(priv->fcc), &(priv->width),
- &(priv->height))) {
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Unable to parse video format structure.\n");
- break;
- }
-
- if (priv->chains[1]->arpmt[priv->chains[1]->nFormatUsed]) {
- if (!extract_audio_format(priv->chains[1]->pmt, &(priv->samplerate), NULL, NULL)) {
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Unable to parse audio format structure.\n");
- DisplayMediaType("audio format failed",priv->chains[1]->arpmt[priv->chains[1]->nFormatUsed]);
- break;
- }
- }
-
- hr = OLE_QUERYINTERFACE(priv->pGraph, IID_IMediaControl,priv->pMediaControl);
- if(FAILED(hr)){
- mp_tmsg(MSGT_TV,MSGL_ERR, "tvi_dshow: Unable to get IMediaControl interface. Error:0x%x\n",(unsigned int)hr);
- break;
- }
- hr = OLE_CALL_ARGS(priv->pBuilder, FindInterface,
- &PIN_CATEGORY_CAPTURE, NULL,
- priv->chains[0]->pCaptureFilter,
- &IID_IAMTVTuner, (void **) &(priv->pTVTuner));
-
- if (!priv->pTVTuner) {
- mp_msg(MSGT_TV, MSGL_DBG2, "tvi_dshow: Unable to access IAMTVTuner (0x%x)\n", (unsigned int)hr);
- }
-
- // shows Tuner capabilities
- get_capabilities(priv);
-
- if (priv->pTVTuner) {
- hr = OLE_CALL_ARGS(priv->pTVTuner, put_CountryCode,
- chanlist2country(priv->tv_param->chanlist));
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: Call to put_CountryCode failed. Error:0x%x\n",(unsigned int)hr);
- }
-
- hr = OLE_CALL_ARGS(priv->pTVTuner, put_Mode, AMTUNER_MODE_TV);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: Call to put_Mode failed. Error:0x%x\n",(unsigned int)hr);
- break;
- }
-
- hr = OLE_CALL_ARGS(priv->pTVTuner, get_ConnectInput, &lInput);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: Call to get_ConnectInput failed. Error:0x%x\n",(unsigned int)hr);
- break;
- }
-
- /* small hack */
- lTunerInput = strstr(priv->tv_param->chanlist, "cable") ? TunerInputCable : TunerInputAntenna;
-
- hr = OLE_CALL_ARGS(priv->pTVTuner, put_InputType, lInput, lTunerInput);
- if(FAILED(hr)){
- mp_msg(MSGT_TV,MSGL_DBG2, "tvi_dshow: Call to put_InputType failed. Error:0x%x\n",(unsigned int)hr);
- break;
- }
-
- }
-
- /**
- for VIVO cards we should check if preview pin is available on video capture device.
- If it is not, we have to connect Video Port Manager filter to VP pin of capture device filter.
- Otherwise we will get 0x8007001f (Device is not functioning properly) when attempting to start graph
- */
- hr = OLE_CALL_ARGS(priv->pBuilder, FindPin,
- (IUnknown *) priv->chains[0]->pCaptureFilter,
- PINDIR_OUTPUT,
- &PIN_CATEGORY_VIDEOPORT, NULL, FALSE,
- 0, (IPin **) & pVPOutPin);
- if (SUCCEEDED(hr)) {
- hr = OLE_CALL_ARGS(priv->pGraph, Render, pVPOutPin);
- OLE_RELEASE_SAFE(pVPOutPin);
-
- if (FAILED(hr)) {
- mp_tmsg(MSGT_TV,MSGL_ERR, "tvi_dshow: Unable to terminate VideoPort pin with any filter in graph. Error:0x%x\n", (unsigned int)hr);
- break;
- }
- }
-
- OLE_CALL_ARGS(priv->pGraph, EnumFilters, &pEnum);
- while (OLE_CALL_ARGS(pEnum, Next, 1, &pFilter, NULL) == S_OK) {
- LPVIDEOWINDOW pVideoWindow;
- hr = OLE_QUERYINTERFACE(pFilter, IID_IVideoWindow, pVideoWindow);
- if (SUCCEEDED(hr))
- {
- if(priv->tv_param->hidden_vp_renderer){
- OLE_CALL_ARGS(pVideoWindow,put_Visible,/* OAFALSE*/ 0);
- OLE_CALL_ARGS(pVideoWindow,put_AutoShow,/* OAFALSE*/ 0);
- }else
- {
- OLE_CALL_ARGS(priv->pGraph, RemoveFilter, pFilter);
- }
- OLE_RELEASE_SAFE(pVideoWindow);
- }
- OLE_RELEASE_SAFE(pFilter);
- }
- OLE_RELEASE_SAFE(pEnum);
- if(priv->tv_param->system_clock)
- {
- LPREFERENCECLOCK rc;
- IBaseFilter* pBF;
- hr = CoCreateInstance((GUID *) & CLSID_SystemClock, NULL,
- CLSCTX_INPROC_SERVER, &IID_IReferenceClock,
- (void *) &rc);
-
- OLE_QUERYINTERFACE(priv->pBuilder,IID_IBaseFilter,pBF);
- OLE_CALL_ARGS(pBF,SetSyncSource,rc);
- }
- if(vbi_get_props(priv,&(priv->tsp))!=TVI_CONTROL_TRUE)
- break;
- result = 1;
- } while(0);
-
- if (!result){
- mp_tmsg(MSGT_TV,MSGL_ERR, "tvi_dshow: Directshow graph initialization failure.\n");
- uninit(priv);
- }
- return result;
-}
-
-/**
- * \brief chain uninitialization
- * \param chain chain data structure
- */
-static void destroy_chain(chain_t *chain)
-{
- int i;
-
- if(!chain)
- return;
-
- OLE_RELEASE_SAFE(chain->pStreamConfig);
- OLE_RELEASE_SAFE(chain->pCaptureFilter);
- OLE_RELEASE_SAFE(chain->pCSGCB);
- OLE_RELEASE_SAFE(chain->pCapturePin);
- OLE_RELEASE_SAFE(chain->pSGIn);
- OLE_RELEASE_SAFE(chain->pSG);
- OLE_RELEASE_SAFE(chain->pSGF);
-
- if (chain->pmt)
- DeleteMediaType(chain->pmt);
-
- if (chain->arpmt) {
- for (i = 0; chain->arpmt[i]; i++) {
- DeleteMediaType(chain->arpmt[i]);
- }
- free(chain->arpmt);
- }
-
- if (chain->arStreamCaps) {
- for (i = 0; chain->arStreamCaps[i]; i++) {
- free(chain->arStreamCaps[i]);
- }
- free(chain->arStreamCaps);
- }
-
- if (chain->rbuf) {
- destroy_ringbuffer(chain->rbuf);
- free(chain->rbuf);
- chain->rbuf = NULL;
- }
- free(chain);
-}
-/**
- * \brief driver uninitialization
- *
- * \param priv driver's private data structure
- *
- * \return always 1
- */
-static int uninit(priv_t * priv)
-{
- int i;
- if (!priv)
- return 1;
- //Debug
- if (priv->dwRegister) {
- RemoveFromRot(priv->dwRegister);
- }
- //stop audio grabber thread
-
- if (priv->state && priv->pMediaControl) {
- OLE_CALL(priv->pMediaControl, Stop);
- }
- OLE_RELEASE_SAFE(priv->pMediaControl);
- priv->state = 0;
-
- if (priv->pGraph) {
- if (priv->chains[0]->pCaptureFilter)
- OLE_CALL_ARGS(priv->pGraph, RemoveFilter, priv->chains[0]->pCaptureFilter);
- if (priv->chains[1]->pCaptureFilter)
- OLE_CALL_ARGS(priv->pGraph, RemoveFilter, priv->chains[1]->pCaptureFilter);
- }
- OLE_RELEASE_SAFE(priv->pCrossbar);
- OLE_RELEASE_SAFE(priv->pVideoProcAmp);
- OLE_RELEASE_SAFE(priv->pGraph);
- OLE_RELEASE_SAFE(priv->pBuilder);
- if(priv->freq_table){
- priv->freq_table_len=-1;
- free(priv->freq_table);
- priv->freq_table=NULL;
- }
-
- for(i=0; i<3;i++)
- {
- destroy_chain(priv->chains[i]);
- priv->chains[i] = NULL;
- }
- CoUninitialize();
- return 1;
-}
-
-/**
- * \brief driver pre-initialization
- *
- * \param device string, containing device name in form "x[.y]", where x is video capture device
- * (default: 0, first available); y (if given) sets audio capture device
- *
- * \return 1 if success,0 - otherwise
- */
-static tvi_handle_t *tvi_init_dshow(tv_param_t* tv_param)
-{
- tvi_handle_t *h;
- priv_t *priv;
- int a;
-
- h = tv_new_handle(sizeof(priv_t), &functions);
- if (!h)
- return NULL;
-
- priv = h->priv;
-
- memset(priv, 0, sizeof(priv_t));
- priv->direct_setfreq_call = 1; //first using direct call. if it fails, workaround will be enabled
- priv->direct_getfreq_call = 1; //first using direct call. if it fails, workaround will be enabled
- priv->adev_index = -1;
- priv->freq_table_len=-1;
- priv->tv_param=tv_param;
-
- if (tv_param->device) {
- if (sscanf(tv_param->device, "%d", &a) == 1) {
- priv->dev_index = a;
- } else {
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Wrong device parameter: %s\n", tv_param->device);
- tv_free_handle(h);
- return NULL;
- }
- if (priv->dev_index < 0) {
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Wrong device index: %d\n", a);
- tv_free_handle(h);
- return NULL;
- }
- }
- if (tv_param->adevice) {
- if (sscanf(tv_param->adevice, "%d", &a) == 1) {
- priv->adev_index = a;
- } else {
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Wrong adevice parameter: %s\n", tv_param->adevice);
- tv_free_handle(h);
- return NULL;
- }
- if (priv->dev_index < 0) {
- mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_dshow: Wrong adevice index: %d\n", a);
- tv_free_handle(h);
- return NULL;
- }
- }
- return h;
-}
-
-/**
- * \brief driver's ioctl handler
- *
- * \param priv driver's private data structure
- * \param cmd ioctl command
- * \param arg ioct command's parameter
- *
- * \return TVI_CONTROL_TRUE if success
- * \return TVI_CONTROL_FALSE if failure
- * \return TVI_CONTROL_UNKNOWN if unknowm cmd called
- */
-static int control(priv_t * priv, int cmd, void *arg)
-{
- switch (cmd) {
-/* need rewrite */
- case TVI_CONTROL_VID_SET_FORMAT:
- {
- int fcc, i,j;
- void* tmp,*tmp2;
- int result = TVI_CONTROL_TRUE;
-
- if (priv->state)
- return TVI_CONTROL_FALSE;
- fcc = *(int *) arg;
-
- if(!priv->chains[0]->arpmt)
- return TVI_CONTROL_FALSE;
- for (i = 0; priv->chains[0]->arpmt[i]; i++)
- if (check_video_format
- (priv->chains[0]->arpmt[i], fcc, priv->width, priv->height))
- break;
- if (!priv->chains[0]->arpmt[i])
- {
- int fps = 0;
- VIDEOINFOHEADER* Vhdr = NULL;
- AM_MEDIA_TYPE *pmt;
-
- mp_msg(MSGT_TV, MSGL_V, "tvi_dshow: will try also use undeclared video format: %dx%d, %s\n",priv->width, priv->height, vo_format_name(fcc));
-
- if (priv->chains[0]->arpmt[0])
- Vhdr = (VIDEOINFOHEADER *) priv->chains[0]->arpmt[0]->pbFormat;
-
- if(Vhdr && Vhdr->bmiHeader.biSizeImage)
- fps = Vhdr->dwBitRate / (8 * Vhdr->bmiHeader.biSizeImage);
-
- pmt=create_video_format(fcc, priv->width, priv->height, fps);
- if(!pmt)
- {
- mp_msg(MSGT_TV, MSGL_V, "tvi_dshow: Unable to create AM_MEDIA_TYPE structure for given format\n");
- return TVI_CONTROL_FALSE;
- }
- priv->chains[0]->arpmt=realloc(priv->chains[0]->arpmt, (i+2)*sizeof(AM_MEDIA_TYPE*));
- priv->chains[0]->arpmt[i+1] = NULL;
- priv->chains[0]->arpmt[i] = pmt;
-
- priv->chains[0]->arStreamCaps=realloc(priv->chains[0]->arStreamCaps, (i+2)*sizeof(void*));
- priv->chains[0]->arpmt[i+1] = NULL;
-
- result = TVI_CONTROL_FALSE;
- }
-
-
- tmp=priv->chains[0]->arpmt[i];
- tmp2=priv->chains[0]->arStreamCaps[i];
- for(j=i; j>0; j--)
- {
- priv->chains[0]->arpmt[j] = priv->chains[0]->arpmt[j-1];
- priv->chains[0]->arStreamCaps[j] = priv->chains[0]->arStreamCaps[j-1];
- }
- priv->chains[0]->arpmt[0] = tmp;
- priv->chains[0]->arStreamCaps[0] = tmp2;
-
- priv->chains[0]->nFormatUsed = 0;
-
- if (priv->chains[0]->pmt)
- DeleteMediaType(priv->chains[0]->pmt);
- priv->chains[0]->pmt =
- CreateMediaType(priv->chains[0]->arpmt[priv->chains[0]->nFormatUsed]);
- DisplayMediaType("VID_SET_FORMAT", priv->chains[0]->pmt);
- /*
- Setting width & height to preferred by driver values
- */
- extract_video_format(priv->chains[0]->arpmt[priv->chains[0]->nFormatUsed],
- &(priv->fcc), &(priv->width),
- &(priv->height));
- return result;
- }
- case TVI_CONTROL_VID_GET_FORMAT:
- {
- if(!priv->chains[0]->pmt)
- return TVI_CONTROL_FALSE;
- /*
- Build video chain (for video format negotiation).
- If this was done before, routine will do nothing.
- */
- build_video_chain(priv);
- DisplayMediaType("VID_GET_FORMAT", priv->chains[0]->pmt);
- if (priv->fcc) {
- *(int *) arg = priv->fcc;
- return TVI_CONTROL_TRUE;
- } else
- return TVI_CONTROL_FALSE;
- }
- case TVI_CONTROL_VID_SET_WIDTH:
- {
- VIDEO_STREAM_CONFIG_CAPS *pCaps;
- VIDEOINFOHEADER *Vhdr;
- int width = *(int *) arg;
- if (priv->state)
- return TVI_CONTROL_FALSE;
-
- pCaps = priv->chains[0]->arStreamCaps[priv->chains[0]->nFormatUsed];
- if (!pCaps)
- return TVI_CONTROL_FALSE;
- if (width < pCaps->MinOutputSize.cx
- || width > pCaps->MaxOutputSize.cx)
- return TVI_CONTROL_FALSE;
-
- if (width % pCaps->OutputGranularityX)
- return TVI_CONTROL_FALSE;
-
- if (!priv->chains[0]->pmt || !priv->chains[0]->pmt->pbFormat)
- return TVI_CONTROL_FALSE;
- Vhdr = (VIDEOINFOHEADER *) priv->chains[0]->pmt->pbFormat;
- Vhdr->bmiHeader.biWidth = width;
- priv->chains[0]->pmt->lSampleSize = Vhdr->bmiHeader.biSizeImage =
- labs(Vhdr->bmiHeader.biBitCount * Vhdr->bmiHeader.biWidth *
- Vhdr->bmiHeader.biHeight) >> 3;
-
- priv->width = width;
-
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_VID_GET_WIDTH:
- {
- if (priv->width) {
- *(int *) arg = priv->width;
- return TVI_CONTROL_TRUE;
- } else
- return TVI_CONTROL_FALSE;
- }
- case TVI_CONTROL_VID_CHK_WIDTH:
- {
- VIDEO_STREAM_CONFIG_CAPS *pCaps;
- int width = *(int *) arg;
- pCaps = priv->chains[0]->arStreamCaps[priv->chains[0]->nFormatUsed];
- if (!pCaps)
- return TVI_CONTROL_FALSE;
- if (width < pCaps->MinOutputSize.cx
- || width > pCaps->MaxOutputSize.cx)
- return TVI_CONTROL_FALSE;
-
- if (width % pCaps->OutputGranularityX)
- return TVI_CONTROL_FALSE;
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_VID_SET_HEIGHT:
- {
- VIDEO_STREAM_CONFIG_CAPS *pCaps;
- VIDEOINFOHEADER *Vhdr;
- int height = *(int *) arg;
- if (priv->state)
- return TVI_CONTROL_FALSE;
-
- pCaps = priv->chains[0]->arStreamCaps[priv->chains[0]->nFormatUsed];
- if (!pCaps)
- return TVI_CONTROL_FALSE;
- if (height < pCaps->MinOutputSize.cy
- || height > pCaps->MaxOutputSize.cy)
- return TVI_CONTROL_FALSE;
-
- if (height % pCaps->OutputGranularityY)
- return TVI_CONTROL_FALSE;
-
- if (!priv->chains[0]->pmt || !priv->chains[0]->pmt->pbFormat)
- return TVI_CONTROL_FALSE;
- Vhdr = (VIDEOINFOHEADER *) priv->chains[0]->pmt->pbFormat;
-
- if (Vhdr->bmiHeader.biHeight < 0)
- Vhdr->bmiHeader.biHeight = -height;
- else
- Vhdr->bmiHeader.biHeight = height;
- priv->chains[0]->pmt->lSampleSize = Vhdr->bmiHeader.biSizeImage =
- labs(Vhdr->bmiHeader.biBitCount * Vhdr->bmiHeader.biWidth *
- Vhdr->bmiHeader.biHeight) >> 3;
-
- priv->height = height;
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_VID_GET_HEIGHT:
- {
- if (priv->height) {
- *(int *) arg = priv->height;
- return TVI_CONTROL_TRUE;
- } else
- return TVI_CONTROL_FALSE;
- }
- case TVI_CONTROL_VID_CHK_HEIGHT:
- {
- VIDEO_STREAM_CONFIG_CAPS *pCaps;
- int height = *(int *) arg;
- pCaps = priv->chains[0]->arStreamCaps[priv->chains[0]->nFormatUsed];
- if (!pCaps)
- return TVI_CONTROL_FALSE;
- if (height < pCaps->MinOutputSize.cy
- || height > pCaps->MaxOutputSize.cy)
- return TVI_CONTROL_FALSE;
-
- if (height % pCaps->OutputGranularityY)
- return TVI_CONTROL_FALSE;
-
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_IS_AUDIO:
- if (!priv->chains[1]->pmt)
- return TVI_CONTROL_FALSE;
- else
- return TVI_CONTROL_TRUE;
- case TVI_CONTROL_IS_VIDEO:
- return TVI_CONTROL_TRUE;
- case TVI_CONTROL_AUD_GET_FORMAT:
- {
- *(int *) arg = AF_FORMAT_S16_LE;
- if (!priv->chains[1]->pmt)
- return TVI_CONTROL_FALSE;
- else
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_AUD_GET_CHANNELS:
- {
- *(int *) arg = priv->channels;
- if (!priv->chains[1]->pmt)
- return TVI_CONTROL_FALSE;
- else
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_AUD_SET_SAMPLERATE:
- {
- int i, samplerate;
- if (priv->state)
- return TVI_CONTROL_FALSE;
- if (!priv->chains[1]->arpmt[0])
- return TVI_CONTROL_FALSE;
-
- samplerate = *(int *) arg;
-
- for (i = 0; priv->chains[1]->arpmt[i]; i++)
- if (check_audio_format
- (priv->chains[1]->arpmt[i], samplerate, 16, priv->channels))
- break;
- if (!priv->chains[1]->arpmt[i]) {
- //request not found. failing back to first available
- mp_tmsg(MSGT_TV, MSGL_WARN, "tvi_dshow: Samplerate %d is not supported by device. Failing back to first available.\n", samplerate);
- i = 0;
- }
- if (priv->chains[1]->pmt)
- DeleteMediaType(priv->chains[1]->pmt);
- priv->chains[1]->pmt = CreateMediaType(priv->chains[1]->arpmt[i]);
- extract_audio_format(priv->chains[1]->arpmt[i], &(priv->samplerate),
- NULL, &(priv->channels));
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_AUD_GET_SAMPLERATE:
- {
- *(int *) arg = priv->samplerate;
- if (!priv->samplerate)
- return TVI_CONTROL_FALSE;
- if (!priv->chains[1]->pmt)
- return TVI_CONTROL_FALSE;
- else
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_AUD_GET_SAMPLESIZE:
- {
- WAVEFORMATEX *pWF;
- if (!priv->chains[1]->pmt)
- return TVI_CONTROL_FALSE;
- if (!priv->chains[1]->pmt->pbFormat)
- return TVI_CONTROL_FALSE;
- pWF = (WAVEFORMATEX *) priv->chains[1]->pmt->pbFormat;
- *(int *) arg = pWF->wBitsPerSample / 8;
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_IS_TUNER:
- {
- if (!priv->pTVTuner)
- return TVI_CONTROL_FALSE;
-
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_TUN_SET_NORM:
- {
- IAMAnalogVideoDecoder *pVD;
- long lAnalogFormat;
- int i;
- HRESULT hr;
-
- i = *(int *) arg;
- i--;
- if (i < 0 || i >= tv_available_norms_count)
- return TVI_CONTROL_FALSE;
- lAnalogFormat = tv_norms[tv_available_norms[i]].index;
-
- hr = OLE_QUERYINTERFACE(priv->chains[0]->pCaptureFilter,IID_IAMAnalogVideoDecoder, pVD);
- if (hr != S_OK)
- return TVI_CONTROL_FALSE;
- hr = OLE_CALL_ARGS(pVD, put_TVFormat, lAnalogFormat);
- OLE_RELEASE_SAFE(pVD);
- if (FAILED(hr))
- return TVI_CONTROL_FALSE;
- else
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_TUN_GET_NORM:
- {
- long lAnalogFormat;
- int i;
- HRESULT hr;
- IAMAnalogVideoDecoder *pVD;
-
- hr = OLE_QUERYINTERFACE(priv->chains[0]->pCaptureFilter,IID_IAMAnalogVideoDecoder, pVD);
- if (hr == S_OK) {
- hr = OLE_CALL_ARGS(pVD, get_TVFormat, &lAnalogFormat);
- OLE_RELEASE_SAFE(pVD);
- }
-
- if (FAILED(hr)) { //trying another method
- if (!priv->pTVTuner)
- return TVI_CONTROL_FALSE;
- hr=OLE_CALL_ARGS(priv->pTVTuner, get_TVFormat, &lAnalogFormat);
- if (FAILED(hr))
- return TVI_CONTROL_FALSE;
- }
- for (i = 0; i < tv_available_norms_count; i++) {
- if (tv_norms[tv_available_norms[i]].index == lAnalogFormat) {
- *(int *) arg = i + 1;
- return TVI_CONTROL_TRUE;
- }
- }
- return TVI_CONTROL_FALSE;
- }
- case TVI_CONTROL_SPC_GET_NORMID:
- {
- int i;
- if (!priv->pTVTuner)
- return TVI_CONTROL_FALSE;
- for (i = 0; i < tv_available_norms_count; i++) {
- if (!strcasecmp
- (tv_norms[tv_available_norms[i]].name, (char *) arg)) {
- *(int *) arg = i + 1;
- return TVI_CONTROL_TRUE;
- }
- }
- return TVI_CONTROL_FALSE;
- }
- case TVI_CONTROL_SPC_SET_INPUT:
- {
- return set_crossbar_input(priv, *(int *) arg);
- }
- case TVI_CONTROL_TUN_GET_FREQ:
- {
- unsigned long lFreq;
- int ret;
- if (!priv->pTVTuner)
- return TVI_CONTROL_FALSE;
-
- ret = get_frequency(priv, &lFreq);
- lFreq = lFreq / (1000000/16); //convert from Hz to 1/16 MHz units
-
- *(unsigned long *) arg = lFreq;
- return ret;
- }
- case TVI_CONTROL_TUN_SET_FREQ:
- {
- unsigned long nFreq = *(unsigned long *) arg;
- if (!priv->pTVTuner)
- return TVI_CONTROL_FALSE;
- //convert to Hz
- nFreq = (1000000/16) * nFreq; //convert from 1/16 MHz units to Hz
- return set_frequency(priv, nFreq);
- }
- case TVI_CONTROL_VID_SET_HUE:
- return set_control(priv, VideoProcAmp_Hue, *(int *) arg);
- case TVI_CONTROL_VID_GET_HUE:
- return get_control(priv, VideoProcAmp_Hue, (int *) arg);
- case TVI_CONTROL_VID_SET_CONTRAST:
- return set_control(priv, VideoProcAmp_Contrast, *(int *) arg);
- case TVI_CONTROL_VID_GET_CONTRAST:
- return get_control(priv, VideoProcAmp_Contrast, (int *) arg);
- case TVI_CONTROL_VID_SET_SATURATION:
- return set_control(priv, VideoProcAmp_Saturation, *(int *) arg);
- case TVI_CONTROL_VID_GET_SATURATION:
- return get_control(priv, VideoProcAmp_Saturation, (int *) arg);
- case TVI_CONTROL_VID_SET_BRIGHTNESS:
- return set_control(priv, VideoProcAmp_Brightness, *(int *) arg);
- case TVI_CONTROL_VID_GET_BRIGHTNESS:
- return get_control(priv, VideoProcAmp_Brightness, (int *) arg);
-
- case TVI_CONTROL_VID_GET_FPS:
- {
- VIDEOINFOHEADER *Vhdr;
- if (!priv->chains[0]->pmt)
- return TVI_CONTROL_FALSE;
- if (!priv->chains[0]->pmt->pbFormat)
- return TVI_CONTROL_FALSE;
- Vhdr = (VIDEOINFOHEADER *) priv->chains[0]->pmt->pbFormat;
- *(float *) arg =
- (1.0 * Vhdr->dwBitRate) / (Vhdr->bmiHeader.biSizeImage * 8);
- return TVI_CONTROL_TRUE;
- }
- case TVI_CONTROL_IMMEDIATE:
- priv->immediate_mode = 1;
- return TVI_CONTROL_TRUE;
- }
- return TVI_CONTROL_UNKNOWN;
-}
diff --git a/stream/tvi_dshow.h b/stream/tvi_dshow.h
deleted file mode 100644
index 7ec1ce8e50..0000000000
--- a/stream/tvi_dshow.h
+++ /dev/null
@@ -1,728 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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.
- *
- * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_TVI_DSHOW_H
-#define MPLAYER_TVI_DSHOW_H
-
-/// \defgroup tvi_dshow TV driver (Directshow)
-
-#define INITGUID
-#include <inttypes.h>
-#include <windows.h>
-//#include <ole2.h>
-#include <vfw.h>
-#include "loader/dshow/mediatype.h"
-#include "loader/dshow/guids.h"
-
-#define wtoa(strW,strA,lenA) WideCharToMultiByte(0,0,strW,-1,strA,lenA,NULL,NULL)
-#define atow(strA,strW,lenW) MultiByteToWideChar(0,0,strA,strlen(strA),strW,lenW)
-
-typedef struct DISPPARAMS *LPDISPPARAMS;
-typedef struct IFileSinkFilter *LPFILESINKFILTER;
-typedef struct IAMCopyCaptureFileProgress *LPAMCOPYCAPTUREFILEPROGRESS;
-typedef struct IErrorLog *LPERRORLOG;
-typedef struct IAMTunerNotification *LPAMTUNERNOTIFICATION;
-typedef struct IFilterGraph *LPFILTERGRAPH;
-typedef struct IBaseFilter *LPBASEFILTER;
-typedef struct IPin *LPPIN;
-typedef struct IEnumPins *LPENUMPINS;
-typedef struct IEnumFilters *LPENUMFILTERS;
-typedef struct IEnumMediaTypes *LPENUMMEDIATYPES;
-typedef struct IReferenceClock *LPREFERENCECLOCK;
-typedef struct IMediaSample *LPMEDIASAMPLE;
-typedef struct IVideoWindow *LPVIDEOWINDOW;
-
-typedef struct
-{
- long cBuffers;
- long cbBuffer;
- long cbAlign;
- long cbPrefix;
-}ALLOCATOR_PROPERTIES;
-
-typedef
- enum tagTunerInputType { TunerInputCable = 0,
- TunerInputAntenna = TunerInputCable + 1
-} TunerInputType;
-typedef enum tagAMTunerModeType {
- AMTUNER_MODE_DEFAULT = 0x0000,
- AMTUNER_MODE_TV = 0x0001,
- AMTUNER_MODE_FM_RADIO = 0x0002,
- AMTUNER_MODE_AM_RADIO = 0x0004,
- AMTUNER_MODE_DSS = 0x0008
-} AMTunerModeType;
-enum tagAMTunerSubChannel { AMTUNER_SUBCHAN_NO_TUNE = -2,
- AMTUNER_SUBCHAN_DEFAULT = -1
-} AMTunerSubChannel;
-typedef enum tagVideoProcAmpProperty {
- VideoProcAmp_Brightness,
- VideoProcAmp_Contrast,
- VideoProcAmp_Hue,
- VideoProcAmp_Saturation,
- VideoProcAmp_Sharpness,
- VideoProcAmp_Gamma,
- VideoProcAmp_ColorEnable,
- VideoProcAmp_WhiteBalance,
- VideoProcAmp_BacklightCompensation,
- VideoProcAmp_Gain
-} VideoProcAmpProperty;
-
-typedef long OAFilterState;
-typedef
- enum tagAnalogVideoStandard { AnalogVideo_None = 0,
- AnalogVideo_NTSC_M = 0x1,
- AnalogVideo_NTSC_M_J = 0x2,
- AnalogVideo_NTSC_433 = 0x4,
- AnalogVideo_PAL_B = 0x10,
- AnalogVideo_PAL_D = 0x20,
- AnalogVideo_PAL_G = 0x40,
- AnalogVideo_PAL_H = 0x80,
- AnalogVideo_PAL_I = 0x100,
- AnalogVideo_PAL_M = 0x200,
- AnalogVideo_PAL_N = 0x400,
- AnalogVideo_PAL_60 = 0x800,
- AnalogVideo_SECAM_B = 0x1000,
- AnalogVideo_SECAM_D = 0x2000,
- AnalogVideo_SECAM_G = 0x4000,
- AnalogVideo_SECAM_H = 0x8000,
- AnalogVideo_SECAM_K = 0x10000,
- AnalogVideo_SECAM_K1 = 0x20000,
- AnalogVideo_SECAM_L = 0x40000,
- AnalogVideo_SECAM_L1 = 0x80000
-} AnalogVideoStandard;
-
-
-typedef LONG_PTR OAHWND;
-typedef enum tagPhysicalConnectorType { PhysConn_Video_Tuner = 1,
- PhysConn_Video_Composite = PhysConn_Video_Tuner + 1,
- PhysConn_Video_SVideo = PhysConn_Video_Composite + 1,
- PhysConn_Video_RGB = PhysConn_Video_SVideo + 1,
- PhysConn_Video_YRYBY = PhysConn_Video_RGB + 1,
- PhysConn_Video_SerialDigital = PhysConn_Video_YRYBY + 1,
- PhysConn_Video_ParallelDigital = PhysConn_Video_SerialDigital + 1,
- PhysConn_Video_SCSI = PhysConn_Video_ParallelDigital + 1,
- PhysConn_Video_AUX = PhysConn_Video_SCSI + 1,
- PhysConn_Video_1394 = PhysConn_Video_AUX + 1,
- PhysConn_Video_USB = PhysConn_Video_1394 + 1,
- PhysConn_Video_VideoDecoder = PhysConn_Video_USB + 1,
- PhysConn_Video_VideoEncoder = PhysConn_Video_VideoDecoder + 1,
- PhysConn_Video_SCART = PhysConn_Video_VideoEncoder + 1,
- PhysConn_Video_Black = PhysConn_Video_SCART + 1,
- PhysConn_Audio_Tuner = 0x1000,
- PhysConn_Audio_Line = PhysConn_Audio_Tuner + 1,
- PhysConn_Audio_Mic = PhysConn_Audio_Line + 1,
- PhysConn_Audio_AESDigital = PhysConn_Audio_Mic + 1,
- PhysConn_Audio_SPDIFDigital = PhysConn_Audio_AESDigital + 1,
- PhysConn_Audio_SCSI = PhysConn_Audio_SPDIFDigital + 1,
- PhysConn_Audio_AUX = PhysConn_Audio_SCSI + 1,
- PhysConn_Audio_1394 = PhysConn_Audio_AUX + 1,
- PhysConn_Audio_USB = PhysConn_Audio_1394 + 1,
- PhysConn_Audio_AudioDecoder = PhysConn_Audio_USB + 1
-} PhysicalConnectorType;
-
-typedef struct VIDEO_STREAM_CONFIG_CAPS {
- GUID guid; // will be MEDIATYPE_Video
- ULONG VideoStandard; // logical OR of all AnalogVideoStandards
- // supported
- SIZE InputSize; // the inherent size of the incoming signal
- // (every pixel unique)
- SIZE MinCroppingSize; // smallest rcSrc cropping rect allowed
- SIZE MaxCroppingSize; // largest rcSrc cropping rect allowed
- int CropGranularityX; // granularity of cropping size
- int CropGranularityY;
- int CropAlignX; // alignment of cropping rect
- int CropAlignY;
- SIZE MinOutputSize; // smallest bitmap stream can produce
- SIZE MaxOutputSize; // largest bitmap stream can produce
- int OutputGranularityX; // granularity of output bitmap size
- int OutputGranularityY;
- int StretchTapsX; // 0, no stretch, 1 pix dup, 2 interp, ...
- int StretchTapsY; // Describes quality of hardware scaler
- int ShrinkTapsX; //
- int ShrinkTapsY; //
- LONGLONG MinFrameInterval; // 100 nS units
- LONGLONG MaxFrameInterval;
- LONG MinBitsPerSecond;
- LONG MaxBitsPerSecond;
-} VIDEO_STREAM_CONFIG_CAPS, *PVIDEO_STREAM_CONFIG_CAPS;
-
-typedef struct AUDIO_STREAM_CONFIG_CAPS {
- GUID guid;
- ULONG MinimumChannels;
- ULONG MaximumChannels;
- ULONG ChannelsGranularity;
- ULONG MinimumBitsPerSample;
- ULONG MaximumBitsPerSample;
- ULONG BitsPerSampleGranularity;
- ULONG MinimumSampleFrequency;
- ULONG MaximumSampleFrequency;
- ULONG SampleFrequencyGranularity;
-} AUDIO_STREAM_CONFIG_CAPS;
-
-typedef enum tagVideoProcAmpFlags {
- VideoProcAmp_Flags_Auto = 0x0001,
- VideoProcAmp_Flags_Manual = 0x0002
-} VideoProcAmpFlags;
-typedef enum {
- PINDIR_INPUT = 0,
- PINDIR_OUTPUT
-} PIN_DIRECTION;
-
-#define KSPROPERTY_SUPPORT_GET 1
-#define KSPROPERTY_SUPPORT_SET 2
-typedef struct {
- GUID Set;
- ULONG Id;
- ULONG Flags;
-} KSIDENTIFIER;
-
-typedef KSIDENTIFIER KSPROPERTY;
-
-
-typedef struct {
- KSPROPERTY Property;
- ULONG Mode; // IN: KSPROPERTY_TUNER_MODE
- ULONG StandardsSupported; // KS_AnalogVideo_* (if TV or DSS)
- ULONG MinFrequency; // Hz
- ULONG MaxFrequency; // Hz
- ULONG TuningGranularity; // Hz
- ULONG NumberOfInputs; // count of inputs
- ULONG SettlingTime; // milliSeconds
- ULONG Strategy; // KS_TUNER_STRATEGY
-} KSPROPERTY_TUNER_MODE_CAPS_S, *PKSPROPERTY_TUNER_MODE_CAPS_S;
-
-typedef struct {
- KSPROPERTY Property;
- ULONG Mode; // IN: KSPROPERTY_TUNER_MODE
-} KSPROPERTY_TUNER_MODE_S, *PKSPROPERTY_TUNER_MODE_S;
-
-typedef struct {
- KSPROPERTY Property;
- ULONG Frequency; // Hz
- ULONG LastFrequency; // Hz (last known good)
- ULONG TuningFlags; // KS_TUNER_TUNING_FLAGS
- ULONG VideoSubChannel; // DSS
- ULONG AudioSubChannel; // DSS
- ULONG Channel; // VBI decoders
- ULONG Country; // VBI decoders
-} KSPROPERTY_TUNER_FREQUENCY_S, *PKSPROPERTY_TUNER_FREQUENCY_S;
-typedef struct {
- KSPROPERTY Property;
- ULONG CurrentFrequency;
- ULONG PLLOffset;
- ULONG SignalStrength;
- ULONG Busy;
-} KSPROPERTY_TUNER_STATUS_S, *PKSPROPERTY_TUNER_STATUS_S;
-typedef enum {
- KS_TUNER_TUNING_EXACT = 1, // No fine tuning
- KS_TUNER_TUNING_FINE, // Fine grained search
- KS_TUNER_TUNING_COARSE, // Coarse search
-} KS_TUNER_TUNING_FLAGS;
-
-typedef enum {
- KSPROPERTY_TUNER_CAPS, // R -overall device capabilities
- KSPROPERTY_TUNER_MODE_CAPS, // R -capabilities in this mode
- KSPROPERTY_TUNER_MODE, // RW -set a mode (TV, FM, AM, DSS)
- KSPROPERTY_TUNER_STANDARD, // R -get TV standard (only if TV mode)
- KSPROPERTY_TUNER_FREQUENCY, // RW -set/get frequency
- KSPROPERTY_TUNER_INPUT, // RW -select an input
- KSPROPERTY_TUNER_STATUS, // R -tuning status
- KSPROPERTY_TUNER_IF_MEDIUM // R O-Medium for IF or Transport Pin
-} KSPROPERTY_TUNER;
-typedef enum {
- KS_TUNER_STRATEGY_PLL = 0X01, // Tune by PLL offset
- KS_TUNER_STRATEGY_SIGNAL_STRENGTH = 0X02, // Tune by signal strength
- KS_TUNER_STRATEGY_DRIVER_TUNES = 0X04, // Driver does fine tuning
-} KS_TUNER_STRATEGY;
-typedef enum tagTVAudioMode {
- AMTVAUDIO_MODE_MONO = 0x0001,
- AMTVAUDIO_MODE_STEREO = 0x0002,
- AMTVAUDIO_MODE_LANG_A = 0x0010,
- AMTVAUDIO_MODE_LANG_B = 0x0020,
- AMTVAUDIO_MODE_LANG_C = 0x0040,
-} TVAudioMode;
-
-typedef struct FilterInfo {
- WCHAR achName[128];
- LPFILTERGRAPH pGraph;
-} FILTER_INFO;
-
-typedef struct PinInfo {
- LPBASEFILTER pFilter;
- PIN_DIRECTION dir;
- unsigned short achName[128];
-} PIN_INFO;
-//-----------------------------------
-
-
-#undef INTERFACE
-#define INTERFACE IPin
-DECLARE_INTERFACE(IPin)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(Connect) (THIS_ IPin *, AM_MEDIA_TYPE *);
- STDMETHOD(ReceiveConnection) (THIS_ IPin *, const AM_MEDIA_TYPE *);
- STDMETHOD(Disconnect) (THIS);
- STDMETHOD(ConnectedTo) (THIS_ IPin **);
- STDMETHOD(ConnectionMediaType) (THIS_ AM_MEDIA_TYPE * pmt);
- STDMETHOD(QueryPinInfo) (THIS_ PIN_INFO *);
- STDMETHOD(QueryDirection) (THIS_ PIN_DIRECTION *);
- STDMETHOD(QueryId) (THIS_ unsigned short **);
- STDMETHOD(QueryAccept) (THIS_ const AM_MEDIA_TYPE *);
- STDMETHOD(EnumMediaTypes) (THIS_ LPENUMMEDIATYPES *);
- STDMETHOD(QueryInternalConnections) (THIS_ IPin **, unsigned long *);
- STDMETHOD(EndOfStream) (THIS);
- STDMETHOD(BeginFlush) (THIS);
- STDMETHOD(EndFlush) (THIS);
- STDMETHOD(NewSegment) (THIS_ REFERENCE_TIME, REFERENCE_TIME, double);
-};
-
-#undef INTERFACE
-#define INTERFACE IBaseFilter
-DECLARE_INTERFACE(IBaseFilter)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(GetClassID) (THIS_ CLSID * pClassID);
- STDMETHOD(Stop) (THIS);
- STDMETHOD(Pause) (THIS);
- STDMETHOD(Run) (THIS_ REFERENCE_TIME tStart);
- STDMETHOD(GetState) (THIS_ unsigned long, void *);
- STDMETHOD(SetSyncSource) (THIS_ LPREFERENCECLOCK);
- STDMETHOD(GetSyncSource) (THIS_ LPREFERENCECLOCK *);
- STDMETHOD(EnumPins) (THIS_ LPENUMPINS *);
- STDMETHOD(FindPin) (THIS_ const unsigned short *, LPPIN *);
- STDMETHOD(QueryFilterInfo) (THIS_ void *);
- STDMETHOD(JoinFilterGraph) (THIS_ LPFILTERGRAPH,
- const unsigned short *);
- STDMETHOD(QueryVendorInfo) (THIS_ unsigned short **);
-};
-
-#undef INTERFACE
-#define INTERFACE IAMTVTuner
-DECLARE_INTERFACE(IAMTVTuner)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(put_Channel) (THIS_ long, long, long);
- STDMETHOD(get_Channel) (THIS_ long *, long *, long *);
- STDMETHOD(ChannelMinMax) (THIS_ long *, long *);
- STDMETHOD(put_CountryCode) (THIS_ long);
- STDMETHOD(get_CountryCode) (THIS_ long *);
- STDMETHOD(put_TuningSpace) (THIS_ long);
- STDMETHOD(get_TuningSpace) (THIS_ long *);
- STDMETHOD(Logon) (THIS_ HANDLE);
- STDMETHOD(Logout) (IAMTVTuner *);
- STDMETHOD(SignalPresen) (THIS_ long *);
- STDMETHOD(put_Mode) (THIS_ AMTunerModeType);
- STDMETHOD(get_Mode) (THIS_ AMTunerModeType *);
- STDMETHOD(GetAvailableModes) (THIS_ long *);
- STDMETHOD(RegisterNotificationCallBack) (THIS_ LPAMTUNERNOTIFICATION,
- long);
- STDMETHOD(UnRegisterNotificationCallBack) (THIS_
- LPAMTUNERNOTIFICATION);
- STDMETHOD(get_AvailableTVFormats) (THIS_ long *);
- STDMETHOD(get_TVFormat) (THIS_ long *);
- STDMETHOD(AutoTune) (THIS_ long, long *);
- STDMETHOD(StoreAutoTune) (IAMTVTuner *);
- STDMETHOD(get_NumInputConnections) (THIS_ long *);
- STDMETHOD(put_InputType) (THIS_ long, TunerInputType);
- STDMETHOD(get_InputType) (THIS_ long, TunerInputType *);
- STDMETHOD(put_ConnectInput) (THIS_ long);
- STDMETHOD(get_ConnectInput) (THIS_ long *);
- STDMETHOD(get_VideoFrequency) (THIS_ long *);
- STDMETHOD(get_AudioFrequency) (THIS_ long *);
-};
-
-#undef INTERFACE
-#define INTERFACE IMediaControl
-DECLARE_INTERFACE(IMediaControl)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(GetTypeInfoCount) (THIS_ UINT *);
- STDMETHOD(GetTypeInfo) (THIS_ UINT, LCID, LPTYPEINFO *);
- STDMETHOD(GetIDsOfNames) (THIS_ REFIID, LPOLESTR *, UINT, LCID,
- DISPID *);
- STDMETHOD(Invoke) (THIS_ DISPID, REFIID, LCID, WORD, LPDISPPARAMS,
- VARIANT *, EXCEPINFO *, UINT *);
- STDMETHOD(Run) (THIS);
- STDMETHOD(Pause) (THIS);
- STDMETHOD(Stop) (THIS);
- STDMETHOD(GetState) (THIS_ LONG, OAFilterState *);
- STDMETHOD(RenderFile) (THIS_ BSTR);
- STDMETHOD(AddSourceFilter) (THIS_ BSTR, LPDISPATCH *);
- STDMETHOD(get_FilterCollection) (THIS_ LPDISPATCH *);
- STDMETHOD(get_RegFilterCollection) (THIS_ LPDISPATCH *);
- STDMETHOD(StopWhenReady) (IMediaControl *);
-};
-
-#undef INTERFACE
-#define INTERFACE IGraphBuilder
-DECLARE_INTERFACE(IGraphBuilder)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(AddFilter) (THIS_ IBaseFilter *, LPCWSTR);
- STDMETHOD(RemoveFilter) (THIS_ IBaseFilter *);
- STDMETHOD(EnumFilters) (THIS_ LPENUMFILTERS *);
- STDMETHOD(FindFilterByName) (THIS_ LPCWSTR, IBaseFilter **);
- STDMETHOD(ConnectDirect) (THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *);
- STDMETHOD(Reconnect) (THIS_ IPin *);
- STDMETHOD(Disconnect) (THIS_ IPin *);
- STDMETHOD(SetDefaultSyncSource) (IGraphBuilder *);
- STDMETHOD(Connect) (THIS_ IPin *, IPin *);
- STDMETHOD(Render) (THIS_ IPin *);
- STDMETHOD(RenderFile) (THIS_ LPCWSTR, LPCWSTR);
- STDMETHOD(AddSourceFilter) (THIS_ LPCWSTR, LPCWSTR, IBaseFilter **);
- STDMETHOD(SetLogFile) (THIS_ DWORD_PTR);
- STDMETHOD(Abort) (IGraphBuilder *);
- STDMETHOD(ShouldOperationContinue) (IGraphBuilder *);
-};
-
-
-#undef INTERFACE
-#define INTERFACE ICaptureGraphBuilder2
-DECLARE_INTERFACE(ICaptureGraphBuilder2)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(SetFiltergraph) (THIS_ IGraphBuilder *);
- STDMETHOD(GetFiltergraph) (THIS_ IGraphBuilder **);
- STDMETHOD(SetOutputFileName) (THIS_ const GUID *, LPCOLESTR,
- IBaseFilter **, LPFILESINKFILTER *);
- STDMETHOD(FindInterface) (THIS_ const GUID *, const GUID *,
- IBaseFilter *, REFIID, void **);
- STDMETHOD(RenderStream) (THIS_ const GUID *, const GUID *, IUnknown *,
- IBaseFilter *, IBaseFilter *);
- STDMETHOD(ControlStream) (THIS_ const GUID *, const GUID *,
- IBaseFilter *, REFERENCE_TIME *,
- REFERENCE_TIME *, WORD, WORD);
- STDMETHOD(AllocCapFile) (THIS_ LPCOLESTR, DWORDLONG);
- STDMETHOD(CopyCaptureFile) (THIS_ LPOLESTR, LPOLESTR, int,
- LPAMCOPYCAPTUREFILEPROGRESS);
- STDMETHOD(FindPin) (THIS_ IUnknown *, PIN_DIRECTION, const GUID *,
- const GUID *, BOOL, int, IPin **);
-};
-
-#undef INTERFACE
-#define INTERFACE ICreateDevEnum
-DECLARE_INTERFACE(ICreateDevEnum)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(CreateClassEnumerator) (THIS_ REFCLSID, IEnumMoniker **,
- DWORD);
-};
-
-#undef INTERFACE
-#define INTERFACE IAMCrossbar
-DECLARE_INTERFACE(IAMCrossbar)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(get_PinCounts) (THIS_ long *, long *);
- STDMETHOD(CanRoute) (THIS_ long, long);
- STDMETHOD(Route) (THIS_ long, long);
- STDMETHOD(get_IsRoutedTo) (THIS_ long, long *);
- STDMETHOD(get_CrossbarPinInfo) (THIS_ BOOL, long, long *, long *);
-};
-
-#ifndef __IPropertyBag_INTERFACE_DEFINED__
-#define __IPropertyBag_INTERFACE_DEFINED__
-#undef INTERFACE
-#define INTERFACE IPropertyBag
-DECLARE_INTERFACE(IPropertyBag)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(Read) (THIS_ LPCOLESTR, LPVARIANT, LPERRORLOG);
- STDMETHOD(Write) (THIS_ LPCOLESTR, LPVARIANT);
-};
-#endif
-
-#undef INTERFACE
-#define INTERFACE IAMStreamConfig
-DECLARE_INTERFACE(IAMStreamConfig)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- HRESULT(STDMETHODCALLTYPE * SetFormat) (THIS_ AM_MEDIA_TYPE *);
- HRESULT(STDMETHODCALLTYPE * GetFormat) (THIS_ AM_MEDIA_TYPE **);
- HRESULT(STDMETHODCALLTYPE * GetNumberOfCapabilities) (THIS_ int *,int *);
- HRESULT(STDMETHODCALLTYPE * GetStreamCaps) (THIS_ int,AM_MEDIA_TYPE **, BYTE *);
-};
-
-#undef INTERFACE
-#define INTERFACE IAMVideoProcAmp
-DECLARE_INTERFACE(IAMVideoProcAmp)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(GetRange) (THIS_ long, long *, long *, long *, long *,long *);
- STDMETHOD(Set) (THIS_ long, long, long);
- STDMETHOD(Get) (THIS_ long, long *, long *);
-};
-
-#undef INTERFACE
-#define INTERFACE IKsPropertySet
-DECLARE_INTERFACE(IKsPropertySet)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- HRESULT(STDMETHODCALLTYPE * Set) (THIS_ REFGUID, DWORD, LPVOID, DWORD,LPVOID, DWORD);
- HRESULT(STDMETHODCALLTYPE * Get) (THIS_ REFGUID, DWORD, LPVOID, DWORD,LPVOID, DWORD, DWORD *);
- HRESULT(STDMETHODCALLTYPE * QuerySupported) (THIS_ REFGUID, DWORD,DWORD *);
-};
-
-#undef INTERFACE
-#define INTERFACE IAMAnalogVideoDecoder
-DECLARE_INTERFACE(IAMAnalogVideoDecoder)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(get_AvailableTVFormats) (THIS_ long *);
- STDMETHOD(put_TVFormat) (THIS_ long);
- STDMETHOD(get_TVFormat) (THIS_ long *);
- STDMETHOD(get_HorizontalLocked) (THIS_ long *);
- STDMETHOD(put_VCRHorizontalLocking) (THIS_ long);
- STDMETHOD(get_VCRHorizontalLocking) (THIS_ long *);
- STDMETHOD(get_NumberOfLines) (THIS_ long *);
- STDMETHOD(put_OutputEnable) (THIS_ long);
- STDMETHOD(get_OutputEnable) (THIS_ long *);
-};
-
-#undef INTERFACE
-#define INTERFACE IAMTVAudio
-DECLARE_INTERFACE(IAMTVAudio)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(GetHardwareSupportedTVAudioModes) (THIS_ long *);
- STDMETHOD(GetAvailableTVAudioModes) (THIS_ long *);
- STDMETHOD(get_TVAudioMode) (THIS_ long *);
- STDMETHOD(put_TVAudioMode) (THIS_ long);
- STDMETHOD(RegisterNotificationCallBack) (THIS_ LPAMTUNERNOTIFICATION,
- long);
- STDMETHOD(UnRegisterNotificationCallBack) (THIS_
- LPAMTUNERNOTIFICATION);
-};
-
-
-#undef INTERFACE
-#define INTERFACE ISampleGrabberCB
-DECLARE_INTERFACE(ISampleGrabberCB)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(SampleCB) (THIS_ double, LPMEDIASAMPLE);
- STDMETHOD(BufferCB) (THIS_ double, BYTE *, long);
-};
-
-#undef INTERFACE
-#define INTERFACE ISampleGrabber
-DECLARE_INTERFACE(ISampleGrabber)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(SetOneShot) (THIS_ BOOL);
- STDMETHOD(SetMediaType) (THIS_ const AM_MEDIA_TYPE *);
- STDMETHOD(GetConnectedMediaType) (THIS_ AM_MEDIA_TYPE *);
- STDMETHOD(SetBufferSamples) (THIS_ BOOL);
- STDMETHOD(GetCurrentBuffer) (THIS_ long *, long *);
- STDMETHOD(GetCurrentSample) (THIS_ LPMEDIASAMPLE *);
- STDMETHOD(SetCallback) (THIS_ ISampleGrabberCB *, long);
-};
-
-#undef INTERFACE
-#define INTERFACE IFilterGraph
-DECLARE_INTERFACE(IFilterGraph)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(AddFilter) (THIS_ LPBASEFILTER, LPCWSTR);
- STDMETHOD(RemoveFilter) (THIS_ LPBASEFILTER);
- STDMETHOD(EnumFilters) (THIS_ LPENUMFILTERS *);
- STDMETHOD(FindFilterByName) (THIS_ LPCWSTR, LPBASEFILTER *);
- STDMETHOD(ConnectDirect) (THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *);
- STDMETHOD(Reconnect) (THIS_ LPPIN);
- STDMETHOD(Disconnect) (THIS_ LPPIN);
- STDMETHOD(SetDefaultSyncSource) (THIS);
-};
-
-#undef INTERFACE
-#define INTERFACE IAMAudioInputMixer
-DECLARE_INTERFACE(IAMAudioInputMixer)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(put_Enable) (THIS_ BOOL);
- STDMETHOD(get_Enable) (THIS_ BOOL *);
- STDMETHOD(put_Mono) (THIS_ BOOL);
- STDMETHOD(get_Mono) (THIS_ BOOL *);
- STDMETHOD(put_MixLevel) (THIS_ double);
- STDMETHOD(get_MixLevel) (THIS_ double *);
- STDMETHOD(put_Pan) (THIS_ double);
- STDMETHOD(get_Pan) (THIS_ double *);
- STDMETHOD(put_Loudness) (THIS_ BOOL);
- STDMETHOD(get_Loudness) (THIS_ BOOL *);
- STDMETHOD(put_Treble) (THIS_ double);
- STDMETHOD(get_Treble) (THIS_ double *);
- STDMETHOD(get_TrebleRange) (THIS_ double *);
- STDMETHOD(put_Bass) (THIS_ double);
- STDMETHOD(get_Bass) (THIS_ double *);
- STDMETHOD(get_BassRange) (THIS_ double *);
-};
-
-
-#undef INTERFACE
-#define INTERFACE IMediaSample
-DECLARE_INTERFACE(IMediaSample)
-{
- STDMETHOD(QueryInterface) (THIS_ const GUID *, void **);
- STDMETHOD_(long, AddRef) (THIS);
- STDMETHOD_(long, Release) (THIS);
- STDMETHOD(GetPointer )(THIS_ unsigned char** );
- STDMETHOD_(LONG,GetSize )(THIS);
- STDMETHOD(GetTime )(THIS_ REFERENCE_TIME* ,REFERENCE_TIME* );
- STDMETHOD(SetTime )(THIS_ REFERENCE_TIME* ,REFERENCE_TIME* );
- STDMETHOD(IsSyncPoint )(THIS);
- STDMETHOD(SetSyncPoint )(THIS_ long );
- STDMETHOD(IsPreroll )(THIS);
- STDMETHOD(SetPreroll )(THIS_ long );
- STDMETHOD_(LONG,GetActualDataLength)(THIS);
- STDMETHOD(SetActualDataLength )(THIS_ long );
- STDMETHOD(GetMediaType )(THIS_ AM_MEDIA_TYPE** );
- STDMETHOD(SetMediaType )(THIS_ AM_MEDIA_TYPE* );
- STDMETHOD(IsDiscontinuity )(THIS);
- STDMETHOD(SetDiscontinuity )(THIS_ long );
- STDMETHOD(GetMediaTime )(THIS_ long long* ,long long* );
- STDMETHOD(SetMediaTime )(THIS_ long long* ,long long* );
-};
-
-
-#undef INTERFACE
-#define INTERFACE IAMBufferNegotiation
-DECLARE_INTERFACE(IAMBufferNegotiation)
-{
- STDMETHOD(QueryInterface )(THIS_ REFIID ,void **);
- STDMETHOD_(ULONG,AddRef )(THIS);
- STDMETHOD_(ULONG,Release )(THIS);
- STDMETHOD(SuggestAllocatorProperties )(THIS_ const ALLOCATOR_PROPERTIES *);
- STDMETHOD(GetAllocatorProperties )(THIS_ ALLOCATOR_PROPERTIES *);
-};
-
-
-#undef INTERFACE
-#define INTERFACE IVideoWindow
-DECLARE_INTERFACE(IVideoWindow)
-{
- STDMETHOD(QueryInterface )(THIS_ REFIID ,void **);
- STDMETHOD_(ULONG,AddRef )(THIS);
- STDMETHOD_(ULONG,Release )(THIS);
- STDMETHOD(GetTypeInfoCount) (THIS_ UINT * );
- STDMETHOD(GetTypeInfo) (THIS_ UINT ,LCID , ITypeInfo ** );
- STDMETHOD(GetIDsOfNames) (THIS_ REFIID ,LPOLESTR * , UINT ,LCID , DISPID * );
- STDMETHOD(Invoke) (THIS_ DISPID ,REFIID , LCID , WORD ,void *, VARIANT * ,EXCEPINFO * , UINT * );
- STDMETHOD(put_Caption) (THIS_ BSTR );
- STDMETHOD(get_Caption) (THIS_ BSTR * );
- STDMETHOD(put_WindowStyle) (THIS_ long );
- STDMETHOD(get_WindowStyle) (THIS_ long *);
- STDMETHOD(put_WindowStyleEx) (THIS_ long );
- STDMETHOD(get_WindowStyleEx) (THIS_ long *);
- STDMETHOD(put_AutoShow) (THIS_ long );
- STDMETHOD(get_AutoShow) (THIS_ long *);
- STDMETHOD(put_WindowState) (THIS_ long );
- STDMETHOD(get_WindowState) (THIS_ long *);
- STDMETHOD(put_BackgroundPalette) (THIS_ long );
- STDMETHOD(get_BackgroundPalette) (THIS_ long *);
- STDMETHOD(put_Visible) (THIS_ long );
- STDMETHOD(get_Visible) (THIS_ long *);
- STDMETHOD(put_Left) (THIS_ long );
- STDMETHOD(get_Left) (THIS_ long *);
- STDMETHOD(put_Width) (THIS_ long );
- STDMETHOD(get_Width) (THIS_ long *);
- STDMETHOD(put_Top) (THIS_ long );
- STDMETHOD(get_Top) (THIS_ long *);
- STDMETHOD(put_Height) (THIS_ long );
- STDMETHOD(get_Height) (THIS_ long *);
- STDMETHOD(put_Owner) (THIS_ OAHWND );
- STDMETHOD(get_Owner) (THIS_ OAHWND * );
- STDMETHOD(put_MessageDrain) (THIS_ OAHWND );
- STDMETHOD(get_MessageDrain) (THIS_ OAHWND * );
- STDMETHOD(get_BorderColor) (THIS_ long *);
- STDMETHOD(put_BorderColor) (THIS_ long );
- STDMETHOD(get_FullScreenMode) (THIS_ long *);
- STDMETHOD(put_FullScreenMode) (THIS_ long );
- STDMETHOD(SetWindowForeground) (THIS_ long );
- STDMETHOD(NotifyOwnerMessage) (THIS_ OAHWND ,long , LONG_PTR ,LONG_PTR );
- STDMETHOD(SetWindowPosition) (THIS_ long ,long , long ,long );
- STDMETHOD(GetWindowPosition) (THIS_ long *,long *, long *,long *);
- STDMETHOD(GetMinIdealImageSize) (THIS_ long *, long *);
- STDMETHOD(GetMaxIdealImageSize) (THIS_ long *, long *);
- STDMETHOD(GetRestorePosition) (THIS_ long *,long *, long *,long *);
- STDMETHOD(HideCursor) (THIS_ long );
- STDMETHOD(IsCursorHidden) (THIS_ long *);
-};
-
-#ifndef DECLARE_ENUMERATOR_
-#define DECLARE_ENUMERATOR_(I,T) \
- DECLARE_INTERFACE_(I,IUnknown) \
- { \
- STDMETHOD(QueryInterface)(I*, REFIID,PVOID*); \
- STDMETHOD_(ULONG,AddRef)(I*); \
- STDMETHOD_(ULONG,Release)(I*); \
- STDMETHOD(Next)(I*, ULONG,T*,ULONG*); \
- STDMETHOD(Skip)(I*, ULONG); \
- STDMETHOD(Reset)(I*); \
- STDMETHOD(Clone)(I*, I**); \
- }
-#endif
-DECLARE_ENUMERATOR_(IEnumFilters, LPBASEFILTER);
-DECLARE_ENUMERATOR_(IEnumPins, LPPIN);
-DECLARE_ENUMERATOR_(IEnumMediaTypes, AM_MEDIA_TYPE *);
-
-#define OLE_CALL(p,method) (p)->lpVtbl->method(p)
-#ifdef __GNUC__
-#define OLE_CALL_ARGS(p, method, a1, args...) (p)->lpVtbl->method(p, a1, ##args)
-#else
-#define OLE_CALL_ARGS(p, method, ...) (p)->lpVtbl->method(p, __VA_ARGS__)
-#endif
-#define OLE_RELEASE_SAFE(p) if(p){ OLE_CALL((IUnknown*)p,Release); p=NULL;}
-#define OLE_QUERYINTERFACE(p,iface,ptr) OLE_CALL_ARGS((IUnknown*)p,QueryInterface,&iface,(void*)&ptr)
-
-#endif /* MPLAYER_TVI_DSHOW_H */