From patchwork Tue Mar 22 13:39:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Romain Beauxis X-Patchwork-Id: 34894 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:ab0:5fda:0:0:0:0:0 with SMTP id g26csp680130uaj; Tue, 22 Mar 2022 06:40:52 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyP9vsE9e28bSsAVd1HMDe3KXLb/MIX/ThKFDF8P/Pzu7JbhCkl1e3RZLIE5S6Kxr/Mfa7X X-Received: by 2002:a05:6402:34d5:b0:416:2f46:48f with SMTP id w21-20020a05640234d500b004162f46048fmr28444517edc.88.1647956452061; Tue, 22 Mar 2022 06:40:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1647956452; cv=none; d=google.com; s=arc-20160816; b=P31bQapgxOnFuFATvUv+3vt2icXF+ASpsZi0Go0N683qjvbkQXYgUReMP4tAAaiVz+ jrrOJm7oST6AzCWMFHX670g1P0O/sBj47m3ddF9sbiKHMGf03QLMt6jzGocFgX3RqXBO /KPDbbtZaqR+FHmhLHXNj6+TUfyvpX8U/UO7+AKaAISAvt3QgZXimfB6k38waajZg6Ie Vkd2LGsowr8Ac+gfwevNrZIJY5MC6tUb+jcr235GF2+E42+4BdAUGzk8bwgMBPWzRd7k bhVQqhpMebo46u93ugn2+WhlVhG4SDRf3bAFaKhoKgmI8xkigcxioBAAmKzuz970V6HG UjSw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=Z0Jjek2G4DhBiVSPgp8nvYAYXbtgYTFlGFk/+84PB5g=; b=VUKPUMEyodTBOwSVUOuStEesZzmP3eVGYNhuMzWbLgiRTzXBlOZJLpsjuWLExKSp2r U4bAvDMFEro2MEP3WUQyxlF+ovD10jaDtDHloYBzQRY2UcAshIlDrHkhmmHEe+oGZ4Ug cNctVlhziLcrC+YqzeBXHLALwzDwEFHpS4gLKCB7i+7W06dYMmsDQUktq8uSba0jJLu4 Kla5pFtBofjd9Lrz6J4yQxqJk6dcNICVjEcSgmdjQwSFVuw8RATKNs4I/geED/OuV7Vp 9AadBeg2jb3PLWDTUP832/ypz+e1L8ElwexmIkIsXzLlpwB4atvNAY84eQ1kVKIz+yC9 ZNaw== 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 hb42-20020a170907162a00b006df76385bd5si10576398ejc.117.2022.03.22.06.40.51; Tue, 22 Mar 2022 06:40:52 -0700 (PDT) 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 C854E68B1A5; Tue, 22 Mar 2022 15:40:28 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ed1-f51.google.com (mail-ed1-f51.google.com [209.85.208.51]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9FD6E68B177 for ; Tue, 22 Mar 2022 15:40:22 +0200 (EET) Received: by mail-ed1-f51.google.com with SMTP id c62so2204328edf.5 for ; Tue, 22 Mar 2022 06:40:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nwxxubwggUA8z1BUIndEKlsCo6aXEfi0TH3pI1/KhrE=; b=pZmHbxtOZz/ZGc3GXdwubbvQnSZFnLNvH9sUgrZ7PpkPseUPuwYXPVoclWm/K+bnw3 UnOVs5si0LsJhNfe5mB11oMwnTsCZMVhjUZPz6WijVlD/gPXeg6hklrnvkzpn6rbW8Gm T81Pb83qRA+fP4jpUStDiEiINp9aEKOHM4Ddf3buKTVUSeYP4NjXENdyQCzLZXynJIHy zr6iy9Vb0SLYYKEPo8Qm5ExCNpxQeZ6+3fKlk53I4OaZ1+LN5kc95NC0AZQHMQr13zCK FhOw5S+axK1lODhvAwoAjVu5Y9ll12SnO24WdzLMy1k5QthhHlBf0HWKam+3f2gz41IF 87JA== X-Gm-Message-State: AOAM531fWuK8fiG658vxPCJYLH3gSovTnw0a2S53PMnZfAp5/XKCOWyn qA0oIeXoQ7FrpRqgl1AK2jSlLY2x5SUV3HZI X-Received: by 2002:a50:f19a:0:b0:418:f94c:fc24 with SMTP id x26-20020a50f19a000000b00418f94cfc24mr26763602edl.34.1647956421587; Tue, 22 Mar 2022 06:40:21 -0700 (PDT) Received: from localhost.localdomain (82-171-134-41.fixed.kpn.net. [82.171.134.41]) by smtp.gmail.com with ESMTPSA id z6-20020a056402274600b004194fc1b7casm2125829edd.48.2022.03.22.06.40.20 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Tue, 22 Mar 2022 06:40:21 -0700 (PDT) From: toots@rastageeks.org To: ffmpeg-devel@ffmpeg.org Date: Tue, 22 Mar 2022 14:39:54 +0100 Message-Id: <20220322133957.81743-4-toots@rastageeks.org> X-Mailer: git-send-email 2.32.0 (Apple Git-132) In-Reply-To: <20220322133957.81743-1-toots@rastageeks.org> References: <20220322133957.81743-1-toots@rastageeks.org> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/6] libavdevice/avfoundation.m: Allow to select devices by unique ID 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 Cc: Romain Beauxis Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: eJEuccGJdc5A From: Romain Beauxis diff --git a/doc/indevs.texi b/doc/indevs.texi index 9d8020311a..858c0fa4e4 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 ID 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 IDs, 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 719276cabf..af52246bf3 100644 --- a/libavdevice/avfoundation.m +++ b/libavdevice/avfoundation.m @@ -40,6 +40,8 @@ #include "libavutil/imgutils.h" #include "avdevice.h" +#define CLEANUP_DEVICE_ID(s) [[s stringByReplacingOccurrencesOfString:@":" withString:@"."] UTF8String] + static const int avf_time_base = 1000000; static const AVRational avf_time_base_q = { @@ -829,21 +831,23 @@ static int avf_read_header(AVFormatContext *s) int index = 0; av_log(ctx, AV_LOG_INFO, "AVFoundation video devices:\n"); for (AVCaptureDevice *device in devices) { - const char *name = [[device localizedName] UTF8String]; - index = [devices indexOfObject:device]; - av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name); + const char *name = [[device localizedName] UTF8String]; + const char *uniqueId = CLEANUP_DEVICE_ID([device uniqueID]); + index = [devices indexOfObject:device]; + av_log(ctx, AV_LOG_INFO, "[%d] %s (ID: %s)\n", index, name, uniqueId); } for (AVCaptureDevice *device in devices_muxed) { - const char *name = [[device localizedName] UTF8String]; - index = [devices count] + [devices_muxed indexOfObject:device]; - av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name); + const char *name = [[device localizedName] UTF8String]; + const char *uniqueId = CLEANUP_DEVICE_ID([device uniqueID]); + index = [devices count] + [devices_muxed indexOfObject:device]; + av_log(ctx, AV_LOG_INFO, "[%d] %s (ID: %s)\n", index, name, uniqueId); } #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 if (num_screens > 0) { CGDirectDisplayID screens[num_screens]; CGGetActiveDisplayList(num_screens, screens, &num_screens); for (int i = 0; i < num_screens; i++) { - av_log(ctx, AV_LOG_INFO, "[%d] Capture screen %d\n", ctx->num_video_devices + i, i); + av_log(ctx, AV_LOG_INFO, "[%d] Capture screen %d (ID: AvfilterAvfoundationCaptureScreen%d)\n", ctx->num_video_devices + i, i, screens[i]); } } #endif @@ -851,7 +855,9 @@ static int avf_read_header(AVFormatContext *s) av_log(ctx, AV_LOG_INFO, "AVFoundation audio devices:\n"); for (AVCaptureDevice *device in audio_devices) { const char *name = [[device localizedName] UTF8String]; + const char *uniqueId = CLEANUP_DEVICE_ID([device uniqueID]); int index = [devices indexOfObject:device]; + av_log(ctx, AV_LOG_INFO, "[%d] %s (ID: %s)\n", index, name, uniqueId); av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name); } goto fail; @@ -919,14 +925,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; + } + + const char *uniqueId = CLEANUP_DEVICE_ID([device uniqueID]); + if (!strncmp(ctx->video_filename, uniqueId, 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; + } + + const char *uniqueId = CLEANUP_DEVICE_ID([device uniqueID]); + if (!strncmp(ctx->video_filename, uniqueId, strlen(ctx->video_filename))) { video_device = device; ctx->video_is_muxed = 1; break; @@ -937,10 +958,23 @@ static int avf_read_header(AVFormatContext *s) // looking for screen inputs if (!video_device) { int idx; + CGDirectDisplayID screens[num_screens]; + CGGetActiveDisplayList(num_screens, screens, &num_screens); + AVCaptureScreenInput* capture_screen_input = NULL; + if(sscanf(ctx->video_filename, "Capture screen %d", &idx) && idx < num_screens) { - CGDirectDisplayID screens[num_screens]; - CGGetActiveDisplayList(num_screens, screens, &num_screens); - AVCaptureScreenInput* capture_screen_input = [[[AVCaptureScreenInput alloc] initWithDisplayID:screens[idx]] autorelease]; + capture_screen_input = [[[AVCaptureScreenInput alloc] initWithDisplayID:screens[idx]] autorelease]; + } + + if(sscanf(ctx->video_filename, "AvfilterAvfoundationCaptureScreen%d", &idx)) { + for (int i = 0; i < num_screens; i++) { + if (screens[i] == idx) { + capture_screen_input = [[[AVCaptureScreenInput alloc] initWithDisplayID:idx] autorelease]; + } + } + } + + if (capture_screen_input) { video_device = (AVCaptureDevice*) capture_screen_input; ctx->video_device_index = ctx->num_video_devices + idx; ctx->video_is_screen = 1; @@ -992,6 +1026,12 @@ static int avf_read_header(AVFormatContext *s) audio_device = device; break; } + + const char *uniqueId = CLEANUP_DEVICE_ID([device uniqueID]); + if (!strncmp(ctx->audio_filename, uniqueId, strlen(ctx->audio_filename))) { + audio_device = device; + break; + } } }