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