summaryrefslogtreecommitdiff
path: root/libavdevice/dshow.c (plain)
blob: f2453e611447706daff93bbfdca42deb2fbd8301
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#include "libavutil/parseutils.h"
24#include "libavutil/pixdesc.h"
25#include "libavutil/opt.h"
26#include "libavformat/internal.h"
27#include "libavformat/riff.h"
28#include "avdevice.h"
29#include "libavcodec/raw.h"
30#include "objidl.h"
31#include "shlwapi.h"
32
33
34static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
35{
36 switch(biCompression) {
37 case BI_BITFIELDS:
38 case BI_RGB:
39 switch(biBitCount) { /* 1-8 are untested */
40 case 1:
41 return AV_PIX_FMT_MONOWHITE;
42 case 4:
43 return AV_PIX_FMT_RGB4;
44 case 8:
45 return AV_PIX_FMT_RGB8;
46 case 16:
47 return AV_PIX_FMT_RGB555;
48 case 24:
49 return AV_PIX_FMT_BGR24;
50 case 32:
51 return AV_PIX_FMT_0RGB32;
52 }
53 }
54 return avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), biCompression); // all others
55}
56
57static int
58dshow_read_close(AVFormatContext *s)
59{
60 struct dshow_ctx *ctx = s->priv_data;
61 AVPacketList *pktl;
62
63 if (ctx->control) {
64 IMediaControl_Stop(ctx->control);
65 IMediaControl_Release(ctx->control);
66 }
67
68 if (ctx->media_event)
69 IMediaEvent_Release(ctx->media_event);
70
71 if (ctx->graph) {
72 IEnumFilters *fenum;
73 int r;
74 r = IGraphBuilder_EnumFilters(ctx->graph, &fenum);
75 if (r == S_OK) {
76 IBaseFilter *f;
77 IEnumFilters_Reset(fenum);
78 while (IEnumFilters_Next(fenum, 1, &f, NULL) == S_OK) {
79 if (IGraphBuilder_RemoveFilter(ctx->graph, f) == S_OK)
80 IEnumFilters_Reset(fenum); /* When a filter is removed,
81 * the list must be reset. */
82 IBaseFilter_Release(f);
83 }
84 IEnumFilters_Release(fenum);
85 }
86 IGraphBuilder_Release(ctx->graph);
87 }
88
89 if (ctx->capture_pin[VideoDevice])
90 libAVPin_Release(ctx->capture_pin[VideoDevice]);
91 if (ctx->capture_pin[AudioDevice])
92 libAVPin_Release(ctx->capture_pin[AudioDevice]);
93 if (ctx->capture_filter[VideoDevice])
94 libAVFilter_Release(ctx->capture_filter[VideoDevice]);
95 if (ctx->capture_filter[AudioDevice])
96 libAVFilter_Release(ctx->capture_filter[AudioDevice]);
97
98 if (ctx->device_pin[VideoDevice])
99 IPin_Release(ctx->device_pin[VideoDevice]);
100 if (ctx->device_pin[AudioDevice])
101 IPin_Release(ctx->device_pin[AudioDevice]);
102 if (ctx->device_filter[VideoDevice])
103 IBaseFilter_Release(ctx->device_filter[VideoDevice]);
104 if (ctx->device_filter[AudioDevice])
105 IBaseFilter_Release(ctx->device_filter[AudioDevice]);
106
107 av_freep(&ctx->device_name[0]);
108 av_freep(&ctx->device_name[1]);
109 av_freep(&ctx->device_unique_name[0]);
110 av_freep(&ctx->device_unique_name[1]);
111
112 if(ctx->mutex)
113 CloseHandle(ctx->mutex);
114 if(ctx->event[0])
115 CloseHandle(ctx->event[0]);
116 if(ctx->event[1])
117 CloseHandle(ctx->event[1]);
118
119 pktl = ctx->pktl;
120 while (pktl) {
121 AVPacketList *next = pktl->next;
122 av_packet_unref(&pktl->pkt);
123 av_free(pktl);
124 pktl = next;
125 }
126
127 CoUninitialize();
128
129 return 0;
130}
131
132static char *dup_wchar_to_utf8(wchar_t *w)
133{
134 char *s = NULL;
135 int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
136 s = av_malloc(l);
137 if (s)
138 WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
139 return s;
140}
141
142static int shall_we_drop(AVFormatContext *s, int index, enum dshowDeviceType devtype)
143{
144 struct dshow_ctx *ctx = s->priv_data;
145 static const uint8_t dropscore[] = {62, 75, 87, 100};
146 const int ndropscores = FF_ARRAY_ELEMS(dropscore);
147 unsigned int buffer_fullness = (ctx->curbufsize[index]*100)/s->max_picture_buffer;
148 const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
149
150 if(dropscore[++ctx->video_frame_num%ndropscores] <= buffer_fullness) {
151 av_log(s, AV_LOG_ERROR,
152 "real-time buffer [%s] [%s input] too full or near too full (%d%% of size: %d [rtbufsize parameter])! frame dropped!\n",
153 ctx->device_name[devtype], devtypename, buffer_fullness, s->max_picture_buffer);
154 return 1;
155 }
156
157 return 0;
158}
159
160static void
161callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType devtype)
162{
163 AVFormatContext *s = priv_data;
164 struct dshow_ctx *ctx = s->priv_data;
165 AVPacketList **ppktl, *pktl_next;
166
167// dump_videohdr(s, vdhdr);
168
169 WaitForSingleObject(ctx->mutex, INFINITE);
170
171 if(shall_we_drop(s, index, devtype))
172 goto fail;
173
174 pktl_next = av_mallocz(sizeof(AVPacketList));
175 if(!pktl_next)
176 goto fail;
177
178 if(av_new_packet(&pktl_next->pkt, buf_size) < 0) {
179 av_free(pktl_next);
180 goto fail;
181 }
182
183 pktl_next->pkt.stream_index = index;
184 pktl_next->pkt.pts = time;
185 memcpy(pktl_next->pkt.data, buf, buf_size);
186
187 for(ppktl = &ctx->pktl ; *ppktl ; ppktl = &(*ppktl)->next);
188 *ppktl = pktl_next;
189 ctx->curbufsize[index] += buf_size;
190
191 SetEvent(ctx->event[1]);
192 ReleaseMutex(ctx->mutex);
193
194 return;
195fail:
196 ReleaseMutex(ctx->mutex);
197 return;
198}
199
200/**
201 * Cycle through available devices using the device enumerator devenum,
202 * retrieve the device with type specified by devtype and return the
203 * pointer to the object found in *pfilter.
204 * If pfilter is NULL, list all device names.
205 */
206static int
207dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
208 enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype,
209 IBaseFilter **pfilter, char **device_unique_name)
210{
211 struct dshow_ctx *ctx = avctx->priv_data;
212 IBaseFilter *device_filter = NULL;
213 IEnumMoniker *classenum = NULL;
214 IMoniker *m = NULL;
215 const char *device_name = ctx->device_name[devtype];
216 int skip = (devtype == VideoDevice) ? ctx->video_device_number
217 : ctx->audio_device_number;
218 int r;
219
220 const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,
221 &CLSID_AudioInputDeviceCategory };
222 const char *devtypename = (devtype == VideoDevice) ? "video" : "audio only";
223 const char *sourcetypename = (sourcetype == VideoSourceDevice) ? "video" : "audio";
224
225 r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[sourcetype],
226 (IEnumMoniker **) &classenum, 0);
227 if (r != S_OK) {
228 av_log(avctx, AV_LOG_ERROR, "Could not enumerate %s devices (or none found).\n",
229 devtypename);
230 return AVERROR(EIO);
231 }
232
233 while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) {
234 IPropertyBag *bag = NULL;
235 char *friendly_name = NULL;
236 char *unique_name = NULL;
237 VARIANT var;
238 IBindCtx *bind_ctx = NULL;
239 LPOLESTR olestr = NULL;
240 LPMALLOC co_malloc = NULL;
241 int i;
242
243 r = CoGetMalloc(1, &co_malloc);
244 if (r != S_OK)
245 goto fail1;
246 r = CreateBindCtx(0, &bind_ctx);
247 if (r != S_OK)
248 goto fail1;
249 /* GetDisplayname works for both video and audio, DevicePath doesn't */
250 r = IMoniker_GetDisplayName(m, bind_ctx, NULL, &olestr);
251 if (r != S_OK)
252 goto fail1;
253 unique_name = dup_wchar_to_utf8(olestr);
254 /* replace ':' with '_' since we use : to delineate between sources */
255 for (i = 0; i < strlen(unique_name); i++) {
256 if (unique_name[i] == ':')
257 unique_name[i] = '_';
258 }
259
260 r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag);
261 if (r != S_OK)
262 goto fail1;
263
264 var.vt = VT_BSTR;
265 r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL);
266 if (r != S_OK)
267 goto fail1;
268 friendly_name = dup_wchar_to_utf8(var.bstrVal);
269
270 if (pfilter) {
271 if (strcmp(device_name, friendly_name) && strcmp(device_name, unique_name))
272 goto fail1;
273
274 if (!skip--) {
275 r = IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter);
276 if (r != S_OK) {
277 av_log(avctx, AV_LOG_ERROR, "Unable to BindToObject for %s\n", device_name);
278 goto fail1;
279 }
280 *device_unique_name = unique_name;
281 // success, loop will end now
282 }
283 } else {
284 av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name);
285 av_log(avctx, AV_LOG_INFO, " Alternative name \"%s\"\n", unique_name);
286 av_free(unique_name);
287 }
288
289fail1:
290 if (olestr && co_malloc)
291 IMalloc_Free(co_malloc, olestr);
292 if (bind_ctx)
293 IBindCtx_Release(bind_ctx);
294 av_free(friendly_name);
295 if (bag)
296 IPropertyBag_Release(bag);
297 IMoniker_Release(m);
298 }
299
300 IEnumMoniker_Release(classenum);
301
302 if (pfilter) {
303 if (!device_filter) {
304 av_log(avctx, AV_LOG_ERROR, "Could not find %s device with name [%s] among source devices of type %s.\n",
305 devtypename, device_name, sourcetypename);
306 return AVERROR(EIO);
307 }
308 *pfilter = device_filter;
309 }
310
311 return 0;
312}
313
314/**
315 * Cycle through available formats using the specified pin,
316 * try to set parameters specified through AVOptions and if successful
317 * return 1 in *pformat_set.
318 * If pformat_set is NULL, list all pin capabilities.
319 */
320static void
321dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
322 IPin *pin, int *pformat_set)
323{
324 struct dshow_ctx *ctx = avctx->priv_data;
325 IAMStreamConfig *config = NULL;
326 AM_MEDIA_TYPE *type = NULL;
327 int format_set = 0;
328 void *caps = NULL;
329 int i, n, size, r;
330
331 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
332 return;
333 if (IAMStreamConfig_GetNumberOfCapabilities(config, &n, &size) != S_OK)
334 goto end;
335
336 caps = av_malloc(size);
337 if (!caps)
338 goto end;
339
340 for (i = 0; i < n && !format_set; i++) {
341 r = IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps);
342 if (r != S_OK)
343 goto next;
344#if DSHOWDEBUG
345 ff_print_AM_MEDIA_TYPE(type);
346#endif
347
348 if (devtype == VideoDevice) {
349 VIDEO_STREAM_CONFIG_CAPS *vcaps = caps;
350 BITMAPINFOHEADER *bih;
351 int64_t *fr;
352 const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL };
353#if DSHOWDEBUG
354 ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps);
355#endif
356 if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) {
357 VIDEOINFOHEADER *v = (void *) type->pbFormat;
358 fr = &v->AvgTimePerFrame;
359 bih = &v->bmiHeader;
360 } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) {
361 VIDEOINFOHEADER2 *v = (void *) type->pbFormat;
362 fr = &v->AvgTimePerFrame;
363 bih = &v->bmiHeader;
364 } else {
365 goto next;
366 }
367 if (!pformat_set) {
368 enum AVPixelFormat pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount);
369 if (pix_fmt == AV_PIX_FMT_NONE) {
370 enum AVCodecID codec_id = av_codec_get_id(tags, bih->biCompression);
371 AVCodec *codec = avcodec_find_decoder(codec_id);
372 if (codec_id == AV_CODEC_ID_NONE || !codec) {
373 av_log(avctx, AV_LOG_INFO, " unknown compression type 0x%X", (int) bih->biCompression);
374 } else {
375 av_log(avctx, AV_LOG_INFO, " vcodec=%s", codec->name);
376 }
377 } else {
378 av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(pix_fmt));
379 }
380 av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n",
381 vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
382 1e7 / vcaps->MaxFrameInterval,
383 vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,
384 1e7 / vcaps->MinFrameInterval);
385 continue;
386 }
387 if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
388 if (ctx->video_codec_id != av_codec_get_id(tags, bih->biCompression))
389 goto next;
390 }
391 if (ctx->pixel_format != AV_PIX_FMT_NONE &&
392 ctx->pixel_format != dshow_pixfmt(bih->biCompression, bih->biBitCount)) {
393 goto next;
394 }
395 if (ctx->framerate) {
396 int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000)
397 / ctx->requested_framerate.num;
398 if (framerate > vcaps->MaxFrameInterval ||
399 framerate < vcaps->MinFrameInterval)
400 goto next;
401 *fr = framerate;
402 }
403 if (ctx->requested_width && ctx->requested_height) {
404 if (ctx->requested_width > vcaps->MaxOutputSize.cx ||
405 ctx->requested_width < vcaps->MinOutputSize.cx ||
406 ctx->requested_height > vcaps->MaxOutputSize.cy ||
407 ctx->requested_height < vcaps->MinOutputSize.cy)
408 goto next;
409 bih->biWidth = ctx->requested_width;
410 bih->biHeight = ctx->requested_height;
411 }
412 } else {
413 AUDIO_STREAM_CONFIG_CAPS *acaps = caps;
414 WAVEFORMATEX *fx;
415#if DSHOWDEBUG
416 ff_print_AUDIO_STREAM_CONFIG_CAPS(acaps);
417#endif
418 if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) {
419 fx = (void *) type->pbFormat;
420 } else {
421 goto next;
422 }
423 if (!pformat_set) {
424 av_log(avctx, AV_LOG_INFO, " min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n",
425 acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency,
426 acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency);
427 continue;
428 }
429 if (ctx->sample_rate) {
430 if (ctx->sample_rate > acaps->MaximumSampleFrequency ||
431 ctx->sample_rate < acaps->MinimumSampleFrequency)
432 goto next;
433 fx->nSamplesPerSec = ctx->sample_rate;
434 }
435 if (ctx->sample_size) {
436 if (ctx->sample_size > acaps->MaximumBitsPerSample ||
437 ctx->sample_size < acaps->MinimumBitsPerSample)
438 goto next;
439 fx->wBitsPerSample = ctx->sample_size;
440 }
441 if (ctx->channels) {
442 if (ctx->channels > acaps->MaximumChannels ||
443 ctx->channels < acaps->MinimumChannels)
444 goto next;
445 fx->nChannels = ctx->channels;
446 }
447 }
448 if (IAMStreamConfig_SetFormat(config, type) != S_OK)
449 goto next;
450 format_set = 1;
451next:
452 if (type->pbFormat)
453 CoTaskMemFree(type->pbFormat);
454 CoTaskMemFree(type);
455 }
456end:
457 IAMStreamConfig_Release(config);
458 av_free(caps);
459 if (pformat_set)
460 *pformat_set = format_set;
461}
462
463/**
464 * Set audio device buffer size in milliseconds (which can directly impact
465 * latency, depending on the device).
466 */
467static int
468dshow_set_audio_buffer_size(AVFormatContext *avctx, IPin *pin)
469{
470 struct dshow_ctx *ctx = avctx->priv_data;
471 IAMBufferNegotiation *buffer_negotiation = NULL;
472 ALLOCATOR_PROPERTIES props = { -1, -1, -1, -1 };
473 IAMStreamConfig *config = NULL;
474 AM_MEDIA_TYPE *type = NULL;
475 int ret = AVERROR(EIO);
476
477 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
478 goto end;
479 if (IAMStreamConfig_GetFormat(config, &type) != S_OK)
480 goto end;
481 if (!IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx))
482 goto end;
483
484 props.cbBuffer = (((WAVEFORMATEX *) type->pbFormat)->nAvgBytesPerSec)
485 * ctx->audio_buffer_size / 1000;
486
487 if (IPin_QueryInterface(pin, &IID_IAMBufferNegotiation, (void **) &buffer_negotiation) != S_OK)
488 goto end;
489 if (IAMBufferNegotiation_SuggestAllocatorProperties(buffer_negotiation, &props) != S_OK)
490 goto end;
491
492 ret = 0;
493
494end:
495 if (buffer_negotiation)
496 IAMBufferNegotiation_Release(buffer_negotiation);
497 if (type) {
498 if (type->pbFormat)
499 CoTaskMemFree(type->pbFormat);
500 CoTaskMemFree(type);
501 }
502 if (config)
503 IAMStreamConfig_Release(config);
504
505 return ret;
506}
507
508/**
509 * Pops up a user dialog allowing them to adjust properties for the given filter, if possible.
510 */
511void
512dshow_show_filter_properties(IBaseFilter *device_filter, AVFormatContext *avctx) {
513 ISpecifyPropertyPages *property_pages = NULL;
514 IUnknown *device_filter_iunknown = NULL;
515 HRESULT hr;
516 FILTER_INFO filter_info = {0}; /* a warning on this line is false positive GCC bug 53119 AFAICT */
517 CAUUID ca_guid = {0};
518
519 hr = IBaseFilter_QueryInterface(device_filter, &IID_ISpecifyPropertyPages, (void **)&property_pages);
520 if (hr != S_OK) {
521 av_log(avctx, AV_LOG_WARNING, "requested filter does not have a property page to show");
522 goto end;
523 }
524 hr = IBaseFilter_QueryFilterInfo(device_filter, &filter_info);
525 if (hr != S_OK) {
526 goto fail;
527 }
528 hr = IBaseFilter_QueryInterface(device_filter, &IID_IUnknown, (void **)&device_filter_iunknown);
529 if (hr != S_OK) {
530 goto fail;
531 }
532 hr = ISpecifyPropertyPages_GetPages(property_pages, &ca_guid);
533 if (hr != S_OK) {
534 goto fail;
535 }
536 hr = OleCreatePropertyFrame(NULL, 0, 0, filter_info.achName, 1, &device_filter_iunknown, ca_guid.cElems,
537 ca_guid.pElems, 0, 0, NULL);
538 if (hr != S_OK) {
539 goto fail;
540 }
541 goto end;
542fail:
543 av_log(avctx, AV_LOG_ERROR, "Failure showing property pages for filter");
544end:
545 if (property_pages)
546 ISpecifyPropertyPages_Release(property_pages);
547 if (device_filter_iunknown)
548 IUnknown_Release(device_filter_iunknown);
549 if (filter_info.pGraph)
550 IFilterGraph_Release(filter_info.pGraph);
551 if (ca_guid.pElems)
552 CoTaskMemFree(ca_guid.pElems);
553}
554
555/**
556 * Cycle through available pins using the device_filter device, of type
557 * devtype, retrieve the first output pin and return the pointer to the
558 * object found in *ppin.
559 * If ppin is NULL, cycle through all pins listing audio/video capabilities.
560 */
561static int
562dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
563 enum dshowSourceFilterType sourcetype, IBaseFilter *device_filter, IPin **ppin)
564{
565 struct dshow_ctx *ctx = avctx->priv_data;
566 IEnumPins *pins = 0;
567 IPin *device_pin = NULL;
568 IPin *pin;
569 int r;
570
571 const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
572 const char *devtypename = (devtype == VideoDevice) ? "video" : "audio only";
573 const char *sourcetypename = (sourcetype == VideoSourceDevice) ? "video" : "audio";
574
575 int set_format = (devtype == VideoDevice && (ctx->framerate ||
576 (ctx->requested_width && ctx->requested_height) ||
577 ctx->pixel_format != AV_PIX_FMT_NONE ||
578 ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO))
579 || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate));
580 int format_set = 0;
581 int should_show_properties = (devtype == VideoDevice) ? ctx->show_video_device_dialog : ctx->show_audio_device_dialog;
582
583 if (should_show_properties)
584 dshow_show_filter_properties(device_filter, avctx);
585
586 r = IBaseFilter_EnumPins(device_filter, &pins);
587 if (r != S_OK) {
588 av_log(avctx, AV_LOG_ERROR, "Could not enumerate pins.\n");
589 return AVERROR(EIO);
590 }
591
592 if (!ppin) {
593 av_log(avctx, AV_LOG_INFO, "DirectShow %s device options (from %s devices)\n",
594 devtypename, sourcetypename);
595 }
596
597 while (!device_pin && IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) {
598 IKsPropertySet *p = NULL;
599 IEnumMediaTypes *types = NULL;
600 PIN_INFO info = {0};
601 AM_MEDIA_TYPE *type;
602 GUID category;
603 DWORD r2;
604 char *name_buf = NULL;
605 wchar_t *pin_id = NULL;
606 char *pin_buf = NULL;
607 char *desired_pin_name = devtype == VideoDevice ? ctx->video_pin_name : ctx->audio_pin_name;
608
609 IPin_QueryPinInfo(pin, &info);
610 IBaseFilter_Release(info.pFilter);
611
612 if (info.dir != PINDIR_OUTPUT)
613 goto next;
614 if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **) &p) != S_OK)
615 goto next;
616 if (IKsPropertySet_Get(p, &AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY,
617 NULL, 0, &category, sizeof(GUID), &r2) != S_OK)
618 goto next;
619 if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
620 goto next;
621 name_buf = dup_wchar_to_utf8(info.achName);
622
623 r = IPin_QueryId(pin, &pin_id);
624 if (r != S_OK) {
625 av_log(avctx, AV_LOG_ERROR, "Could not query pin id\n");
626 return AVERROR(EIO);
627 }
628 pin_buf = dup_wchar_to_utf8(pin_id);
629
630 if (!ppin) {
631 av_log(avctx, AV_LOG_INFO, " Pin \"%s\" (alternative pin name \"%s\")\n", name_buf, pin_buf);
632 dshow_cycle_formats(avctx, devtype, pin, NULL);
633 goto next;
634 }
635
636 if (desired_pin_name) {
637 if(strcmp(name_buf, desired_pin_name) && strcmp(pin_buf, desired_pin_name)) {
638 av_log(avctx, AV_LOG_DEBUG, "skipping pin \"%s\" (\"%s\") != requested \"%s\"\n",
639 name_buf, pin_buf, desired_pin_name);
640 goto next;
641 }
642 }
643
644 if (set_format) {
645 dshow_cycle_formats(avctx, devtype, pin, &format_set);
646 if (!format_set) {
647 goto next;
648 }
649 }
650 if (devtype == AudioDevice && ctx->audio_buffer_size) {
651 if (dshow_set_audio_buffer_size(avctx, pin) < 0) {
652 av_log(avctx, AV_LOG_ERROR, "unable to set audio buffer size %d to pin, using pin anyway...", ctx->audio_buffer_size);
653 }
654 }
655
656 if (IPin_EnumMediaTypes(pin, &types) != S_OK)
657 goto next;
658
659 IEnumMediaTypes_Reset(types);
660 /* in case format_set was not called, just verify the majortype */
661 while (!device_pin && IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) {
662 if (IsEqualGUID(&type->majortype, mediatype[devtype])) {
663 device_pin = pin;
664 av_log(avctx, AV_LOG_DEBUG, "Selecting pin %s on %s\n", name_buf, devtypename);
665 goto next;
666 }
667 CoTaskMemFree(type);
668 }
669
670next:
671 if (types)
672 IEnumMediaTypes_Release(types);
673 if (p)
674 IKsPropertySet_Release(p);
675 if (device_pin != pin)
676 IPin_Release(pin);
677 av_free(name_buf);
678 av_free(pin_buf);
679 if (pin_id)
680 CoTaskMemFree(pin_id);
681 }
682
683 IEnumPins_Release(pins);
684
685 if (ppin) {
686 if (set_format && !format_set) {
687 av_log(avctx, AV_LOG_ERROR, "Could not set %s options\n", devtypename);
688 return AVERROR(EIO);
689 }
690 if (!device_pin) {
691 av_log(avctx, AV_LOG_ERROR,
692 "Could not find output pin from %s capture device.\n", devtypename);
693 return AVERROR(EIO);
694 }
695 *ppin = device_pin;
696 }
697
698 return 0;
699}
700
701/**
702 * List options for device with type devtype, source filter type sourcetype
703 *
704 * @param devenum device enumerator used for accessing the device
705 */
706static int
707dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum,
708 enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype)
709{
710 struct dshow_ctx *ctx = avctx->priv_data;
711 IBaseFilter *device_filter = NULL;
712 char *device_unique_name = NULL;
713 int r;
714
715 if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name)) < 0)
716 return r;
717 ctx->device_filter[devtype] = device_filter;
718 if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, NULL)) < 0)
719 return r;
720 av_freep(&device_unique_name);
721 return 0;
722}
723
724static int
725dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
726 enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype)
727{
728 struct dshow_ctx *ctx = avctx->priv_data;
729 IBaseFilter *device_filter = NULL;
730 char *device_filter_unique_name = NULL;
731 IGraphBuilder *graph = ctx->graph;
732 IPin *device_pin = NULL;
733 libAVPin *capture_pin = NULL;
734 libAVFilter *capture_filter = NULL;
735 ICaptureGraphBuilder2 *graph_builder2 = NULL;
736 int ret = AVERROR(EIO);
737 int r;
738 IStream *ifile_stream = NULL;
739 IStream *ofile_stream = NULL;
740 IPersistStream *pers_stream = NULL;
741 enum dshowDeviceType otherDevType = (devtype == VideoDevice) ? AudioDevice : VideoDevice;
742
743 const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
744
745
746 if ( ((ctx->audio_filter_load_file) && (strlen(ctx->audio_filter_load_file)>0) && (sourcetype == AudioSourceDevice)) ||
747 ((ctx->video_filter_load_file) && (strlen(ctx->video_filter_load_file)>0) && (sourcetype == VideoSourceDevice)) ) {
748 HRESULT hr;
749 char *filename = NULL;
750
751 if (sourcetype == AudioSourceDevice)
752 filename = ctx->audio_filter_load_file;
753 else
754 filename = ctx->video_filter_load_file;
755
756 hr = SHCreateStreamOnFile ((LPCSTR) filename, STGM_READ, &ifile_stream);
757 if (S_OK != hr) {
758 av_log(avctx, AV_LOG_ERROR, "Could not open capture filter description file.\n");
759 goto error;
760 }
761
762 hr = OleLoadFromStream(ifile_stream, &IID_IBaseFilter, (void **) &device_filter);
763 if (hr != S_OK) {
764 av_log(avctx, AV_LOG_ERROR, "Could not load capture filter from file.\n");
765 goto error;
766 }
767
768 if (sourcetype == AudioSourceDevice)
769 av_log(avctx, AV_LOG_INFO, "Audio-");
770 else
771 av_log(avctx, AV_LOG_INFO, "Video-");
772 av_log(avctx, AV_LOG_INFO, "Capture filter loaded successfully from file \"%s\".\n", filename);
773 } else {
774
775 if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_filter_unique_name)) < 0) {
776 ret = r;
777 goto error;
778 }
779 }
780 if (ctx->device_filter[otherDevType]) {
781 // avoid adding add two instances of the same device to the graph, one for video, one for audio
782 // a few devices don't support this (could also do this check earlier to avoid double crossbars, etc. but they seem OK)
783 if (strcmp(device_filter_unique_name, ctx->device_unique_name[otherDevType]) == 0) {
784 av_log(avctx, AV_LOG_DEBUG, "reusing previous graph capture filter... %s\n", device_filter_unique_name);
785 IBaseFilter_Release(device_filter);
786 device_filter = ctx->device_filter[otherDevType];
787 IBaseFilter_AddRef(ctx->device_filter[otherDevType]);
788 } else {
789 av_log(avctx, AV_LOG_DEBUG, "not reusing previous graph capture filter %s != %s\n", device_filter_unique_name, ctx->device_unique_name[otherDevType]);
790 }
791 }
792
793 ctx->device_filter [devtype] = device_filter;
794 ctx->device_unique_name [devtype] = device_filter_unique_name;
795
796 r = IGraphBuilder_AddFilter(graph, device_filter, NULL);
797 if (r != S_OK) {
798 av_log(avctx, AV_LOG_ERROR, "Could not add device filter to graph.\n");
799 goto error;
800 }
801
802 if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, &device_pin)) < 0) {
803 ret = r;
804 goto error;
805 }
806
807 ctx->device_pin[devtype] = device_pin;
808
809 capture_filter = libAVFilter_Create(avctx, callback, devtype);
810 if (!capture_filter) {
811 av_log(avctx, AV_LOG_ERROR, "Could not create grabber filter.\n");
812 goto error;
813 }
814 ctx->capture_filter[devtype] = capture_filter;
815
816 if ( ((ctx->audio_filter_save_file) && (strlen(ctx->audio_filter_save_file)>0) && (sourcetype == AudioSourceDevice)) ||
817 ((ctx->video_filter_save_file) && (strlen(ctx->video_filter_save_file)>0) && (sourcetype == VideoSourceDevice)) ) {
818
819 HRESULT hr;
820 char *filename = NULL;
821
822 if (sourcetype == AudioSourceDevice)
823 filename = ctx->audio_filter_save_file;
824 else
825 filename = ctx->video_filter_save_file;
826
827 hr = SHCreateStreamOnFile ((LPCSTR) filename, STGM_CREATE | STGM_READWRITE, &ofile_stream);
828 if (S_OK != hr) {
829 av_log(avctx, AV_LOG_ERROR, "Could not create capture filter description file.\n");
830 goto error;
831 }
832
833 hr = IBaseFilter_QueryInterface(device_filter, &IID_IPersistStream, (void **) &pers_stream);
834 if (hr != S_OK) {
835 av_log(avctx, AV_LOG_ERROR, "Query for IPersistStream failed.\n");
836 goto error;
837 }
838
839 hr = OleSaveToStream(pers_stream, ofile_stream);
840 if (hr != S_OK) {
841 av_log(avctx, AV_LOG_ERROR, "Could not save capture filter \n");
842 goto error;
843 }
844
845 hr = IStream_Commit(ofile_stream, STGC_DEFAULT);
846 if (S_OK != hr) {
847 av_log(avctx, AV_LOG_ERROR, "Could not commit capture filter data to file.\n");
848 goto error;
849 }
850
851 if (sourcetype == AudioSourceDevice)
852 av_log(avctx, AV_LOG_INFO, "Audio-");
853 else
854 av_log(avctx, AV_LOG_INFO, "Video-");
855 av_log(avctx, AV_LOG_INFO, "Capture filter saved successfully to file \"%s\".\n", filename);
856 }
857
858 r = IGraphBuilder_AddFilter(graph, (IBaseFilter *) capture_filter,
859 filter_name[devtype]);
860 if (r != S_OK) {
861 av_log(avctx, AV_LOG_ERROR, "Could not add capture filter to graph\n");
862 goto error;
863 }
864
865 libAVPin_AddRef(capture_filter->pin);
866 capture_pin = capture_filter->pin;
867 ctx->capture_pin[devtype] = capture_pin;
868
869 r = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER,
870 &IID_ICaptureGraphBuilder2, (void **) &graph_builder2);
871 if (r != S_OK) {
872 av_log(avctx, AV_LOG_ERROR, "Could not create CaptureGraphBuilder2\n");
873 goto error;
874 }
875 ICaptureGraphBuilder2_SetFiltergraph(graph_builder2, graph);
876 if (r != S_OK) {
877 av_log(avctx, AV_LOG_ERROR, "Could not set graph for CaptureGraphBuilder2\n");
878 goto error;
879 }
880
881 r = ICaptureGraphBuilder2_RenderStream(graph_builder2, NULL, NULL, (IUnknown *) device_pin, NULL /* no intermediate filter */,
882 (IBaseFilter *) capture_filter); /* connect pins, optionally insert intermediate filters like crossbar if necessary */
883
884 if (r != S_OK) {
885 av_log(avctx, AV_LOG_ERROR, "Could not RenderStream to connect pins\n");
886 goto error;
887 }
888
889 r = dshow_try_setup_crossbar_options(graph_builder2, device_filter, devtype, avctx);
890
891 if (r != S_OK) {
892 av_log(avctx, AV_LOG_ERROR, "Could not setup CrossBar\n");
893 goto error;
894 }
895
896 ret = 0;
897
898error:
899 if (graph_builder2 != NULL)
900 ICaptureGraphBuilder2_Release(graph_builder2);
901
902 if (pers_stream)
903 IPersistStream_Release(pers_stream);
904
905 if (ifile_stream)
906 IStream_Release(ifile_stream);
907
908 if (ofile_stream)
909 IStream_Release(ofile_stream);
910
911 return ret;
912}
913
914static enum AVCodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
915{
916 switch (sample_fmt) {
917 case AV_SAMPLE_FMT_U8: return AV_CODEC_ID_PCM_U8;
918 case AV_SAMPLE_FMT_S16: return AV_CODEC_ID_PCM_S16LE;
919 case AV_SAMPLE_FMT_S32: return AV_CODEC_ID_PCM_S32LE;
920 default: return AV_CODEC_ID_NONE; /* Should never happen. */
921 }
922}
923
924static enum AVSampleFormat sample_fmt_bits_per_sample(int bits)
925{
926 switch (bits) {
927 case 8: return AV_SAMPLE_FMT_U8;
928 case 16: return AV_SAMPLE_FMT_S16;
929 case 32: return AV_SAMPLE_FMT_S32;
930 default: return AV_SAMPLE_FMT_NONE; /* Should never happen. */
931 }
932}
933
934static int
935dshow_add_device(AVFormatContext *avctx,
936 enum dshowDeviceType devtype)
937{
938 struct dshow_ctx *ctx = avctx->priv_data;
939 AM_MEDIA_TYPE type;
940 AVCodecParameters *par;
941 AVStream *st;
942 int ret = AVERROR(EIO);
943
944 st = avformat_new_stream(avctx, NULL);
945 if (!st) {
946 ret = AVERROR(ENOMEM);
947 goto error;
948 }
949 st->id = devtype;
950
951 ctx->capture_filter[devtype]->stream_index = st->index;
952
953 libAVPin_ConnectionMediaType(ctx->capture_pin[devtype], &type);
954
955 par = st->codecpar;
956 if (devtype == VideoDevice) {
957 BITMAPINFOHEADER *bih = NULL;
958 AVRational time_base;
959
960 if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) {
961 VIDEOINFOHEADER *v = (void *) type.pbFormat;
962 time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
963 bih = &v->bmiHeader;
964 } else if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo2)) {
965 VIDEOINFOHEADER2 *v = (void *) type.pbFormat;
966 time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
967 bih = &v->bmiHeader;
968 }
969 if (!bih) {
970 av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
971 goto error;
972 }
973
974 st->avg_frame_rate = av_inv_q(time_base);
975 st->r_frame_rate = av_inv_q(time_base);
976
977 par->codec_type = AVMEDIA_TYPE_VIDEO;
978 par->width = bih->biWidth;
979 par->height = bih->biHeight;
980 par->codec_tag = bih->biCompression;
981 par->format = dshow_pixfmt(bih->biCompression, bih->biBitCount);
982 if (bih->biCompression == MKTAG('H', 'D', 'Y', 'C')) {
983 av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for HDYC...\n");
984 par->color_range = AVCOL_RANGE_MPEG; // just in case it needs this...
985 }
986 if (par->format == AV_PIX_FMT_NONE) {
987 const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL };
988 par->codec_id = av_codec_get_id(tags, bih->biCompression);
989 if (par->codec_id == AV_CODEC_ID_NONE) {
990 av_log(avctx, AV_LOG_ERROR, "Unknown compression type. "
991 "Please report type 0x%X.\n", (int) bih->biCompression);
992 return AVERROR_PATCHWELCOME;
993 }
994 par->bits_per_coded_sample = bih->biBitCount;
995 } else {
996 par->codec_id = AV_CODEC_ID_RAWVIDEO;
997 if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) {
998 par->bits_per_coded_sample = bih->biBitCount;
999 par->extradata = av_malloc(9 + AV_INPUT_BUFFER_PADDING_SIZE);
1000 if (par->extradata) {
1001 par->extradata_size = 9;
1002 memcpy(par->extradata, "BottomUp", 9);
1003 }
1004 }
1005 }
1006 } else {
1007 WAVEFORMATEX *fx = NULL;
1008
1009 if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) {
1010 fx = (void *) type.pbFormat;
1011 }
1012 if (!fx) {
1013 av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
1014 goto error;
1015 }
1016
1017 par->codec_type = AVMEDIA_TYPE_AUDIO;
1018 par->format = sample_fmt_bits_per_sample(fx->wBitsPerSample);
1019 par->codec_id = waveform_codec_id(par->format);
1020 par->sample_rate = fx->nSamplesPerSec;
1021 par->channels = fx->nChannels;
1022 }
1023
1024 avpriv_set_pts_info(st, 64, 1, 10000000);
1025
1026 ret = 0;
1027
1028error:
1029 return ret;
1030}
1031
1032static int parse_device_name(AVFormatContext *avctx)
1033{
1034 struct dshow_ctx *ctx = avctx->priv_data;
1035 char **device_name = ctx->device_name;
1036 char *name = av_strdup(avctx->filename);
1037 char *tmp = name;
1038 int ret = 1;
1039 char *type;
1040
1041 while ((type = strtok(tmp, "="))) {
1042 char *token = strtok(NULL, ":");
1043 tmp = NULL;
1044
1045 if (!strcmp(type, "video")) {
1046 device_name[0] = token;
1047 } else if (!strcmp(type, "audio")) {
1048 device_name[1] = token;
1049 } else {
1050 device_name[0] = NULL;
1051 device_name[1] = NULL;
1052 break;
1053 }
1054 }
1055
1056 if (!device_name[0] && !device_name[1]) {
1057 ret = 0;
1058 } else {
1059 if (device_name[0])
1060 device_name[0] = av_strdup(device_name[0]);
1061 if (device_name[1])
1062 device_name[1] = av_strdup(device_name[1]);
1063 }
1064
1065 av_free(name);
1066 return ret;
1067}
1068
1069static int dshow_read_header(AVFormatContext *avctx)
1070{
1071 struct dshow_ctx *ctx = avctx->priv_data;
1072 IGraphBuilder *graph = NULL;
1073 ICreateDevEnum *devenum = NULL;
1074 IMediaControl *control = NULL;
1075 IMediaEvent *media_event = NULL;
1076 HANDLE media_event_handle;
1077 HANDLE proc;
1078 int ret = AVERROR(EIO);
1079 int r;
1080
1081 CoInitialize(0);
1082
1083 if (!ctx->list_devices && !parse_device_name(avctx)) {
1084 av_log(avctx, AV_LOG_ERROR, "Malformed dshow input string.\n");
1085 goto error;
1086 }
1087
1088 ctx->video_codec_id = avctx->video_codec_id ? avctx->video_codec_id
1089 : AV_CODEC_ID_RAWVIDEO;
1090 if (ctx->pixel_format != AV_PIX_FMT_NONE) {
1091 if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
1092 av_log(avctx, AV_LOG_ERROR, "Pixel format may only be set when "
1093 "video codec is not set or set to rawvideo\n");
1094 ret = AVERROR(EINVAL);
1095 goto error;
1096 }
1097 }
1098 if (ctx->framerate) {
1099 r = av_parse_video_rate(&ctx->requested_framerate, ctx->framerate);
1100 if (r < 0) {
1101 av_log(avctx, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", ctx->framerate);
1102 goto error;
1103 }
1104 }
1105
1106 r = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
1107 &IID_IGraphBuilder, (void **) &graph);
1108 if (r != S_OK) {
1109 av_log(avctx, AV_LOG_ERROR, "Could not create capture graph.\n");
1110 goto error;
1111 }
1112 ctx->graph = graph;
1113
1114 r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
1115 &IID_ICreateDevEnum, (void **) &devenum);
1116 if (r != S_OK) {
1117 av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n");
1118 goto error;
1119 }
1120
1121 if (ctx->list_devices) {
1122 av_log(avctx, AV_LOG_INFO, "DirectShow video devices (some may be both video and audio devices)\n");
1123 dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL, NULL);
1124 av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n");
1125 dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL, NULL);
1126 ret = AVERROR_EXIT;
1127 goto error;
1128 }
1129 if (ctx->list_options) {
1130 if (ctx->device_name[VideoDevice])
1131 if ((r = dshow_list_device_options(avctx, devenum, VideoDevice, VideoSourceDevice))) {
1132 ret = r;
1133 goto error;
1134 }
1135 if (ctx->device_name[AudioDevice]) {
1136 if (dshow_list_device_options(avctx, devenum, AudioDevice, AudioSourceDevice)) {
1137 /* show audio options from combined video+audio sources as fallback */
1138 if ((r = dshow_list_device_options(avctx, devenum, AudioDevice, VideoSourceDevice))) {
1139 ret = r;
1140 goto error;
1141 }
1142 }
1143 }
1144 }
1145 if (ctx->device_name[VideoDevice]) {
1146 if ((r = dshow_open_device(avctx, devenum, VideoDevice, VideoSourceDevice)) < 0 ||
1147 (r = dshow_add_device(avctx, VideoDevice)) < 0) {
1148 ret = r;
1149 goto error;
1150 }
1151 }
1152 if (ctx->device_name[AudioDevice]) {
1153 if ((r = dshow_open_device(avctx, devenum, AudioDevice, AudioSourceDevice)) < 0 ||
1154 (r = dshow_add_device(avctx, AudioDevice)) < 0) {
1155 av_log(avctx, AV_LOG_INFO, "Searching for audio device within video devices for %s\n", ctx->device_name[AudioDevice]);
1156 /* see if there's a video source with an audio pin with the given audio name */
1157 if ((r = dshow_open_device(avctx, devenum, AudioDevice, VideoSourceDevice)) < 0 ||
1158 (r = dshow_add_device(avctx, AudioDevice)) < 0) {
1159 ret = r;
1160 goto error;
1161 }
1162 }
1163 }
1164 if (ctx->list_options) {
1165 /* allow it to list crossbar options in dshow_open_device */
1166 ret = AVERROR_EXIT;
1167 goto error;
1168 }
1169 ctx->curbufsize[0] = 0;
1170 ctx->curbufsize[1] = 0;
1171 ctx->mutex = CreateMutex(NULL, 0, NULL);
1172 if (!ctx->mutex) {
1173 av_log(avctx, AV_LOG_ERROR, "Could not create Mutex\n");
1174 goto error;
1175 }
1176 ctx->event[1] = CreateEvent(NULL, 1, 0, NULL);
1177 if (!ctx->event[1]) {
1178 av_log(avctx, AV_LOG_ERROR, "Could not create Event\n");
1179 goto error;
1180 }
1181
1182 r = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **) &control);
1183 if (r != S_OK) {
1184 av_log(avctx, AV_LOG_ERROR, "Could not get media control.\n");
1185 goto error;
1186 }
1187 ctx->control = control;
1188
1189 r = IGraphBuilder_QueryInterface(graph, &IID_IMediaEvent, (void **) &media_event);
1190 if (r != S_OK) {
1191 av_log(avctx, AV_LOG_ERROR, "Could not get media event.\n");
1192 goto error;
1193 }
1194 ctx->media_event = media_event;
1195
1196 r = IMediaEvent_GetEventHandle(media_event, (void *) &media_event_handle);
1197 if (r != S_OK) {
1198 av_log(avctx, AV_LOG_ERROR, "Could not get media event handle.\n");
1199 goto error;
1200 }
1201 proc = GetCurrentProcess();
1202 r = DuplicateHandle(proc, media_event_handle, proc, &ctx->event[0],
1203 0, 0, DUPLICATE_SAME_ACCESS);
1204 if (!r) {
1205 av_log(avctx, AV_LOG_ERROR, "Could not duplicate media event handle.\n");
1206 goto error;
1207 }
1208
1209 r = IMediaControl_Run(control);
1210 if (r == S_FALSE) {
1211 OAFilterState pfs;
1212 r = IMediaControl_GetState(control, 0, &pfs);
1213 }
1214 if (r != S_OK) {
1215 av_log(avctx, AV_LOG_ERROR, "Could not run graph (sometimes caused by a device already in use by other application)\n");
1216 goto error;
1217 }
1218
1219 ret = 0;
1220
1221error:
1222
1223 if (devenum)
1224 ICreateDevEnum_Release(devenum);
1225
1226 if (ret < 0)
1227 dshow_read_close(avctx);
1228
1229 return ret;
1230}
1231
1232/**
1233 * Checks media events from DirectShow and returns -1 on error or EOF. Also
1234 * purges all events that might be in the event queue to stop the trigger
1235 * of event notification.
1236 */
1237static int dshow_check_event_queue(IMediaEvent *media_event)
1238{
1239 LONG_PTR p1, p2;
1240 long code;
1241 int ret = 0;
1242
1243 while (IMediaEvent_GetEvent(media_event, &code, &p1, &p2, 0) != E_ABORT) {
1244 if (code == EC_COMPLETE || code == EC_DEVICE_LOST || code == EC_ERRORABORT)
1245 ret = -1;
1246 IMediaEvent_FreeEventParams(media_event, code, p1, p2);
1247 }
1248
1249 return ret;
1250}
1251
1252static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt)
1253{
1254 struct dshow_ctx *ctx = s->priv_data;
1255 AVPacketList *pktl = NULL;
1256
1257 while (!ctx->eof && !pktl) {
1258 WaitForSingleObject(ctx->mutex, INFINITE);
1259 pktl = ctx->pktl;
1260 if (pktl) {
1261 *pkt = pktl->pkt;
1262 ctx->pktl = ctx->pktl->next;
1263 av_free(pktl);
1264 ctx->curbufsize[pkt->stream_index] -= pkt->size;
1265 }
1266 ResetEvent(ctx->event[1]);
1267 ReleaseMutex(ctx->mutex);
1268 if (!pktl) {
1269 if (dshow_check_event_queue(ctx->media_event) < 0) {
1270 ctx->eof = 1;
1271 } else if (s->flags & AVFMT_FLAG_NONBLOCK) {
1272 return AVERROR(EAGAIN);
1273 } else {
1274 WaitForMultipleObjects(2, ctx->event, 0, INFINITE);
1275 }
1276 }
1277 }
1278
1279 return ctx->eof ? AVERROR(EIO) : pkt->size;
1280}
1281
1282#define OFFSET(x) offsetof(struct dshow_ctx, x)
1283#define DEC AV_OPT_FLAG_DECODING_PARAM
1284static const AVOption options[] = {
1285 { "video_size", "set video size given a string such as 640x480 or hd720.", OFFSET(requested_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
1286 { "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, -1, INT_MAX, DEC },
1287 { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
1288 { "sample_rate", "set audio sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
1289 { "sample_size", "set audio sample size", OFFSET(sample_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 16, DEC },
1290 { "channels", "set number of audio channels, such as 1 or 2", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
1291 { "audio_buffer_size", "set audio device buffer latency size in milliseconds (default is the device's default)", OFFSET(audio_buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
1292 { "list_devices", "list available devices", OFFSET(list_devices), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, DEC },
1293 { "list_options", "list available options for specified device", OFFSET(list_options), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, DEC },
1294 { "video_device_number", "set video device number for devices with same name (starts at 0)", OFFSET(video_device_number), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
1295 { "audio_device_number", "set audio device number for devices with same name (starts at 0)", OFFSET(audio_device_number), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
1296 { "video_pin_name", "select video capture pin by name", OFFSET(video_pin_name),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
1297 { "audio_pin_name", "select audio capture pin by name", OFFSET(audio_pin_name),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
1298 { "crossbar_video_input_pin_number", "set video input pin number for crossbar device", OFFSET(crossbar_video_input_pin_number), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, DEC },
1299 { "crossbar_audio_input_pin_number", "set audio input pin number for crossbar device", OFFSET(crossbar_audio_input_pin_number), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, DEC },
1300 { "show_video_device_dialog", "display property dialog for video capture device", OFFSET(show_video_device_dialog), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
1301 { "show_audio_device_dialog", "display property dialog for audio capture device", OFFSET(show_audio_device_dialog), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
1302 { "show_video_crossbar_connection_dialog", "display property dialog for crossbar connecting pins filter on video device", OFFSET(show_video_crossbar_connection_dialog), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
1303 { "show_audio_crossbar_connection_dialog", "display property dialog for crossbar connecting pins filter on audio device", OFFSET(show_audio_crossbar_connection_dialog), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
1304 { "show_analog_tv_tuner_dialog", "display property dialog for analog tuner filter", OFFSET(show_analog_tv_tuner_dialog), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
1305 { "show_analog_tv_tuner_audio_dialog", "display property dialog for analog tuner audio filter", OFFSET(show_analog_tv_tuner_audio_dialog), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
1306 { "audio_device_load", "load audio capture filter device (and properties) from file", OFFSET(audio_filter_load_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
1307 { "audio_device_save", "save audio capture filter device (and properties) to file", OFFSET(audio_filter_save_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
1308 { "video_device_load", "load video capture filter device (and properties) from file", OFFSET(video_filter_load_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
1309 { "video_device_save", "save video capture filter device (and properties) to file", OFFSET(video_filter_save_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
1310 { NULL },
1311};
1312
1313static const AVClass dshow_class = {
1314 .class_name = "dshow indev",
1315 .item_name = av_default_item_name,
1316 .option = options,
1317 .version = LIBAVUTIL_VERSION_INT,
1318 .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,
1319};
1320
1321AVInputFormat ff_dshow_demuxer = {
1322 .name = "dshow",
1323 .long_name = NULL_IF_CONFIG_SMALL("DirectShow capture"),
1324 .priv_data_size = sizeof(struct dshow_ctx),
1325 .read_header = dshow_read_header,
1326 .read_packet = dshow_read_packet,
1327 .read_close = dshow_read_close,
1328 .flags = AVFMT_NOFILE,
1329 .priv_class = &dshow_class,
1330};
1331