[FFmpeg-devel] [PATCH] lavd/qtkit: Support choosing the input device by index or by name.
Lukasz Marek
lukasz.m.luki2 at gmail.com
Sun Mar 30 21:54:47 CEST 2014
On 30.03.2014 21:17, Thilo Borgmann wrote:
>>From a44489698c7237988817a63e55058e0d49b120dc Mon Sep 17 00:00:00 2001
> From: Thilo Borgmann<thilo.borgmann at mail.de>
> Date: Sun, 30 Mar 2014 21:13:04 +0200
> Subject: [PATCH 1/2] lavd/qtkit: Support choosing the input device by index or
> by name.
>
> ---
> doc/indevs.texi | 8 +++++++-
> libavdevice/qtkit.m | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 59 insertions(+), 3 deletions(-)
>
> diff --git a/doc/indevs.texi b/doc/indevs.texi
> index e1ff231..b54df72 100644
> --- a/doc/indevs.texi
> +++ b/doc/indevs.texi
> @@ -535,12 +535,18 @@ ffmpeg -f pulse -i default /tmp/pulse.wav
>
> QTKit input device.
>
> -The filename passed as input is unused. The default device will be chosen.
> +The filename passed as input is parsed to contain either a device name or index.
> +The default device will be chosen if an empty string is given.
> +The available devices can be enumerated by using -list_devices.
>
> @example
> ffmpeg -f isight -i "" out.mpg
> @end example
>
> + at example
> +ffmpeg -f qtkit -list_devices true -i ""
> + at end example
> +
> @section sndio
>
> sndio input device.
> diff --git a/libavdevice/qtkit.m b/libavdevice/qtkit.m
> index 038ce02..edcc518 100644
> --- a/libavdevice/qtkit.m
> +++ b/libavdevice/qtkit.m
> @@ -53,6 +53,9 @@ typedef struct
> pthread_cond_t frame_wait_cond;
> id qt_delegate;
>
> + int list_devices;
> + int video_device_index;
> +
> QTCaptureSession* capture_session;
> QTCaptureDecompressedVideoOutput* video_output;
> CVImageBufferRef current_frame;
> @@ -145,8 +148,51 @@ static int qtkit_read_header(AVFormatContext *s)
> pthread_mutex_init(&ctx->frame_lock, NULL);
> pthread_cond_init(&ctx->frame_wait_cond, NULL);
>
> - // Find default capture device
> - QTCaptureDevice *video_device = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeMuxed];
> + // List devices if requested
> + if (ctx->list_devices) {
> + av_log(ctx, AV_LOG_INFO, "QTKit video devices:\n");
> + NSArray *devices = [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo];
> + for (QTCaptureDevice *device in devices) {
> + char *name = [[device localizedDisplayName] UTF8String];
> + int index = [devices indexOfObject:device];
> + av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name);
> + }
> + goto fail;
> + }
> +
> + // Find capture device
> + QTCaptureDevice *video_device = nil;
> +
> + // check for device index given in filename
> + if (ctx->video_device_index == -1) {
> + sscanf(s->filename, "%d", &ctx->video_device_index);
> + }
I'm not sure it is required. It can possibly lead to scan a random
number that is a part of device name.
> + if (ctx->video_device_index != -1) {
> + NSArray *devices = [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo];
> +
> + if (ctx->video_device_index >= [devices count]) {
> + av_log(ctx, AV_LOG_ERROR, "Invalid device index\n");
> + goto fail;
> + }
> +
> + video_device = [devices objectAtIndex:ctx->video_device_index];
> + } else if (strncmp(s->filename, "", 1)) {
Many devices uses string "default" for this reason, not empty string. Be
free to ignore this, but this would make it more consistent with other
devices.
> + NSArray *devices = [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo];
> +
> + for (QTCaptureDevice *device in devices) {
> + if (!strncmp(s->filename, [[device localizedDisplayName] UTF8String], strlen(s->filename))) {
> + video_device = device;
> + break;
> + }
> + }
> + if (!video_device) {
> + av_log(ctx, AV_LOG_ERROR, "Video device not found\n");
> + goto fail;
> + }
> + } else {
> + video_device = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeMuxed];
> + }
>
> BOOL success = [video_device open:nil];
>
> @@ -284,6 +330,10 @@ static int qtkit_close(AVFormatContext *s)
>
> static const AVOption options[] = {
> { "frame_rate", "set frame rate", offsetof(CaptureContext, frame_rate), AV_OPT_TYPE_FLOAT, { .dbl = 30.0 }, 0.1, 30.0, AV_OPT_TYPE_VIDEO_RATE, NULL },
> + { "list_devices", "list available devices", offsetof(CaptureContext, list_devices), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
> + { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
> + { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
> + { "video_device_index", "select video device by index for devices with same name (starts at 0)", offsetof(CaptureContext, video_device_index), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
> { NULL },
> };
You may also consider implementing .get_device_list callback to obtain
device list programmatically (as another patch).
More information about the ffmpeg-devel
mailing list