summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
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);