Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: toots@rastageeks.org
To: ffmpeg-devel@ffmpeg.org
Cc: thilo.borgmann@mail.de, Romain Beauxis <toots@rastageeks.org>,
	epirat07@gmail.com
Subject: [FFmpeg-devel] [PATCH 2/4] libavdevice/avfoundation.m: Allow to select devices by unique ID
Date: Sun, 30 Jan 2022 11:30:45 -0600
Message-ID: <20220130173045.32690-3-toots@rastageeks.org> (raw)
In-Reply-To: <20220130173045.32690-1-toots@rastageeks.org>

From: Romain Beauxis <toots@rastageeks.org>

This adds a backward-compatible method to select devices using a unique ID that should not change accross device reboot or when a device is added or removed.

Signed-off-by: Romain Beauxis <toots@rastageeks.org>
---
 doc/indevs.texi            |  6 ++--
 libavdevice/avfoundation.m | 64 +++++++++++++++++++++++++++++++-------
 2 files changed, 56 insertions(+), 14 deletions(-)

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 <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 d8bcd98f81..a837042a6d 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 = {
@@ -822,21 +824,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
@@ -844,7 +848,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;
@@ -910,14 +916,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;
@@ -928,10 +949,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;
@@ -983,6 +1017,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;
+                }
             }
         }
 
-- 
2.32.0 (Apple Git-132)

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

  parent reply	other threads:[~2022-01-30 17:33 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-30 17:30 [FFmpeg-devel] [PATCH 0/4] Cleanup avfoundation input toots
2022-01-30 17:30 ` [FFmpeg-devel] [PATCH 1/4] Use appropriate method for device discovery, fix crash with bogus device index toots
2022-01-31 10:10   ` Thilo Borgmann
2022-01-31 14:19     ` Romain Beauxis
2022-01-30 17:30 ` toots [this message]
2022-01-30 17:30 ` [FFmpeg-devel] [PATCH 3/4] libavdevice/avfoundation.m: use setAudioSettings, extend supported formats toots
2022-01-30 17:30 ` [FFmpeg-devel] [PATCH 4/4] libavdevice/avfoundation.m: Replace mutex-based concurrency handling in avfoundation.m by a thread-safe fifo queue with maximum length toots

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220130173045.32690-3-toots@rastageeks.org \
    --to=toots@rastageeks.org \
    --cc=epirat07@gmail.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    --cc=thilo.borgmann@mail.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git