PR #23613 opened by Gabriel Balaich (ninbura)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23613
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23613.patch
# Summary of changes
This PR adds the ability for macOS users to list & select avfoundation
video/audio inputs via unique ID & serial, where-as previously only name &
index were the available options.
# Why selecting video/audio inputs via name/index is unreliable.
1. When multiple video/audio inputs of the same model are attached to the same
system, you cannot uniquely select said inputs via name.
2. Video input indexes can change after hot plugs and system restarts.
3. Audio input indexes can change when connecting/disconnecting audio inputs.
4. When multiple video inputs of the same model are attached to the same
system, the source selected via index can randomly change from run-to-run (see
example below).
See attached `index-frame-test.zsh` & `capture.log` for full command & output.
```Zsh
=== frame 1 @ 2026-06-26_20-05-42.877 (index 0, 3840x2160@60) ===
Input #0, avfoundation, from '':
Duration: N/A, start: 4412.272300, bitrate: N/A
Stream #0:0: Video: rawvideo (NV12 / 0x3231564E), nv12, 3840x2160, 60 fps, 60
tbr, 1000k tbn, start 4412.272300
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo (native) -> mjpeg (native))
Output #0, image2, to
'index-frame-test/run_2026-06-26_20-05-42_idx0/frame-01_2026-06-26_20-05-42.877.jpg':
Metadata:
encoder : Lavf62.19.101
Stream #0:0: Video: mjpeg, yuv420p(pc, progressive), 3840x2160, q=2-31, 200
kb/s, 60 fps, 60 tbn
Metadata:
encoder : Lavc62.36.101 mjpeg
Side data:
CPB properties: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay:
N/A
[image2 @ 0xbe1018280] The specified filename
'index-frame-test/run_2026-06-26_20-05-42_idx0/frame-01_2026-06-26_20-05-42.877.jpg'
does not contain an image sequence pattern or a pattern is invalid.
[image2 @ 0xbe1018280] Use a pattern such as %03d for an image sequence or use
the -update option (with -frames:v 1 if needed) to write a single image.
[out#0/image2 @ 0xbe12900c0] video:378KiB audio:0KiB subtitle:0KiB other
streams:0KiB global headers:0KiB muxing overhead: unknown
frame= 1 fps=0.0 q=12.7 Lsize=N/A time=00:00:00.01 bitrate=N/A speed=0.657x
elapsed=0:00:00.02
# Repeated 10 times...
```
Output changes despite looping the same FFmpeg command 10x times against the
same input. As far as I can tell this is due to 1 or many inputs sharing the
same name (same model).
<img src="/attachments/ed927d62-8258-4797-82eb-49ee014de73c" alt="Screenshot
2026-06-26 at 23.06.49" width="1200">
# Why unique ID is desirable, and when it's undesirable.
### Desirable
- Unique ID allows you to select an audio device with an identifier that *never
changes*.
- Persistent across restarts, hot plugs, and when increasing or decreasing the
amount of audio I/O attached to you system (index can change in these
scenarios).
- Allows for selecting 1 of many audio devices with the same name.
- ```Zsh
[AVFoundation indev @ 0xb0cc18180] [4] same-name-test
uid=com.rogueamoeba.Loopback::F43848CE-D7CE-4C9C-B5F6-04F55190C157 serial=N/A
[AVFoundation indev @ 0xb0cc18180] [6] same-name-test
uid=com.rogueamoeba.Loopback::18AAEF28-5258-490C-8DC8-85FB09624E83 serial=N/A
```
### Undesirable
- A video source's unique ID *can change* after hotplugs & system restarts.
- ```Zsh
# Baseline before hot plug
[1] Elgato 4K X uid=0x232000000fd9009b serial=A7SNB504219J0R
[3] Elgato 4K X uid=0x222000000fd9009b serial=A7SNB50423R73R
[6] Elgato 4K X uid=0x252000000fd9009c serial=A7SNB50424UBQI
# After hot plug (index & uid can change)
[1] Elgato 4K X uid=0x232000000fd9009b serial=A7SNB504219J0R
[3] Elgato 4K X uid=0x222000000fd9009b serial=A7SNB50423R73R
[4] Elgato 4K X uid=0x252000000fd9009b serial=A7SNB50424UBQI
# After restart (index & uid can change)
[0] Elgato 4K X uid=0x232000000fd9009b serial=A7SNB50424UBQI
[2] Elgato 4K X uid=0x252000000fd9009b serial=A7SNB504219J0R
[3] Elgato 4K X uid=0x262000000fd9009b serial=A7SNB50423R73R
```
# Why serial is desirable, and its limitations.
### Desirable
- Serial allows you to select video/audio inputs with an identifier that *never
changes* (tested with hot plugs & restarts).
- Does not suffer from the same behavior as index where feed can randomly
change run-to-run (tested with loops).
- Unique across multiple units of the same device/model & name.
- Provides a common identifier, like name, for selecting/correlating a pair of
video/audio inputs from the same device.
### Limitations
- Serial is only available for USB devices, but nearly all consumer-grade
capture cards for macOS are connected via USB.
>From e4cd3786b7b88e4f36f2278de8e30f94d1ffaa35 Mon Sep 17 00:00:00 2001
From: Gabriel Balaich <[email protected]>
Date: Fri, 26 Jun 2026 21:08:55 -0600
Subject: [PATCH] avdevice/avfoundation: add device selection by USB serial and
unique ID
A capture device could previously be selected only by index or by name.
Both are unreliable when multiple audio/video devices share a name or
across reboots. AVFoundation reorders the device indices, and the USB
video uniqueID embeds the macOS locationID, which is reassigned on
reboot or replug and can then resolve to a different physical device.
Add four options:
-video_device_serial / -audio_device_serial
-video_device_uid / -audio_device_uid
The USB serial number is the only identifier that stays pegged to a
given physical unit. For video it is resolved to the device's current
locationID via IOKit. For audio it is matched against the uniqueID,
which already embeds it. The unique ID covers devices that have no
serial, such as virtual camera/audio devices.
-list_devices additionally prints each device's uniqueID and USB serial
so the values can be discovered. IOKit is detected in configure and used
only when available.
Signed-off-by: Gabriel Balaich <[email protected]>
---
Changelog | 1 +
configure | 4 +-
doc/indevs.texi | 21 ++-
libavdevice/avfoundation.m | 263 ++++++++++++++++++++++++++++++++++++-
4 files changed, 281 insertions(+), 8 deletions(-)
diff --git a/Changelog b/Changelog
index 2ad3ee255f..714a45322c 100644
--- a/Changelog
+++ b/Changelog
@@ -18,6 +18,7 @@ version <next>:
- Remove ogg/celt parsing
- Bitstream filter to split Dolby Vision multi-layer HEVC
- Add AMF hardware memory mapping support.
+- AVFoundation input device selection by unique ID and USB serial number
version 8.1:
diff --git a/configure b/configure
index a6bbb86807..f594e7c881 100755
--- a/configure
+++ b/configure
@@ -2723,6 +2723,7 @@ HAVE_LIST="
$TYPES_LIST
gzip
ioctl_posix
+ iokit
libdrm_getfb2
makeinfo_html
opencl_d3d11
@@ -4039,7 +4040,7 @@ android_camera_indev_deps="android camera2ndk mediandk
pthreads"
alsa_indev_deps="alsa"
alsa_outdev_deps="alsa"
avfoundation_indev_deps="avfoundation corevideo coremedia pthreads
AVCaptureSession"
-avfoundation_indev_suggest="coregraphics applicationservices"
+avfoundation_indev_suggest="coregraphics applicationservices iokit"
avfoundation_indev_extralibs="-framework Foundation"
audiotoolbox_outdev_deps="audiotoolbox pthreads AudioObjectPropertyAddress"
audiotoolbox_outdev_extralibs="-framework AudioToolbox -framework CoreAudio"
@@ -7145,6 +7146,7 @@ enabled avfoundation && {
disable coregraphics applicationservices
check_lib coregraphics CoreGraphics/CoreGraphics.h
CGGetActiveDisplayList "-framework CoreGraphics" ||
check_lib applicationservices ApplicationServices/ApplicationServices.h
CGGetActiveDisplayList "-framework ApplicationServices"
+ check_lib iokit IOKit/IOKitLib.h
IOServiceGetMatchingServices "-framework IOKit"
check_objc_class AVFoundation/AVFoundation.h AVCaptureSession
}
diff --git a/doc/indevs.texi b/doc/indevs.texi
index 8822e070fe..6554203509 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -148,8 +148,8 @@ AVFoundation supports the following options:
@table @option
@item -list_devices <TRUE|FALSE>
-If set to true, a list of all available input devices is given showing all
-device names and indices.
+If set to true, a list of all available input devices is given showing their
+index, name, unique ID, and USB serial number (when available).
@item -video_device_index <INDEX>
Specify the video device by its index. Overrides anything given in the input
filename.
@@ -157,6 +157,23 @@ Specify the video device by its index. Overrides anything
given in the input fil
@item -audio_device_index <INDEX>
Specify the audio device by its index. Overrides anything given in the input
filename.
+@item -video_device_serial <SERIAL>
+Specify the video device by its USB serial number (USB devices only). Unlike
the
+index, this is stable across reboots and device reordering. Overrides anything
+given in the input filename.
+
+@item -audio_device_serial <SERIAL>
+Specify the audio device by its USB serial number, matched against the device's
+unique ID on a best-effort basis. See @option{-video_device_serial}.
+
+@item -video_device_uid <UID>
+Specify the video device by its AVFoundation unique ID (as shown by
+@option{-list_devices}). Unique-ID stability is device-dependent and is not
+reliable for USB capture devices; prefer @option{-video_device_serial} for
those.
+
+@item -audio_device_uid <UID>
+Specify the audio device by its AVFoundation unique ID. See
@option{-video_device_uid}.
+
@item -pixel_format <FORMAT>
Request the video device to use a specific pixel format.
If the specified format is not supported, a list of available formats is given
diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
index ebec1ac4f2..2f5988b318 100644
--- a/libavdevice/avfoundation.m
+++ b/libavdevice/avfoundation.m
@@ -25,7 +25,19 @@
* @author Thilo Borgmann <[email protected]>
*/
+#include "config.h"
+
#import <AVFoundation/AVFoundation.h>
+#if HAVE_IOKIT
+# import <IOKit/IOKitLib.h>
+ /* kIOMainPortDefault replaced kIOMasterPortDefault in the macOS 12 SDK. */
+# if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) &&
__MAC_OS_X_VERSION_MAX_ALLOWED >= 120000
+# define AVF_IO_MAIN_PORT_DEFAULT kIOMainPortDefault
+# else
+# define AVF_IO_MAIN_PORT_DEFAULT kIOMasterPortDefault
+# endif
+#endif
+
#include <pthread.h>
#include "libavutil/channel_layout.h"
@@ -111,6 +123,10 @@ typedef struct
char *url;
char *video_filename;
char *audio_filename;
+ char *video_device_serial;
+ char *audio_device_serial;
+ char *video_device_uid;
+ char *audio_device_uid;
int num_video_devices;
@@ -821,6 +837,230 @@ static NSArray* getDevicesWithMediaType(AVMediaType
mediaType) {
#endif
}
+#if HAVE_IOKIT
+/* Newer macOS exposes USB devices as IOUSBHostDevice; pre-10.11 systems and
some
+ * devices still use the legacy IOUSBDevice class. Try the modern class first.
*/
+static const char *const avf_usb_match_classes[] = { "IOUSBHostDevice",
"IOUSBDevice" };
+
+static int avf_io_get_string(io_service_t service, CFStringRef key, char *buf,
size_t size)
+{
+ CFTypeRef ref = IORegistryEntryCreateCFProperty(service, key,
kCFAllocatorDefault, 0);
+ int ok = ref && CFGetTypeID(ref) == CFStringGetTypeID() &&
CFStringGetCString(ref, buf, size, kCFStringEncodingUTF8);
+ if (ref)
+ CFRelease(ref);
+ return ok;
+}
+
+static int avf_io_get_uint32(io_service_t service, CFStringRef key, uint32_t
*out)
+{
+ CFTypeRef ref = IORegistryEntryCreateCFProperty(service, key,
kCFAllocatorDefault, 0);
+ int ok = ref && CFGetTypeID(ref) == CFNumberGetTypeID() &&
CFNumberGetValue(ref, kCFNumberSInt32Type, out);
+ if (ref)
+ CFRelease(ref);
+ return ok;
+}
+#endif
+
+static int64_t avf_usb_location_for_serial(const char *serial)
+{
+#if HAVE_IOKIT
+ int64_t location = -1;
+
+ for (size_t i = 0; i < FF_ARRAY_ELEMS(avf_usb_match_classes) && location <
0; i++) {
+ io_iterator_t iterator = 0;
+ io_service_t service;
+
+ if (IOServiceGetMatchingServices(AVF_IO_MAIN_PORT_DEFAULT,
+ IOServiceMatching(avf_usb_match_classes[i]), &iterator) !=
KERN_SUCCESS)
+ continue;
+
+ while (location < 0 && (service = IOIteratorNext(iterator))) {
+ char found[256];
+ uint32_t loc;
+ if (avf_io_get_string(service, CFSTR("USB Serial Number"), found,
sizeof(found)) &&
+ !strcmp(found, serial) &&
+ avf_io_get_uint32(service, CFSTR("locationID"), &loc))
+ location = loc;
+ IOObjectRelease(service);
+ }
+ IOObjectRelease(iterator);
+ }
+
+ return location;
+#else
+ return -1;
+#endif
+}
+
+static NSString *avf_usb_serial_for_location(uint32_t location)
+{
+#if HAVE_IOKIT
+ NSString *serial = nil;
+
+ for (size_t i = 0; i < FF_ARRAY_ELEMS(avf_usb_match_classes) && !serial;
i++) {
+ io_iterator_t iterator = 0;
+ io_service_t service;
+
+ if (IOServiceGetMatchingServices(AVF_IO_MAIN_PORT_DEFAULT,
+ IOServiceMatching(avf_usb_match_classes[i]), &iterator) !=
KERN_SUCCESS)
+ continue;
+
+ while (!serial && (service = IOIteratorNext(iterator))) {
+ char found[256];
+ uint32_t loc;
+ if (avf_io_get_uint32(service, CFSTR("locationID"), &loc) && loc
== location &&
+ avf_io_get_string(service, CFSTR("USB Serial Number"), found,
sizeof(found)))
+ serial = [NSString stringWithUTF8String:found];
+ IOObjectRelease(service);
+ }
+ IOObjectRelease(iterator);
+ }
+
+ return serial;
+#else
+ return nil;
+#endif
+}
+
+// USB video uniqueID = locationID<<32 | VID<<16 | PID; match on the
locationID.
+static AVCaptureDevice *avf_video_device_with_serial(const char *serial,
+ NSArray *devices, NSArray *devices_muxed, int *is_muxed)
+{
+ int64_t location = avf_usb_location_for_serial(serial);
+ NSArray *lists[2] = { devices, devices_muxed };
+
+ if (location < 0)
+ return nil;
+
+ for (int i = 0; i < 2; i++) {
+ for (AVCaptureDevice *device in lists[i]) {
+ NSString *uid = [device uniqueID];
+ if ([uid hasPrefix:@"0x"] &&
+ (uint32_t)(strtoull([uid UTF8String], NULL, 16) >> 32) ==
(uint32_t)location) {
+ *is_muxed = (i == 1);
+ return device;
+ }
+ }
+ }
+
+ return nil;
+}
+
+static AVCaptureDevice *avf_video_device_with_uid(const char *uid,
+ NSArray *devices, NSArray *devices_muxed, int *is_muxed)
+{
+ NSString *want = [NSString stringWithUTF8String:uid];
+ NSArray *lists[2] = { devices, devices_muxed };
+
+ for (int i = 0; i < 2; i++) {
+ for (AVCaptureDevice *device in lists[i]) {
+ if ([[device uniqueID] isEqualToString:want]) {
+ *is_muxed = (i == 1);
+ return device;
+ }
+ }
+ }
+
+ return nil;
+}
+
+// USB audio uniqueID embeds the serial (...:SERIAL:N); match it directly.
+static AVCaptureDevice *avf_audio_device_with_serial(const char *serial,
NSArray *devices)
+{
+ NSString *needle = [NSString stringWithFormat:@":%s:", serial];
+
+ for (AVCaptureDevice *device in devices) {
+ if ([[device uniqueID] rangeOfString:needle].location != NSNotFound)
+ return device;
+ }
+
+ return nil;
+}
+
+static AVCaptureDevice *avf_audio_device_with_uid(const char *uid, NSArray
*devices)
+{
+ NSString *want = [NSString stringWithUTF8String:uid];
+
+ for (AVCaptureDevice *device in devices) {
+ if ([[device uniqueID] isEqualToString:want])
+ return device;
+ }
+
+ return nil;
+}
+
+// Best-effort serial string for -list_devices, or "N/A".
+static const char *avf_device_listing_serial(AVCaptureDevice *device)
+{
+ NSString *uid = [device uniqueID];
+
+ if ([uid hasPrefix:@"0x"]) {
+ unsigned long long value = strtoull([uid UTF8String], NULL, 16);
+ NSString *serial = avf_usb_serial_for_location((uint32_t)(value >>
32));
+ return serial.length ? [serial UTF8String] : "N/A";
+ } else {
+ // Trust the serial field only when the trailing field is the numeric
engine index.
+ NSArray<NSString *> *fields = [uid componentsSeparatedByString:@":"];
+ if (fields.count >= 2) {
+ NSString *serial = fields[fields.count - 2];
+ NSString *index = fields[fields.count - 1];
+ if (serial.length && index.length &&
+ [index rangeOfCharacterFromSet:
+ [[NSCharacterSet decimalDigitCharacterSet]
invertedSet]].location == NSNotFound)
+ return [serial UTF8String];
+ }
+ return "N/A";
+ }
+}
+
+// Returns 1 if a serial/uid selector was set (*device = match, or nil after
logging on miss), else 0.
+static int avf_video_device_from_string(AVFContext *ctx, NSArray *devices,
+ NSArray *devices_muxed, AVCaptureDevice **device)
+{
+ if (ctx->video_device_serial && *ctx->video_device_serial) {
+ *device = avf_video_device_with_serial(ctx->video_device_serial,
+ devices, devices_muxed, &ctx->video_is_muxed);
+ if (!*device)
+ av_log(ctx, AV_LOG_ERROR,
+ "Video capture device with serial number '%s' not found\n",
+ ctx->video_device_serial);
+ return 1;
+ }
+ if (ctx->video_device_uid && *ctx->video_device_uid) {
+ *device = avf_video_device_with_uid(ctx->video_device_uid,
+ devices, devices_muxed, &ctx->video_is_muxed);
+ if (!*device)
+ av_log(ctx, AV_LOG_ERROR,
+ "Video capture device with unique ID '%s' not found\n",
+ ctx->video_device_uid);
+ return 1;
+ }
+ return 0;
+}
+
+static int avf_audio_device_from_string(AVFContext *ctx, AVCaptureDevice
**device)
+{
+ if (ctx->audio_device_serial && *ctx->audio_device_serial) {
+ NSArray *devices = getDevicesWithMediaType(AVMediaTypeAudio);
+ *device = avf_audio_device_with_serial(ctx->audio_device_serial,
devices);
+ if (!*device)
+ av_log(ctx, AV_LOG_ERROR,
+ "Audio capture device with serial number '%s' not found\n",
+ ctx->audio_device_serial);
+ return 1;
+ }
+ if (ctx->audio_device_uid && *ctx->audio_device_uid) {
+ NSArray *devices = getDevicesWithMediaType(AVMediaTypeAudio);
+ *device = avf_audio_device_with_uid(ctx->audio_device_uid, devices);
+ if (!*device)
+ av_log(ctx, AV_LOG_ERROR,
+ "Audio capture device with unique ID '%s' not found\n",
+ ctx->audio_device_uid);
+ return 1;
+ }
+ return 0;
+}
+
static int avf_read_header(AVFormatContext *s)
{
int ret = 0;
@@ -848,12 +1088,14 @@ static int avf_read_header(AVFormatContext *s)
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);
+ av_log(ctx, AV_LOG_INFO, "[%d] %s uid=%s serial=%s\n", index,
name,
+ [[device uniqueID] UTF8String],
avf_device_listing_serial(device));
}
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);
+ av_log(ctx, AV_LOG_INFO, "[%d] %s uid=%s serial=%s\n", index,
name,
+ [[device uniqueID] UTF8String],
avf_device_listing_serial(device));
}
#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
if (num_screens > 0) {
@@ -870,7 +1112,8 @@ static int avf_read_header(AVFormatContext *s)
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);
+ av_log(ctx, AV_LOG_INFO, "[%d] %s uid=%s serial=%s\n", index,
name,
+ [[device uniqueID] UTF8String],
avf_device_listing_serial(device));
}
goto fail;
}
@@ -888,7 +1131,10 @@ static int avf_read_header(AVFormatContext *s)
sscanf(ctx->audio_filename, "%d", &ctx->audio_device_index);
}
- if (ctx->video_device_index >= 0) {
+ if (avf_video_device_from_string(ctx, devices, devices_muxed,
&video_device)) {
+ if (!video_device)
+ goto fail;
+ } else if (ctx->video_device_index >= 0) {
if (ctx->video_device_index < ctx->num_video_devices) {
if (ctx->video_device_index < [devices count]) {
video_device = [devices objectAtIndex:ctx->video_device_index];
@@ -989,7 +1235,10 @@ static int avf_read_header(AVFormatContext *s)
}
// get audio device
- if (ctx->audio_device_index >= 0) {
+ if (avf_audio_device_from_string(ctx, &audio_device)) {
+ if (!audio_device)
+ goto fail;
+ } else if (ctx->audio_device_index >= 0) {
NSArray *devices = getDevicesWithMediaType(AVMediaTypeAudio);
if (ctx->audio_device_index >= [devices count]) {
@@ -1278,6 +1527,10 @@ static const AVOption options[] = {
{ "list_devices", "list available devices", offsetof(AVFContext,
list_devices), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
{ "video_device_index", "select video device by index for devices with
same name (starts at 0)", offsetof(AVFContext, video_device_index),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
{ "audio_device_index", "select audio device by index for devices with
same name (starts at 0)", offsetof(AVFContext, audio_device_index),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
+ { "video_device_serial", "select video device by USB serial number (stable
across reboots and reordering)", offsetof(AVFContext, video_device_serial),
AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
+ { "audio_device_serial", "select audio device by USB serial number
(best-effort match within its unique ID)", offsetof(AVFContext,
audio_device_serial), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0,
AV_OPT_FLAG_DECODING_PARAM },
+ { "video_device_uid", "select video device by its AVFoundation unique ID",
offsetof(AVFContext, video_device_uid), AV_OPT_TYPE_STRING, {.str = NULL}, 0,
0, AV_OPT_FLAG_DECODING_PARAM },
+ { "audio_device_uid", "select audio device by its AVFoundation unique ID",
offsetof(AVFContext, audio_device_uid), AV_OPT_TYPE_STRING, {.str = NULL}, 0,
0, AV_OPT_FLAG_DECODING_PARAM },
{ "pixel_format", "set pixel format", offsetof(AVFContext, pixel_format),
AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_YUV420P}, 0, INT_MAX,
AV_OPT_FLAG_DECODING_PARAM},
{ "framerate", "set frame rate", offsetof(AVFContext, framerate),
AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM
},
{ "video_size", "set video size", offsetof(AVFContext, width),
AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
--
2.52.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]