[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