Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 + AV_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. };
  1326.