FFmpeg
Loading...
Searching...
No Matches
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
33long 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}
39long 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}
79long 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}
92long 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}
103long 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}
119long 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}
127long 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}
138long 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}
143long WINAPI ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes)
144{
145 const AM_MEDIA_TYPE *type = NULL;
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}
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}
177{
178 dshowdebug("ff_dshow_pin_EndFlush(%p)\n", this);
179 /* I don't care. */
180 return S_OK;
181}
182long 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
238static 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 ****************************************************************************/
254long 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}
273long 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}
278long 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}
290long 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;
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++)
365 ff_dshow_meminputpin_Receive(this, samples[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}
#define L(x)
Definition vpx_arith.h:36
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
dshowDeviceType
@ VideoDevice
#define DECLARE_QUERYINTERFACE(prefix, class,...)
unsigned long WINAPI ff_dshow_pin_Release(DShowPin *)
#define DECLARE_CREATE(prefix, class, setup,...)
void ff_print_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *type)
#define dshowdebug(...)
void ff_dshow_pin_Destroy(DShowPin *)
long WINAPI ff_dshow_pin_QueryInterface(DShowPin *, const GUID *, void **)
long ff_copy_dshow_media_type(AM_MEDIA_TYPE *dst, const AM_MEDIA_TYPE *src)
long WINAPI ff_dshow_meminputpin_QueryInterface(DShowMemInputPin *, const GUID *, void **)
Definition dshow_pin.c:254
#define DECLARE_RELEASE(prefix, class)
unsigned long WINAPI ff_dshow_filter_AddRef(DShowFilter *)
DShowEnumMediaTypes * ff_dshow_enummediatypes_Create(const AM_MEDIA_TYPE *type)
#define DECLARE_ADDREF(prefix, class)
struct DShowMemInputPin DShowMemInputPin
long WINAPI ff_dshow_pin_Connect(DShowPin *, IPin *, const AM_MEDIA_TYPE *)
#define SETVTBL(vtbl, prefix, fn)
#define DECLARE_DESTROY(prefix, class, func)
unsigned long WINAPI ff_dshow_pin_AddRef(DShowPin *)
long WINAPI ff_dshow_meminputpin_ReceiveCanBlock(DShowMemInputPin *this)
Definition dshow_pin.c:370
long WINAPI ff_dshow_pin_NewSegment(DShowPin *this, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
Definition dshow_pin.c:182
long WINAPI ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample)
Definition dshow_pin.c:290
long WINAPI ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type)
Definition dshow_pin.c:39
unsigned long WINAPI ff_dshow_meminputpin_AddRef(DShowMemInputPin *this)
Definition dshow_pin.c:261
long WINAPI ff_dshow_pin_BeginFlush(DShowPin *this)
Definition dshow_pin.c:170
long WINAPI ff_dshow_meminputpin_NotifyAllocator(DShowMemInputPin *this, IMemAllocator *alloc, BOOL rdwr)
Definition dshow_pin.c:278
static void ff_dshow_pin_Free(DShowPin *this)
Definition dshow_pin.c:238
long WINAPI ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes)
Definition dshow_pin.c:143
unsigned long WINAPI ff_dshow_meminputpin_Release(DShowMemInputPin *this)
Definition dshow_pin.c:267
long WINAPI ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir)
Definition dshow_pin.c:119
static int ff_dshow_pin_Setup(DShowPin *this, DShowFilter *filter)
Definition dshow_pin.c:190
long WINAPI ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, IMediaSample **samples, long n, long *nproc)
Definition dshow_pin.c:358
long WINAPI ff_dshow_pin_EndOfStream(DShowPin *this)
Definition dshow_pin.c:164
void ff_dshow_meminputpin_Destroy(DShowMemInputPin *this)
Definition dshow_pin.c:377
#define imemoffset
Definition dshow_pin.c:26
long WINAPI ff_dshow_pin_QueryInternalConnections(DShowPin *this, IPin **pin, unsigned long *npin)
Definition dshow_pin.c:158
long WINAPI ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info)
Definition dshow_pin.c:103
long WINAPI ff_dshow_pin_QueryAccept(DShowPin *this, const AM_MEDIA_TYPE *type)
Definition dshow_pin.c:138
long WINAPI ff_dshow_pin_EndFlush(DShowPin *this)
Definition dshow_pin.c:176
long WINAPI ff_dshow_meminputpin_GetAllocator(DShowMemInputPin *this, IMemAllocator **alloc)
Definition dshow_pin.c:273
long WINAPI ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type)
Definition dshow_pin.c:92
long WINAPI ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin)
Definition dshow_pin.c:79
long WINAPI ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id)
Definition dshow_pin.c:127
long WINAPI ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *this, ALLOCATOR_PROPERTIES *props)
Definition dshow_pin.c:284
long WINAPI ff_dshow_pin_Disconnect(DShowPin *this)
Definition dshow_pin.c:66
static int dummy
Definition ffplay.c:3754
#define sample
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
int index
Definition gxfenc.c:90
cl_device_type type
Memory handling functions.
#define av_malloc(s)
Definition ops_static.c:52
Format I/O context.
Definition avformat.h:1333
void(* callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType type)
int64_t start_time
enum dshowDeviceType type
IReferenceClock * clock
DShowFilter * filter
#define av_freep(p)
#define av_log(a,...)
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29
static AVFormatContext * ctx
Definition movenc.c:49