Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: "Marvin Scholz" <epirat07@gmail.com>
To: "FFmpeg development discussions and patches" <ffmpeg-devel@ffmpeg.org>
Subject: Re: [FFmpeg-devel] [PATCH v4 3/3] libavdevice/avfoundation.m: Allow to select devices by unique ID.
Date: Fri, 17 Dec 2021 22:51:59 +0100
Message-ID: <BB48D632-143B-479A-8AFE-25D61A685997@gmail.com> (raw)
In-Reply-To: <b0da2587-6a5b-eb42-c605-03e495e5ca30@rastageeks.org>



On 17 Dec 2021, at 16:12, Romain Beauxis wrote:

> This is the third patch of a series of 3 that cleanup and enhance the
> avfoundation implementation for libavdevice.
>
> Changes:
> v2: None
> v3:
>   * Switched unique ID to use system-prodvided unique ID
>   * Implemented unique IDs for screen capture
> v4: Cleanup
>
> This patch adds a unique ID to avfoundation devices. 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.
>
> Example of output:
> ./ffmpeg -f avfoundation -list_devices true -i ""
> [...]
> [AVFoundation indev @ 0x158705230] AVFoundation video devices:
> [AVFoundation indev @ 0x158705230] [0] FaceTime HD Camera (ID:
> 47B4B64B70674B9CAD2BAE273A71F4B5)
> [AVFoundation indev @ 0x158705230] [1] Capture screen 0 (ID:
> AvfilterAvfoundationCaptureScreen1)
> [AVFoundation indev @ 0x158705230] AVFoundation audio devices:
> [AVFoundation indev @ 0x158705230] [0] Loopback Audio (ID:
> com.rogueamoeba.Loopback.A5668B36-711E-4DF5-8A8D-7148508C735B)
> [AVFoundation indev @ 0x158705230] [1] MacBook Pro Microphone (ID:
> BuiltInMicrophoneDevice)
>
> Notes:
> * Unique names do not seem to follow any specific pattern. I have used
> one similar to the builtin microphone for screen capture
> * The : substitution is actually required. The loopback device above 
> did
> have it in its name.
>

Is there no way to escape the : in the command so that we would not
need to mess with the ID the system gives us?
And if we need to, it would be ideal to have a fully reversible way of
doing so, as then you could just reverse the mangling and use
`deviceWithUniqueID:` instead of iterating all devices.

That said, if thats not easily doable I am fine with the patch as-is,
aside from the minor comments below, thanks for your work on this.

> Signed-off-by: Romain Beauxis <toots@rastageeks.org>
> ---
>  doc/indevs.texi            |  6 ++--
>  libavdevice/avfoundation.m | 72 
> +++++++++++++++++++++++++++++---------
>  2 files changed, 60 insertions(+), 18 deletions(-)
>
> diff --git a/doc/indevs.texi b/doc/indevs.texi
> index 5be647f70a..2b55399c8c 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.

This should say ID I think, as hash was never mentioned before.

>   There are two device name aliases:
>  @table @code
> diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
> index b602cfbe95..25286507d6 100644
> --- a/libavdevice/avfoundation.m
> +++ b/libavdevice/avfoundation.m
> @@ -39,6 +39,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 = {
> @@ -797,21 +799,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
> @@ -819,9 +823,10 @@ static int avf_read_header(AVFormatContext *s)
>          av_log(ctx, AV_LOG_INFO, "AVFoundation audio devices:\n");
>          devices = [AVCaptureDevice 
> devicesWithMediaType:AVMediaTypeAudio];
>          for (AVCaptureDevice *device in devices) {
> -            const char *name = [[device localizedName] UTF8String];
> -            int 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]);
> +            int index            = [devices indexOfObject:device];
> +            av_log(ctx, AV_LOG_INFO, "[%d] %s (ID: %s)\n", index, 
> name, uniqueId);
>          }
>           goto fail;
>      }
> @@ -883,14 +888,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;
> @@ -901,10 +921,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;
> @@ -955,7 +988,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;
> +            }
> +
> +            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".
_______________________________________________
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".

  reply	other threads:[~2021-12-17 21:52 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-17 15:12 Romain Beauxis
2021-12-17 21:51 ` Marvin Scholz [this message]
2021-12-18 15:58   ` Romain Beauxis

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=BB48D632-143B-479A-8AFE-25D61A685997@gmail.com \
    --to=epirat07@gmail.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    /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