[FFmpeg-devel] Fw: [PATCH] DirectShow patches

Stefano Sabatini stefano.sabatini-lala at poste.it
Sat Sep 10 00:08:21 CEST 2011


On date Friday 2011-09-09 00:29:47 -0300, Ramiro Polla encoded:
[...]
> From 2bb545f0beed2de14aa044ae2a102894e0f20b5f Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:08:43 -0300
> Subject: [PATCH 01/13] dshow: factorise cycling through devices
> 
> ---
>  libavdevice/dshow.c |   53 +++++++++++++++++++++++++++++++++++++-------------
>  1 files changed, 39 insertions(+), 14 deletions(-)
> 
> diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> index 10e3d4f..025237d 100644
> --- a/libavdevice/dshow.c
> +++ b/libavdevice/dshow.c
> @@ -213,36 +213,32 @@ fail:
>      return;
>  }
>  
> +/**
> + * Cycle through available devices using the device enumerator devenum,
> + * retrieve the device with type specified by devtype and return the
> + * pointer to the object found in *pfilter.
> + */
>  static int
> -dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
> -                  enum dshowDeviceType devtype)
> +dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
> +                    enum dshowDeviceType devtype, IBaseFilter **pfilter)
>  {
>      struct dshow_ctx *ctx = avctx->priv_data;
>      IBaseFilter *device_filter = NULL;
>      IEnumMoniker *classenum = NULL;
> -    IGraphBuilder *graph = ctx->graph;
> -    IEnumPins *pins = 0;
>      IMoniker *m = NULL;
> -    IPin *device_pin = NULL;
> -    libAVPin *capture_pin = NULL;
> -    libAVFilter *capture_filter = NULL;
>      const char *device_name = ctx->device_name[devtype];
> -    int ret = AVERROR(EIO);
> -    IPin *pin;
>      int r;
>  
>      const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,
>                                     &CLSID_AudioInputDeviceCategory };
> -    const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
>      const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
> -    const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
>  
>      r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[devtype],
>                                               (IEnumMoniker **) &classenum, 0);
>      if (r != S_OK) {
>          av_log(avctx, AV_LOG_ERROR, "Could not enumerate %s devices.\n",
>                 devtypename);
> -        goto error;
> +        return AVERROR(EIO);
>      }
>  
>      while (IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK && !device_filter) {
> @@ -274,11 +270,42 @@ fail1:
>          IMoniker_Release(m);
>      }
>  
> +    IEnumMoniker_Release(classenum);
> +
>      if (!device_filter) {
>          av_log(avctx, AV_LOG_ERROR, "Could not find %s device.\n",
>                 devtypename);
> +        return AVERROR(EIO);
> +    }
> +    *pfilter = device_filter;
> +
> +    return 0;
> +}
> +
> +static int
> +dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
> +                  enum dshowDeviceType devtype)
> +{
> +    struct dshow_ctx *ctx = avctx->priv_data;
> +    IBaseFilter *device_filter = NULL;
> +    IGraphBuilder *graph = ctx->graph;
> +    IEnumPins *pins = 0;
> +    IPin *device_pin = NULL;
> +    libAVPin *capture_pin = NULL;
> +    libAVFilter *capture_filter = NULL;
> +    int ret = AVERROR(EIO);
> +    IPin *pin;
> +    int r;
> +
> +    const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
> +    const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
> +    const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
> +
> +    if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0) {
> +        ret = r;
>          goto error;
>      }
> +
>      ctx->device_filter [devtype] = device_filter;
>  
>      r = IGraphBuilder_AddFilter(graph, device_filter, NULL);
> @@ -371,8 +398,6 @@ next:
>  error:
>      if (pins)
>          IEnumPins_Release(pins);
> -    if (classenum)
> -        IEnumMoniker_Release(classenum);
>  
>      return ret;
>  }
> -- 
> 1.7.4.1

Looks fine. 

> From 4082d1d159feaabf0d3ef2ee8645e7440db80a2d Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:09:23 -0300
> Subject: [PATCH 02/13] dshow: add option to list devices
> 
> ---
>  libavdevice/dshow.c |   41 ++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 40 insertions(+), 1 deletions(-)
> 
> diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> index 025237d..2c298b2 100644
> --- a/libavdevice/dshow.c
> +++ b/libavdevice/dshow.c
> @@ -19,14 +19,20 @@
>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>   */
>  
> +#include "libavutil/opt.h"
> +
>  #include "avdevice.h"
>  #include "dshow.h"
>  
>  struct dshow_ctx {
> +    const AVClass *class;
> +
>      IGraphBuilder *graph;
>  
>      char *device_name[2];
>  
> +    int   list_devices;
> +
>      IBaseFilter *device_filter[2];
>      IPin        *device_pin[2];
>      libAVFilter *capture_filter[2];
> @@ -217,6 +223,7 @@ fail:
>   * Cycle through available devices using the device enumerator devenum,
>   * retrieve the device with type specified by devtype and return the
>   * pointer to the object found in *pfilter.
> + * If pfilter is NULL, list all device names.
>   */
>  static int
>  dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
> @@ -257,10 +264,14 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
>  
>          buf = dup_wchar_to_utf8(var.bstrVal);
>  
> +        if (pfilter) {
>          if (strcmp(device_name, buf))
>              goto fail1;
>  
>          IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter);
> +        } else {
> +            av_log(avctx, AV_LOG_INFO, " \"%s\"\n", buf);
> +        }
>  
>  fail1:
>          if (buf)
> @@ -272,12 +283,14 @@ fail1:
>  
>      IEnumMoniker_Release(classenum);
>  
> +    if (pfilter) {
>      if (!device_filter) {
>          av_log(avctx, AV_LOG_ERROR, "Could not find %s device.\n",
>                 devtypename);
>          return AVERROR(EIO);
>      }
>      *pfilter = device_filter;
> +    }
>  
>      return 0;
>  }
> @@ -555,7 +568,7 @@ static int dshow_read_header(AVFormatContext *avctx, AVFormatParameters *ap)
>      int ret = AVERROR(EIO);
>      int r;
>  
> -    if (!parse_device_name(avctx)) {
> +    if (!ctx->list_devices && !parse_device_name(avctx)) {
>          av_log(avctx, AV_LOG_ERROR, "Malformed dshow input string.\n");
>          goto error;
>      }
> @@ -577,6 +590,15 @@ static int dshow_read_header(AVFormatContext *avctx, AVFormatParameters *ap)
>          goto error;
>      }
>  
> +    if (ctx->list_devices) {
> +        av_log(avctx, AV_LOG_INFO, "DirectShow video devices\n");
> +        dshow_cycle_devices(avctx, devenum, VideoDevice, NULL);
> +        av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n");
> +        dshow_cycle_devices(avctx, devenum, AudioDevice, NULL);
> +        ret = AVERROR_EXIT;
> +        goto error;
> +    }
> +
>      if (ctx->device_name[VideoDevice]) {
>          ret = dshow_open_device(avctx, devenum, VideoDevice);
>          if (ret < 0)
> @@ -664,6 +686,22 @@ static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt)
>      return pkt->size;
>  }
>  
> +#define OFFSET(x) offsetof(struct dshow_ctx, x)
> +#define DEC AV_OPT_FLAG_DECODING_PARAM
> +static const AVOption options[] = {
> +    { "list_devices", "list available devices", OFFSET(list_devices), FF_OPT_TYPE_INT, {.dbl=0}, 0, 1, DEC, "list_devices" },
> +    { "true", "", 0, FF_OPT_TYPE_CONST, {.dbl=1}, 0, 0, DEC, "list_devices" },
> +    { "false", "", 0, FF_OPT_TYPE_CONST, {.dbl=0}, 0, 0, DEC, "list_devices" },
> +    { NULL },
> +};
> +
> +static const AVClass dshow_class = {
> +    .class_name = "DirectShow indev",
> +    .item_name  = av_default_item_name,
> +    .option     = options,
> +    .version    = LIBAVUTIL_VERSION_INT,
> +};
> +
>  AVInputFormat ff_dshow_demuxer = {
>      "dshow",
>      NULL_IF_CONFIG_SMALL("DirectShow capture"),
> @@ -673,4 +711,5 @@ AVInputFormat ff_dshow_demuxer = {
>      dshow_read_packet,
>      dshow_read_close,
>      .flags = AVFMT_NOFILE,
> +    .priv_class = &dshow_class,
>  };
> -- 
> 1.7.4.1

Looks fine. 

> From 2092ce8fd6d2b86d4cca94d2f5e4b97dd7edcb0f Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:09:42 -0300
> Subject: [PATCH 03/13] dshow: indent

Should be OK.

> From dfda276cd1458fbd9409dd7284ada7c97ac734bb Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:10:07 -0300
> Subject: [PATCH 04/13] dshow: factorise cycling through pins
> 
> ---
>  libavdevice/dshow.c |   73 ++++++++++++++++++++++++++++++++------------------
>  1 files changed, 47 insertions(+), 26 deletions(-)
> 
> diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> index 7035337..a64e645 100644
> --- a/libavdevice/dshow.c
> +++ b/libavdevice/dshow.c
> @@ -295,42 +295,27 @@ fail1:
>      return 0;
>  }
>  
> +/**
> + * Cycle through available pins using the device_filter device, retrieve
> + * the first output pin and return the pointer to the object found in
> + * *ppin.
> + */

Please also mention the devtype parameter: maybe something like:

|retrieve the first output pin with media type specified by devtype,
|and return ...

>  static int
> -dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
> -                  enum dshowDeviceType devtype)
> +dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
> +                 IBaseFilter *device_filter, IPin **ppin)
>  {
> -    struct dshow_ctx *ctx = avctx->priv_data;
> -    IBaseFilter *device_filter = NULL;
> -    IGraphBuilder *graph = ctx->graph;
>      IEnumPins *pins = 0;
>      IPin *device_pin = NULL;
> -    libAVPin *capture_pin = NULL;
> -    libAVFilter *capture_filter = NULL;
> -    int ret = AVERROR(EIO);
>      IPin *pin;
>      int r;
>  
>      const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
>      const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
> -    const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
> -
> -    if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0) {
> -        ret = r;
> -        goto error;
> -    }
> -
> -    ctx->device_filter [devtype] = device_filter;
> -
> -    r = IGraphBuilder_AddFilter(graph, device_filter, NULL);
> -    if (r != S_OK) {
> -        av_log(avctx, AV_LOG_ERROR, "Could not add device filter to graph.\n");
> -        goto error;
> -    }
>  
>      r = IBaseFilter_EnumPins(device_filter, &pins);
>      if (r != S_OK) {
>          av_log(avctx, AV_LOG_ERROR, "Could not enumerate pins.\n");
> -        goto error;
> +        return AVERROR(EIO);
>      }
>  
>      while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK && !device_pin) {
> @@ -375,9 +360,48 @@ next:
>              IPin_Release(pin);
>      }
>  
> +    IEnumPins_Release(pins);
> +
>      if (!device_pin) {
>          av_log(avctx, AV_LOG_ERROR,
>                 "Could not find output pin from %s capture device.\n", devtypename);
> +        return AVERROR(EIO);
> +    }
> +    *ppin = device_pin;
> +
> +    return 0;
> +}
> +
> +static int
> +dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
> +                  enum dshowDeviceType devtype)
> +{
> +    struct dshow_ctx *ctx = avctx->priv_data;
> +    IBaseFilter *device_filter = NULL;
> +    IGraphBuilder *graph = ctx->graph;
> +    IPin *device_pin = NULL;
> +    libAVPin *capture_pin = NULL;
> +    libAVFilter *capture_filter = NULL;
> +    int ret = AVERROR(EIO);
> +    int r;
> +
> +    const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
> +
> +    if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0) {
> +        ret = r;
> +        goto error;
> +    }
> +
> +    ctx->device_filter [devtype] = device_filter;
> +
> +    r = IGraphBuilder_AddFilter(graph, device_filter, NULL);
> +    if (r != S_OK) {
> +        av_log(avctx, AV_LOG_ERROR, "Could not add device filter to graph.\n");
> +        goto error;
> +    }
> +
> +    if ((r = dshow_cycle_pins(avctx, devtype, device_filter, &device_pin)) < 0) {
> +        ret = r;
>          goto error;
>      }
>      ctx->device_pin[devtype] = device_pin;
> @@ -409,9 +433,6 @@ next:
>      ret = 0;
>  
>  error:
> -    if (pins)
> -        IEnumPins_Release(pins);
> -
>      return ret;
>  }
>  
> -- 
> 1.7.4.1

Looks nice otherwise. 


> From dedda404994e03afe48df3d876aa688839673657 Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:10:22 -0300
> Subject: [PATCH 05/13] dshow: initialize variable to prevent releasing random data
> 
> ---
>  libavdevice/dshow.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> index a64e645..fe1598a 100644
> --- a/libavdevice/dshow.c
> +++ b/libavdevice/dshow.c
> @@ -320,7 +320,7 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
>  
>      while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK && !device_pin) {
>          IKsPropertySet *p = NULL;
> -        IEnumMediaTypes *types;
> +        IEnumMediaTypes *types = NULL;
>          PIN_INFO info = {0};
>          AM_MEDIA_TYPE *type;
>          GUID category;
> -- 
> 1.7.4.1

FineOfCourse.

> From 986ff7585bbb6485e00eb9f6085e6f6e2cb7cfde Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:12:42 -0300
> Subject: [PATCH 06/13] dshow: add audio/video options
> 
> ---
>  libavdevice/dshow.c        |  159 ++++++++++++++++++++++++++++++++++++++++++++
>  libavdevice/dshow.h        |    2 +
>  libavdevice/dshow_common.c |   49 ++++++++++++++
>  3 files changed, 210 insertions(+), 0 deletions(-)
> 
> diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> index fe1598a..9159ba6 100644
> --- a/libavdevice/dshow.c
> +++ b/libavdevice/dshow.c
> @@ -19,6 +19,7 @@
>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>   */
>  
> +#include "libavutil/parseutils.h"
>  #include "libavutil/opt.h"
>  
>  #include "avdevice.h"
> @@ -46,6 +47,17 @@ struct dshow_ctx {
>      unsigned int video_frame_num;
>  
>      IMediaControl *control;
> +
> +    char *video_size;
> +    char *framerate;
> +
> +    int requested_width;
> +    int requested_height;
> +    AVRational requested_framerate;
> +
> +    int sample_rate;
> +    int sample_size;
> +    int channels;
>  };
>  
>  static enum PixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
> @@ -296,6 +308,117 @@ fail1:
>  }
>  

>  /**
> + * Cycle through available formats using the specified pin,
> + * try to set parameters specified through AVOptions and if successful
> + * return 1 in *pformat_set.
> + */
> +static void
> +dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
> +                    IPin *pin, AM_MEDIA_TYPE *type, int *pformat_set)
> +{

Please also document what AM_MEDIA_TYPE type is good for.

> +    struct dshow_ctx *ctx = avctx->priv_data;
> +    IAMStreamConfig *config = NULL;
> +    int format_set = 0;
> +    void *caps = NULL;
> +    int i, n, size;
> +
> +    if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
> +        return;
> +    if (IAMStreamConfig_GetNumberOfCapabilities(config, &n, &size) != S_OK)
> +        goto end;
> +
> +    caps = av_malloc(size);
> +    if (!caps)
> +        goto end;
> +
> +    for (i = 0; i < n && !format_set; i++) {
> +        IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps);
> +
> +#if DSHOWDEBUG
> +        ff_print_AM_MEDIA_TYPE(type);
> +#endif
> +
> +        if (devtype == VideoDevice) {
> +            VIDEO_STREAM_CONFIG_CAPS *vcaps = caps;
> +            BITMAPINFOHEADER *bih;
> +            int64_t *fr;
> +#if DSHOWDEBUG
> +            ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps);
> +#endif
> +            if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) {
> +                VIDEOINFOHEADER *v = (void *) type->pbFormat;
> +                fr = &v->AvgTimePerFrame;
> +                bih = &v->bmiHeader;
> +            } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) {
> +                VIDEOINFOHEADER2 *v = (void *) type->pbFormat;
> +                fr = &v->AvgTimePerFrame;
> +                bih = &v->bmiHeader;
> +            } else {
> +                goto next;
> +            }

> +            if (ctx->framerate) {
> +                int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000)
> +                                            /  ctx->requested_framerate.num;
> +                if (framerate > vcaps->MaxFrameInterval ||
> +                    framerate < vcaps->MinFrameInterval)
> +                    goto next;
> +                *fr = framerate;
> +            }
> +            if (ctx->video_size) {
> +                if (ctx->requested_width  > vcaps->MaxOutputSize.cx ||
> +                    ctx->requested_width  < vcaps->MinOutputSize.cx ||
> +                    ctx->requested_height > vcaps->MaxOutputSize.cy ||
> +                    ctx->requested_height < vcaps->MinOutputSize.cy)
> +                    goto next;
> +                bih->biWidth  = ctx->requested_width;
> +                bih->biHeight = ctx->requested_height;
> +            }

Note: in case framerate is set and video_size is invalid, framerate is
set but then code fails and goes to the next capability, not sure this
is a problem though. Maybe you may set both fr and bih only when both
checks have been passed.

> +        } else {
> +            AUDIO_STREAM_CONFIG_CAPS *acaps = caps;
> +            WAVEFORMATEX *fx;
> +#if DSHOWDEBUG
> +            ff_print_AUDIO_STREAM_CONFIG_CAPS(acaps);
> +#endif
> +            if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) {
> +                fx = (void *) type->pbFormat;
> +            } else {
> +                goto next;
> +            }

> +            if (ctx->sample_rate) {
> +                if (ctx->sample_rate > acaps->MaximumSampleFrequency ||
> +                    ctx->sample_rate < acaps->MinimumSampleFrequency)
> +                    goto next;
> +                fx->nSamplesPerSec = ctx->sample_rate;
> +            }
> +            if (ctx->sample_size) {
> +                if (ctx->sample_size > acaps->MaximumBitsPerSample ||
> +                    ctx->sample_size < acaps->MinimumBitsPerSample)
> +                    goto next;
> +                fx->wBitsPerSample = ctx->sample_size;
> +            }
> +            if (ctx->channels) {
> +                if (ctx->channels > acaps->MaximumChannels ||
> +                    ctx->channels < acaps->MinimumChannels)
> +                    goto next;
> +                fx->nChannels = ctx->channels;
> +            }

Same consideration here.

> +        }
> +        if (IAMStreamConfig_SetFormat(config, type) != S_OK)
> +            goto next;
> +        format_set = 1;
> +next:
> +        if (type->pbFormat)
> +            CoTaskMemFree(type->pbFormat);
> +        CoTaskMemFree(type);
> +    }
> +end:
> +    IAMStreamConfig_Release(config);
> +    if (caps)
> +        av_free(caps);
> +    *pformat_set = format_set;
> +}
> +
> +/**
>   * Cycle through available pins using the device_filter device, retrieve
>   * the first output pin and return the pointer to the object found in
>   * *ppin.
> @@ -304,6 +427,7 @@ static int
>  dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
>                   IBaseFilter *device_filter, IPin **ppin)
>  {
> +    struct dshow_ctx *ctx = avctx->priv_data;
>      IEnumPins *pins = 0;
>      IPin *device_pin = NULL;
>      IPin *pin;
> @@ -312,6 +436,10 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
>      const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
>      const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
>  
> +    int set_format = (devtype == VideoDevice && (ctx->video_size || ctx->framerate))
> +                  || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate));
> +    int format_set = 0;
> +
>      r = IBaseFilter_EnumPins(device_filter, &pins);
>      if (r != S_OK) {
>          av_log(avctx, AV_LOG_ERROR, "Could not enumerate pins.\n");
> @@ -339,6 +467,13 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
>          if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
>              goto next;
>  
> +        if (set_format) {
> +            dshow_cycle_formats(avctx, devtype, pin, type, &format_set);
> +            if (!format_set) {
> +                goto next;
> +            }
> +        }
> +
>          if (IPin_EnumMediaTypes(pin, &types) != S_OK)
>              goto next;
>  
> @@ -362,6 +497,10 @@ next:
>  
>      IEnumPins_Release(pins);
>  
> +    if (set_format && !format_set) {
> +        av_log(avctx, AV_LOG_ERROR, "Could not set %s options\n", devtypename);
> +        return AVERROR(EIO);
> +    }
>      if (!device_pin) {
>          av_log(avctx, AV_LOG_ERROR,
>                 "Could not find output pin from %s capture device.\n", devtypename);
> @@ -594,6 +733,21 @@ static int dshow_read_header(AVFormatContext *avctx, AVFormatParameters *ap)
>          goto error;
>      }
>  
> +    if (ctx->video_size) {
> +        r = av_parse_video_size(&ctx->requested_width, &ctx->requested_height, ctx->video_size);

> +        if (r < 0) {
> +            av_log(avctx, AV_LOG_ERROR, "Couldn't parse video size.\n");
> +            goto error;
> +        }

nit: "Could not parse video size '%s'.\n"

Rationale: contractions are better avoided (easier on non fluent
readers), pointing the invalid string improves feedback.

> +    }
> +    if (ctx->framerate) {
> +        r = av_parse_video_rate(&ctx->requested_framerate, ctx->framerate);
> +        if (r < 0) {
> +            av_log(avctx, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", ctx->framerate);
> +            goto error;
> +        }
> +    }
> +
>      CoInitialize(0);
>  
>      r = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
> @@ -710,6 +864,11 @@ static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt)
>  #define OFFSET(x) offsetof(struct dshow_ctx, x)
>  #define DEC AV_OPT_FLAG_DECODING_PARAM
>  static const AVOption options[] = {
> +    { "video_size", "set video size given a string such as 640x480 or hd720.", OFFSET(video_size), FF_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
> +    { "framerate", "set video frame rate", OFFSET(framerate), FF_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
> +    { "sample_rate", "set audio sample rate, such as 8000 or 44100", OFFSET(sample_rate), FF_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
> +    { "sample_size", "set audio sample size, such as 8 or 16", OFFSET(sample_size), FF_OPT_TYPE_INT, {.dbl = 0}, 0, 16, DEC },
> +    { "channels", "set number of audio channels, such as 1 or 2", OFFSET(channels), FF_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
>      { "list_devices", "list available devices", OFFSET(list_devices), FF_OPT_TYPE_INT, {.dbl=0}, 0, 1, DEC, "list_devices" },
>      { "true", "", 0, FF_OPT_TYPE_CONST, {.dbl=1}, 0, 0, DEC, "list_devices" },
>      { "false", "", 0, FF_OPT_TYPE_CONST, {.dbl=0}, 0, 0, DEC, "list_devices" },
> diff --git a/libavdevice/dshow.h b/libavdevice/dshow.h
> index 4e79680..83c71c4 100644
> --- a/libavdevice/dshow.h
> +++ b/libavdevice/dshow.h
> @@ -29,6 +29,8 @@
>  #include <dvdmedia.h>
>  
>  long ff_copy_dshow_media_type(AM_MEDIA_TYPE *dst, const AM_MEDIA_TYPE *src);
> +void ff_print_VIDEO_STREAM_CONFIG_CAPS(const VIDEO_STREAM_CONFIG_CAPS *caps);
> +void ff_print_AUDIO_STREAM_CONFIG_CAPS(const AUDIO_STREAM_CONFIG_CAPS *caps);
>  void ff_print_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *type);
>  void ff_printGUID(const GUID *g);
>  
> diff --git a/libavdevice/dshow_common.c b/libavdevice/dshow_common.c
> index c813dc1..8fe2f77 100644
> --- a/libavdevice/dshow_common.c
> +++ b/libavdevice/dshow_common.c
> @@ -82,6 +82,55 @@ static void dump_bih(void *s, BITMAPINFOHEADER *bih)
>  }
>  #endif
>  
> +void ff_print_VIDEO_STREAM_CONFIG_CAPS(const VIDEO_STREAM_CONFIG_CAPS *caps)
> +{
> +#if DSHOWDEBUG
> +    dshowdebug(" VIDEO_STREAM_CONFIG_CAPS\n");
> +    dshowdebug("  guid\t");
> +    ff_printGUID(&caps->guid);
> +    dshowdebug("\n");
> +    dshowdebug("  VideoStandard\t%lu\n", caps->VideoStandard);
> +    dshowdebug("  InputSize %ld\t%ld\n", caps->InputSize.cx, caps->InputSize.cy);
> +    dshowdebug("  MinCroppingSize %ld\t%ld\n", caps->MinCroppingSize.cx, caps->MinCroppingSize.cy);
> +    dshowdebug("  MaxCroppingSize %ld\t%ld\n", caps->MaxCroppingSize.cx, caps->MaxCroppingSize.cy);
> +    dshowdebug("  CropGranularityX\t%d\n", caps->CropGranularityX);
> +    dshowdebug("  CropGranularityY\t%d\n", caps->CropGranularityY);
> +    dshowdebug("  CropAlignX\t%d\n", caps->CropAlignX);
> +    dshowdebug("  CropAlignY\t%d\n", caps->CropAlignY);
> +    dshowdebug("  MinOutputSize %ld\t%ld\n", caps->MinOutputSize.cx, caps->MinOutputSize.cy);
> +    dshowdebug("  MaxOutputSize %ld\t%ld\n", caps->MaxOutputSize.cx, caps->MaxOutputSize.cy);
> +    dshowdebug("  OutputGranularityX\t%d\n", caps->OutputGranularityX);
> +    dshowdebug("  OutputGranularityY\t%d\n", caps->OutputGranularityY);
> +    dshowdebug("  StretchTapsX\t%d\n", caps->StretchTapsX);
> +    dshowdebug("  StretchTapsY\t%d\n", caps->StretchTapsY);
> +    dshowdebug("  ShrinkTapsX\t%d\n", caps->ShrinkTapsX);
> +    dshowdebug("  ShrinkTapsY\t%d\n", caps->ShrinkTapsY);
> +    dshowdebug("  MinFrameInterval\t%"PRId64"\n", caps->MinFrameInterval);
> +    dshowdebug("  MaxFrameInterval\t%"PRId64"\n", caps->MaxFrameInterval);
> +    dshowdebug("  MinBitsPerSecond\t%ld\n", caps->MinBitsPerSecond);
> +    dshowdebug("  MaxBitsPerSecond\t%ld\n", caps->MaxBitsPerSecond);
> +#endif
> +}
> +
> +void ff_print_AUDIO_STREAM_CONFIG_CAPS(const AUDIO_STREAM_CONFIG_CAPS *caps)
> +{
> +#if DSHOWDEBUG
> +    dshowdebug(" AUDIO_STREAM_CONFIG_CAPS\n");
> +    dshowdebug("  guid\t");
> +    ff_printGUID(&caps->guid);
> +    dshowdebug("\n");
> +    dshowdebug("  MinimumChannels\t%lu\n", caps->MinimumChannels);
> +    dshowdebug("  MaximumChannels\t%lu\n", caps->MaximumChannels);
> +    dshowdebug("  ChannelsGranularity\t%lu\n", caps->ChannelsGranularity);
> +    dshowdebug("  MinimumBitsPerSample\t%lu\n", caps->MinimumBitsPerSample);
> +    dshowdebug("  MaximumBitsPerSample\t%lu\n", caps->MaximumBitsPerSample);
> +    dshowdebug("  BitsPerSampleGranularity\t%lu\n", caps->BitsPerSampleGranularity);
> +    dshowdebug("  MinimumSampleFrequency\t%lu\n", caps->MinimumSampleFrequency);
> +    dshowdebug("  MaximumSampleFrequency\t%lu\n", caps->MaximumSampleFrequency);
> +    dshowdebug("  SampleFrequencyGranularity\t%lu\n", caps->SampleFrequencyGranularity);
> +#endif
> +}

Unrelated: this use of dshowdebug() is a bit weird, maybe you may
replace DSHOWDEBUG -> DEBUG, and dshowdebug() with av_dlog().

>  void ff_print_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *type)
>  {
>  #if DSHOWDEBUG
> -- 
> 1.7.4.1

Looks fine otherwise. 

> From fbbbd88514c18e89fd72f20df8180f0f3251350b Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:15:14 -0300
> Subject: [PATCH 07/13] dshow: add option to list audio/video options
> 
> ---
>  libavdevice/dshow.c |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 57 insertions(+), 0 deletions(-)
> 
> diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> index 9159ba6..d46f14e 100644
> --- a/libavdevice/dshow.c
> +++ b/libavdevice/dshow.c
> @@ -32,6 +32,7 @@ struct dshow_ctx {
>  
>      char *device_name[2];
>  
> +    int   list_options;
>      int   list_devices;
>  
>      IBaseFilter *device_filter[2];
> @@ -311,6 +312,7 @@ fail1:
>   * Cycle through available formats using the specified pin,
>   * try to set parameters specified through AVOptions and if successful
>   * return 1 in *pformat_set.
> + * If pformat_set is NULL, list all pin capabilities.
>   */
>  static void
>  dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
> @@ -356,6 +358,14 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
>              } else {
>                  goto next;
>              }
> +            if (!pformat_set) {
> +                av_log(avctx, AV_LOG_INFO, "  min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n",
> +                       vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
> +                       1e7 / vcaps->MinFrameInterval,
> +                       vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,
> +                       1e7 / vcaps->MaxFrameInterval);
> +                continue;
> +            }
>              if (ctx->framerate) {
>                  int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000)
>                                              /  ctx->requested_framerate.num;
> @@ -384,6 +394,12 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
>              } else {
>                  goto next;
>              }
> +            if (!pformat_set) {
> +                av_log(avctx, AV_LOG_INFO, "  min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n",
> +                       acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency,
> +                       acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency);
> +                continue;
> +            }
>              if (ctx->sample_rate) {
>                  if (ctx->sample_rate > acaps->MaximumSampleFrequency ||
>                      ctx->sample_rate < acaps->MinimumSampleFrequency)
> @@ -415,6 +431,7 @@ end:
>      IAMStreamConfig_Release(config);
>      if (caps)
>          av_free(caps);
> +    if (pformat_set)
>      *pformat_set = format_set;
>  }
>  
> @@ -422,6 +439,7 @@ end:
>   * Cycle through available pins using the device_filter device, retrieve
>   * the first output pin and return the pointer to the object found in
>   * *ppin.
> + * If ppin is NULL, cycle through all pins listing audio/video capabilities.
>   */
>  static int
>  dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
> @@ -446,6 +464,10 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
>          return AVERROR(EIO);
>      }
>  
> +    if (!ppin) {
> +        av_log(avctx, AV_LOG_INFO, "DirectShow %s device options\n",
> +               devtypename);
> +    }
>      while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK && !device_pin) {
>          IKsPropertySet *p = NULL;
>          IEnumMediaTypes *types = NULL;
> @@ -467,6 +489,13 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
>          if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
>              goto next;
>  
> +        if (!ppin) {
> +            char *buf = dup_wchar_to_utf8(info.achName);
> +            av_log(avctx, AV_LOG_INFO, " Pin \"%s\"\n", buf);
> +            av_free(buf);
> +            dshow_cycle_formats(avctx, devtype, pin, type, NULL);
> +            goto next;
> +        }
>          if (set_format) {
>              dshow_cycle_formats(avctx, devtype, pin, type, &format_set);
>              if (!format_set) {
> @@ -497,6 +526,7 @@ next:
>  
>      IEnumPins_Release(pins);
>  
> +    if (ppin) {
>      if (set_format && !format_set) {
>          av_log(avctx, AV_LOG_ERROR, "Could not set %s options\n", devtypename);
>          return AVERROR(EIO);
> @@ -507,6 +537,22 @@ next:
>          return AVERROR(EIO);
>      }
>      *ppin = device_pin;
> +    }
> +
> +    return 0;
> +}
> +
> +static int
> +dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum,
> +                          enum dshowDeviceType devtype)
> +{
> +    IBaseFilter *device_filter = NULL;
> +    int r;
> +
> +    if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0)
> +        return r;
> +    if ((r = dshow_cycle_pins(avctx, devtype, device_filter, NULL)) < 0)
> +        return r;
>  
>      return 0;
>  }
> @@ -773,6 +819,14 @@ static int dshow_read_header(AVFormatContext *avctx, AVFormatParameters *ap)
>          ret = AVERROR_EXIT;
>          goto error;
>      }
> +    if (ctx->list_options) {
> +        if (ctx->device_name[VideoDevice])
> +            dshow_list_device_options(avctx, devenum, VideoDevice);
> +        if (ctx->device_name[AudioDevice])
> +            dshow_list_device_options(avctx, devenum, AudioDevice);
> +        ret = AVERROR_EXIT;
> +        goto error;
> +    }
>  
>      if (ctx->device_name[VideoDevice]) {
>          ret = dshow_open_device(avctx, devenum, VideoDevice);
> @@ -872,6 +926,9 @@ static const AVOption options[] = {
>      { "list_devices", "list available devices", OFFSET(list_devices), FF_OPT_TYPE_INT, {.dbl=0}, 0, 1, DEC, "list_devices" },
>      { "true", "", 0, FF_OPT_TYPE_CONST, {.dbl=1}, 0, 0, DEC, "list_devices" },
>      { "false", "", 0, FF_OPT_TYPE_CONST, {.dbl=0}, 0, 0, DEC, "list_devices" },
> +    { "list_options", "list available options for specified device", OFFSET(list_options), FF_OPT_TYPE_INT, {.dbl=0}, 0, 1, DEC, "list_options" },
> +    { "true", "", 0, FF_OPT_TYPE_CONST, {.dbl=1}, 0, 0, DEC, "list_options" },
> +    { "false", "", 0, FF_OPT_TYPE_CONST, {.dbl=0}, 0, 0, DEC, "list_options" },
>      { NULL },
>  };

Looks fine to me.


> -- 
> 1.7.4.1
> 

> From fa840689dbbc0f91b1e52304fd25f7c6bb3a51b0 Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:15:22 -0300
> Subject: [PATCH 08/13] dshow: indent
[...]

> From 6dc357c10df32e16ee70f02963546b24a7b55359 Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:15:41 -0300
> Subject: [PATCH 09/13] doc: add documentation for dshow indev
> 
> ---
>  doc/indevs.texi |   77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 77 insertions(+), 0 deletions(-)

This was already reviewed/approved by me.

> From f4b81cb7fde769552ee26528c6ae83b8899c35a0 Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:15:54 -0300
> Subject: [PATCH 10/13] dshow: release pin on disconnect
> 
> ---
>  libavdevice/dshow_pin.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c
> index f31ecc6..5e14108 100644
> --- a/libavdevice/dshow_pin.c
> +++ b/libavdevice/dshow_pin.c
> @@ -73,6 +73,7 @@ libAVPin_Disconnect(libAVPin *this)
>          return VFW_E_NOT_STOPPED;
>      if (!this->connectedto)
>          return S_FALSE;
> +    IPin_Release(this->connectedto);
>      this->connectedto = NULL;
>  
>      return S_OK;
> -- 
> 1.7.4.1

I trust you this is correct.

> From 3e405fb74a1bfa2eaff677ea85712e0d4ba14464 Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:16:06 -0300
> Subject: [PATCH 11/13] dshow: cleanup filters and pins on capture interface
> 
> ---
>  libavdevice/dshow_enumpins.c |    8 +++++++-
>  libavdevice/dshow_filter.c   |    8 +++++++-
>  2 files changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/libavdevice/dshow_enumpins.c b/libavdevice/dshow_enumpins.c
> index 97890fb..02e967a 100644
> --- a/libavdevice/dshow_enumpins.c
> +++ b/libavdevice/dshow_enumpins.c
> @@ -94,6 +94,12 @@ libAVEnumPins_Setup(libAVEnumPins *this, libAVPin *pin, libAVFilter *filter)
>  
>      return 1;
>  }
> +static int
> +libAVEnumPins_Cleanup(libAVEnumPins *this)
> +{
> +    libAVFilter_Release(this->filter);
> +    return 1;
> +}
>  DECLARE_CREATE(libAVEnumPins, libAVEnumPins_Setup(this, pin, filter),
>                 libAVPin *pin, libAVFilter *filter)
> -DECLARE_DESTROY(libAVEnumPins, nothing)
> +DECLARE_DESTROY(libAVEnumPins, libAVEnumPins_Cleanup)
> diff --git a/libavdevice/dshow_filter.c b/libavdevice/dshow_filter.c
> index e5a3be8..64e8306 100644
> --- a/libavdevice/dshow_filter.c
> +++ b/libavdevice/dshow_filter.c
> @@ -191,6 +191,12 @@ libAVFilter_Setup(libAVFilter *this, void *priv_data, void *callback,
>  
>      return 1;
>  }
> +static int
> +libAVFilter_Cleanup(libAVFilter *this)
> +{
> +    libAVPin_Release(this->pin);
> +    return 1;
> +}
>  DECLARE_CREATE(libAVFilter, libAVFilter_Setup(this, priv_data, callback, type),
>                 void *priv_data, void *callback, enum dshowDeviceType type)
> -DECLARE_DESTROY(libAVFilter, nothing)
> +DECLARE_DESTROY(libAVFilter, libAVFilter_Cleanup)
> -- 
> 1.7.4.1

OK, I tried to understand the code in dshow* but this is beyond my
capabilities without a serious study, but I trust you on this (well
you're the supposed dshow maintainer afterall). If you can say a few
words about how all this is supposed to work that would be helpful.


> From 799497f89385a583038d0ac65a2160f561a15de7 Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:16:17 -0300
> Subject: [PATCH 12/13] dshow: invert condition to avoid leaking objects
> 
> ---
>  libavdevice/dshow.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> index 79c91b6..d830786 100644
> --- a/libavdevice/dshow.c
> +++ b/libavdevice/dshow.c
> @@ -261,7 +261,7 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
>          return AVERROR(EIO);
>      }
>  
> -    while (IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK && !device_filter) {
> +    while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) {
>          IPropertyBag *bag = NULL;
>          char *buf = NULL;
>          VARIANT var;
> @@ -468,7 +468,7 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
>          av_log(avctx, AV_LOG_INFO, "DirectShow %s device options\n",
>                 devtypename);
>      }
> -    while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK && !device_pin) {
> +    while (!device_pin && IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) {
>          IKsPropertySet *p = NULL;
>          IEnumMediaTypes *types = NULL;
>          PIN_INFO info = {0};
> @@ -507,7 +507,7 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
>              goto next;
>  
>          IEnumMediaTypes_Reset(types);
> -        while (IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK && !device_pin) {
> +        while (!device_pin && IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) {
>              if (IsEqualGUID(&type->majortype, mediatype[devtype])) {
>                  device_pin = pin;
>                  goto next;
> -- 
> 1.7.4.1

Makes sense.

> From e880c249258b24fb4455e2b3ac14f834394ae734 Mon Sep 17 00:00:00 2001
> From: Ramiro Polla <ramiro.polla at gmail.com>
> Date: Fri, 9 Sep 2011 00:16:28 -0300
> Subject: [PATCH 13/13] dshow: remove filters directly instead of enumerating them first
> 
> ---
>  libavdevice/dshow.c |   26 ++++++++++++--------------
>  1 files changed, 12 insertions(+), 14 deletions(-)
> 
> diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> index d830786..be194cb 100644
> --- a/libavdevice/dshow.c
> +++ b/libavdevice/dshow.c
> @@ -112,6 +112,18 @@ dshow_read_close(AVFormatContext *s)
>          IMediaControl_Release(ctx->control);
>      }
>  
> +    if (ctx->graph) {
> +        if (ctx->capture_filter[VideoDevice])
> +            IGraphBuilder_RemoveFilter(ctx->graph, (IBaseFilter *) ctx->capture_filter[VideoDevice]);
> +        if (ctx->capture_filter[AudioDevice])
> +            IGraphBuilder_RemoveFilter(ctx->graph, (IBaseFilter *) ctx->capture_filter[AudioDevice]);
> +        if (ctx->device_filter[VideoDevice])
> +            IGraphBuilder_RemoveFilter(ctx->graph, ctx->device_filter[VideoDevice]);
> +        if (ctx->device_filter[AudioDevice])
> +            IGraphBuilder_RemoveFilter(ctx->graph, ctx->device_filter[AudioDevice]);
> +        IGraphBuilder_Release(ctx->graph);
> +    }
> +
>      if (ctx->capture_pin[VideoDevice])
>          libAVPin_Release(ctx->capture_pin[VideoDevice]);
>      if (ctx->capture_pin[AudioDevice])
> @@ -130,20 +142,6 @@ dshow_read_close(AVFormatContext *s)
>      if (ctx->device_filter[AudioDevice])
>          IBaseFilter_Release(ctx->device_filter[AudioDevice]);
>  
> -    if (ctx->graph) {
> -        IEnumFilters *fenum;
> -        int r;
> -        r = IGraphBuilder_EnumFilters(ctx->graph, &fenum);
> -        if (r == S_OK) {
> -            IBaseFilter *f;
> -            IEnumFilters_Reset(fenum);
> -            while (IEnumFilters_Next(fenum, 1, &f, NULL) == S_OK)
> -                IGraphBuilder_RemoveFilter(ctx->graph, f);
> -            IEnumFilters_Release(fenum);
> -        }
> -        IGraphBuilder_Release(ctx->graph);
> -    }
> -
>      if (ctx->device_name[0])
>          av_free(ctx->device_name[0]);
>      if (ctx->device_name[1])

The enumerative method seems more generic/robust to me (no need to
explicitely enumerate the created filters), but that's bikeshed so I
leave this to you.

...

I'll apply the patches which look fine to me in a day or so (unless
Michael/you beat me at it) unless I see no more comments.

Thanks.
-- 
FFmpeg = Fundamentalist Furious Mean Powerful Eager Game


More information about the ffmpeg-devel mailing list