2 * DirectShow capture interface
3 * Copyright (c) 2010 Ramiro Polla
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "dshow_capture.h"
25 #define imemoffset offsetof(libAVPin, imemvtbl)
27 DECLARE_QUERYINTERFACE(libAVPin
,
28 { {&IID_IUnknown
,0}, {&IID_IPin
,0}, {&IID_IMemInputPin
,imemoffset
} })
29 DECLARE_ADDREF(libAVPin
)
30 DECLARE_RELEASE(libAVPin
)
33 libAVPin_Connect(libAVPin
*this, IPin
*pin
, const AM_MEDIA_TYPE
*type
)
35 dshowdebug("libAVPin_Connect(%p, %p, %p)\n", this, pin
, type
);
36 /* Input pins receive connections. */
40 libAVPin_ReceiveConnection(libAVPin
*this, IPin
*pin
,
41 const AM_MEDIA_TYPE
*type
)
43 enum dshowDeviceType devtype
= this->filter
->type
;
44 dshowdebug("libAVPin_ReceiveConnection(%p)\n", this);
48 if (this->connectedto
)
49 return VFW_E_ALREADY_CONNECTED
;
51 ff_print_AM_MEDIA_TYPE(type
);
52 if (devtype
== VideoDevice
) {
53 if (!IsEqualGUID(&type
->majortype
, &MEDIATYPE_Video
))
54 return VFW_E_TYPE_NOT_ACCEPTED
;
56 if (!IsEqualGUID(&type
->majortype
, &MEDIATYPE_Audio
))
57 return VFW_E_TYPE_NOT_ACCEPTED
;
61 this->connectedto
= pin
;
63 ff_copy_dshow_media_type(&this->type
, type
);
68 libAVPin_Disconnect(libAVPin
*this)
70 dshowdebug("libAVPin_Disconnect(%p)\n", this);
72 if (this->filter
->state
!= State_Stopped
)
73 return VFW_E_NOT_STOPPED
;
74 if (!this->connectedto
)
76 IPin_Release(this->connectedto
);
77 this->connectedto
= NULL
;
82 libAVPin_ConnectedTo(libAVPin
*this, IPin
**pin
)
84 dshowdebug("libAVPin_ConnectedTo(%p)\n", this);
88 if (!this->connectedto
)
89 return VFW_E_NOT_CONNECTED
;
90 IPin_AddRef(this->connectedto
);
91 *pin
= this->connectedto
;
96 libAVPin_ConnectionMediaType(libAVPin
*this, AM_MEDIA_TYPE
*type
)
98 dshowdebug("libAVPin_ConnectionMediaType(%p)\n", this);
102 if (!this->connectedto
)
103 return VFW_E_NOT_CONNECTED
;
105 return ff_copy_dshow_media_type(type
, &this->type
);
108 libAVPin_QueryPinInfo(libAVPin
*this, PIN_INFO
*info
)
110 dshowdebug("libAVPin_QueryPinInfo(%p)\n", this);
116 libAVFilter_AddRef(this->filter
);
118 info
->pFilter
= (IBaseFilter
*) this->filter
;
119 info
->dir
= PINDIR_INPUT
;
120 wcscpy(info
->achName
, L
"Capture");
125 libAVPin_QueryDirection(libAVPin
*this, PIN_DIRECTION
*dir
)
127 dshowdebug("libAVPin_QueryDirection(%p)\n", this);
134 libAVPin_QueryId(libAVPin
*this, wchar_t **id
)
136 dshowdebug("libAVPin_QueryId(%p)\n", this);
141 *id
= wcsdup(L
"libAV Pin");
146 libAVPin_QueryAccept(libAVPin
*this, const AM_MEDIA_TYPE
*type
)
148 dshowdebug("libAVPin_QueryAccept(%p)\n", this);
152 libAVPin_EnumMediaTypes(libAVPin
*this, IEnumMediaTypes
**enumtypes
)
154 const AM_MEDIA_TYPE
*type
= NULL
;
155 libAVEnumMediaTypes
*new;
156 dshowdebug("libAVPin_EnumMediaTypes(%p)\n", this);
160 new = libAVEnumMediaTypes_Create(type
);
162 return E_OUTOFMEMORY
;
164 *enumtypes
= (IEnumMediaTypes
*) new;
168 libAVPin_QueryInternalConnections(libAVPin
*this, IPin
**pin
,
171 dshowdebug("libAVPin_QueryInternalConnections(%p)\n", this);
175 libAVPin_EndOfStream(libAVPin
*this)
177 dshowdebug("libAVPin_EndOfStream(%p)\n", this);
182 libAVPin_BeginFlush(libAVPin
*this)
184 dshowdebug("libAVPin_BeginFlush(%p)\n", this);
189 libAVPin_EndFlush(libAVPin
*this)
191 dshowdebug("libAVPin_EndFlush(%p)\n", this);
196 libAVPin_NewSegment(libAVPin
*this, REFERENCE_TIME start
, REFERENCE_TIME stop
,
199 dshowdebug("libAVPin_NewSegment(%p)\n", this);
205 libAVPin_Setup(libAVPin
*this, libAVFilter
*filter
)
207 IPinVtbl
*vtbl
= this->vtbl
;
208 IMemInputPinVtbl
*imemvtbl
;
213 imemvtbl
= av_malloc(sizeof(IMemInputPinVtbl
));
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
);
227 this->imemvtbl
= imemvtbl
;
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
);
248 this->filter
= filter
;
252 DECLARE_CREATE(libAVPin
, libAVPin_Setup(this, filter
), libAVFilter
*filter
)
253 DECLARE_DESTROY(libAVPin
, nothing
)
255 /*****************************************************************************
257 ****************************************************************************/
259 libAVMemInputPin_QueryInterface(libAVMemInputPin
*this, const GUID
*riid
,
262 libAVPin
*pin
= (libAVPin
*) ((uint8_t *) this - imemoffset
);
263 dshowdebug("libAVMemInputPin_QueryInterface(%p)\n", this);
264 return libAVPin_QueryInterface(pin
, riid
, ppvObject
);
267 libAVMemInputPin_AddRef(libAVMemInputPin
*this)
269 libAVPin
*pin
= (libAVPin
*) ((uint8_t *) this - imemoffset
);
270 dshowdebug("libAVMemInputPin_AddRef(%p)\n", this);
271 return libAVPin_AddRef(pin
);
274 libAVMemInputPin_Release(libAVMemInputPin
*this)
276 libAVPin
*pin
= (libAVPin
*) ((uint8_t *) this - imemoffset
);
277 dshowdebug("libAVMemInputPin_Release(%p)\n", this);
278 return libAVPin_Release(pin
);
281 libAVMemInputPin_GetAllocator(libAVMemInputPin
*this, IMemAllocator
**alloc
)
283 dshowdebug("libAVMemInputPin_GetAllocator(%p)\n", this);
284 return VFW_E_NO_ALLOCATOR
;
287 libAVMemInputPin_NotifyAllocator(libAVMemInputPin
*this, IMemAllocator
*alloc
,
290 dshowdebug("libAVMemInputPin_NotifyAllocator(%p)\n", this);
294 libAVMemInputPin_GetAllocatorRequirements(libAVMemInputPin
*this,
295 ALLOCATOR_PROPERTIES
*props
)
297 dshowdebug("libAVMemInputPin_GetAllocatorRequirements(%p)\n", this);
301 libAVMemInputPin_Receive(libAVMemInputPin
*this, IMediaSample
*sample
)
303 libAVPin
*pin
= (libAVPin
*) ((uint8_t *) this - imemoffset
);
304 enum dshowDeviceType devtype
= pin
->filter
->type
;
311 dshowdebug("libAVMemInputPin_Receive(%p)\n", this);
316 if (devtype
== VideoDevice
) {
317 /* PTS from video devices is unreliable. */
318 IReferenceClock
*clock
= pin
->filter
->clock
;
319 IReferenceClock_GetTime(clock
, &curtime
);
322 IMediaSample_GetTime(sample
, &curtime
, &dummy
);
323 curtime
+= pin
->filter
->start_time
;
326 buf_size
= IMediaSample_GetActualDataLength(sample
);
327 IMediaSample_GetPointer(sample
, &buf
);
328 priv_data
= pin
->filter
->priv_data
;
329 index
= pin
->filter
->stream_index
;
331 pin
->filter
->callback(priv_data
, index
, buf
, buf_size
, curtime
, devtype
);
336 libAVMemInputPin_ReceiveMultiple(libAVMemInputPin
*this,
337 IMediaSample
**samples
, long n
, long *nproc
)
340 dshowdebug("libAVMemInputPin_ReceiveMultiple(%p)\n", this);
342 for (i
= 0; i
< n
; i
++)
343 libAVMemInputPin_Receive(this, samples
[i
]);
349 libAVMemInputPin_ReceiveCanBlock(libAVMemInputPin
*this)
351 dshowdebug("libAVMemInputPin_ReceiveCanBlock(%p)\n", this);
352 /* I swear I will not block. */
357 libAVMemInputPin_Destroy(libAVMemInputPin
*this)
359 libAVPin
*pin
= (libAVPin
*) ((uint8_t *) this - imemoffset
);
360 dshowdebug("libAVMemInputPin_Destroy(%p)\n", this);
361 libAVPin_Destroy(pin
);