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 <to...@rastageeks.org>
---
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 <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 <AVFoundation/AVFoundation.h>
+#import <CommonCrypto/CommonDigest.h>

#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;
            }
-- 
2.30.1 (Apple Git-130)

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

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

Reply via email to