FFmpeg
dshow_pin.c
Go to the documentation of this file.
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 #include "libavutil/mem.h"
23 #include "dshow_capture.h"
24 
25 #include <stddef.h>
26 #define imemoffset offsetof(DShowPin, imemvtbl)
27 
29  { {&IID_IUnknown,0}, {&IID_IPin,0}, {&IID_IMemInputPin,imemoffset} })
32 
33 long WINAPI ff_dshow_pin_Connect(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type)
34 {
35  dshowdebug("ff_dshow_pin_Connect(%p, %p, %p)\n", this, pin, type);
36  /* Input pins receive connections. */
37  return S_FALSE;
38 }
39 long WINAPI ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin,
40  const AM_MEDIA_TYPE *type)
41 {
42  enum dshowDeviceType devtype = this->filter->type;
43  dshowdebug("ff_dshow_pin_ReceiveConnection(%p)\n", this);
44 
45  if (!pin)
46  return E_POINTER;
47  if (this->connectedto)
48  return VFW_E_ALREADY_CONNECTED;
49 
51  if (devtype == VideoDevice) {
52  if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video))
53  return VFW_E_TYPE_NOT_ACCEPTED;
54  } else {
55  if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Audio))
56  return VFW_E_TYPE_NOT_ACCEPTED;
57  }
58 
59  IPin_AddRef(pin);
60  this->connectedto = pin;
61 
62  ff_copy_dshow_media_type(&this->type, type);
63 
64  return S_OK;
65 }
67 {
68  dshowdebug("ff_dshow_pin_Disconnect(%p)\n", this);
69 
70  if (this->filter->state != State_Stopped)
71  return VFW_E_NOT_STOPPED;
72  if (!this->connectedto)
73  return S_FALSE;
74  IPin_Release(this->connectedto);
75  this->connectedto = NULL;
76 
77  return S_OK;
78 }
79 long WINAPI ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin)
80 {
81  dshowdebug("ff_dshow_pin_ConnectedTo(%p)\n", this);
82 
83  if (!pin)
84  return E_POINTER;
85  if (!this->connectedto)
86  return VFW_E_NOT_CONNECTED;
87  IPin_AddRef(this->connectedto);
88  *pin = this->connectedto;
89 
90  return S_OK;
91 }
92 long WINAPI ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type)
93 {
94  dshowdebug("ff_dshow_pin_ConnectionMediaType(%p)\n", this);
95 
96  if (!type)
97  return E_POINTER;
98  if (!this->connectedto)
99  return VFW_E_NOT_CONNECTED;
100 
101  return ff_copy_dshow_media_type(type, &this->type);
102 }
103 long WINAPI ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info)
104 {
105  dshowdebug("ff_dshow_pin_QueryPinInfo(%p)\n", this);
106 
107  if (!info)
108  return E_POINTER;
109 
110  if (this->filter)
112 
113  info->pFilter = (IBaseFilter *) this->filter;
114  info->dir = PINDIR_INPUT;
115  wcscpy(info->achName, L"Capture");
116 
117  return S_OK;
118 }
119 long WINAPI ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir)
120 {
121  dshowdebug("ff_dshow_pin_QueryDirection(%p)\n", this);
122  if (!dir)
123  return E_POINTER;
124  *dir = PINDIR_INPUT;
125  return S_OK;
126 }
127 long WINAPI ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id)
128 {
129  dshowdebug("ff_dshow_pin_QueryId(%p)\n", this);
130 
131  if (!id)
132  return E_POINTER;
133 
134  *id = wcsdup(L"libAV Pin");
135 
136  return S_OK;
137 }
138 long WINAPI ff_dshow_pin_QueryAccept(DShowPin *this, const AM_MEDIA_TYPE *type)
139 {
140  dshowdebug("ff_dshow_pin_QueryAccept(%p)\n", this);
141  return S_FALSE;
142 }
143 long WINAPI ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes)
144 {
145  const AM_MEDIA_TYPE *type = NULL;
146  DShowEnumMediaTypes *new;
147  dshowdebug("ff_dshow_pin_EnumMediaTypes(%p)\n", this);
148 
149  if (!enumtypes)
150  return E_POINTER;
152  if (!new)
153  return E_OUTOFMEMORY;
154 
155  *enumtypes = (IEnumMediaTypes *) new;
156  return S_OK;
157 }
158 long WINAPI ff_dshow_pin_QueryInternalConnections(DShowPin *this, IPin **pin,
159  unsigned long *npin)
160 {
161  dshowdebug("ff_dshow_pin_QueryInternalConnections(%p)\n", this);
162  return E_NOTIMPL;
163 }
165 {
166  dshowdebug("ff_dshow_pin_EndOfStream(%p)\n", this);
167  /* I don't care. */
168  return S_OK;
169 }
171 {
172  dshowdebug("ff_dshow_pin_BeginFlush(%p)\n", this);
173  /* I don't care. */
174  return S_OK;
175 }
176 long WINAPI ff_dshow_pin_EndFlush(DShowPin *this)
177 {
178  dshowdebug("ff_dshow_pin_EndFlush(%p)\n", this);
179  /* I don't care. */
180  return S_OK;
181 }
182 long WINAPI ff_dshow_pin_NewSegment(DShowPin *this, REFERENCE_TIME start, REFERENCE_TIME stop,
183  double rate)
184 {
185  dshowdebug("ff_dshow_pin_NewSegment(%p)\n", this);
186  /* I don't care. */
187  return S_OK;
188 }
189 
191 {
192  IPinVtbl *vtbl = this->vtbl;
193  IMemInputPinVtbl *imemvtbl;
194 
195  if (!filter)
196  return 0;
197 
198  imemvtbl = av_malloc(sizeof(IMemInputPinVtbl));
199  if (!imemvtbl)
200  return 0;
201 
202  SETVTBL(imemvtbl, meminputpin, QueryInterface);
203  SETVTBL(imemvtbl, meminputpin, AddRef);
204  SETVTBL(imemvtbl, meminputpin, Release);
205  SETVTBL(imemvtbl, meminputpin, GetAllocator);
206  SETVTBL(imemvtbl, meminputpin, NotifyAllocator);
207  SETVTBL(imemvtbl, meminputpin, GetAllocatorRequirements);
208  SETVTBL(imemvtbl, meminputpin, Receive);
209  SETVTBL(imemvtbl, meminputpin, ReceiveMultiple);
210  SETVTBL(imemvtbl, meminputpin, ReceiveCanBlock);
211 
212  this->imemvtbl = imemvtbl;
213 
214  SETVTBL(vtbl, pin, QueryInterface);
215  SETVTBL(vtbl, pin, AddRef);
216  SETVTBL(vtbl, pin, Release);
217  SETVTBL(vtbl, pin, Connect);
218  SETVTBL(vtbl, pin, ReceiveConnection);
219  SETVTBL(vtbl, pin, Disconnect);
220  SETVTBL(vtbl, pin, ConnectedTo);
221  SETVTBL(vtbl, pin, ConnectionMediaType);
222  SETVTBL(vtbl, pin, QueryPinInfo);
223  SETVTBL(vtbl, pin, QueryDirection);
224  SETVTBL(vtbl, pin, QueryId);
225  SETVTBL(vtbl, pin, QueryAccept);
226  SETVTBL(vtbl, pin, EnumMediaTypes);
227  SETVTBL(vtbl, pin, QueryInternalConnections);
228  SETVTBL(vtbl, pin, EndOfStream);
229  SETVTBL(vtbl, pin, BeginFlush);
230  SETVTBL(vtbl, pin, EndFlush);
231  SETVTBL(vtbl, pin, NewSegment);
232 
233  this->filter = filter;
234 
235  return 1;
236 }
237 
238 static void ff_dshow_pin_Free(DShowPin *this)
239 {
240  if (!this)
241  return;
242  av_freep(&this->imemvtbl);
243  if (this->type.pbFormat) {
244  CoTaskMemFree(this->type.pbFormat);
245  this->type.pbFormat = NULL;
246  }
247 }
250 
251 /*****************************************************************************
252  * DShowMemInputPin
253  ****************************************************************************/
254 long WINAPI ff_dshow_meminputpin_QueryInterface(DShowMemInputPin *this, const GUID *riid,
255  void **ppvObject)
256 {
257  DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset);
258  dshowdebug("ff_dshow_meminputpin_QueryInterface(%p)\n", this);
259  return ff_dshow_pin_QueryInterface(pin, riid, ppvObject);
260 }
262 {
263  DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset);
264  dshowdebug("ff_dshow_meminputpin_AddRef(%p)\n", this);
265  return ff_dshow_pin_AddRef(pin);
266 }
268 {
269  DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset);
270  dshowdebug("ff_dshow_meminputpin_Release(%p)\n", this);
271  return ff_dshow_pin_Release(pin);
272 }
273 long WINAPI ff_dshow_meminputpin_GetAllocator(DShowMemInputPin *this, IMemAllocator **alloc)
274 {
275  dshowdebug("ff_dshow_meminputpin_GetAllocator(%p)\n", this);
276  return VFW_E_NO_ALLOCATOR;
277 }
278 long WINAPI ff_dshow_meminputpin_NotifyAllocator(DShowMemInputPin *this, IMemAllocator *alloc,
279  BOOL rdwr)
280 {
281  dshowdebug("ff_dshow_meminputpin_NotifyAllocator(%p)\n", this);
282  return S_OK;
283 }
285  ALLOCATOR_PROPERTIES *props)
286 {
287  dshowdebug("ff_dshow_meminputpin_GetAllocatorRequirements(%p)\n", this);
288  return E_NOTIMPL;
289 }
290 long WINAPI ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample)
291 {
292  DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset);
293  enum dshowDeviceType devtype = pin->filter->type;
294  void *priv_data;
296  uint8_t *buf;
297  int buf_size; /* todo should be a long? */
298  int index;
299  int64_t chosentime = 0;
300  int64_t sampletime = 0;
301  int64_t graphtime = 0;
302  int use_sample_time = 1;
303  const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
304  IReferenceClock *clock = pin->filter->clock;
305  int64_t dummy;
306  struct dshow_ctx *ctx;
307  HRESULT hr;
308 
309 
310  dshowdebug("ff_dshow_meminputpin_Receive(%p)\n", this);
311 
312  if (!sample)
313  return E_POINTER;
314 
315  priv_data = pin->filter->priv_data;
316  s = priv_data;
317  ctx = s->priv_data;
318 
319  hr = IMediaSample_GetTime(sample, &sampletime, &dummy);
320  IReferenceClock_GetTime(clock, &graphtime);
321  if (devtype == VideoDevice && !ctx->use_video_device_timestamps) {
322  /* PTS from video devices is unreliable. */
323  chosentime = graphtime;
324  use_sample_time = 0;
325  } else {
326  if (hr == VFW_E_SAMPLE_TIME_NOT_SET || sampletime == 0) {
327  chosentime = graphtime;
328  use_sample_time = 0;
330  "frame with missing sample timestamp encountered, falling back to graph timestamp\n");
331  }
332  else if (sampletime > 400000000000000000LL) {
333  /* initial frames sometimes start < 0 (shown as a very large number here,
334  like 437650244077016960 which FFmpeg doesn't like).
335  TODO figure out math. For now just drop them. */
337  "dropping initial (or ending) sample with odd PTS too high %"PRId64"\n", sampletime);
338  return S_OK;
339  } else
340  chosentime = sampletime;
341  }
342  // media sample time is relative to graph start time
343  sampletime += pin->filter->start_time;
344  if (use_sample_time)
345  chosentime += pin->filter->start_time;
346 
347  buf_size = IMediaSample_GetActualDataLength(sample);
348  IMediaSample_GetPointer(sample, &buf);
349  index = pin->filter->stream_index;
350 
351  av_log(s, AV_LOG_VERBOSE, "passing through packet of type %s size %8d "
352  "timestamp %"PRId64" orig timestamp %"PRId64" graph timestamp %"PRId64" diff %"PRId64" %s\n",
353  devtypename, buf_size, chosentime, sampletime, graphtime, graphtime - sampletime, ctx->device_name[devtype]);
354  pin->filter->callback(priv_data, index, buf, buf_size, chosentime, devtype);
355 
356  return S_OK;
357 }
359  IMediaSample **samples, long n, long *nproc)
360 {
361  int i;
362  dshowdebug("ff_dshow_meminputpin_ReceiveMultiple(%p)\n", this);
363 
364  for (i = 0; i < n; i++)
366 
367  *nproc = n;
368  return S_OK;
369 }
371 {
372  dshowdebug("ff_dshow_meminputpin_ReceiveCanBlock(%p)\n", this);
373  /* I swear I will not block. */
374  return S_FALSE;
375 }
376 
378 {
379  DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset);
380  dshowdebug("ff_dshow_meminputpin_Destroy(%p)\n", this);
382 }
ff_dshow_meminputpin_Receive
long WINAPI ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample)
Definition: dshow_pin.c:290
DECLARE_CREATE
#define DECLARE_CREATE(prefix, class, setup,...)
Definition: dshow_capture.h:123
ff_dshow_meminputpin_QueryInterface
long WINAPI ff_dshow_meminputpin_QueryInterface(DShowMemInputPin *this, const GUID *riid, void **ppvObject)
Definition: dshow_pin.c:254
ff_dshow_meminputpin_AddRef
unsigned long WINAPI ff_dshow_meminputpin_AddRef(DShowMemInputPin *this)
Definition: dshow_pin.c:261
DShowPin::filter
DShowFilter * filter
Definition: dshow_capture.h:165
ff_dshow_meminputpin_GetAllocatorRequirements
long WINAPI ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *this, ALLOCATOR_PROPERTIES *props)
Definition: dshow_pin.c:284
VideoDevice
@ VideoDevice
Definition: dshow_capture.h:62
ff_dshow_pin_QueryInterface
long WINAPI ff_dshow_pin_QueryInterface(DShowPin *, const GUID *, void **)
ff_dshow_pin_Release
unsigned long WINAPI ff_dshow_pin_Release(DShowPin *)
dshow_capture.h
ff_dshow_pin_BeginFlush
long WINAPI ff_dshow_pin_BeginFlush(DShowPin *this)
Definition: dshow_pin.c:170
ff_dshow_pin_QueryInternalConnections
long WINAPI ff_dshow_pin_QueryInternalConnections(DShowPin *this, IPin **pin, unsigned long *npin)
Definition: dshow_pin.c:158
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
filter
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
Definition: filter_design.txt:228
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
ff_dshow_pin_EndOfStream
long WINAPI ff_dshow_pin_EndOfStream(DShowPin *this)
Definition: dshow_pin.c:164
ff_dshow_pin_ConnectionMediaType
long WINAPI ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type)
Definition: dshow_pin.c:92
ff_dshow_pin_Destroy
void ff_dshow_pin_Destroy(DShowPin *)
dummy
int dummy
Definition: motion.c:66
ff_dshow_pin_EnumMediaTypes
long WINAPI ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes)
Definition: dshow_pin.c:143
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
ff_print_AM_MEDIA_TYPE
void ff_print_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *type)
Definition: dshow_common.c:134
DECLARE_ADDREF
#define DECLARE_ADDREF(prefix, class)
Definition: dshow_capture.h:94
ff_dshow_meminputpin_ReceiveCanBlock
long WINAPI ff_dshow_meminputpin_ReceiveCanBlock(DShowMemInputPin *this)
Definition: dshow_pin.c:370
ff_dshow_pin_ConnectedTo
long WINAPI ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin)
Definition: dshow_pin.c:79
ff_dshow_pin_Free
static void ff_dshow_pin_Free(DShowPin *this)
Definition: dshow_pin.c:238
dshow_ctx
Definition: dshow_capture.h:286
ff_dshow_pin_EndFlush
long WINAPI ff_dshow_pin_EndFlush(DShowPin *this)
Definition: dshow_pin.c:176
s
#define s(width, name)
Definition: cbs_vp9.c:198
dshowdebug
#define dshowdebug(...)
Definition: dshow_capture.h:50
info
MIPS optimizations info
Definition: mips.txt:2
ff_copy_dshow_media_type
long ff_copy_dshow_media_type(AM_MEDIA_TYPE *dst, const AM_MEDIA_TYPE *src)
Definition: dshow_common.c:24
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
DShowFilter::type
enum dshowDeviceType type
Definition: dshow_capture.h:259
ctx
AVFormatContext * ctx
Definition: movenc.c:49
DShowFilter
Definition: dshow_capture.h:249
SETVTBL
#define SETVTBL(vtbl, prefix, fn)
Definition: dshow_capture.h:145
AVFormatContext
Format I/O context.
Definition: avformat.h:1255
NULL
#define NULL
Definition: coverity.c:32
DShowEnumMediaTypes
Definition: dshow_capture.h:228
ff_dshow_pin_QueryPinInfo
long WINAPI ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info)
Definition: dshow_pin.c:103
ff_dshow_meminputpin_GetAllocator
long WINAPI ff_dshow_meminputpin_GetAllocator(DShowMemInputPin *this, IMemAllocator **alloc)
Definition: dshow_pin.c:273
index
int index
Definition: gxfenc.c:90
ff_dshow_enummediatypes_Create
DShowEnumMediaTypes * ff_dshow_enummediatypes_Create(const AM_MEDIA_TYPE *type)
ff_dshow_pin_NewSegment
long WINAPI ff_dshow_pin_NewSegment(DShowPin *this, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
Definition: dshow_pin.c:182
ff_dshow_pin_ReceiveConnection
long WINAPI ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type)
Definition: dshow_pin.c:39
sample
#define sample
Definition: flacdsp_template.c:44
DShowMemInputPin
struct DShowMemInputPin DShowMemInputPin
Definition: dshow_capture.h:152
ff_dshow_pin_QueryDirection
long WINAPI ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir)
Definition: dshow_pin.c:119
DECLARE_DESTROY
#define DECLARE_DESTROY(prefix, class, func)
Definition: dshow_capture.h:112
ff_dshow_meminputpin_Release
unsigned long WINAPI ff_dshow_meminputpin_Release(DShowMemInputPin *this)
Definition: dshow_pin.c:267
ff_dshow_pin_Disconnect
long WINAPI ff_dshow_pin_Disconnect(DShowPin *this)
Definition: dshow_pin.c:66
imemoffset
#define imemoffset
Definition: dshow_pin.c:26
DShowFilter::clock
IReferenceClock * clock
Definition: dshow_capture.h:258
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ff_dshow_pin_Setup
static int ff_dshow_pin_Setup(DShowPin *this, DShowFilter *filter)
Definition: dshow_pin.c:190
ff_dshow_meminputpin_Destroy
void ff_dshow_meminputpin_Destroy(DShowMemInputPin *this)
Definition: dshow_pin.c:377
DShowFilter::stream_index
int stream_index
Definition: dshow_capture.h:261
ff_dshow_filter_AddRef
unsigned long WINAPI ff_dshow_filter_AddRef(DShowFilter *)
DECLARE_RELEASE
#define DECLARE_RELEASE(prefix, class)
Definition: dshow_capture.h:101
DShowFilter::priv_data
void * priv_data
Definition: dshow_capture.h:260
ff_dshow_pin_QueryAccept
long WINAPI ff_dshow_pin_QueryAccept(DShowPin *this, const AM_MEDIA_TYPE *type)
Definition: dshow_pin.c:138
L
#define L(x)
Definition: vpx_arith.h:36
samples
Filter the word “frame” indicates either a video frame or a group of audio samples
Definition: filter_design.txt:8
ff_dshow_pin_AddRef
unsigned long WINAPI ff_dshow_pin_AddRef(DShowPin *)
mem.h
DECLARE_QUERYINTERFACE
DECLARE_QUERYINTERFACE(pin, DShowPin, { {&IID_IUnknown, 0}, {&IID_IPin, 0}, {&IID_IMemInputPin, imemoffset} })
Definition: dshow_pin.c:28
ff_dshow_pin_Connect
long WINAPI ff_dshow_pin_Connect(DShowPin *, IPin *, const AM_MEDIA_TYPE *)
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
ff_dshow_meminputpin_ReceiveMultiple
long WINAPI ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, IMediaSample **samples, long n, long *nproc)
Definition: dshow_pin.c:358
ff_dshow_pin_QueryId
long WINAPI ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id)
Definition: dshow_pin.c:127
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
ff_dshow_meminputpin_NotifyAllocator
long WINAPI ff_dshow_meminputpin_NotifyAllocator(DShowMemInputPin *this, IMemAllocator *alloc, BOOL rdwr)
Definition: dshow_pin.c:278
DShowFilter::callback
void(* callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType type)
Definition: dshow_capture.h:263
DShowFilter::start_time
int64_t start_time
Definition: dshow_capture.h:262
DShowPin
Definition: dshow_capture.h:160
dshowDeviceType
dshowDeviceType
Definition: dshow_capture.h:61