1/* 2 * DirectShow capture interface 3 * Copyright (c) 2010 Ramiro Polla 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#ifndef AVDEVICE_DSHOW_H 23#define AVDEVICE_DSHOW_H 24 25#define DSHOWDEBUG 0 26 27#include "avdevice.h" 28 29#define COBJMACROS 30#include <windows.h> 31#define NO_DSHOW_STRSAFE 32#include <dshow.h> 33#include <dvdmedia.h> 34 35/* EC_DEVICE_LOST is not defined in MinGW dshow headers. */ 36#ifndef EC_DEVICE_LOST 37#define EC_DEVICE_LOST 0x1f 38#endif 39 40long ff_copy_dshow_media_type(AM_MEDIA_TYPE *dst, const AM_MEDIA_TYPE *src); 41void ff_print_VIDEO_STREAM_CONFIG_CAPS(const VIDEO_STREAM_CONFIG_CAPS *caps); 42void ff_print_AUDIO_STREAM_CONFIG_CAPS(const AUDIO_STREAM_CONFIG_CAPS *caps); 43void ff_print_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *type); 44void ff_printGUID(const GUID *g); 45 46#if DSHOWDEBUG 47extern const AVClass *ff_dshow_context_class_ptr; 48#define dshowdebug(...) av_log(&ff_dshow_context_class_ptr, AV_LOG_DEBUG, __VA_ARGS__) 49#else 50#define dshowdebug(...) 51#endif 52 53static inline void nothing(void *foo) 54{ 55} 56 57struct GUIDoffset { 58 const GUID *iid; 59 int offset; 60}; 61 62enum dshowDeviceType { 63 VideoDevice = 0, 64 AudioDevice = 1, 65}; 66 67#define DECLARE_QUERYINTERFACE(class, ...) \ 68long WINAPI \ 69class##_QueryInterface(class *this, const GUID *riid, void **ppvObject) \ 70{ \ 71 struct GUIDoffset ifaces[] = __VA_ARGS__; \ 72 int i; \ 73 dshowdebug(AV_STRINGIFY(class)"_QueryInterface(%p, %p, %p)\n", this, riid, ppvObject); \ 74 ff_printGUID(riid); \ 75 if (!ppvObject) \ 76 return E_POINTER; \ 77 for (i = 0; i < sizeof(ifaces)/sizeof(ifaces[0]); i++) { \ 78 if (IsEqualGUID(riid, ifaces[i].iid)) { \ 79 void *obj = (void *) ((uint8_t *) this + ifaces[i].offset); \ 80 class##_AddRef(this); \ 81 dshowdebug("\tfound %d with offset %d\n", i, ifaces[i].offset); \ 82 *ppvObject = (void *) obj; \ 83 return S_OK; \ 84 } \ 85 } \ 86 dshowdebug("\tE_NOINTERFACE\n"); \ 87 *ppvObject = NULL; \ 88 return E_NOINTERFACE; \ 89} 90#define DECLARE_ADDREF(class) \ 91unsigned long WINAPI \ 92class##_AddRef(class *this) \ 93{ \ 94 dshowdebug(AV_STRINGIFY(class)"_AddRef(%p)\t%ld\n", this, this->ref+1); \ 95 return InterlockedIncrement(&this->ref); \ 96} 97#define DECLARE_RELEASE(class) \ 98unsigned long WINAPI \ 99class##_Release(class *this) \ 100{ \ 101 long ref = InterlockedDecrement(&this->ref); \ 102 dshowdebug(AV_STRINGIFY(class)"_Release(%p)\t%ld\n", this, ref); \ 103 if (!ref) \ 104 class##_Destroy(this); \ 105 return ref; \ 106} 107 108#define DECLARE_DESTROY(class, func) \ 109void class##_Destroy(class *this) \ 110{ \ 111 dshowdebug(AV_STRINGIFY(class)"_Destroy(%p)\n", this); \ 112 func(this); \ 113 if (this) { \ 114 if (this->vtbl) \ 115 CoTaskMemFree(this->vtbl); \ 116 CoTaskMemFree(this); \ 117 } \ 118} 119#define DECLARE_CREATE(class, setup, ...) \ 120class *class##_Create(__VA_ARGS__) \ 121{ \ 122 class *this = CoTaskMemAlloc(sizeof(class)); \ 123 void *vtbl = CoTaskMemAlloc(sizeof(*this->vtbl)); \ 124 dshowdebug(AV_STRINGIFY(class)"_Create(%p)\n", this); \ 125 if (!this || !vtbl) \ 126 goto fail; \ 127 ZeroMemory(this, sizeof(class)); \ 128 ZeroMemory(vtbl, sizeof(*this->vtbl)); \ 129 this->ref = 1; \ 130 this->vtbl = vtbl; \ 131 if (!setup) \ 132 goto fail; \ 133 dshowdebug("created "AV_STRINGIFY(class)" %p\n", this); \ 134 return this; \ 135fail: \ 136 class##_Destroy(this); \ 137 dshowdebug("could not create "AV_STRINGIFY(class)"\n"); \ 138 return NULL; \ 139} 140 141#define SETVTBL(vtbl, class, fn) \ 142 do { (vtbl)->fn = (void *) class##_##fn; } while(0) 143 144/***************************************************************************** 145 * Forward Declarations 146 ****************************************************************************/ 147typedef struct libAVPin libAVPin; 148typedef struct libAVMemInputPin libAVMemInputPin; 149typedef struct libAVEnumPins libAVEnumPins; 150typedef struct libAVEnumMediaTypes libAVEnumMediaTypes; 151typedef struct libAVFilter libAVFilter; 152 153/***************************************************************************** 154 * libAVPin 155 ****************************************************************************/ 156struct libAVPin { 157 IPinVtbl *vtbl; 158 long ref; 159 libAVFilter *filter; 160 IPin *connectedto; 161 AM_MEDIA_TYPE type; 162 IMemInputPinVtbl *imemvtbl; 163}; 164 165long WINAPI libAVPin_QueryInterface (libAVPin *, const GUID *, void **); 166unsigned long WINAPI libAVPin_AddRef (libAVPin *); 167unsigned long WINAPI libAVPin_Release (libAVPin *); 168long WINAPI libAVPin_Connect (libAVPin *, IPin *, const AM_MEDIA_TYPE *); 169long WINAPI libAVPin_ReceiveConnection (libAVPin *, IPin *, const AM_MEDIA_TYPE *); 170long WINAPI libAVPin_Disconnect (libAVPin *); 171long WINAPI libAVPin_ConnectedTo (libAVPin *, IPin **); 172long WINAPI libAVPin_ConnectionMediaType (libAVPin *, AM_MEDIA_TYPE *); 173long WINAPI libAVPin_QueryPinInfo (libAVPin *, PIN_INFO *); 174long WINAPI libAVPin_QueryDirection (libAVPin *, PIN_DIRECTION *); 175long WINAPI libAVPin_QueryId (libAVPin *, wchar_t **); 176long WINAPI libAVPin_QueryAccept (libAVPin *, const AM_MEDIA_TYPE *); 177long WINAPI libAVPin_EnumMediaTypes (libAVPin *, IEnumMediaTypes **); 178long WINAPI libAVPin_QueryInternalConnections(libAVPin *, IPin **, unsigned long *); 179long WINAPI libAVPin_EndOfStream (libAVPin *); 180long WINAPI libAVPin_BeginFlush (libAVPin *); 181long WINAPI libAVPin_EndFlush (libAVPin *); 182long WINAPI libAVPin_NewSegment (libAVPin *, REFERENCE_TIME, REFERENCE_TIME, double); 183 184long WINAPI libAVMemInputPin_QueryInterface (libAVMemInputPin *, const GUID *, void **); 185unsigned long WINAPI libAVMemInputPin_AddRef (libAVMemInputPin *); 186unsigned long WINAPI libAVMemInputPin_Release (libAVMemInputPin *); 187long WINAPI libAVMemInputPin_GetAllocator (libAVMemInputPin *, IMemAllocator **); 188long WINAPI libAVMemInputPin_NotifyAllocator (libAVMemInputPin *, IMemAllocator *, BOOL); 189long WINAPI libAVMemInputPin_GetAllocatorRequirements(libAVMemInputPin *, ALLOCATOR_PROPERTIES *); 190long WINAPI libAVMemInputPin_Receive (libAVMemInputPin *, IMediaSample *); 191long WINAPI libAVMemInputPin_ReceiveMultiple (libAVMemInputPin *, IMediaSample **, long, long *); 192long WINAPI libAVMemInputPin_ReceiveCanBlock (libAVMemInputPin *); 193 194void libAVPin_Destroy(libAVPin *); 195libAVPin *libAVPin_Create (libAVFilter *filter); 196 197void libAVMemInputPin_Destroy(libAVMemInputPin *); 198 199/***************************************************************************** 200 * libAVEnumPins 201 ****************************************************************************/ 202struct libAVEnumPins { 203 IEnumPinsVtbl *vtbl; 204 long ref; 205 int pos; 206 libAVPin *pin; 207 libAVFilter *filter; 208}; 209 210long WINAPI libAVEnumPins_QueryInterface(libAVEnumPins *, const GUID *, void **); 211unsigned long WINAPI libAVEnumPins_AddRef (libAVEnumPins *); 212unsigned long WINAPI libAVEnumPins_Release (libAVEnumPins *); 213long WINAPI libAVEnumPins_Next (libAVEnumPins *, unsigned long, IPin **, unsigned long *); 214long WINAPI libAVEnumPins_Skip (libAVEnumPins *, unsigned long); 215long WINAPI libAVEnumPins_Reset (libAVEnumPins *); 216long WINAPI libAVEnumPins_Clone (libAVEnumPins *, libAVEnumPins **); 217 218void libAVEnumPins_Destroy(libAVEnumPins *); 219libAVEnumPins *libAVEnumPins_Create (libAVPin *pin, libAVFilter *filter); 220 221/***************************************************************************** 222 * libAVEnumMediaTypes 223 ****************************************************************************/ 224struct libAVEnumMediaTypes { 225 IEnumPinsVtbl *vtbl; 226 long ref; 227 int pos; 228 AM_MEDIA_TYPE type; 229}; 230 231long WINAPI libAVEnumMediaTypes_QueryInterface(libAVEnumMediaTypes *, const GUID *, void **); 232unsigned long WINAPI libAVEnumMediaTypes_AddRef (libAVEnumMediaTypes *); 233unsigned long WINAPI libAVEnumMediaTypes_Release (libAVEnumMediaTypes *); 234long WINAPI libAVEnumMediaTypes_Next (libAVEnumMediaTypes *, unsigned long, AM_MEDIA_TYPE **, unsigned long *); 235long WINAPI libAVEnumMediaTypes_Skip (libAVEnumMediaTypes *, unsigned long); 236long WINAPI libAVEnumMediaTypes_Reset (libAVEnumMediaTypes *); 237long WINAPI libAVEnumMediaTypes_Clone (libAVEnumMediaTypes *, libAVEnumMediaTypes **); 238 239void libAVEnumMediaTypes_Destroy(libAVEnumMediaTypes *); 240libAVEnumMediaTypes *libAVEnumMediaTypes_Create(const AM_MEDIA_TYPE *type); 241 242/***************************************************************************** 243 * libAVFilter 244 ****************************************************************************/ 245struct libAVFilter { 246 IBaseFilterVtbl *vtbl; 247 long ref; 248 const wchar_t *name; 249 libAVPin *pin; 250 FILTER_INFO info; 251 FILTER_STATE state; 252 IReferenceClock *clock; 253 enum dshowDeviceType type; 254 void *priv_data; 255 int stream_index; 256 int64_t start_time; 257 void (*callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType type); 258}; 259 260long WINAPI libAVFilter_QueryInterface (libAVFilter *, const GUID *, void **); 261unsigned long WINAPI libAVFilter_AddRef (libAVFilter *); 262unsigned long WINAPI libAVFilter_Release (libAVFilter *); 263long WINAPI libAVFilter_GetClassID (libAVFilter *, CLSID *); 264long WINAPI libAVFilter_Stop (libAVFilter *); 265long WINAPI libAVFilter_Pause (libAVFilter *); 266long WINAPI libAVFilter_Run (libAVFilter *, REFERENCE_TIME); 267long WINAPI libAVFilter_GetState (libAVFilter *, DWORD, FILTER_STATE *); 268long WINAPI libAVFilter_SetSyncSource (libAVFilter *, IReferenceClock *); 269long WINAPI libAVFilter_GetSyncSource (libAVFilter *, IReferenceClock **); 270long WINAPI libAVFilter_EnumPins (libAVFilter *, IEnumPins **); 271long WINAPI libAVFilter_FindPin (libAVFilter *, const wchar_t *, IPin **); 272long WINAPI libAVFilter_QueryFilterInfo(libAVFilter *, FILTER_INFO *); 273long WINAPI libAVFilter_JoinFilterGraph(libAVFilter *, IFilterGraph *, const wchar_t *); 274long WINAPI libAVFilter_QueryVendorInfo(libAVFilter *, wchar_t **); 275 276void libAVFilter_Destroy(libAVFilter *); 277libAVFilter *libAVFilter_Create (void *, void *, enum dshowDeviceType); 278 279#endif /* AVDEVICE_DSHOW_H */ 280