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 "dshow_capture.h"
23 
24 #include <stddef.h>
25 #define imemoffset offsetof(libAVPin, imemvtbl)
26 
28  { {&IID_IUnknown,0}, {&IID_IPin,0}, {&IID_IMemInputPin,imemoffset} })
31 
32 long WINAPI
33 libAVPin_Connect(libAVPin *this, IPin *pin, const AM_MEDIA_TYPE *type)
34 {
35  dshowdebug("libAVPin_Connect(%p, %p, %p)\n", this, pin, type);
36  /* Input pins receive connections. */
37  return S_FALSE;
38 }
39 long WINAPI
41  const AM_MEDIA_TYPE *type)
42 {
43  enum dshowDeviceType devtype = this->filter->type;
44  dshowdebug("libAVPin_ReceiveConnection(%p)\n", this);
45 
46  if (!pin)
47  return E_POINTER;
48  if (this->connectedto)
49  return VFW_E_ALREADY_CONNECTED;
50 
52  if (devtype == VideoDevice) {
53  if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video))
54  return VFW_E_TYPE_NOT_ACCEPTED;
55  } else {
56  if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Audio))
57  return VFW_E_TYPE_NOT_ACCEPTED;
58  }
59 
60  IPin_AddRef(pin);
61  this->connectedto = pin;
62 
63  ff_copy_dshow_media_type(&this->type, type);
64 
65  return S_OK;
66 }
67 long WINAPI
69 {
70  dshowdebug("libAVPin_Disconnect(%p)\n", this);
71 
72  if (this->filter->state != State_Stopped)
73  return VFW_E_NOT_STOPPED;
74  if (!this->connectedto)
75  return S_FALSE;
76  IPin_Release(this->connectedto);
77  this->connectedto = NULL;
78 
79  return S_OK;
80 }
81 long WINAPI
82 libAVPin_ConnectedTo(libAVPin *this, IPin **pin)
83 {
84  dshowdebug("libAVPin_ConnectedTo(%p)\n", this);
85 
86  if (!pin)
87  return E_POINTER;
88  if (!this->connectedto)
89  return VFW_E_NOT_CONNECTED;
90  IPin_AddRef(this->connectedto);
91  *pin = this->connectedto;
92 
93  return S_OK;
94 }
95 long WINAPI
96 libAVPin_ConnectionMediaType(libAVPin *this, AM_MEDIA_TYPE *type)
97 {
98  dshowdebug("libAVPin_ConnectionMediaType(%p)\n", this);
99 
100  if (!type)
101  return E_POINTER;
102  if (!this->connectedto)
103  return VFW_E_NOT_CONNECTED;
104 
105  return ff_copy_dshow_media_type(type, &this->type);
106 }
107 long WINAPI
109 {
110  dshowdebug("libAVPin_QueryPinInfo(%p)\n", this);
111 
112  if (!info)
113  return E_POINTER;
114 
115  if (this->filter)
116  libAVFilter_AddRef(this->filter);
117 
118  info->pFilter = (IBaseFilter *) this->filter;
119  info->dir = PINDIR_INPUT;
120  wcscpy(info->achName, L"Capture");
121 
122  return S_OK;
123 }
124 long WINAPI
125 libAVPin_QueryDirection(libAVPin *this, PIN_DIRECTION *dir)
126 {
127  dshowdebug("libAVPin_QueryDirection(%p)\n", this);
128  if (!dir)
129  return E_POINTER;
130  *dir = PINDIR_INPUT;
131  return S_OK;
132 }
133 long WINAPI
134 libAVPin_QueryId(libAVPin *this, wchar_t **id)
135 {
136  dshowdebug("libAVPin_QueryId(%p)\n", this);
137 
138  if (!id)
139  return E_POINTER;
140 
141  *id = wcsdup(L"libAV Pin");
142 
143  return S_OK;
144 }
145 long WINAPI
146 libAVPin_QueryAccept(libAVPin *this, const AM_MEDIA_TYPE *type)
147 {
148  dshowdebug("libAVPin_QueryAccept(%p)\n", this);
149  return S_FALSE;
150 }
151 long WINAPI
152 libAVPin_EnumMediaTypes(libAVPin *this, IEnumMediaTypes **enumtypes)
153 {
154  const AM_MEDIA_TYPE *type = NULL;
155  libAVEnumMediaTypes *new;
156  dshowdebug("libAVPin_EnumMediaTypes(%p)\n", this);
157 
158  if (!enumtypes)
159  return E_POINTER;
160  new = libAVEnumMediaTypes_Create(type);
161  if (!new)
162  return E_OUTOFMEMORY;
163 
164  *enumtypes = (IEnumMediaTypes *) new;
165  return S_OK;
166 }
167 long WINAPI
169  unsigned long *npin)
170 {
171  dshowdebug("libAVPin_QueryInternalConnections(%p)\n", this);
172  return E_NOTIMPL;
173 }
174 long WINAPI
176 {
177  dshowdebug("libAVPin_EndOfStream(%p)\n", this);
178  /* I don't care. */
179  return S_OK;
180 }
181 long WINAPI
183 {
184  dshowdebug("libAVPin_BeginFlush(%p)\n", this);
185  /* I don't care. */
186  return S_OK;
187 }
188 long WINAPI
190 {
191  dshowdebug("libAVPin_EndFlush(%p)\n", this);
192  /* I don't care. */
193  return S_OK;
194 }
195 long WINAPI
196 libAVPin_NewSegment(libAVPin *this, REFERENCE_TIME start, REFERENCE_TIME stop,
197  double rate)
198 {
199  dshowdebug("libAVPin_NewSegment(%p)\n", this);
200  /* I don't care. */
201  return S_OK;
202 }
203 
204 static int
206 {
207  IPinVtbl *vtbl = this->vtbl;
208  IMemInputPinVtbl *imemvtbl;
209 
210  if (!filter)
211  return 0;
212 
213  imemvtbl = av_malloc(sizeof(IMemInputPinVtbl));
214  if (!imemvtbl)
215  return 0;
216 
217  SETVTBL(imemvtbl, libAVMemInputPin, QueryInterface);
218  SETVTBL(imemvtbl, libAVMemInputPin, AddRef);
219  SETVTBL(imemvtbl, libAVMemInputPin, Release);
220  SETVTBL(imemvtbl, libAVMemInputPin, GetAllocator);
221  SETVTBL(imemvtbl, libAVMemInputPin, NotifyAllocator);
222  SETVTBL(imemvtbl, libAVMemInputPin, GetAllocatorRequirements);
223  SETVTBL(imemvtbl, libAVMemInputPin, Receive);
224  SETVTBL(imemvtbl, libAVMemInputPin, ReceiveMultiple);
225  SETVTBL(imemvtbl, libAVMemInputPin, ReceiveCanBlock);
226 
227  this->imemvtbl = imemvtbl;
228 
229  SETVTBL(vtbl, libAVPin, QueryInterface);
230  SETVTBL(vtbl, libAVPin, AddRef);
231  SETVTBL(vtbl, libAVPin, Release);
232  SETVTBL(vtbl, libAVPin, Connect);
233  SETVTBL(vtbl, libAVPin, ReceiveConnection);
234  SETVTBL(vtbl, libAVPin, Disconnect);
235  SETVTBL(vtbl, libAVPin, ConnectedTo);
236  SETVTBL(vtbl, libAVPin, ConnectionMediaType);
237  SETVTBL(vtbl, libAVPin, QueryPinInfo);
238  SETVTBL(vtbl, libAVPin, QueryDirection);
239  SETVTBL(vtbl, libAVPin, QueryId);
240  SETVTBL(vtbl, libAVPin, QueryAccept);
241  SETVTBL(vtbl, libAVPin, EnumMediaTypes);
242  SETVTBL(vtbl, libAVPin, QueryInternalConnections);
243  SETVTBL(vtbl, libAVPin, EndOfStream);
244  SETVTBL(vtbl, libAVPin, BeginFlush);
245  SETVTBL(vtbl, libAVPin, EndFlush);
246  SETVTBL(vtbl, libAVPin, NewSegment);
247 
248  this->filter = filter;
249 
250  return 1;
251 }
254 
255 /*****************************************************************************
256  * libAVMemInputPin
257  ****************************************************************************/
258 long WINAPI
260  void **ppvObject)
261 {
262  libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
263  dshowdebug("libAVMemInputPin_QueryInterface(%p)\n", this);
264  return libAVPin_QueryInterface(pin, riid, ppvObject);
265 }
266 unsigned long WINAPI
268 {
269  libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
270  dshowdebug("libAVMemInputPin_AddRef(%p)\n", this);
271  return libAVPin_AddRef(pin);
272 }
273 unsigned long WINAPI
275 {
276  libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
277  dshowdebug("libAVMemInputPin_Release(%p)\n", this);
278  return libAVPin_Release(pin);
279 }
280 long WINAPI
281 libAVMemInputPin_GetAllocator(libAVMemInputPin *this, IMemAllocator **alloc)
282 {
283  dshowdebug("libAVMemInputPin_GetAllocator(%p)\n", this);
284  return VFW_E_NO_ALLOCATOR;
285 }
286 long WINAPI
288  BOOL rdwr)
289 {
290  dshowdebug("libAVMemInputPin_NotifyAllocator(%p)\n", this);
291  return S_OK;
292 }
293 long WINAPI
295  ALLOCATOR_PROPERTIES *props)
296 {
297  dshowdebug("libAVMemInputPin_GetAllocatorRequirements(%p)\n", this);
298  return E_NOTIMPL;
299 }
300 long WINAPI
302 {
303  libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
304  enum dshowDeviceType devtype = pin->filter->type;
305  void *priv_data;
306  uint8_t *buf;
307  int buf_size;
308  int index;
309  int64_t curtime;
310 
311  dshowdebug("libAVMemInputPin_Receive(%p)\n", this);
312 
313  if (!sample)
314  return E_POINTER;
315 
316  if (devtype == VideoDevice) {
317  /* PTS from video devices is unreliable. */
318  IReferenceClock *clock = pin->filter->clock;
319  IReferenceClock_GetTime(clock, &curtime);
320  } else {
321  int64_t dummy;
322  IMediaSample_GetTime(sample, &curtime, &dummy);
323  curtime += pin->filter->start_time;
324  }
325 
326  buf_size = IMediaSample_GetActualDataLength(sample);
327  IMediaSample_GetPointer(sample, &buf);
328  priv_data = pin->filter->priv_data;
329  index = pin->filter->stream_index;
330 
331  pin->filter->callback(priv_data, index, buf, buf_size, curtime);
332 
333  return S_OK;
334 }
335 long WINAPI
337  IMediaSample **samples, long n, long *nproc)
338 {
339  int i;
340  dshowdebug("libAVMemInputPin_ReceiveMultiple(%p)\n", this);
341 
342  for (i = 0; i < n; i++)
343  libAVMemInputPin_Receive(this, samples[i]);
344 
345  *nproc = n;
346  return S_OK;
347 }
348 long WINAPI
350 {
351  dshowdebug("libAVMemInputPin_ReceiveCanBlock(%p)\n", this);
352  /* I swear I will not block. */
353  return S_FALSE;
354 }
355 
356 void
358 {
359  libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset);
360  dshowdebug("libAVMemInputPin_Destroy(%p)\n", this);
361  libAVPin_Destroy(pin);
362 }
long WINAPI libAVPin_ReceiveConnection(libAVPin *this, IPin *pin, const AM_MEDIA_TYPE *type)
Definition: dshow_pin.c:40
Definition: start.py:1
#define S_OK
Definition: windows2linux.h:40
long WINAPI libAVMemInputPin_GetAllocatorRequirements(libAVMemInputPin *this, ALLOCATOR_PROPERTIES *props)
Definition: dshow_pin.c:294
enum dshowDeviceType type
#define dshowdebug(...)
Definition: dshow_capture.h:50
#define DECLARE_DESTROY(class, func)
unsigned long WINAPI libAVPin_Release(libAVPin *)
dshowDeviceType
Definition: dshow_capture.h:62
long WINAPI libAVPin_QueryAccept(libAVPin *this, const AM_MEDIA_TYPE *type)
Definition: dshow_pin.c:146
#define E_POINTER
Definition: windows2linux.h:43
#define sample
long WINAPI libAVPin_QueryPinInfo(libAVPin *this, PIN_INFO *info)
Definition: dshow_pin.c:108
#define DECLARE_CREATE(class, setup,...)
IReferenceClock * clock
void libAVPin_Destroy(libAVPin *)
long WINAPI libAVPin_QueryId(libAVPin *this, wchar_t **id)
Definition: dshow_pin.c:134
uint8_t
long WINAPI libAVPin_Connect(libAVPin *, IPin *, const AM_MEDIA_TYPE *)
long WINAPI libAVMemInputPin_GetAllocator(libAVMemInputPin *this, IMemAllocator **alloc)
Definition: dshow_pin.c:281
the mask is usually to keep the same permissions Filters should remove permissions on reference they give to output whenever necessary It can be automatically done by setting the rej_perms field on the output pad Here are a few guidelines corresponding to common 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
DECLARE_QUERYINTERFACE(libAVPin,{{&IID_IUnknown, 0},{&IID_IPin, 0},{&IID_IMemInputPin, imemoffset}})
Definition: dshow_pin.c:27
long WINAPI libAVMemInputPin_ReceiveCanBlock(libAVMemInputPin *this)
Definition: dshow_pin.c:349
long WINAPI libAVPin_EnumMediaTypes(libAVPin *this, IEnumMediaTypes **enumtypes)
Definition: dshow_pin.c:152
#define DECLARE_RELEASE(class)
Definition: dshow_capture.h:97
long ff_copy_dshow_media_type(AM_MEDIA_TYPE *dst, const AM_MEDIA_TYPE *src)
Definition: dshow_common.c:24
long WINAPI libAVPin_NewSegment(libAVPin *this, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
Definition: dshow_pin.c:196
unsigned long WINAPI libAVPin_AddRef(libAVPin *)
void * priv_data
MIPS optimizations info
Definition: mips.txt:2
long WINAPI libAVPin_ConnectedTo(libAVPin *this, IPin **pin)
Definition: dshow_pin.c:82
#define L(x)
long WINAPI libAVMemInputPin_QueryInterface(libAVMemInputPin *this, const GUID *riid, void **ppvObject)
Definition: dshow_pin.c:259
NULL
Definition: eval.c:55
#define SETVTBL(vtbl, class, fn)
long WINAPI libAVPin_QueryDirection(libAVPin *this, PIN_DIRECTION *dir)
Definition: dshow_pin.c:125
long WINAPI libAVPin_EndOfStream(libAVPin *this)
Definition: dshow_pin.c:175
long WINAPI libAVPin_EndFlush(libAVPin *this)
Definition: dshow_pin.c:189
long WINAPI libAVPin_Disconnect(libAVPin *this)
Definition: dshow_pin.c:68
void * buf
Definition: avisynth_c.h:594
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
unsigned long WINAPI libAVFilter_AddRef(libAVFilter *)
int index
Definition: gxfenc.c:89
synthesis window for stochastic i
long WINAPI libAVMemInputPin_Receive(libAVMemInputPin *this, IMediaSample *sample)
Definition: dshow_pin.c:301
void libAVMemInputPin_Destroy(libAVMemInputPin *this)
Definition: dshow_pin.c:357
static int libAVPin_Setup(libAVPin *this, libAVFilter *filter)
Definition: dshow_pin.c:205
unsigned long WINAPI libAVMemInputPin_AddRef(libAVMemInputPin *this)
Definition: dshow_pin.c:267
#define type
static void nothing(void *foo)
Definition: dshow_capture.h:53
#define E_OUTOFMEMORY
Definition: windows2linux.h:45
int64_t start_time
long WINAPI libAVPin_QueryInterface(libAVPin *, const GUID *, void **)
void(* callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time)
unsigned long WINAPI libAVMemInputPin_Release(libAVMemInputPin *this)
Definition: dshow_pin.c:274
#define imemoffset
Definition: dshow_pin.c:25
long WINAPI libAVMemInputPin_NotifyAllocator(libAVMemInputPin *this, IMemAllocator *alloc, BOOL rdwr)
Definition: dshow_pin.c:287
long WINAPI libAVMemInputPin_ReceiveMultiple(libAVMemInputPin *this, IMediaSample **samples, long n, long *nproc)
Definition: dshow_pin.c:336
long WINAPI libAVPin_BeginFlush(libAVPin *this)
Definition: dshow_pin.c:182
uint32_t BOOL
#define S_FALSE
Definition: windows2linux.h:41
half analysis window size pin
long WINAPI libAVPin_QueryInternalConnections(libAVPin *this, IPin **pin, unsigned long *npin)
Definition: dshow_pin.c:168
libAVEnumMediaTypes * libAVEnumMediaTypes_Create(const AM_MEDIA_TYPE *type)
void ff_print_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *type)
Definition: dshow_common.c:134
long WINAPI libAVPin_ConnectionMediaType(libAVPin *this, AM_MEDIA_TYPE *type)
Definition: dshow_pin.c:96
Filter the word “frame” indicates either a video frame or a group of audio samples
struct libAVMemInputPin libAVMemInputPin
#define DECLARE_ADDREF(class)
Definition: dshow_capture.h:90
int dummy
Definition: motion-test.c:64
libAVFilter * filter