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

Michael Niedermayer michaelni at gmx.at
Tue Sep 6 21:23:54 CEST 2011


Hi stefano, ramiro

On Tue, Sep 06, 2011 at 02:40:40PM +0200, Stefano Sabatini wrote:
> On date Sunday 2011-09-04 15:09:20 +0200, Michael Niedermayer encoded:
> > Hi list
> > 
> > Here are some patches from ramiro that he had difficulty sending to
> > ffmpeg-devel
> > 
> > -- 
> > Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> > 
> > Incandescent light bulbs waste a lot of energy as heat so the EU forbids them.
> > Their replacement, compact fluorescent lamps, much more expensive, dont fit in
> > many old lamps, flicker, contain toxic mercury, produce a fraction of the light
> > that is claimed and in a unnatural spectrum rendering colors different than
> > in natural light. Ah and we now need to turn the heaters up more in winter to
> > compensate the lower wasted heat. Who wins? Not the environment, thats for sure
> 
> > From 258047ff61bc67ddf14145e052a7ef8a1472e77c Mon Sep 17 00:00:00 2001
> > From: Ramiro Polla <ramiro.polla at gmail.com>
> > Date: Fri, 2 Sep 2011 01:33:07 -0300
> > Subject: [PATCH 1/7] vfwcap: actually use framerate option
> > 
> > ---
> >  libavdevice/vfwcap.c |    5 +++++
> >  1 files changed, 5 insertions(+), 0 deletions(-)
> > 
> > diff --git a/libavdevice/vfwcap.c b/libavdevice/vfwcap.c
> > index 6f42f9e..e5ecf84 100644
> > --- a/libavdevice/vfwcap.c
> > +++ b/libavdevice/vfwcap.c
> > @@ -314,6 +314,11 @@ static int vfw_read_header(AVFormatContext *s, AVFormatParameters *ap)
> >  
> >      dump_bih(s, &bi->bmiHeader);
> >  
> > +    ret = av_parse_video_rate(&framerate_q, ctx->framerate);
> > +    if (ret < 0) {
> > +        av_log(s, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", ctx->framerate);
> > +        goto fail;
> > +    }
> >  
> >      if (ctx->video_size) {
> >          ret = av_parse_video_size(&bi->bmiHeader.biWidth, &bi->bmiHeader.biHeight, ctx->video_size);
> > -- 
> > 1.7.4.1
> > 
> 
> FineOfCourse.

applied


> 
> > From 5a9489310a45a71d81903ebdba250c6fc45a89de Mon Sep 17 00:00:00 2001
> > From: Ramiro Polla <ramiro.polla at gmail.com>
> > Date: Fri, 2 Sep 2011 01:33:24 -0300
> > Subject: [PATCH 2/7] dshow: remove some unused code
> > 
> > ---
> >  libavdevice/dshow.c |    7 +------
> >  1 files changed, 1 insertions(+), 6 deletions(-)
> > 
> > diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> > index 348fda6..9913569 100644
> > --- a/libavdevice/dshow.c
> > +++ b/libavdevice/dshow.c
> > @@ -19,8 +19,6 @@
> >   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> >   */
> >  
> > -#include "libavformat/timefilter.h"
> > -
> >  #include "avdevice.h"
> >  #include "dshow.h"
> >  
> > @@ -42,8 +40,6 @@ struct dshow_ctx {
> >      unsigned int video_frame_num;
> >  
> >      IMediaControl *control;
> > -
> > -    TimeFilter *timefilter;
> >  };
> >  
> >  static enum PixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
> > @@ -223,7 +219,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
> >      const char *device_name = ctx->device_name[devtype];
> >      int ret = AVERROR(EIO);
> >      IPin *pin;
> > -    int r, i;
> > +    int r;
> >  
> >      const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,
> >                                     &CLSID_AudioInputDeviceCategory };
> > @@ -287,7 +283,6 @@ fail1:
> >          goto error;
> >      }
> >  
> > -    i = 0;
> >      while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK && !device_pin) {
> >          IKsPropertySet *p = NULL;
> >          IEnumMediaTypes *types;
> > -- 
> > 1.7.4.1
> 
> Trivial, looks fine.

applied


> 
> > From 7f31d80dcb137fdd15bfef855e4dabe6aca9f527 Mon Sep 17 00:00:00 2001
> > From: Ramiro Polla <ramiro.polla at gmail.com>
> > Date: Fri, 2 Sep 2011 01:33:41 -0300
> > Subject: [PATCH 3/7] dshow: add option to list devices
> > 
> > ---
> >  libavdevice/dshow.c |   43 ++++++++++++++++++++++++++++++++++++++++++-
> >  1 files changed, 42 insertions(+), 1 deletions(-)
> > 
> > diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> > index 9913569..555a2b8 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 {
> > +    AVClass *class;
> > +
> >      IGraphBuilder *graph;
> >  
> >      char *device_name[2];
> >  
> > +    int   list_devices;
> > +
> >      IBaseFilter *device_filter[2];
> >      IPin        *device_pin[2];
> >      libAVFilter *capture_filter[2];
> > @@ -208,6 +214,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
> >                    enum dshowDeviceType devtype)
> >  {
> >      struct dshow_ctx *ctx = avctx->priv_data;
> > +    int list_devices = ctx->list_devices;
> >      IBaseFilter *device_filter = NULL;
> >      IEnumMoniker *classenum = NULL;
> >      IGraphBuilder *graph = ctx->graph;
> > @@ -235,6 +242,9 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
> >          goto error;
> >      }
> >  
> > +    if (list_devices) {
> > +        av_log(avctx, AV_LOG_INFO, "DirectShow %s devices\n", devtypename);
> > +    }
> >      while (IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK && !device_filter) {
> >          IPropertyBag *bag = NULL;
> >          char *buf = NULL;
> > @@ -251,6 +261,11 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
> >  
> >          buf = dup_wchar_to_utf8(var.bstrVal);
> >  
> > +        if (list_devices) {
> > +            av_log(avctx, AV_LOG_INFO, " \"%s\"\n", buf);
> > +            goto fail1;
> > +        }
> > +
> >          if (strcmp(device_name, buf))
> >              goto fail1;
> >  
> > @@ -263,6 +278,9 @@ fail1:
> >              IPropertyBag_Release(bag);
> >          IMoniker_Release(m);
> >      }
> 
> > +    if (list_devices) {
> > +        goto error;
> > +    }
> 
> And set ret to AVERROR_EXIT, like it is done in the openal input
> device.
> 
> >  
> >      if (!device_filter) {
> >          av_log(avctx, AV_LOG_ERROR, "Could not find %s device.\n",
> > @@ -520,7 +538,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;
> >      }
> > @@ -542,6 +560,12 @@ static int dshow_read_header(AVFormatContext *avctx, AVFormatParameters *ap)
> >          goto error;
> >      }
> >  
> > +    if (ctx->list_devices) {
> > +        dshow_open_device(avctx, devenum, VideoDevice);
> > +        dshow_open_device(avctx, devenum, AudioDevice);
> > +        goto error;
> 
> same here, maybe you could propagate the error code.
> 
> > +    }
> > +
> >      if (ctx->device_name[VideoDevice]) {
> >          ret = dshow_open_device(avctx, devenum, VideoDevice);
> >          if (ret < 0)
> > @@ -629,6 +653,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"),
> > @@ -638,4 +678,5 @@ AVInputFormat ff_dshow_demuxer = {
> >      dshow_read_packet,
> >      dshow_read_close,
> >      .flags = AVFMT_NOFILE,
> > +    .priv_class = &dshow_class,
> >  };
> > -- 
> > 1.7.4.1
> 
> Sounds/Looks good otherwise.
> 
> > From 2cb98e2cd3b29bc49d9dedd7af6bc3a10beadf3e Mon Sep 17 00:00:00 2001
> > From: Ramiro Polla <ramiro.polla at gmail.com>
> > Date: Fri, 2 Sep 2011 01:33:57 -0300
> > Subject: [PATCH 4/7] dshow: add audio/video options
> > 
> > ---
> >  libavdevice/dshow.c        |  150 ++++++++++++++++++++++++++++++++++++++++++++
> >  libavdevice/dshow.h        |    2 +
> >  libavdevice/dshow_common.c |   49 ++++++++++++++
> >  3 files changed, 201 insertions(+), 0 deletions(-)
> > 
> > diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> > index 555a2b8..4cda218 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)
> > @@ -210,6 +222,109 @@ fail:
> >  }
> >  
> >  static int
> > +dshow_set_format(AVFormatContext *avctx, enum dshowDeviceType devtype,
> > +                 IPin *pin, AM_MEDIA_TYPE *type)
> > +{
> > +    struct dshow_ctx *ctx = avctx->priv_data;
> > +    IAMStreamConfig *c = NULL;
> 
> nit: better to call it "config", more readable
> 
> > +    void *caps = NULL;
> > +    int i, n, size;
> > +    int ret = 0;
> > +
> > +    if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &c) != S_OK)
> > +        return 0;
> > +    if (IAMStreamConfig_GetNumberOfCapabilities(c, &n, &size) != S_OK)
> > +        goto end;
> > +
> > +    caps = av_malloc(size);
> > +    if (!caps)
> > +        goto end;
> > +
> > +    for (i = 0; i < n; i++) {
> > +        IAMStreamConfig_GetStreamCaps(c, 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;
> 
> nit++: maybe ih/ih2 for consistency with the code below (fx).
> 
> > +                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 {
> > +                continue;
> > +            }
> > +            if (ctx->framerate) {
> 
> > +                int64_t framerate = (ctx->requested_framerate.den*10000000)
> > +                                  /  ctx->requested_framerate.num;
> 
> possible overflow? A cast to int64_t should be enough to fix it.
> 
> > +                if (framerate > vcaps->MaxFrameInterval ||
> > +                    framerate < vcaps->MinFrameInterval)
> > +                    continue;
> > +                *fr = framerate;
> > +            }
> > +            if (ctx->video_size) {
> > +                if (ctx->requested_width  > vcaps->MaxOutputSize.cx ||
> > +                    ctx->requested_width  < vcaps->MinOutputSize.cx ||
> 
> > +                    ctx->requested_height < vcaps->MinOutputSize.cy ||
> > +                    ctx->requested_height < vcaps->MinOutputSize.cy)
> 
> typo: missing > vcaps->MaxOutputSize.cy check
> 
> > +                    continue;
> > +                bih->biWidth  = ctx->requested_width;
> > +                bih->biHeight = ctx->requested_height;
> > +            }
> > +        } 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 {
> > +                continue;
> > +            }
> > +            if (ctx->sample_rate) {
> > +                if (ctx->sample_rate > acaps->MaximumSampleFrequency ||
> > +                    ctx->sample_rate < acaps->MinimumSampleFrequency)
> > +                    continue;
> > +                fx->nSamplesPerSec = ctx->sample_rate;
> > +            }
> > +            if (ctx->sample_size) {
> > +                if (ctx->sample_size > acaps->MaximumBitsPerSample ||
> > +                    ctx->sample_size < acaps->MinimumBitsPerSample)
> > +                    continue;
> > +                fx->wBitsPerSample = ctx->sample_size;
> > +            }
> > +            if (ctx->channels) {
> > +                if (ctx->channels > acaps->MaximumChannels ||
> > +                    ctx->channels < acaps->MinimumChannels)
> > +                    continue;
> > +                fx->nChannels = ctx->channels;
> > +            }
> > +        }
> 
> > +        if (IAMStreamConfig_SetFormat(c, type) != S_OK)
> > +            continue;
> > +        ret = 1;
> > +        break;
> 
> Can't get the logic of the loop, i suppose it cycles through all the
> "capabilities", set the given parameters in the config struct, tries
> the next one in case of failure, returns with success when it
> succeeds.
> 
> What looks weird to me is the need to cycle through many capabilities
> until you get the "right" one, but then I don't know the DShow API at
> all, and being it from MS I expect all the kinds of quirks.
> 
> > +    }
> > +end:
> > +    if (c)
> > +        IAMStreamConfig_Release(c);
> > +    av_free(caps);
> > +    return ret;
> > +}
> > +
> > +static int
> >  dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
> >                    enum dshowDeviceType devtype)
> >  {
> > @@ -234,6 +349,10 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
> >      const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
> >      const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
> >  
> > +    int set_format = (devtype == VideoDevice && (ctx->video_size || ctx->framerate))
> > +                  || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate));
> > +    int format_set = 1;
> > +
> >      r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[devtype],
> >                                               (IEnumMoniker **) &classenum, 0);
> >      if (r != S_OK) {
> > @@ -322,6 +441,13 @@ fail1:
> >          if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
> >              goto next;
> >  
> > +        if (set_format) {
> > +            format_set = dshow_set_format(avctx, devtype, pin, type);
> > +            if (!format_set) {
> > +                goto next;
> > +            }
> > +        }
> > +
> >          if (IPin_EnumMediaTypes(pin, &types) != S_OK)
> >              goto next;
> >  
> > @@ -342,6 +468,10 @@ next:
> >          if (device_pin != pin)
> >              IPin_Release(pin);
> >      }
> > +    if (!format_set) {
> > +        av_log(avctx, AV_LOG_ERROR, "Could not set %s options\n", devtypename);
> > +        goto error;
> > +    }
> >  
> >      if (!device_pin) {
> >          av_log(avctx, AV_LOG_ERROR,
> > @@ -543,6 +673,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;
> > +        }
> > +    }
> > +    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,
> > @@ -656,6 +801,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", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), FF_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
> > +    { "framerate", "", OFFSET(framerate), FF_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
> > +    { "sample_rate", "", OFFSET(sample_rate), FF_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
> > +    { "sample_size", "", OFFSET(sample_size), FF_OPT_TYPE_INT, {.dbl = 0}, 0, 16, DEC },
> > +    { "channels", "", OFFSET(channels), FF_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
> 
> please document all these, also semantics is "what the option does"
> rather than "what the argument is", so documentation for video_size
> should be:
> "set frame size, accept a string as ..." - no need for the ending point
> 
> >      { "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
> > +}
> > +
> >  void ff_print_AM_MEDIA_TYPE(const AM_MEDIA_TYPE *type)
> >  {
> >  #if DSHOWDEBUG
> 
> > -- 
> > 1.7.4.1
> > 
> 
> > From bdb1c350d63f3a29b187405d33e45ddade6d287f Mon Sep 17 00:00:00 2001
> > From: Ramiro Polla <ramiro.polla at gmail.com>
> > Date: Fri, 2 Sep 2011 01:34:43 -0300
> > Subject: [PATCH 5/7] dshow: add option to list audio/video options
> > 
> > ---
> >  libavdevice/dshow.c |   37 ++++++++++++++++++++++++++++++++++---
> >  1 files changed, 34 insertions(+), 3 deletions(-)
> > 
> > diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> > index 4cda218..133e7be 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];
> > @@ -223,7 +224,7 @@ fail:
> >  
> >  static int
> >  dshow_set_format(AVFormatContext *avctx, enum dshowDeviceType devtype,
> > -                 IPin *pin, AM_MEDIA_TYPE *type)
> > +                 IPin *pin, AM_MEDIA_TYPE *type, int list_options)
> >  {
> >      struct dshow_ctx *ctx = avctx->priv_data;
> >      IAMStreamConfig *c = NULL;
> > @@ -265,6 +266,14 @@ dshow_set_format(AVFormatContext *avctx, enum dshowDeviceType devtype,
> >              } else {
> >                  continue;
> >              }
> > +            if (list_options) {
> > +                av_log(avctx, AV_LOG_INFO, "  %ldx%ld %gfps -> %ldx%ld %gfps\n",
> 
> nit maybe: min_size=WxH min_fps=%f max_size=WxH min_fps=...
> 
> so you don't need to check the code to understand what the "->" means
> in this context
> 
> > +                       vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
> > +                       1. / (1e-7 * vcaps->MinFrameInterval),
> > +                       vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,
> > +                       1. / (1e-7 * vcaps->MaxFrameInterval));
> > +                continue;
> > +            }
> >              if (ctx->framerate) {
> >                  int64_t framerate = (ctx->requested_framerate.den*10000000)
> >                                    /  ctx->requested_framerate.num;
> > @@ -293,6 +302,12 @@ dshow_set_format(AVFormatContext *avctx, enum dshowDeviceType devtype,
> >              } else {
> >                  continue;
> >              }
> > +            if (list_options) {
> > +                av_log(avctx, AV_LOG_INFO, "  %luch %lu-bit %6luHz -> %luch %lu-bit %6luHz\n",
> 
> same consideration as above
> 
> > +                       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)
> > @@ -339,6 +354,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
> >      libAVPin *capture_pin = NULL;
> >      libAVFilter *capture_filter = NULL;
> >      const char *device_name = ctx->device_name[devtype];
> > +    int list_options = ctx->list_options;
> >      int ret = AVERROR(EIO);
> >      IPin *pin;
> >      int r;
> > @@ -420,6 +436,10 @@ fail1:
> >          goto error;
> >      }
> >  
> > +    if (list_options) {
> > +        av_log(avctx, AV_LOG_INFO, "DirectShow %s device \"%s\" options\n",
> > +               devtypename, device_name);
> > +    }
> >      while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK && !device_pin) {
> >          IKsPropertySet *p = NULL;
> >          IEnumMediaTypes *types;
> > @@ -441,8 +461,13 @@ fail1:
> >          if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
> >              goto next;
> >  
> > -        if (set_format) {
> > -            format_set = dshow_set_format(avctx, devtype, pin, type);
> > +        if (set_format || list_options) {
> > +            if (list_options) {
> > +                char *buf = dup_wchar_to_utf8(info.achName);
> > +                av_log(avctx, AV_LOG_INFO, " Pin \"%s\"\n", buf);
> > +                av_free(buf);
> > +            }
> > +            format_set = dshow_set_format(avctx, devtype, pin, type, list_options);
> >              if (!format_set) {
> >                  goto next;
> >              }
> > @@ -468,6 +493,9 @@ next:
> >          if (device_pin != pin)
> >              IPin_Release(pin);
> >      }
> > +    if (list_options) {
> > +        goto error;
> > +    }
> >      if (!format_set) {
> >          av_log(avctx, AV_LOG_ERROR, "Could not set %s options\n", devtypename);
> >          goto error;
> > @@ -809,6 +837,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 },
> >  };
> 
> Would be possible to have distinct list_options() and list_devices()
> functions, rather than have their code interspersed with the
> set_format()/open_device() code?
> 
> I'm fine to do that with another patch if possible, should help
> readability/maintainability.
> 
> >  
> > -- 
> > 1.7.4.1
> > 
> 
> > From 187fb0f71a283e929712b8d47b7f540ee89eebc1 Mon Sep 17 00:00:00 2001
> > From: Ramiro Polla <ramiro.polla at gmail.com>
> > Date: Fri, 2 Sep 2011 01:35:21 -0300
> > Subject: [PATCH 6/7] doc: add documentation for dshow indev
> > 
> > ---
> >  doc/indevs.texi |   73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 files changed, 73 insertions(+), 0 deletions(-)
> > 
> > diff --git a/doc/indevs.texi b/doc/indevs.texi
> > index c38031f..af95e00 100644
> > --- a/doc/indevs.texi
> > +++ b/doc/indevs.texi
> > @@ -55,6 +55,79 @@ For more information see:
> >  
> >  BSD video input device.
> >  
> > + at section dshow
> > +
> > +Windows DirectShow input device.
> > +
> > +DirectShow support is enabled when FFmpeg is built with mingw-w64.
> > +Currently only audio and video devices are supported.
> > +
> > +Multiple devices may be opened as separate inputs, but they may also be
> > +opened on the same input, which should improve synchronism between them.
> > +
> > +The input name should be in the format:
> > +
> > + at example
> > + at var{TYPE}=@var{NAME}[:@var{TYPE}=@var{NAME}]
> > + at end example
> > +
> > +where @var{TYPE} can be either @var{audio} or @var{video},
> > +and @var{NAME} is the device's name.
> > +
> > + at subsection Options
> > +
> > +If no options are specified, the device's defaults are used.
> 
> > +If the device does not support the requested options, FFmpeg
> > +will fail to open it.
> 
> Not clear what "FFmpeg" means in this case (the tool?, the project
> code?), maybe better:
> 
> If the accessed DirectShow device does not support the requested
> options, it will fail to open it.
> 
> 
> > +
> > + at table @option
> > +
> > + at item video_size
> > +Set the video size in the captured video.
> > +
> > + at item framerate
> > +Set the framerate in the captured video.
> > +
> > + at item sample_rate
> > +Set the sample rate (in Hz) of the captured audio.
> > +
> > + at item sample_size
> > +Set the sample size (in bits) of the captured audio.
> > +
> > + at item channels
> > +Set the number of channels in the captured audio.
> > +
> > + at item list_devices
> > +If set to @option{true}, print a list of devices and exit.
> > +
> > + at item list_options
> > +If set to @option{true}, print a list of selected device's options
> > +and exit.
> > +
> > + at end table
> > +
> 
> > + at subsection Examples
> > +
> > +Print the list of DirectShow supported devices and exit:
> > + at example
> > +$ ffmpeg -list_devices true -f dshow -i dummy
> > + at end example
> > +
> > +Open video device @var{Camera}:
> > + at example
> > +$ ffmpeg -f dshow -i video="Camera"
> > + at end example
> > +
> > +Open video device @var{Camera} and audio device @var{Microphone}:
> > + at example
> > +$ ffmpeg -f dshow -i video="Camera":audio="Microphone"
> > + at end example
> > +
> > +Print the list of supported options in selected device and exit:
> > + at example
> > +$ ffmpeg -list_options true -f dshow -i video="Camera"
> > + at end example
> > +
> 
> If you want to increase the niceness level:
> @itemize
> @item Do this...
> @example
> ...
> @end example
> 
> like in the lavfi device docs.
> 
> >  @section dv1394
> >  
> >  Linux DV 1394 input device.
> > -- 
> > 1.7.4.1
> > 
> 
> > From dac5ebc024fdef89f2d426be918653778177b4ab Mon Sep 17 00:00:00 2001
> > From: Ramiro Polla <ramiro.polla at gmail.com>
> > Date: Fri, 2 Sep 2011 01:35:47 -0300
> > Subject: [PATCH 7/7] dshow: properly disconnect and remove filters from graph
> > 
> > ---
> >  libavdevice/dshow.c |   18 ++++++++++++++----
> >  1 files changed, 14 insertions(+), 4 deletions(-)
> > 
> > diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
> > index 133e7be..45d3f10 100644
> > --- a/libavdevice/dshow.c
> > +++ b/libavdevice/dshow.c
> > @@ -111,11 +111,7 @@ dshow_read_close(AVFormatContext *s)
> >          IMediaControl_Stop(ctx->control);
> >          IMediaControl_Release(ctx->control);
> >      }
> > -    if (ctx->graph)
> > -        IGraphBuilder_Release(ctx->graph);
> >  
> > -    /* FIXME remove filters from graph */
> > -    /* FIXME disconnect pins */
> >      if (ctx->capture_pin[VideoDevice])
> >          libAVPin_Release(ctx->capture_pin[VideoDevice]);
> >      if (ctx->capture_pin[AudioDevice])
> > @@ -134,6 +130,20 @@ 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])
> 
> Looks fine to me.

applied

so, 1,2 and 7 applied

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

No snowflake in an avalanche ever feels responsible. -- Voltaire
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20110906/6900a0e6/attachment.asc>


More information about the ffmpeg-devel mailing list