From patchwork Mon Dec 13 16:40:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Romain Beauxis X-Patchwork-Id: 32447 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:cd86:0:0:0:0:0 with SMTP id d128csp5668499iog; Mon, 13 Dec 2021 08:40:43 -0800 (PST) X-Google-Smtp-Source: ABdhPJxyZ+F0GaZlheomj6Qy630sjT7fECkWUuQQyGK2r8gOHrgHln1YIcXsJ1kBOdZ4Vgn6/PRv X-Received: by 2002:a17:907:3da6:: with SMTP id he38mr43961518ejc.151.1639413643360; Mon, 13 Dec 2021 08:40:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1639413643; cv=none; d=google.com; s=arc-20160816; b=Z5kViBiBYrjf1dmKrSvdFUUZnUn7uqUOgQcA7ih19kroz1/CP3K6fHoxp43dfCKgSe qTqk2ibUUzwGM2vy/Hd4rhF9XZjKBw3u4j5jb9yflKTD4WzQ2vWwe8MVuk33MDmKzzR1 I887dF9NMRIToilSJ9zPsJPzNQXDSsYIaXYoxM3bJJdBhsWoCV7dV9U1gtg2YHZxDle/ B3hbtU2Iaje9b9X+UaVE7b/yQlYR2wkP98jP/8BhtgrRisyNzQjcwllGITvki8aGJX2C Zz+c6A5P3jr2zN5GgmJmX2Qj4RlTMQbAFnXrdfnyq/2PVeksVm1MebgwTiPBdza8Fvgq hsLg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:to:date:message-id:mime-version:from :delivered-to; bh=S3Z1k9cezHKZmCO+1e3CZlH4rqUG8jIhmpQGUNQZDQc=; b=JgLJ8J+RLEF4ZhyINRluFHrkeXoYgzQkyQGbevvnTmNu13WahTQI+FYGpomlbWYonR qrCw7CS05NFNqxR2LFuHRTXB1ut3+WpLK8A2qiE5mxc8YeiuHSvXiGiioIEXVL48iPES nQZO1JvQQUaSHkBZjodWTpeg/mjD+huSepJUc378LX0Q5e0IKSdEG2ATb6j7XFvPqSpc 9anrNQUEhv2EsBuffK3xKeGJJP/V5zbp2WVm0MIJVFRFkNItMYQxi9J0JlhVUTLjjNto e7vPuaDNo/9hcABL2LL15LNKnMxbWenEhZmiYcRHSZ2jJogVSRRvbambmUvWXl+vTiza OI3A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id x22si1719693edl.139.2021.12.13.08.40.43; Mon, 13 Dec 2021 08:40:43 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6BC6268B005; Mon, 13 Dec 2021 18:40:40 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qv1-f42.google.com (mail-qv1-f42.google.com [209.85.219.42]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0B09168AFFA for ; Mon, 13 Dec 2021 18:40:34 +0200 (EET) Received: by mail-qv1-f42.google.com with SMTP id gu12so14885749qvb.6 for ; Mon, 13 Dec 2021 08:40:33 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:content-transfer-encoding:mime-version :subject:message-id:date:to; bh=c8z5m6kPYJ+9OUuPFO4Gi78UBtQgLUNxZQgNru6HupY=; b=Kh/fQs8rhSUvQ3tsuNoy1RVm9IZPhvSs1D0u0OU38IWPgHmAAWm8DQylUN1F1aZbMQ nKNNhm3curFdXMm51zO+gqEvFNwe8SqWcRYn0fDWKT3lYFXns23/bph5yHy1w+Oo1yMz E7ThEo9ErDJmF/u/vq25fodoqXS6oZIW74nnPGIO3cWkPAadELcPReLUVqlTr+VeNz7k eMu3Kp1UifsYIoxQCMoJ9LtO6WKdHTR+2/fb6CJ74jkJVCzrsL5UXoEaP6DsnVBiv43r 3Z8RZd7u+HrfPb0CXB+ovZrf3CkH3JQ/rbe4Z4SOK/Bn8ODwFeY7LYDdV7oibczYT/gt iYig== X-Gm-Message-State: AOAM533+Rf0zt3WmsluAAPgzico2GT2sQ4L55L8+hLHFVN1iFAOOM9JO 02EVvL2GKQKTygFgH0HW4OoJKpuppAk= X-Received: by 2002:a05:6214:e47:: with SMTP id o7mr44257841qvc.61.1639413632260; Mon, 13 Dec 2021 08:40:32 -0800 (PST) Received: from smtpclient.apple ([172.58.129.176]) by smtp.gmail.com with ESMTPSA id bm25sm6277781qkb.4.2021.12.13.08.40.31 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 13 Dec 2021 08:40:31 -0800 (PST) From: Romain Beauxis Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.100.0.2.22\)) Message-Id: <5835AAC9-4ECD-4007-906B-8A9497EF911B@rastageeks.org> Date: Mon, 13 Dec 2021 10:40:31 -0600 To: ffmpeg-devel@ffmpeg.org X-Mailer: Apple Mail (2.3654.100.0.2.22) Subject: [FFmpeg-devel] [PATCH v2 03/03] libavdevice/avfoundation.m: Allow to select devices by digest. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: VOd5mA9yRxre This is the third patch of a series of 3 that cleanup and enhance the avfoundation implementation for libavdevice. This patch adds a digest to avfoundation devices, when available. This is needed because device index can change while the machine is running when devices are plugged or unplugged and device names can be tricky to use with localization and etc. The only device type that are excluded are screen capture because the logic to select them seems a little different and I wanted to minimized the changes. Also, for these devices, the name is localized in english, quite straight forward and should not change. Signed-off-by: Romain Beauxis --- doc/indevs.texi | 6 ++-- libavdevice/avfoundation.m | 60 ++++++++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index 5be647f70a..8345b64a28 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -114,7 +114,7 @@ The input filename has to be given in the following syntax: -i "[[VIDEO]:[AUDIO]]" @end example The first entry selects the video input while the latter selects the audio input. -The stream has to be specified by the device name or the device index as shown by the device list. +The stream has to be specified by the device name, index or digest as shown by the device list. Alternatively, the video and/or audio input device can be chosen by index using the @option{ -video_device_index @@ -127,7 +127,9 @@ and/or device name or index given in the input filename. All available devices can be enumerated by using @option{-list_devices true}, listing -all device names and corresponding indices. +all device names, corresponding indices and digests, when available. Device name can be +tricky to use when localized and device index can change when devices are plugged or unplugged. A device +hash, when available, uniquely identifies a device and should not change over time. There are two device name aliases: @table @code diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m index 95414fd16a..bede51bda0 100644 --- a/libavdevice/avfoundation.m +++ b/libavdevice/avfoundation.m @@ -26,6 +26,7 @@ */ #import +#import #include "libavutil/channel_layout.h" #include "libavutil/pixdesc.h" @@ -79,6 +80,28 @@ { AV_PIX_FMT_NONE, 0 } }; +#define DEVICES_DIGEST_LENGTH 8 + +@interface AvdeviceAvfoundationDigest : NSObject ++ (NSString *)fromString:(NSString *)input; +@end + +@implementation AvdeviceAvfoundationDigest : NSObject ++ (NSString *) fromString:(NSString *)input { + const char *cStr = [input UTF8String]; + unsigned char digest[CC_SHA256_DIGEST_LENGTH]; + CC_SHA256( cStr, strlen(cStr), digest ); + + NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; + + for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) + [output appendFormat:@"%02x", digest[i]]; + + // The "d" prefix makes sure that digest strings are never mistaken for numbers. + return [@"d" stringByAppendingString:[output substringToIndex:DEVICES_DIGEST_LENGTH]]; +} +@end + #define MAX_QUEUED_OBJECTS 10 @interface AvdeviceAvfoundationBuffer : NSObject @@ -860,13 +883,15 @@ static int avf_read_header(AVFormatContext *s) av_log(ctx, AV_LOG_INFO, "AVFoundation video devices:\n"); for (AVCaptureDevice *device in devices) { const char *name = [[device localizedName] UTF8String]; + NSString *digest = [AvdeviceAvfoundationDigest fromString:[[NSString alloc] initWithUTF8String:name]]; index = [devices indexOfObject:device]; - av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name); + av_log(ctx, AV_LOG_INFO, "[%d] %s (digest: %s)\n", index, name, [digest UTF8String]); } for (AVCaptureDevice *device in devices_muxed) { const char *name = [[device localizedName] UTF8String]; + NSString *digest = [AvdeviceAvfoundationDigest fromString:[[NSString alloc] initWithUTF8String:name]]; index = [devices count] + [devices_muxed indexOfObject:device]; - av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name); + av_log(ctx, AV_LOG_INFO, "[%d] %s (digest: %s)\n", index, name, [digest UTF8String]); } #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 if (num_screens > 0) { @@ -882,8 +907,9 @@ static int avf_read_header(AVFormatContext *s) devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio]; for (AVCaptureDevice *device in devices) { const char *name = [[device localizedName] UTF8String]; + NSString *digest = [AvdeviceAvfoundationDigest fromString:[[NSString alloc] initWithUTF8String:name]]; int index = [devices indexOfObject:device]; - av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name); + av_log(ctx, AV_LOG_INFO, "[%d] %s (digest: %s)\n", index, name, [digest UTF8String]); } goto fail; } @@ -945,14 +971,29 @@ static int avf_read_header(AVFormatContext *s) } else { // looking for video inputs for (AVCaptureDevice *device in devices) { - if (!strncmp(ctx->video_filename, [[device localizedName] UTF8String], strlen(ctx->video_filename))) { + const char *name = [[device localizedName] UTF8String]; + if (!strncmp(ctx->video_filename, name, strlen(ctx->video_filename))) { + video_device = device; + break; + } + + NSString *digest = [AvdeviceAvfoundationDigest fromString:[[NSString alloc] initWithUTF8String:name]]; + if (!strncmp(ctx->video_filename, [digest UTF8String], strlen(ctx->video_filename))) { video_device = device; break; } } // looking for muxed inputs for (AVCaptureDevice *device in devices_muxed) { - if (!strncmp(ctx->video_filename, [[device localizedName] UTF8String], strlen(ctx->video_filename))) { + const char *name = [[device localizedName] UTF8String]; + if (!strncmp(ctx->video_filename, name, strlen(ctx->video_filename))) { + video_device = device; + ctx->video_is_muxed = 1; + break; + } + + NSString *digest = [AvdeviceAvfoundationDigest fromString:[[NSString alloc] initWithUTF8String:name]]; + if (!strncmp(ctx->video_filename, [digest UTF8String], strlen(ctx->video_filename))) { video_device = device; ctx->video_is_muxed = 1; break; @@ -1017,7 +1058,14 @@ static int avf_read_header(AVFormatContext *s) NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio]; for (AVCaptureDevice *device in devices) { - if (!strncmp(ctx->audio_filename, [[device localizedName] UTF8String], strlen(ctx->audio_filename))) { + const char *name = [[device localizedName] UTF8String]; + if (!strncmp(ctx->audio_filename, name, strlen(ctx->audio_filename))) { + audio_device = device; + break; + } + + NSString *digest = [AvdeviceAvfoundationDigest fromString:[[NSString alloc] initWithUTF8String:name]]; + if (!strncmp(ctx->audio_filename, [digest UTF8String], strlen(ctx->audio_filename))) { audio_device = device; break; }