FFmpeg  4.3.6
dshow.c
Go to the documentation of this file.
1 /*
2  * Directshow capture interface
3  * Copyright (c) 2010 Ramiro Polla
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "dshow_capture.h"
23 #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
59 {
60  struct dshow_ctx *ctx = s->priv_data;
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])
91  if (ctx->capture_pin[AudioDevice])
93  if (ctx->capture_filter[VideoDevice])
95  if (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 
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,
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  unique_name = NULL;
282  // success, loop will end now
283  }
284  } else {
285  av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name);
286  av_log(avctx, AV_LOG_INFO, " Alternative name \"%s\"\n", unique_name);
287  }
288 
289 fail1:
290  if (olestr && co_malloc)
291  IMalloc_Free(co_malloc, olestr);
292  if (bind_ctx)
293  IBindCtx_Release(bind_ctx);
294  av_freep(&friendly_name);
295  av_freep(&unique_name);
296  if (bag)
297  IPropertyBag_Release(bag);
298  IMoniker_Release(m);
299  }
300 
301  IEnumMoniker_Release(classenum);
302 
303  if (pfilter) {
304  if (!device_filter) {
305  av_log(avctx, AV_LOG_ERROR, "Could not find %s device with name [%s] among source devices of type %s.\n",
306  devtypename, device_name, sourcetypename);
307  return AVERROR(EIO);
308  }
309  *pfilter = device_filter;
310  }
311 
312  return 0;
313 }
314 
315 /**
316  * Cycle through available formats using the specified pin,
317  * try to set parameters specified through AVOptions and if successful
318  * return 1 in *pformat_set.
319  * If pformat_set is NULL, list all pin capabilities.
320  */
321 static void
323  IPin *pin, int *pformat_set)
324 {
325  struct dshow_ctx *ctx = avctx->priv_data;
326  IAMStreamConfig *config = NULL;
327  AM_MEDIA_TYPE *type = NULL;
328  int format_set = 0;
329  void *caps = NULL;
330  int i, n, size, r;
331 
332  if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
333  return;
334  if (IAMStreamConfig_GetNumberOfCapabilities(config, &n, &size) != S_OK)
335  goto end;
336 
337  caps = av_malloc(size);
338  if (!caps)
339  goto end;
340 
341  for (i = 0; i < n && !format_set; i++) {
342  r = IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps);
343  if (r != S_OK)
344  goto next;
345 #if DSHOWDEBUG
347 #endif
348 
349  if (devtype == VideoDevice) {
350  VIDEO_STREAM_CONFIG_CAPS *vcaps = caps;
351  BITMAPINFOHEADER *bih;
352  int64_t *fr;
353  const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL };
354 #if DSHOWDEBUG
356 #endif
357  if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) {
358  VIDEOINFOHEADER *v = (void *) type->pbFormat;
359  fr = &v->AvgTimePerFrame;
360  bih = &v->bmiHeader;
361  } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) {
362  VIDEOINFOHEADER2 *v = (void *) type->pbFormat;
363  fr = &v->AvgTimePerFrame;
364  bih = &v->bmiHeader;
365  } else {
366  goto next;
367  }
368  if (!pformat_set) {
369  enum AVPixelFormat pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount);
370  if (pix_fmt == AV_PIX_FMT_NONE) {
371  enum AVCodecID codec_id = av_codec_get_id(tags, bih->biCompression);
372  AVCodec *codec = avcodec_find_decoder(codec_id);
373  if (codec_id == AV_CODEC_ID_NONE || !codec) {
374  av_log(avctx, AV_LOG_INFO, " unknown compression type 0x%X", (int) bih->biCompression);
375  } else {
376  av_log(avctx, AV_LOG_INFO, " vcodec=%s", codec->name);
377  }
378  } else {
379  av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(pix_fmt));
380  }
381  av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n",
382  vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
383  1e7 / vcaps->MaxFrameInterval,
384  vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,
385  1e7 / vcaps->MinFrameInterval);
386  continue;
387  }
388  if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
389  if (ctx->video_codec_id != av_codec_get_id(tags, bih->biCompression))
390  goto next;
391  }
392  if (ctx->pixel_format != AV_PIX_FMT_NONE &&
393  ctx->pixel_format != dshow_pixfmt(bih->biCompression, bih->biBitCount)) {
394  goto next;
395  }
396  if (ctx->framerate) {
397  int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000)
398  / ctx->requested_framerate.num;
399  if (framerate > vcaps->MaxFrameInterval ||
400  framerate < vcaps->MinFrameInterval)
401  goto next;
402  *fr = framerate;
403  }
404  if (ctx->requested_width && ctx->requested_height) {
405  if (ctx->requested_width > vcaps->MaxOutputSize.cx ||
406  ctx->requested_width < vcaps->MinOutputSize.cx ||
407  ctx->requested_height > vcaps->MaxOutputSize.cy ||
408  ctx->requested_height < vcaps->MinOutputSize.cy)
409  goto next;
410  bih->biWidth = ctx->requested_width;
411  bih->biHeight = ctx->requested_height;
412  }
413  } else {
414  AUDIO_STREAM_CONFIG_CAPS *acaps = caps;
415  WAVEFORMATEX *fx;
416 #if DSHOWDEBUG
418 #endif
419  if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) {
420  fx = (void *) type->pbFormat;
421  } else {
422  goto next;
423  }
424  if (!pformat_set) {
425  av_log(avctx, AV_LOG_INFO, " min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n",
426  acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency,
427  acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency);
428  continue;
429  }
430  if (ctx->sample_rate) {
431  if (ctx->sample_rate > acaps->MaximumSampleFrequency ||
432  ctx->sample_rate < acaps->MinimumSampleFrequency)
433  goto next;
434  fx->nSamplesPerSec = ctx->sample_rate;
435  }
436  if (ctx->sample_size) {
437  if (ctx->sample_size > acaps->MaximumBitsPerSample ||
438  ctx->sample_size < acaps->MinimumBitsPerSample)
439  goto next;
440  fx->wBitsPerSample = ctx->sample_size;
441  }
442  if (ctx->channels) {
443  if (ctx->channels > acaps->MaximumChannels ||
444  ctx->channels < acaps->MinimumChannels)
445  goto next;
446  fx->nChannels = ctx->channels;
447  }
448  }
449  if (IAMStreamConfig_SetFormat(config, type) != S_OK)
450  goto next;
451  format_set = 1;
452 next:
453  if (type->pbFormat)
454  CoTaskMemFree(type->pbFormat);
455  CoTaskMemFree(type);
456  }
457 end:
458  IAMStreamConfig_Release(config);
459  av_free(caps);
460  if (pformat_set)
461  *pformat_set = format_set;
462 }
463 
464 /**
465  * Set audio device buffer size in milliseconds (which can directly impact
466  * latency, depending on the device).
467  */
468 static int
470 {
471  struct dshow_ctx *ctx = avctx->priv_data;
472  IAMBufferNegotiation *buffer_negotiation = NULL;
473  ALLOCATOR_PROPERTIES props = { -1, -1, -1, -1 };
474  IAMStreamConfig *config = NULL;
475  AM_MEDIA_TYPE *type = NULL;
476  int ret = AVERROR(EIO);
477 
478  if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
479  goto end;
480  if (IAMStreamConfig_GetFormat(config, &type) != S_OK)
481  goto end;
482  if (!IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx))
483  goto end;
484 
485  props.cbBuffer = (((WAVEFORMATEX *) type->pbFormat)->nAvgBytesPerSec)
486  * ctx->audio_buffer_size / 1000;
487 
488  if (IPin_QueryInterface(pin, &IID_IAMBufferNegotiation, (void **) &buffer_negotiation) != S_OK)
489  goto end;
490  if (IAMBufferNegotiation_SuggestAllocatorProperties(buffer_negotiation, &props) != S_OK)
491  goto end;
492 
493  ret = 0;
494 
495 end:
496  if (buffer_negotiation)
497  IAMBufferNegotiation_Release(buffer_negotiation);
498  if (type) {
499  if (type->pbFormat)
500  CoTaskMemFree(type->pbFormat);
501  CoTaskMemFree(type);
502  }
503  if (config)
504  IAMStreamConfig_Release(config);
505 
506  return ret;
507 }
508 
509 /**
510  * Pops up a user dialog allowing them to adjust properties for the given filter, if possible.
511  */
512 void
514  ISpecifyPropertyPages *property_pages = NULL;
515  IUnknown *device_filter_iunknown = NULL;
516  HRESULT hr;
517  FILTER_INFO filter_info = {0}; /* a warning on this line is false positive GCC bug 53119 AFAICT */
518  CAUUID ca_guid = {0};
519 
520  hr = IBaseFilter_QueryInterface(device_filter, &IID_ISpecifyPropertyPages, (void **)&property_pages);
521  if (hr != S_OK) {
522  av_log(avctx, AV_LOG_WARNING, "requested filter does not have a property page to show");
523  goto end;
524  }
525  hr = IBaseFilter_QueryFilterInfo(device_filter, &filter_info);
526  if (hr != S_OK) {
527  goto fail;
528  }
529  hr = IBaseFilter_QueryInterface(device_filter, &IID_IUnknown, (void **)&device_filter_iunknown);
530  if (hr != S_OK) {
531  goto fail;
532  }
533  hr = ISpecifyPropertyPages_GetPages(property_pages, &ca_guid);
534  if (hr != S_OK) {
535  goto fail;
536  }
537  hr = OleCreatePropertyFrame(NULL, 0, 0, filter_info.achName, 1, &device_filter_iunknown, ca_guid.cElems,
538  ca_guid.pElems, 0, 0, NULL);
539  if (hr != S_OK) {
540  goto fail;
541  }
542  goto end;
543 fail:
544  av_log(avctx, AV_LOG_ERROR, "Failure showing property pages for filter");
545 end:
546  if (property_pages)
547  ISpecifyPropertyPages_Release(property_pages);
548  if (device_filter_iunknown)
549  IUnknown_Release(device_filter_iunknown);
550  if (filter_info.pGraph)
551  IFilterGraph_Release(filter_info.pGraph);
552  if (ca_guid.pElems)
553  CoTaskMemFree(ca_guid.pElems);
554 }
555 
556 /**
557  * Cycle through available pins using the device_filter device, of type
558  * devtype, retrieve the first output pin and return the pointer to the
559  * object found in *ppin.
560  * If ppin is NULL, cycle through all pins listing audio/video capabilities.
561  */
562 static int
564  enum dshowSourceFilterType sourcetype, IBaseFilter *device_filter, IPin **ppin)
565 {
566  struct dshow_ctx *ctx = avctx->priv_data;
567  IEnumPins *pins = 0;
568  IPin *device_pin = NULL;
569  IPin *pin;
570  int r;
571 
572  const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
573  const char *devtypename = (devtype == VideoDevice) ? "video" : "audio only";
574  const char *sourcetypename = (sourcetype == VideoSourceDevice) ? "video" : "audio";
575 
576  int set_format = (devtype == VideoDevice && (ctx->framerate ||
577  (ctx->requested_width && ctx->requested_height) ||
578  ctx->pixel_format != AV_PIX_FMT_NONE ||
580  || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate));
581  int format_set = 0;
582  int should_show_properties = (devtype == VideoDevice) ? ctx->show_video_device_dialog : ctx->show_audio_device_dialog;
583 
584  if (should_show_properties)
585  dshow_show_filter_properties(device_filter, avctx);
586 
587  r = IBaseFilter_EnumPins(device_filter, &pins);
588  if (r != S_OK) {
589  av_log(avctx, AV_LOG_ERROR, "Could not enumerate pins.\n");
590  return AVERROR(EIO);
591  }
592 
593  if (!ppin) {
594  av_log(avctx, AV_LOG_INFO, "DirectShow %s device options (from %s devices)\n",
595  devtypename, sourcetypename);
596  }
597 
598  while (!device_pin && IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) {
599  IKsPropertySet *p = NULL;
600  IEnumMediaTypes *types = NULL;
601  PIN_INFO info = {0};
602  AM_MEDIA_TYPE *type;
603  GUID category;
604  DWORD r2;
605  char *name_buf = NULL;
606  wchar_t *pin_id = NULL;
607  char *pin_buf = NULL;
608  char *desired_pin_name = devtype == VideoDevice ? ctx->video_pin_name : ctx->audio_pin_name;
609 
610  IPin_QueryPinInfo(pin, &info);
611  IBaseFilter_Release(info.pFilter);
612 
613  if (info.dir != PINDIR_OUTPUT)
614  goto next;
615  if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **) &p) != S_OK)
616  goto next;
617  if (IKsPropertySet_Get(p, &AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY,
618  NULL, 0, &category, sizeof(GUID), &r2) != S_OK)
619  goto next;
620  if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
621  goto next;
622  name_buf = dup_wchar_to_utf8(info.achName);
623 
624  r = IPin_QueryId(pin, &pin_id);
625  if (r != S_OK) {
626  av_log(avctx, AV_LOG_ERROR, "Could not query pin id\n");
627  return AVERROR(EIO);
628  }
629  pin_buf = dup_wchar_to_utf8(pin_id);
630 
631  if (!ppin) {
632  av_log(avctx, AV_LOG_INFO, " Pin \"%s\" (alternative pin name \"%s\")\n", name_buf, pin_buf);
633  dshow_cycle_formats(avctx, devtype, pin, NULL);
634  goto next;
635  }
636 
637  if (desired_pin_name) {
638  if(strcmp(name_buf, desired_pin_name) && strcmp(pin_buf, desired_pin_name)) {
639  av_log(avctx, AV_LOG_DEBUG, "skipping pin \"%s\" (\"%s\") != requested \"%s\"\n",
640  name_buf, pin_buf, desired_pin_name);
641  goto next;
642  }
643  }
644 
645  if (set_format) {
646  dshow_cycle_formats(avctx, devtype, pin, &format_set);
647  if (!format_set) {
648  goto next;
649  }
650  }
651  if (devtype == AudioDevice && ctx->audio_buffer_size) {
652  if (dshow_set_audio_buffer_size(avctx, pin) < 0) {
653  av_log(avctx, AV_LOG_ERROR, "unable to set audio buffer size %d to pin, using pin anyway...", ctx->audio_buffer_size);
654  }
655  }
656 
657  if (IPin_EnumMediaTypes(pin, &types) != S_OK)
658  goto next;
659 
660  IEnumMediaTypes_Reset(types);
661  /* in case format_set was not called, just verify the majortype */
662  while (!device_pin && IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) {
663  if (IsEqualGUID(&type->majortype, mediatype[devtype])) {
664  device_pin = pin;
665  av_log(avctx, AV_LOG_DEBUG, "Selecting pin %s on %s\n", name_buf, devtypename);
666  goto next;
667  }
668  CoTaskMemFree(type);
669  }
670 
671 next:
672  if (types)
673  IEnumMediaTypes_Release(types);
674  if (p)
675  IKsPropertySet_Release(p);
676  if (device_pin != pin)
677  IPin_Release(pin);
678  av_free(name_buf);
679  av_free(pin_buf);
680  if (pin_id)
681  CoTaskMemFree(pin_id);
682  }
683 
684  IEnumPins_Release(pins);
685 
686  if (ppin) {
687  if (set_format && !format_set) {
688  av_log(avctx, AV_LOG_ERROR, "Could not set %s options\n", devtypename);
689  return AVERROR(EIO);
690  }
691  if (!device_pin) {
692  av_log(avctx, AV_LOG_ERROR,
693  "Could not find output pin from %s capture device.\n", devtypename);
694  return AVERROR(EIO);
695  }
696  *ppin = device_pin;
697  }
698 
699  return 0;
700 }
701 
702 /**
703  * List options for device with type devtype, source filter type sourcetype
704  *
705  * @param devenum device enumerator used for accessing the device
706  */
707 static int
708 dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum,
709  enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype)
710 {
711  struct dshow_ctx *ctx = avctx->priv_data;
712  IBaseFilter *device_filter = NULL;
713  char *device_unique_name = NULL;
714  int r;
715 
716  if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name)) < 0)
717  return r;
718  ctx->device_filter[devtype] = device_filter;
719  if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, NULL)) < 0)
720  return r;
721  av_freep(&device_unique_name);
722  return 0;
723 }
724 
725 static int
726 dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
727  enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype)
728 {
729  struct dshow_ctx *ctx = avctx->priv_data;
730  IBaseFilter *device_filter = NULL;
731  char *device_filter_unique_name = NULL;
732  IGraphBuilder *graph = ctx->graph;
733  IPin *device_pin = NULL;
736  ICaptureGraphBuilder2 *graph_builder2 = NULL;
737  int ret = AVERROR(EIO);
738  int r;
739  IStream *ifile_stream = NULL;
740  IStream *ofile_stream = NULL;
741  IPersistStream *pers_stream = NULL;
742  enum dshowDeviceType otherDevType = (devtype == VideoDevice) ? AudioDevice : VideoDevice;
743 
744  const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
745 
746 
747  if ( ((ctx->audio_filter_load_file) && (strlen(ctx->audio_filter_load_file)>0) && (sourcetype == AudioSourceDevice)) ||
748  ((ctx->video_filter_load_file) && (strlen(ctx->video_filter_load_file)>0) && (sourcetype == VideoSourceDevice)) ) {
749  HRESULT hr;
750  char *filename = NULL;
751 
752  if (sourcetype == AudioSourceDevice)
753  filename = ctx->audio_filter_load_file;
754  else
755  filename = ctx->video_filter_load_file;
756 
757  hr = SHCreateStreamOnFile ((LPCSTR) filename, STGM_READ, &ifile_stream);
758  if (S_OK != hr) {
759  av_log(avctx, AV_LOG_ERROR, "Could not open capture filter description file.\n");
760  goto error;
761  }
762 
763  hr = OleLoadFromStream(ifile_stream, &IID_IBaseFilter, (void **) &device_filter);
764  if (hr != S_OK) {
765  av_log(avctx, AV_LOG_ERROR, "Could not load capture filter from file.\n");
766  goto error;
767  }
768 
769  if (sourcetype == AudioSourceDevice)
770  av_log(avctx, AV_LOG_INFO, "Audio-");
771  else
772  av_log(avctx, AV_LOG_INFO, "Video-");
773  av_log(avctx, AV_LOG_INFO, "Capture filter loaded successfully from file \"%s\".\n", filename);
774  } else {
775 
776  if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_filter_unique_name)) < 0) {
777  ret = r;
778  goto error;
779  }
780  }
781  if (ctx->device_filter[otherDevType]) {
782  // avoid adding add two instances of the same device to the graph, one for video, one for audio
783  // a few devices don't support this (could also do this check earlier to avoid double crossbars, etc. but they seem OK)
784  if (strcmp(device_filter_unique_name, ctx->device_unique_name[otherDevType]) == 0) {
785  av_log(avctx, AV_LOG_DEBUG, "reusing previous graph capture filter... %s\n", device_filter_unique_name);
786  IBaseFilter_Release(device_filter);
787  device_filter = ctx->device_filter[otherDevType];
788  IBaseFilter_AddRef(ctx->device_filter[otherDevType]);
789  } else {
790  av_log(avctx, AV_LOG_DEBUG, "not reusing previous graph capture filter %s != %s\n", device_filter_unique_name, ctx->device_unique_name[otherDevType]);
791  }
792  }
793 
794  ctx->device_filter [devtype] = device_filter;
795  ctx->device_unique_name [devtype] = device_filter_unique_name;
796 
797  r = IGraphBuilder_AddFilter(graph, device_filter, NULL);
798  if (r != S_OK) {
799  av_log(avctx, AV_LOG_ERROR, "Could not add device filter to graph.\n");
800  goto error;
801  }
802 
803  if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, &device_pin)) < 0) {
804  ret = r;
805  goto error;
806  }
807 
808  ctx->device_pin[devtype] = device_pin;
809 
810  capture_filter = libAVFilter_Create(avctx, callback, devtype);
811  if (!capture_filter) {
812  av_log(avctx, AV_LOG_ERROR, "Could not create grabber filter.\n");
813  goto error;
814  }
815  ctx->capture_filter[devtype] = capture_filter;
816 
817  if ( ((ctx->audio_filter_save_file) && (strlen(ctx->audio_filter_save_file)>0) && (sourcetype == AudioSourceDevice)) ||
818  ((ctx->video_filter_save_file) && (strlen(ctx->video_filter_save_file)>0) && (sourcetype == VideoSourceDevice)) ) {
819 
820  HRESULT hr;
821  char *filename = NULL;
822 
823  if (sourcetype == AudioSourceDevice)
824  filename = ctx->audio_filter_save_file;
825  else
826  filename = ctx->video_filter_save_file;
827 
828  hr = SHCreateStreamOnFile ((LPCSTR) filename, STGM_CREATE | STGM_READWRITE, &ofile_stream);
829  if (S_OK != hr) {
830  av_log(avctx, AV_LOG_ERROR, "Could not create capture filter description file.\n");
831  goto error;
832  }
833 
834  hr = IBaseFilter_QueryInterface(device_filter, &IID_IPersistStream, (void **) &pers_stream);
835  if (hr != S_OK) {
836  av_log(avctx, AV_LOG_ERROR, "Query for IPersistStream failed.\n");
837  goto error;
838  }
839 
840  hr = OleSaveToStream(pers_stream, ofile_stream);
841  if (hr != S_OK) {
842  av_log(avctx, AV_LOG_ERROR, "Could not save capture filter \n");
843  goto error;
844  }
845 
846  hr = IStream_Commit(ofile_stream, STGC_DEFAULT);
847  if (S_OK != hr) {
848  av_log(avctx, AV_LOG_ERROR, "Could not commit capture filter data to file.\n");
849  goto error;
850  }
851 
852  if (sourcetype == AudioSourceDevice)
853  av_log(avctx, AV_LOG_INFO, "Audio-");
854  else
855  av_log(avctx, AV_LOG_INFO, "Video-");
856  av_log(avctx, AV_LOG_INFO, "Capture filter saved successfully to file \"%s\".\n", filename);
857  }
858 
859  r = IGraphBuilder_AddFilter(graph, (IBaseFilter *) capture_filter,
860  filter_name[devtype]);
861  if (r != S_OK) {
862  av_log(avctx, AV_LOG_ERROR, "Could not add capture filter to graph\n");
863  goto error;
864  }
865 
866  libAVPin_AddRef(capture_filter->pin);
867  capture_pin = capture_filter->pin;
868  ctx->capture_pin[devtype] = capture_pin;
869 
870  r = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER,
871  &IID_ICaptureGraphBuilder2, (void **) &graph_builder2);
872  if (r != S_OK) {
873  av_log(avctx, AV_LOG_ERROR, "Could not create CaptureGraphBuilder2\n");
874  goto error;
875  }
876  ICaptureGraphBuilder2_SetFiltergraph(graph_builder2, graph);
877  if (r != S_OK) {
878  av_log(avctx, AV_LOG_ERROR, "Could not set graph for CaptureGraphBuilder2\n");
879  goto error;
880  }
881 
882  r = ICaptureGraphBuilder2_RenderStream(graph_builder2, NULL, NULL, (IUnknown *) device_pin, NULL /* no intermediate filter */,
883  (IBaseFilter *) capture_filter); /* connect pins, optionally insert intermediate filters like crossbar if necessary */
884 
885  if (r != S_OK) {
886  av_log(avctx, AV_LOG_ERROR, "Could not RenderStream to connect pins\n");
887  goto error;
888  }
889 
890  r = dshow_try_setup_crossbar_options(graph_builder2, device_filter, devtype, avctx);
891 
892  if (r != S_OK) {
893  av_log(avctx, AV_LOG_ERROR, "Could not setup CrossBar\n");
894  goto error;
895  }
896 
897  ret = 0;
898 
899 error:
900  if (graph_builder2 != NULL)
901  ICaptureGraphBuilder2_Release(graph_builder2);
902 
903  if (pers_stream)
904  IPersistStream_Release(pers_stream);
905 
906  if (ifile_stream)
907  IStream_Release(ifile_stream);
908 
909  if (ofile_stream)
910  IStream_Release(ofile_stream);
911 
912  return ret;
913 }
914 
915 static enum AVCodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
916 {
917  switch (sample_fmt) {
921  default: return AV_CODEC_ID_NONE; /* Should never happen. */
922  }
923 }
924 
926 {
927  switch (bits) {
928  case 8: return AV_SAMPLE_FMT_U8;
929  case 16: return AV_SAMPLE_FMT_S16;
930  case 32: return AV_SAMPLE_FMT_S32;
931  default: return AV_SAMPLE_FMT_NONE; /* Should never happen. */
932  }
933 }
934 
935 static int
937  enum dshowDeviceType devtype)
938 {
939  struct dshow_ctx *ctx = avctx->priv_data;
940  AM_MEDIA_TYPE type;
941  AVCodecParameters *par;
942  AVStream *st;
943  int ret = AVERROR(EIO);
944 
945  type.pbFormat = NULL;
946 
947  st = avformat_new_stream(avctx, NULL);
948  if (!st) {
949  ret = AVERROR(ENOMEM);
950  goto error;
951  }
952  st->id = devtype;
953 
954  ctx->capture_filter[devtype]->stream_index = st->index;
955 
956  libAVPin_ConnectionMediaType(ctx->capture_pin[devtype], &type);
957 
958  par = st->codecpar;
959  if (devtype == VideoDevice) {
960  BITMAPINFOHEADER *bih = NULL;
961  AVRational time_base;
962 
963  if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) {
964  VIDEOINFOHEADER *v = (void *) type.pbFormat;
965  time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
966  bih = &v->bmiHeader;
967  } else if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo2)) {
968  VIDEOINFOHEADER2 *v = (void *) type.pbFormat;
969  time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
970  bih = &v->bmiHeader;
971  }
972  if (!bih) {
973  av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
974  goto error;
975  }
976 
977  st->avg_frame_rate = av_inv_q(time_base);
978  st->r_frame_rate = av_inv_q(time_base);
979 
981  par->width = bih->biWidth;
982  par->height = bih->biHeight;
983  par->codec_tag = bih->biCompression;
984  par->format = dshow_pixfmt(bih->biCompression, bih->biBitCount);
985  if (bih->biCompression == MKTAG('H', 'D', 'Y', 'C')) {
986  av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for HDYC...\n");
987  par->color_range = AVCOL_RANGE_MPEG; // just in case it needs this...
988  }
989  if (par->format == AV_PIX_FMT_NONE) {
990  const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL };
991  par->codec_id = av_codec_get_id(tags, bih->biCompression);
992  if (par->codec_id == AV_CODEC_ID_NONE) {
993  av_log(avctx, AV_LOG_ERROR, "Unknown compression type. "
994  "Please report type 0x%X.\n", (int) bih->biCompression);
995  ret = AVERROR_PATCHWELCOME;
996  goto error;
997  }
998  par->bits_per_coded_sample = bih->biBitCount;
999  } else {
1001  if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) {
1002  par->bits_per_coded_sample = bih->biBitCount;
1003  if (par->height < 0) {
1004  par->height *= -1;
1005  } else {
1007  if (par->extradata) {
1008  par->extradata_size = 9;
1009  memcpy(par->extradata, "BottomUp", 9);
1010  }
1011  }
1012  }
1013  }
1014  } else {
1015  WAVEFORMATEX *fx = NULL;
1016 
1017  if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) {
1018  fx = (void *) type.pbFormat;
1019  }
1020  if (!fx) {
1021  av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
1022  goto error;
1023  }
1024 
1026  par->format = sample_fmt_bits_per_sample(fx->wBitsPerSample);
1027  par->codec_id = waveform_codec_id(par->format);
1028  par->sample_rate = fx->nSamplesPerSec;
1029  par->channels = fx->nChannels;
1030  }
1031 
1032  avpriv_set_pts_info(st, 64, 1, 10000000);
1033 
1034  ret = 0;
1035 
1036 error:
1037  if (type.pbFormat)
1038  CoTaskMemFree(type.pbFormat);
1039  return ret;
1040 }
1041 
1043 {
1044  struct dshow_ctx *ctx = avctx->priv_data;
1045  char **device_name = ctx->device_name;
1046  char *name = av_strdup(avctx->url);
1047  char *tmp = name;
1048  int ret = 1;
1049  char *type;
1050 
1051  while ((type = strtok(tmp, "="))) {
1052  char *token = strtok(NULL, ":");
1053  tmp = NULL;
1054 
1055  if (!strcmp(type, "video")) {
1056  device_name[0] = token;
1057  } else if (!strcmp(type, "audio")) {
1058  device_name[1] = token;
1059  } else {
1060  device_name[0] = NULL;
1061  device_name[1] = NULL;
1062  break;
1063  }
1064  }
1065 
1066  if (!device_name[0] && !device_name[1]) {
1067  ret = 0;
1068  } else {
1069  if (device_name[0])
1070  device_name[0] = av_strdup(device_name[0]);
1071  if (device_name[1])
1072  device_name[1] = av_strdup(device_name[1]);
1073  }
1074 
1075  av_free(name);
1076  return ret;
1077 }
1078 
1080 {
1081  struct dshow_ctx *ctx = avctx->priv_data;
1082  IGraphBuilder *graph = NULL;
1083  ICreateDevEnum *devenum = NULL;
1084  IMediaControl *control = NULL;
1085  IMediaEvent *media_event = NULL;
1086  HANDLE media_event_handle;
1087  HANDLE proc;
1088  int ret = AVERROR(EIO);
1089  int r;
1090 
1091  CoInitialize(0);
1092 
1093  if (!ctx->list_devices && !parse_device_name(avctx)) {
1094  av_log(avctx, AV_LOG_ERROR, "Malformed dshow input string.\n");
1095  goto error;
1096  }
1097 
1098  ctx->video_codec_id = avctx->video_codec_id ? avctx->video_codec_id
1100  if (ctx->pixel_format != AV_PIX_FMT_NONE) {
1101  if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
1102  av_log(avctx, AV_LOG_ERROR, "Pixel format may only be set when "
1103  "video codec is not set or set to rawvideo\n");
1104  ret = AVERROR(EINVAL);
1105  goto error;
1106  }
1107  }
1108  if (ctx->framerate) {
1110  if (r < 0) {
1111  av_log(avctx, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", ctx->framerate);
1112  goto error;
1113  }
1114  }
1115 
1116  r = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
1117  &IID_IGraphBuilder, (void **) &graph);
1118  if (r != S_OK) {
1119  av_log(avctx, AV_LOG_ERROR, "Could not create capture graph.\n");
1120  goto error;
1121  }
1122  ctx->graph = graph;
1123 
1124  r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
1125  &IID_ICreateDevEnum, (void **) &devenum);
1126  if (r != S_OK) {
1127  av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n");
1128  goto error;
1129  }
1130 
1131  if (ctx->list_devices) {
1132  av_log(avctx, AV_LOG_INFO, "DirectShow video devices (some may be both video and audio devices)\n");
1134  av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n");
1136  ret = AVERROR_EXIT;
1137  goto error;
1138  }
1139  if (ctx->list_options) {
1140  if (ctx->device_name[VideoDevice])
1141  if ((r = dshow_list_device_options(avctx, devenum, VideoDevice, VideoSourceDevice))) {
1142  ret = r;
1143  goto error;
1144  }
1145  if (ctx->device_name[AudioDevice]) {
1147  /* show audio options from combined video+audio sources as fallback */
1148  if ((r = dshow_list_device_options(avctx, devenum, AudioDevice, VideoSourceDevice))) {
1149  ret = r;
1150  goto error;
1151  }
1152  }
1153  }
1154  }
1155  if (ctx->device_name[VideoDevice]) {
1156  if ((r = dshow_open_device(avctx, devenum, VideoDevice, VideoSourceDevice)) < 0 ||
1157  (r = dshow_add_device(avctx, VideoDevice)) < 0) {
1158  ret = r;
1159  goto error;
1160  }
1161  }
1162  if (ctx->device_name[AudioDevice]) {
1163  if ((r = dshow_open_device(avctx, devenum, AudioDevice, AudioSourceDevice)) < 0 ||
1164  (r = dshow_add_device(avctx, AudioDevice)) < 0) {
1165  av_log(avctx, AV_LOG_INFO, "Searching for audio device within video devices for %s\n", ctx->device_name[AudioDevice]);
1166  /* see if there's a video source with an audio pin with the given audio name */
1167  if ((r = dshow_open_device(avctx, devenum, AudioDevice, VideoSourceDevice)) < 0 ||
1168  (r = dshow_add_device(avctx, AudioDevice)) < 0) {
1169  ret = r;
1170  goto error;
1171  }
1172  }
1173  }
1174  if (ctx->list_options) {
1175  /* allow it to list crossbar options in dshow_open_device */
1176  ret = AVERROR_EXIT;
1177  goto error;
1178  }
1179  ctx->curbufsize[0] = 0;
1180  ctx->curbufsize[1] = 0;
1181  ctx->mutex = CreateMutex(NULL, 0, NULL);
1182  if (!ctx->mutex) {
1183  av_log(avctx, AV_LOG_ERROR, "Could not create Mutex\n");
1184  goto error;
1185  }
1186  ctx->event[1] = CreateEvent(NULL, 1, 0, NULL);
1187  if (!ctx->event[1]) {
1188  av_log(avctx, AV_LOG_ERROR, "Could not create Event\n");
1189  goto error;
1190  }
1191 
1192  r = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **) &control);
1193  if (r != S_OK) {
1194  av_log(avctx, AV_LOG_ERROR, "Could not get media control.\n");
1195  goto error;
1196  }
1197  ctx->control = control;
1198 
1199  r = IGraphBuilder_QueryInterface(graph, &IID_IMediaEvent, (void **) &media_event);
1200  if (r != S_OK) {
1201  av_log(avctx, AV_LOG_ERROR, "Could not get media event.\n");
1202  goto error;
1203  }
1204  ctx->media_event = media_event;
1205 
1206  r = IMediaEvent_GetEventHandle(media_event, (void *) &media_event_handle);
1207  if (r != S_OK) {
1208  av_log(avctx, AV_LOG_ERROR, "Could not get media event handle.\n");
1209  goto error;
1210  }
1211  proc = GetCurrentProcess();
1212  r = DuplicateHandle(proc, media_event_handle, proc, &ctx->event[0],
1213  0, 0, DUPLICATE_SAME_ACCESS);
1214  if (!r) {
1215  av_log(avctx, AV_LOG_ERROR, "Could not duplicate media event handle.\n");
1216  goto error;
1217  }
1218 
1219  r = IMediaControl_Run(control);
1220  if (r == S_FALSE) {
1221  OAFilterState pfs;
1222  r = IMediaControl_GetState(control, 0, &pfs);
1223  }
1224  if (r != S_OK) {
1225  av_log(avctx, AV_LOG_ERROR, "Could not run graph (sometimes caused by a device already in use by other application)\n");
1226  goto error;
1227  }
1228 
1229  ret = 0;
1230 
1231 error:
1232 
1233  if (devenum)
1234  ICreateDevEnum_Release(devenum);
1235 
1236  if (ret < 0)
1237  dshow_read_close(avctx);
1238 
1239  return ret;
1240 }
1241 
1242 /**
1243  * Checks media events from DirectShow and returns -1 on error or EOF. Also
1244  * purges all events that might be in the event queue to stop the trigger
1245  * of event notification.
1246  */
1247 static int dshow_check_event_queue(IMediaEvent *media_event)
1248 {
1249  LONG_PTR p1, p2;
1250  long code;
1251  int ret = 0;
1252 
1253  while (IMediaEvent_GetEvent(media_event, &code, &p1, &p2, 0) != E_ABORT) {
1254  if (code == EC_COMPLETE || code == EC_DEVICE_LOST || code == EC_ERRORABORT)
1255  ret = -1;
1256  IMediaEvent_FreeEventParams(media_event, code, p1, p2);
1257  }
1258 
1259  return ret;
1260 }
1261 
1263 {
1264  struct dshow_ctx *ctx = s->priv_data;
1265  AVPacketList *pktl = NULL;
1266 
1267  while (!ctx->eof && !pktl) {
1268  WaitForSingleObject(ctx->mutex, INFINITE);
1269  pktl = ctx->pktl;
1270  if (pktl) {
1271  *pkt = pktl->pkt;
1272  ctx->pktl = ctx->pktl->next;
1273  av_free(pktl);
1274  ctx->curbufsize[pkt->stream_index] -= pkt->size;
1275  }
1276  ResetEvent(ctx->event[1]);
1277  ReleaseMutex(ctx->mutex);
1278  if (!pktl) {
1279  if (dshow_check_event_queue(ctx->media_event) < 0) {
1280  ctx->eof = 1;
1281  } else if (s->flags & AVFMT_FLAG_NONBLOCK) {
1282  return AVERROR(EAGAIN);
1283  } else {
1284  WaitForMultipleObjects(2, ctx->event, 0, INFINITE);
1285  }
1286  }
1287  }
1288 
1289  return ctx->eof ? AVERROR(EIO) : pkt->size;
1290 }
1291 
1292 #define OFFSET(x) offsetof(struct dshow_ctx, x)
1293 #define DEC AV_OPT_FLAG_DECODING_PARAM
1294 static const AVOption options[] = {
1295  { "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 },
1296  { "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, -1, INT_MAX, DEC },
1297  { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
1298  { "sample_rate", "set audio sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
1299  { "sample_size", "set audio sample size", OFFSET(sample_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 16, DEC },
1300  { "channels", "set number of audio channels, such as 1 or 2", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
1301  { "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 },
1302  { "list_devices", "list available devices", OFFSET(list_devices), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, DEC },
1303  { "list_options", "list available options for specified device", OFFSET(list_options), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, DEC },
1304  { "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 },
1305  { "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 },
1306  { "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 },
1307  { "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 },
1308  { "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 },
1309  { "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 },
1310  { "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 },
1311  { "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 },
1312  { "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 },
1313  { "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 },
1314  { "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 },
1315  { "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 },
1316  { "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 },
1317  { "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 },
1318  { "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 },
1319  { "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 },
1320  { NULL },
1321 };
1322 
1323 static const AVClass dshow_class = {
1324  .class_name = "dshow indev",
1325  .item_name = av_default_item_name,
1326  .option = options,
1327  .version = LIBAVUTIL_VERSION_INT,
1329 };
1330 
1332  .name = "dshow",
1333  .long_name = NULL_IF_CONFIG_SMALL("DirectShow capture"),
1334  .priv_data_size = sizeof(struct dshow_ctx),
1335  .read_header = dshow_read_header,
1336  .read_packet = dshow_read_packet,
1337  .read_close = dshow_read_close,
1338  .flags = AVFMT_NOFILE,
1339  .priv_class = &dshow_class,
1340 };
category
Definition: openal-dec.c:248
void dshow_show_filter_properties(IBaseFilter *device_filter, AVFormatContext *avctx)
Pops up a user dialog allowing them to adjust properties for the given filter, if possible...
Definition: dshow.c:513
#define NULL
Definition: coverity.c:32
int requested_width
static enum AVPixelFormat pix_fmt
int size
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
Definition: parseutils.c:179
static int dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype, IBaseFilter *device_filter, IPin **ppin)
Cycle through available pins using the device_filter device, of type devtype, retrieve the first outp...
Definition: dshow.c:563
char * audio_filter_load_file
void ff_print_VIDEO_STREAM_CONFIG_CAPS(const VIDEO_STREAM_CONFIG_CAPS *caps)
Definition: dshow_common.c:85
AVOption.
Definition: opt.h:246
#define WaitForSingleObject(a, b)
Definition: w32pthreads.h:64
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4948
static enum AVSampleFormat sample_fmt_bits_per_sample(int bits)
Definition: dshow.c:925
unsigned int max_picture_buffer
Maximum amount of memory in bytes to use for buffering frames obtained from realtime capture devices...
Definition: avformat.h:1567
HRESULT dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, enum dshowDeviceType devtype, AVFormatContext *avctx)
Given a fully constructed graph, check if there is a cross bar filter, and configure its pins if so...
int list_devices
AVInputFormat ff_dshow_demuxer
Definition: dshow.c:1331
int audio_device_number
unsigned long WINAPI libAVPin_Release(libAVPin *)
dshowDeviceType
Definition: dshow_capture.h:61
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
IMediaEvent * media_event
int num
Numerator.
Definition: rational.h:59
int index
stream index in AVFormatContext
Definition: avformat.h:877
int size
Definition: packet.h:356
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
static int dshow_add_device(AVFormatContext *avctx, enum dshowDeviceType devtype)
Definition: dshow.c:936
char * video_filter_load_file
static AVPacket pkt
static void error(const char *err)
enum AVCodecID video_codec_id
AVCodec.
Definition: codec.h:190
int framerate
Definition: h264_levels.c:65
This struct describes the properties of an encoded stream.
Definition: codec_par.h:52
int show_analog_tv_tuner_audio_dialog
packed RGB 1:2:1 bitstream, 4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in ...
Definition: pixfmt.h:87
int show_audio_crossbar_connection_dialog
Format I/O context.
Definition: avformat.h:1351
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
#define AVFMT_FLAG_NONBLOCK
Do not block when reading packets from input.
Definition: avformat.h:1485
IBaseFilter * device_filter[2]
uint8_t
#define av_malloc(s)
AV_SAMPLE_FMT_U8
const struct AVCodecTag * avformat_get_riff_video_tags(void)
Definition: riff.c:608
int width
Video only.
Definition: codec_par.h:126
static int dshow_read_close(AVFormatContext *s)
Definition: dshow.c:58
AVOptions.
enum AVCodecID av_codec_get_id(const struct AVCodecTag *const *tags, unsigned int tag)
Get the AVCodecID for the given codec tag tag.
AVPacket pkt
Definition: avformat.h:2025
#define f(width, name)
Definition: cbs_vp9.c:255
static int dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum, enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype)
Definition: dshow.c:726
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:92
libAVFilter * libAVFilter_Create(void *, void *, enum dshowDeviceType)
char * video_filter_save_file
int id
Format-specific stream ID.
Definition: avformat.h:883
AVPacketList * pktl
static void dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, IPin *pin, int *pformat_set)
Cycle through available formats using the specified pin, try to set parameters specified through AVOp...
Definition: dshow.c:322
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4526
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1482
uint8_t * data
Definition: packet.h:355
int audio_buffer_size
channels
Definition: aptx.h:33
signed 32 bits
Definition: samplefmt.h:62
dshowSourceFilterType
Definition: dshow_capture.h:66
enum AVCodecID video_codec_id
Forced video codec_id.
Definition: avformat.h:1537
#define av_log(a,...)
#define AV_OPT_FLAG_ENCODING_PARAM
a generic parameter which can be set by the user for muxing or encoding
Definition: opt.h:276
static const AVOption options[]
Definition: dshow.c:1294
static int dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype, IBaseFilter **pfilter, char **device_unique_name)
Cycle through available devices using the device enumerator devenum, retrieve the device with type sp...
Definition: dshow.c:207
Main libavdevice API header.
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:88
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
libAVPin * capture_pin[2]
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
HANDLE mutex
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:188
const uint8_t * code
Definition: spdifenc.c:413
char * url
input or output URL.
Definition: avformat.h:1447
const char * r
Definition: vf_curves.c:114
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
const char * name
Name of the codec implementation.
Definition: codec.h:197
uint8_t bits
Definition: vp3data.h:202
unsigned long WINAPI libAVPin_AddRef(libAVPin *)
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:949
#define fail()
Definition: checkasm.h:123
int extradata_size
Size of the extradata content in bytes.
Definition: codec_par.h:78
#define OFFSET(x)
Definition: dshow.c:1292
static int shall_we_drop(AVFormatContext *s, int index, enum dshowDeviceType devtype)
Definition: dshow.c:142
static char * dup_wchar_to_utf8(wchar_t *w)
Definition: dshow.c:132
static const AVClass dshow_class
Definition: dshow.c:1323
const char * name
Definition: qsvenc.c:46
static void callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType devtype)
Definition: dshow.c:161
Raw Video Codec.
static int parse_device_name(AVFormatContext *avctx)
Definition: dshow.c:1042
void ff_print_AUDIO_STREAM_CONFIG_CAPS(const AUDIO_STREAM_CONFIG_CAPS *caps)
Definition: dshow_common.c:115
uint8_t w
Definition: llviddspenc.c:38
static int dshow_read_header(AVFormatContext *avctx)
Definition: dshow.c:1079
AVRational requested_framerate
internal header for RIFF based (de)muxers do NOT include this in end user applications ...
AVFormatContext * ctx
Definition: movenc.c:48
char * audio_filter_save_file
#define s(width, name)
Definition: cbs_vp9.c:257
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
enum AVCodecID codec_id
Definition: vaapi_decode.c:369
enum AVColorRange color_range
Video only.
Definition: codec_par.h:146
#define L(x)
Definition: vp56_arith.h:36
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
char * video_pin_name
#define FF_ARRAY_ELEMS(a)
#define DEC
Definition: dshow.c:1293
Stream structure.
Definition: avformat.h:876
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
sample_rate
enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc)
Definition: utils.c:483
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
static int set_format(void *obj, const char *name, int fmt, int search_flags, enum AVOptionType type, const char *desc, int nb_fmts)
Definition: opt.c:670
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:605
static enum AVCodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
Definition: dshow.c:915
const char * friendly_name
static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
Definition: dshow.c:34
#define EC_DEVICE_LOST
Definition: dshow_capture.h:40
int list_options
Describe the class of an AVClass context structure.
Definition: log.h:67
enum AVPixelFormat pixel_format
int index
Definition: gxfenc.c:89
Rational number (pair of numerator and denominator).
Definition: rational.h:58
int show_audio_device_dialog
static int dshow_set_audio_buffer_size(AVFormatContext *avctx, IPin *pin)
Set audio device buffer size in milliseconds (which can directly impact latency, depending on the dev...
Definition: dshow.c:469
char * device_name[2]
int show_video_device_dialog
cl_device_type type
int requested_height
offset must point to two consecutive integers
Definition: opt.h:233
HANDLE event[2]
misc parsing utilities
static int dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum, enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype)
List options for device with type devtype, source filter type sourcetype.
Definition: dshow.c:708
AVCodec * avcodec_find_decoder(enum AVCodecID id)
Find a registered decoder with a matching codec ID.
Definition: allcodecs.c:919
int crossbar_audio_input_pin_number
the normal 219*2^(n-8) "MPEG" YUV ranges
Definition: pixfmt.h:534
char * audio_pin_name
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:159
int sample_rate
Audio only.
Definition: codec_par.h:170
int64_t curbufsize[2]
int video_device_number
unsigned long WINAPI libAVFilter_Release(libAVFilter *)
libAVFilter * capture_filter[2]
struct AVPacketList * next
Definition: avformat.h:2026
if(ret< 0)
Definition: vf_mcdeint.c:279
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:458
Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb...
Definition: pixfmt.h:75
signed 16 bits
Definition: samplefmt.h:61
IMediaControl * control
long WINAPI libAVPin_ConnectionMediaType(libAVPin *, AM_MEDIA_TYPE *)
Definition: dshow_pin.c:96
packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
Definition: pixfmt.h:86
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:385
int den
Denominator.
Definition: rational.h:60
static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: dshow.c:1262
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:215
char * device_unique_name[2]
int crossbar_video_input_pin_number
#define av_free(p)
IPin * device_pin[2]
void * priv_data
Format private data.
Definition: avformat.h:1379
const struct PixelFormatTag * avpriv_get_raw_pix_fmt_tags(void)
Definition: raw.c:299
int bits_per_coded_sample
The number of bits per sample in the codedwords.
Definition: codec_par.h:102
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:74
int channels
Audio only.
Definition: codec_par.h:166
void ff_print_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *type)
Definition: dshow_common.c:134
#define av_freep(p)
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:650
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1023
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: codec_par.h:64
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2465
int stream_index
Definition: packet.h:357
int show_video_crossbar_connection_dialog
static int dshow_check_event_queue(IMediaEvent *media_event)
Checks media events from DirectShow and returns -1 on error or EOF.
Definition: dshow.c:1247
#define MKTAG(a, b, c, d)
Definition: common.h:406
AVRational r_frame_rate
Real base framerate of the stream.
Definition: avformat.h:1000
unsigned int video_frame_num
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
This structure stores compressed data.
Definition: packet.h:332
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:348
int show_analog_tv_tuner_dialog
#define AV_PIX_FMT_0RGB32
Definition: pixfmt.h:374
IGraphBuilder * graph
char * framerate
static uint8_t tmp[11]
Definition: aes_ctr.c:26