From: Luca Barbato <[email protected]>
- renaming
- refactor
---
configure | 2 +-
libavdevice/avfoundation_dec.m | 221 ++++++++++++++++++++++-------------------
2 files changed, 119 insertions(+), 104 deletions(-)
diff --git a/configure b/configure
index 7bdc523..e371e54 100755
--- a/configure
+++ b/configure
@@ -4561,7 +4561,7 @@ check_struct linux/videodev2.h "struct v4l2_frmivalenum"
discrete
check_header AVFoundation/AVFoundation.h &&
check_objcflags -fobjc-arc &&
- add_extralibs -framework Foundation -framework AVFoundation || \
+ add_extralibs -framework Foundation -framework AVFoundation -framework
CoreMedia || \
disable AVFoundation_AVFoundation_h
check_header sys/videoio.h
diff --git a/libavdevice/avfoundation_dec.m b/libavdevice/avfoundation_dec.m
index 7bac610..c5ec320 100644
--- a/libavdevice/avfoundation_dec.m
+++ b/libavdevice/avfoundation_dec.m
@@ -33,12 +33,12 @@
#include "avdevice.h"
-struct AVFPixelFormatSpec {
- enum AVPixelFormat ff_id;
- OSType avf_id;
+struct AVPixelFormatMap {
+ enum AVPixelFormat pix_fmt;
+ OSType core_video_fmt;
};
-static const struct AVFPixelFormatSpec avf_pixel_formats[] = {
+static const struct AVPixelFormatMap pixel_format_map[] = {
{ AV_PIX_FMT_MONOBLACK, kCVPixelFormatType_1Monochrome },
{ AV_PIX_FMT_RGB555BE, kCVPixelFormatType_16BE555 },
{ AV_PIX_FMT_RGB555LE, kCVPixelFormatType_16LE555 },
@@ -67,24 +67,44 @@ static const struct AVFPixelFormatSpec avf_pixel_formats[]
= {
{ AV_PIX_FMT_NONE, 0 }
};
-typedef struct AVFoundationCaptureContext {
- AVClass *class;
- int list_devices;
+static enum AVPixelFormat core_video_to_pix_fmt(OSType core_video_fmt)
+{
+ int i;
+ for (i = 0; pixel_format_map[i].pix_fmt != AV_PIX_FMT_NONE; i++) {
+ if (core_video_fmt == pixel_format_map[i].core_video_fmt)
+ return pixel_format_map[i].pix_fmt;
+ }
+ return AV_PIX_FMT_NONE;
+}
+static OSType pix_fmt_to_core_video(enum AVPixelFormat pix_fmt)
+{
+ int i;
+ for (i = 0; pixel_format_map[i].pix_fmt != AV_PIX_FMT_NONE; i++) {
+ if (pix_fmt == pixel_format_map[i].pix_fmt)
+ return pixel_format_map[i].core_video_fmt;
+ }
+ return 0;
+}
+
+typedef struct AVFoundationCaptureContext {
+ AVClass *class;
+ /* AVOptions */
+ int list_devices;
enum AVPixelFormat pixel_format;
- int video_stream_index;
+ int video_stream_index;
- int64_t first_pts;
- int frames_captured;
+ int64_t first_pts;
+ int frames_captured;
pthread_mutex_t frame_lock;
- pthread_cond_t frame_wait_cond;
-
- CFTypeRef session; /** AVCaptureSession*/
- CFTypeRef video_delegate; /** AVFFrameReceiver */
- CFTypeRef video_output; /** AVCaptureVideoDataOutput */
- CVImageBufferRef current_frame; /** CVImageBufferRef */
+ pthread_cond_t frame_wait_cond;
+ /* ARC-compatible pointers to ObjC objects */
+ CFTypeRef session; /* AVCaptureSession */
+ CFTypeRef video_output;
+ CFTypeRef video_delegate;
+ CVImageBufferRef current_frame;
} AVFoundationCaptureContext;
#define AUDIO_DEVICES 1
@@ -142,9 +162,7 @@ static void unlock_frames(AVFoundationCaptureContext* ctx)
pthread_mutex_unlock(&ctx->frame_lock);
}
-/** FrameReceiver class - delegate for AVCaptureSession
- */
-@interface AVFFrameReceiver : NSObject
<AVCaptureVideoDataOutputSampleBufferDelegate>
+@interface VideoCapture : NSObject
<AVCaptureVideoDataOutputSampleBufferDelegate>
{
AVFoundationCaptureContext* _context;
}
@@ -157,7 +175,7 @@ static void unlock_frames(AVFoundationCaptureContext* ctx)
@end
-@implementation AVFFrameReceiver
+@implementation VideoCapture
- (id)initWithContext:(AVFoundationCaptureContext*)context
{
@@ -188,12 +206,9 @@ static void unlock_frames(AVFoundationCaptureContext* ctx)
@end
-// Remove '[]' from the device name
-NSString *pat = @"(?<=\\[).*?(?=\\])";
-
static int setup_stream(AVFormatContext *s, AVCaptureDevice *device)
{
- NSLog(@"setting up stream for device %@ ID\n", [device uniqueID]);
+ av_log(s, AV_LOG_INFO, "Setting up stream for device %s\n", [[device
uniqueID] UTF8String]);
AVFoundationCaptureContext *ctx = s->priv_data;
NSError *__autoreleasing error = nil;
@@ -217,8 +232,9 @@ static int setup_stream(AVFormatContext *s, AVCaptureDevice
*device)
// add the output devices
if ([device hasMediaType:AVMediaTypeVideo]) {
-
AVCaptureVideoDataOutput* out = [[AVCaptureVideoDataOutput alloc]
init];
+ NSNumber *core_video_fmt = nil;
+ enum AVPixelFormat pixel_format;
if (!out) {
av_log(s, AV_LOG_ERROR, "Failed to init AV video output\n");
return -1;
@@ -226,61 +242,45 @@ static int setup_stream(AVFormatContext *s,
AVCaptureDevice *device)
[out setAlwaysDiscardsLateVideoFrames:YES];
-
- // select pixel format
- struct AVFPixelFormatSpec pxl_fmt_spec;
- pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE;
-
- av_log(s, AV_LOG_ERROR, "Supported pixel formats:\n");
- for (NSNumber *pxl_fmt in [out availableVideoCVPixelFormatTypes]) {
- struct AVFPixelFormatSpec pxl_fmt_dummy;
- pxl_fmt_dummy.ff_id = AV_PIX_FMT_NONE;
- for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE;
i++) {
- if ([pxl_fmt intValue] == avf_pixel_formats[i].avf_id) {
- pxl_fmt_dummy = avf_pixel_formats[i];
- break;
- }
- }
-
- if (pxl_fmt_dummy.ff_id != AV_PIX_FMT_NONE) {
- av_log(s, AV_LOG_ERROR, " %s: %d \n",
av_get_pix_fmt_name(pxl_fmt_dummy.ff_id),
- pxl_fmt_dummy.avf_id);
-
- // select first supported pixel format instead of user
selected (or default) pixel format
- if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
- pxl_fmt_spec = pxl_fmt_dummy;
- }
+ // Map the first supported pixel format
+ av_log(s, AV_LOG_VERBOSE, "Supported pixel formats:\n");
+ for (NSNumber *cv_pixel_format in [out
availableVideoCVPixelFormatTypes]) {
+ OSType cv_fmt = [cv_pixel_format intValue];
+ enum AVPixelFormat pix_fmt = core_video_to_pix_fmt(cv_fmt);
+ if (pix_fmt != AV_PIX_FMT_NONE) {
+ av_log(s, AV_LOG_VERBOSE, " %s: %d\n",
+ av_get_pix_fmt_name(pix_fmt),
+ cv_fmt);
+ core_video_fmt = cv_pixel_format;
+ pixel_format = pix_fmt;
}
}
// fail if there is no appropriate pixel format or print a warning
about overriding the pixel format
- if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
+ if (!core_video_fmt) {
return 1;
} else {
- av_log(s, AV_LOG_WARNING, "Overriding selected pixel format to use
%s instead.\n",
- av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
+ av_log(s, AV_LOG_INFO, "Using %s.\n",
+ av_get_pix_fmt_name(pixel_format));
}
- ctx->pixel_format = pxl_fmt_spec.ff_id;
- NSNumber *pixel_format = [NSNumber
numberWithUnsignedInt:pxl_fmt_spec.avf_id];
- NSDictionary *capture_dict = [NSDictionary
dictionaryWithObject:pixel_format
-
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
+ ctx->pixel_format = pixel_format;
+ NSDictionary *capture_dict = [NSDictionary
dictionaryWithObject:core_video_fmt
+
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
[out setVideoSettings:capture_dict];
- AVFFrameReceiver* delegate = [[AVFFrameReceiver alloc]
initWithContext:ctx];
+ VideoCapture *delegate = [[VideoCapture alloc] initWithContext:ctx];
dispatch_queue_t queue = dispatch_queue_create("avf_queue", NULL);
[out setSampleBufferDelegate:delegate queue:queue];
- ctx->video_delegate = (__bridge_retained CFTypeRef) delegate;
-
if ([session canAddOutput:out]) {
[session addOutput:out];
- ctx->video_output = (__bridge_retained CFTypeRef) out;
+ ctx->video_output = (__bridge_retained CFTypeRef) out;
+ ctx->video_delegate = (__bridge_retained CFTypeRef) delegate;
} else {
av_log(s, AV_LOG_ERROR, "can't add video output to capture
session\n");
return -1;
}
- NSLog(@"%@", device);
}
return 0;
@@ -329,8 +329,6 @@ static int get_video_config(AVFormatContext *s)
static void destroy_context(AVFoundationCaptureContext* ctx)
{
- NSLog(@"Destroying context");
-
AVCaptureSession *session = (__bridge AVCaptureSession*)ctx->session;
[session stopRunning];
@@ -349,65 +347,82 @@ static int setup_default_stream(AVFormatContext *s)
AVCaptureDevice *device;
for (NSString *type in @[AVMediaTypeVideo]) {
device = [AVCaptureDevice defaultDeviceWithMediaType:type];
- if (device)
+ if (device) {
+ av_log(s, AV_LOG_INFO, "Using default device %s\n",
+ [[device uniqueID] UTF8String]);
return setup_stream(s, device);
+ }
}
return -1;
}
+static AVCaptureDevice* create_device(AVFormatContext *s)
+{
+ NSString* filename;
+ NSError* __autoreleasing error = nil;
+ NSRegularExpression *exp;
+ NSArray* matches;
+ AVCaptureDevice* device;
+
+ filename = [NSString stringWithFormat:@"%s", s->filename];
+
+ if ((device = [AVCaptureDevice deviceWithUniqueID:filename])) {
+ av_log(s, AV_LOG_INFO, "Device with name %s found\n",[filename
UTF8String]);
+ return device;
+ }
+
+ // Remove '[]' from the device name
+ NSString *pat = @"(?<=\\[).*?(?=\\])";
+ exp = [NSRegularExpression regularExpressionWithPattern:pat
+ options:0
+ error:&error];
+ if (!exp) {
+ av_log(s, AV_LOG_ERROR, "%s\n",
+ [[error localizedDescription] UTF8String]);
+ return NULL;
+ }
+
+ av_log(s, AV_LOG_INFO, "device name: %s\n",[filename UTF8String]);
+
+ matches = [exp matchesInString:filename options:0
+ range:NSMakeRange(0, [filename length])];
+
+ if (matches.count > 0) {
+ for (NSTextCheckingResult *match in matches) {
+ NSRange range = [match rangeAtIndex:0];
+ NSString *uniqueID = [filename
substringWithRange:NSMakeRange(range.location, range.length)];
+ av_log(s, AV_LOG_INFO, "opening device with ID: %s\n", [uniqueID
UTF8String]);
+ if (!(device = [AVCaptureDevice deviceWithUniqueID:uniqueID])) {
+ // report error
+ av_log(s, AV_LOG_ERROR, "Device with name %s not
found",[filename UTF8String]);
+ return NULL;
+ }
+ return device;
+ }
+ }
+ return NULL;
+}
+
static int setup_streams(AVFormatContext *s)
{
- NSLog(@"setting streams");
AVFoundationCaptureContext *ctx = s->priv_data;
int ret;
- NSError *__autoreleasing error = nil;
- NSArray *matches;
- NSString *filename;
AVCaptureDevice *device;
- NSRegularExpression *exp;
pthread_mutex_init(&ctx->frame_lock, NULL);
pthread_cond_init(&ctx->frame_wait_cond, NULL);
ctx->session = (__bridge_retained CFTypeRef)[[AVCaptureSession alloc]
init];
- if (s->filename[0] != '[') {
+ if (!strncmp(s->filename, "default", 7)) {
ret = setup_default_stream(s);
} else {
- exp = [NSRegularExpression regularExpressionWithPattern:pat
- options:0
- error:&error];
- if (!exp) {
- av_log(s, AV_LOG_ERROR, "%s\n",
- [[error localizedDescription] UTF8String]);
- return AVERROR(ENOMEM);
- }
-
- filename = [NSString stringWithFormat:@"%s", s->filename];
- av_log(s, AV_LOG_INFO, "device name: %s\n",[filename UTF8String]);
-
- matches = [exp matchesInString:filename options:0
- range:NSMakeRange(0, [filename length])];
-
- if (matches.count > 0) {
- for (NSTextCheckingResult *match in matches) {
- NSRange range = [match rangeAtIndex:0];
- NSString *uniqueID = [filename substringWithRange:range];
- av_log(s, AV_LOG_INFO, "opening device with ID:
%s\n",[uniqueID UTF8String]);
- if (!(device = [AVCaptureDevice deviceWithUniqueID:uniqueID]))
{
- // report error
- av_log(s, AV_LOG_ERROR, "Device with name %s not
found",[filename UTF8String]);
- return AVERROR(EINVAL);
- }
- ret = setup_stream(s, device);
- if (ret < 0) {
- // avfoundation_close
- return ret;
- }
- }
+ device = create_device(s);
+ if (device) {
+ ret = setup_stream(s, device);
} else {
- av_log(s, AV_LOG_ERROR, "No matches for %s",[filename UTF8String]);
+ av_log(s, AV_LOG_ERROR, "No matches for %s\n", s->filename);
ret = setup_default_stream(s);
}
}
@@ -479,7 +494,7 @@ static int avfoundation_read_packet(AVFormatContext *s,
AVPacket *pkt)
static int avfoundation_read_close(AVFormatContext *s)
{
- NSLog(@"Closing session...");
+ av_log(s, AV_LOG_INFO, "Closing session...\n");
AVFoundationCaptureContext *ctx = s->priv_data;
destroy_context(ctx);
return 0;
--
2.6.2
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel