7b7cd68ab4350531fb247cc81bdc50f1e85ba72c
[ffmpeg.git] / libavdevice / avfoundation.m
1 /*
2  * AVFoundation input device
3  * Copyright (c) 2014 Thilo Borgmann <thilo.borgmann@mail.de>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file
24  * AVFoundation input device
25  * @author Thilo Borgmann <thilo.borgmann@mail.de>
26  */
27
28 #import <AVFoundation/AVFoundation.h>
29 #include <pthread.h>
30
31 #include "libavutil/pixdesc.h"
32 #include "libavutil/opt.h"
33 #include "libavutil/avstring.h"
34 #include "libavformat/internal.h"
35 #include "libavutil/internal.h"
36 #include "libavutil/parseutils.h"
37 #include "libavutil/time.h"
38 #include "avdevice.h"
39
40 static const int avf_time_base = 1000000;
41
42 static const AVRational avf_time_base_q = {
43     .num = 1,
44     .den = avf_time_base
45 };
46
47 struct AVFPixelFormatSpec {
48     enum AVPixelFormat ff_id;
49     OSType avf_id;
50 };
51
52 static const struct AVFPixelFormatSpec avf_pixel_formats[] = {
53     { AV_PIX_FMT_MONOBLACK,    kCVPixelFormatType_1Monochrome },
54     { AV_PIX_FMT_RGB555BE,     kCVPixelFormatType_16BE555 },
55     { AV_PIX_FMT_RGB555LE,     kCVPixelFormatType_16LE555 },
56     { AV_PIX_FMT_RGB565BE,     kCVPixelFormatType_16BE565 },
57     { AV_PIX_FMT_RGB565LE,     kCVPixelFormatType_16LE565 },
58     { AV_PIX_FMT_RGB24,        kCVPixelFormatType_24RGB },
59     { AV_PIX_FMT_BGR24,        kCVPixelFormatType_24BGR },
60     { AV_PIX_FMT_0RGB,         kCVPixelFormatType_32ARGB },
61     { AV_PIX_FMT_BGR0,         kCVPixelFormatType_32BGRA },
62     { AV_PIX_FMT_0BGR,         kCVPixelFormatType_32ABGR },
63     { AV_PIX_FMT_RGB0,         kCVPixelFormatType_32RGBA },
64     { AV_PIX_FMT_BGR48BE,      kCVPixelFormatType_48RGB },
65     { AV_PIX_FMT_UYVY422,      kCVPixelFormatType_422YpCbCr8 },
66     { AV_PIX_FMT_YUVA444P,     kCVPixelFormatType_4444YpCbCrA8R },
67     { AV_PIX_FMT_YUVA444P16LE, kCVPixelFormatType_4444AYpCbCr16 },
68     { AV_PIX_FMT_YUV444P,      kCVPixelFormatType_444YpCbCr8 },
69     { AV_PIX_FMT_YUV422P16,    kCVPixelFormatType_422YpCbCr16 },
70     { AV_PIX_FMT_YUV422P10,    kCVPixelFormatType_422YpCbCr10 },
71     { AV_PIX_FMT_YUV444P10,    kCVPixelFormatType_444YpCbCr10 },
72     { AV_PIX_FMT_YUV420P,      kCVPixelFormatType_420YpCbCr8Planar },
73     { AV_PIX_FMT_NV12,         kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange },
74     { AV_PIX_FMT_YUYV422,      kCVPixelFormatType_422YpCbCr8_yuvs },
75 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
76     { AV_PIX_FMT_GRAY8,        kCVPixelFormatType_OneComponent8 },
77 #endif
78     { AV_PIX_FMT_NONE, 0 }
79 };
80
81 typedef struct
82 {
83     AVClass*        class;
84
85     int             frames_captured;
86     int             audio_frames_captured;
87     int64_t         first_pts;
88     int64_t         first_audio_pts;
89     pthread_mutex_t frame_lock;
90     pthread_cond_t  frame_wait_cond;
91     id              avf_delegate;
92     id              avf_audio_delegate;
93
94     AVRational      framerate;
95     int             width, height;
96
97     int             list_devices;
98     int             video_device_index;
99     int             video_stream_index;
100     int             audio_device_index;
101     int             audio_stream_index;
102
103     char            *video_filename;
104     char            *audio_filename;
105
106     int             num_video_devices;
107
108     int             audio_channels;
109     int             audio_bits_per_sample;
110     int             audio_float;
111     int             audio_be;
112     int             audio_signed_integer;
113     int             audio_packed;
114     int             audio_non_interleaved;
115
116     int32_t         *audio_buffer;
117     int             audio_buffer_size;
118
119     enum AVPixelFormat pixel_format;
120
121     AVCaptureSession         *capture_session;
122     AVCaptureVideoDataOutput *video_output;
123     AVCaptureAudioDataOutput *audio_output;
124     CMSampleBufferRef         current_frame;
125     CMSampleBufferRef         current_audio_frame;
126 } AVFContext;
127
128 static void lock_frames(AVFContext* ctx)
129 {
130     pthread_mutex_lock(&ctx->frame_lock);
131 }
132
133 static void unlock_frames(AVFContext* ctx)
134 {
135     pthread_mutex_unlock(&ctx->frame_lock);
136 }
137
138 /** FrameReciever class - delegate for AVCaptureSession
139  */
140 @interface AVFFrameReceiver : NSObject
141 {
142     AVFContext* _context;
143 }
144
145 - (id)initWithContext:(AVFContext*)context;
146
147 - (void)  captureOutput:(AVCaptureOutput *)captureOutput
148   didOutputSampleBuffer:(CMSampleBufferRef)videoFrame
149          fromConnection:(AVCaptureConnection *)connection;
150
151 @end
152
153 @implementation AVFFrameReceiver
154
155 - (id)initWithContext:(AVFContext*)context
156 {
157     if (self = [super init]) {
158         _context = context;
159     }
160     return self;
161 }
162
163 - (void)  captureOutput:(AVCaptureOutput *)captureOutput
164   didOutputSampleBuffer:(CMSampleBufferRef)videoFrame
165          fromConnection:(AVCaptureConnection *)connection
166 {
167     lock_frames(_context);
168
169     if (_context->current_frame != nil) {
170         CFRelease(_context->current_frame);
171     }
172
173     _context->current_frame = (CMSampleBufferRef)CFRetain(videoFrame);
174
175     pthread_cond_signal(&_context->frame_wait_cond);
176
177     unlock_frames(_context);
178
179     ++_context->frames_captured;
180 }
181
182 @end
183
184 /** AudioReciever class - delegate for AVCaptureSession
185  */
186 @interface AVFAudioReceiver : NSObject
187 {
188     AVFContext* _context;
189 }
190
191 - (id)initWithContext:(AVFContext*)context;
192
193 - (void)  captureOutput:(AVCaptureOutput *)captureOutput
194   didOutputSampleBuffer:(CMSampleBufferRef)audioFrame
195          fromConnection:(AVCaptureConnection *)connection;
196
197 @end
198
199 @implementation AVFAudioReceiver
200
201 - (id)initWithContext:(AVFContext*)context
202 {
203     if (self = [super init]) {
204         _context = context;
205     }
206     return self;
207 }
208
209 - (void)  captureOutput:(AVCaptureOutput *)captureOutput
210   didOutputSampleBuffer:(CMSampleBufferRef)audioFrame
211          fromConnection:(AVCaptureConnection *)connection
212 {
213     lock_frames(_context);
214
215     if (_context->current_audio_frame != nil) {
216         CFRelease(_context->current_audio_frame);
217     }
218
219     _context->current_audio_frame = (CMSampleBufferRef)CFRetain(audioFrame);
220
221     pthread_cond_signal(&_context->frame_wait_cond);
222
223     unlock_frames(_context);
224
225     ++_context->audio_frames_captured;
226 }
227
228 @end
229
230 static void destroy_context(AVFContext* ctx)
231 {
232     [ctx->capture_session stopRunning];
233
234     [ctx->capture_session release];
235     [ctx->video_output    release];
236     [ctx->audio_output    release];
237     [ctx->avf_delegate    release];
238     [ctx->avf_audio_delegate release];
239
240     ctx->capture_session = NULL;
241     ctx->video_output    = NULL;
242     ctx->audio_output    = NULL;
243     ctx->avf_delegate    = NULL;
244     ctx->avf_audio_delegate = NULL;
245
246     av_freep(&ctx->audio_buffer);
247
248     pthread_mutex_destroy(&ctx->frame_lock);
249     pthread_cond_destroy(&ctx->frame_wait_cond);
250
251     if (ctx->current_frame) {
252         CFRelease(ctx->current_frame);
253     }
254 }
255
256 static void parse_device_name(AVFormatContext *s)
257 {
258     AVFContext *ctx = (AVFContext*)s->priv_data;
259     char *tmp = av_strdup(s->filename);
260     char *save;
261
262     if (tmp[0] != ':') {
263         ctx->video_filename = av_strtok(tmp,  ":", &save);
264         ctx->audio_filename = av_strtok(NULL, ":", &save);
265     } else {
266         ctx->audio_filename = av_strtok(tmp,  ":", &save);
267     }
268 }
269
270 /**
271  * Configure the video device.
272  *
273  * Configure the video device using a run-time approach to access properties
274  * since formats, activeFormat are available since  iOS >= 7.0 or OSX >= 10.7
275  * and activeVideoMaxFrameDuration is available since i0S >= 7.0 and OSX >= 10.9.
276  *
277  * The NSUndefinedKeyException must be handled by the caller of this function.
278  *
279  */
280 static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
281 {
282     AVFContext *ctx = (AVFContext*)s->priv_data;
283
284     double framerate = av_q2d(ctx->framerate);
285     NSObject *range = nil;
286     NSObject *format = nil;
287     NSObject *selected_range = nil;
288     NSObject *selected_format = nil;
289
290     for (format in [video_device valueForKey:@"formats"]) {
291         CMFormatDescriptionRef formatDescription;
292         CMVideoDimensions dimensions;
293
294         formatDescription = (CMFormatDescriptionRef) [format performSelector:@selector(formatDescription)];
295         dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
296
297         if ((ctx->width == 0 && ctx->height == 0) ||
298             (dimensions.width == ctx->width && dimensions.height == ctx->height)) {
299
300             selected_format = format;
301
302             for (range in [format valueForKey:@"videoSupportedFrameRateRanges"]) {
303                 double max_framerate;
304
305                 [[range valueForKey:@"maxFrameRate"] getValue:&max_framerate];
306                 if (fabs (framerate - max_framerate) < 0.01) {
307                     selected_range = range;
308                     break;
309                 }
310             }
311         }
312     }
313
314     if (!selected_format) {
315         av_log(s, AV_LOG_ERROR, "Selected video size (%dx%d) is not supported by the device\n",
316             ctx->width, ctx->height);
317         goto unsupported_format;
318     }
319
320     if (!selected_range) {
321         av_log(s, AV_LOG_ERROR, "Selected framerate (%f) is not supported by the device\n",
322             framerate);
323         goto unsupported_format;
324     }
325
326     if ([video_device lockForConfiguration:NULL] == YES) {
327         NSValue *min_frame_duration = [selected_range valueForKey:@"minFrameDuration"];
328
329         [video_device setValue:selected_format forKey:@"activeFormat"];
330         [video_device setValue:min_frame_duration forKey:@"activeVideoMinFrameDuration"];
331         [video_device setValue:min_frame_duration forKey:@"activeVideoMaxFrameDuration"];
332     } else {
333         av_log(s, AV_LOG_ERROR, "Could not lock device for configuration");
334         return AVERROR(EINVAL);
335     }
336
337     return 0;
338
339 unsupported_format:
340
341     av_log(s, AV_LOG_ERROR, "Supported modes:\n");
342     for (format in [video_device valueForKey:@"formats"]) {
343         CMFormatDescriptionRef formatDescription;
344         CMVideoDimensions dimensions;
345
346         formatDescription = (CMFormatDescriptionRef) [format performSelector:@selector(formatDescription)];
347         dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
348
349         for (range in [format valueForKey:@"videoSupportedFrameRateRanges"]) {
350             double min_framerate;
351             double max_framerate;
352
353             [[range valueForKey:@"minFrameRate"] getValue:&min_framerate];
354             [[range valueForKey:@"maxFrameRate"] getValue:&max_framerate];
355             av_log(s, AV_LOG_ERROR, "  %dx%d@[%f %f]fps\n",
356                 dimensions.width, dimensions.height,
357                 min_framerate, max_framerate);
358         }
359     }
360     return AVERROR(EINVAL);
361 }
362
363 static int add_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
364 {
365     AVFContext *ctx = (AVFContext*)s->priv_data;
366     int ret;
367     NSError *error  = nil;
368     AVCaptureInput* capture_input = nil;
369     struct AVFPixelFormatSpec pxl_fmt_spec;
370     NSNumber *pixel_format;
371     NSDictionary *capture_dict;
372     dispatch_queue_t queue;
373
374     if (ctx->video_device_index < ctx->num_video_devices) {
375         capture_input = (AVCaptureInput*) [[[AVCaptureDeviceInput alloc] initWithDevice:video_device error:&error] autorelease];
376     } else {
377         capture_input = (AVCaptureInput*) video_device;
378     }
379
380     if (!capture_input) {
381         av_log(s, AV_LOG_ERROR, "Failed to create AV capture input device: %s\n",
382                [[error localizedDescription] UTF8String]);
383         return 1;
384     }
385
386     if ([ctx->capture_session canAddInput:capture_input]) {
387         [ctx->capture_session addInput:capture_input];
388     } else {
389         av_log(s, AV_LOG_ERROR, "can't add video input to capture session\n");
390         return 1;
391     }
392
393     // Attaching output
394     ctx->video_output = [[AVCaptureVideoDataOutput alloc] init];
395
396     if (!ctx->video_output) {
397         av_log(s, AV_LOG_ERROR, "Failed to init AV video output\n");
398         return 1;
399     }
400
401     // Configure device framerate and video size
402     @try {
403         if ((ret = configure_video_device(s, video_device)) < 0) {
404             return ret;
405         }
406     } @catch (NSException *exception) {
407         if (![[exception name] isEqualToString:NSUndefinedKeyException]) {
408           av_log (s, AV_LOG_ERROR, "An error occured: %s", [exception.reason UTF8String]);
409           return AVERROR_EXTERNAL;
410         }
411     }
412
413     // select pixel format
414     pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE;
415
416     for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE; i++) {
417         if (ctx->pixel_format == avf_pixel_formats[i].ff_id) {
418             pxl_fmt_spec = avf_pixel_formats[i];
419             break;
420         }
421     }
422
423     // check if selected pixel format is supported by AVFoundation
424     if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
425         av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by AVFoundation.\n",
426                av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
427         return 1;
428     }
429
430     // check if the pixel format is available for this device
431     if ([[ctx->video_output availableVideoCVPixelFormatTypes] indexOfObject:[NSNumber numberWithInt:pxl_fmt_spec.avf_id]] == NSNotFound) {
432         av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by the input device.\n",
433                av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
434
435         pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE;
436
437         av_log(s, AV_LOG_ERROR, "Supported pixel formats:\n");
438         for (NSNumber *pxl_fmt in [ctx->video_output availableVideoCVPixelFormatTypes]) {
439             struct AVFPixelFormatSpec pxl_fmt_dummy;
440             pxl_fmt_dummy.ff_id = AV_PIX_FMT_NONE;
441             for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE; i++) {
442                 if ([pxl_fmt intValue] == avf_pixel_formats[i].avf_id) {
443                     pxl_fmt_dummy = avf_pixel_formats[i];
444                     break;
445                 }
446             }
447
448             if (pxl_fmt_dummy.ff_id != AV_PIX_FMT_NONE) {
449                 av_log(s, AV_LOG_ERROR, "  %s\n", av_get_pix_fmt_name(pxl_fmt_dummy.ff_id));
450
451                 // select first supported pixel format instead of user selected (or default) pixel format
452                 if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
453                     pxl_fmt_spec = pxl_fmt_dummy;
454                 }
455             }
456         }
457
458         // fail if there is no appropriate pixel format or print a warning about overriding the pixel format
459         if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
460             return 1;
461         } else {
462             av_log(s, AV_LOG_WARNING, "Overriding selected pixel format to use %s instead.\n",
463                    av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
464         }
465     }
466
467     ctx->pixel_format          = pxl_fmt_spec.ff_id;
468     pixel_format = [NSNumber numberWithUnsignedInt:pxl_fmt_spec.avf_id];
469     capture_dict = [NSDictionary dictionaryWithObject:pixel_format
470                                                forKey:(id)kCVPixelBufferPixelFormatTypeKey];
471
472     [ctx->video_output setVideoSettings:capture_dict];
473     [ctx->video_output setAlwaysDiscardsLateVideoFrames:YES];
474
475     ctx->avf_delegate = [[AVFFrameReceiver alloc] initWithContext:ctx];
476
477     queue = dispatch_queue_create("avf_queue", NULL);
478     [ctx->video_output setSampleBufferDelegate:ctx->avf_delegate queue:queue];
479     dispatch_release(queue);
480
481     if ([ctx->capture_session canAddOutput:ctx->video_output]) {
482         [ctx->capture_session addOutput:ctx->video_output];
483     } else {
484         av_log(s, AV_LOG_ERROR, "can't add video output to capture session\n");
485         return 1;
486     }
487
488     return 0;
489 }
490
491 static int add_audio_device(AVFormatContext *s, AVCaptureDevice *audio_device)
492 {
493     AVFContext *ctx = (AVFContext*)s->priv_data;
494     NSError *error  = nil;
495     AVCaptureDeviceInput* audio_dev_input = [[[AVCaptureDeviceInput alloc] initWithDevice:audio_device error:&error] autorelease];
496     dispatch_queue_t queue;
497
498     if (!audio_dev_input) {
499         av_log(s, AV_LOG_ERROR, "Failed to create AV capture input device: %s\n",
500                [[error localizedDescription] UTF8String]);
501         return 1;
502     }
503
504     if ([ctx->capture_session canAddInput:audio_dev_input]) {
505         [ctx->capture_session addInput:audio_dev_input];
506     } else {
507         av_log(s, AV_LOG_ERROR, "can't add audio input to capture session\n");
508         return 1;
509     }
510
511     // Attaching output
512     ctx->audio_output = [[AVCaptureAudioDataOutput alloc] init];
513
514     if (!ctx->audio_output) {
515         av_log(s, AV_LOG_ERROR, "Failed to init AV audio output\n");
516         return 1;
517     }
518
519     ctx->avf_audio_delegate = [[AVFAudioReceiver alloc] initWithContext:ctx];
520
521     queue = dispatch_queue_create("avf_audio_queue", NULL);
522     [ctx->audio_output setSampleBufferDelegate:ctx->avf_audio_delegate queue:queue];
523     dispatch_release(queue);
524
525     if ([ctx->capture_session canAddOutput:ctx->audio_output]) {
526         [ctx->capture_session addOutput:ctx->audio_output];
527     } else {
528         av_log(s, AV_LOG_ERROR, "adding audio output to capture session failed\n");
529         return 1;
530     }
531
532     return 0;
533 }
534
535 static int get_video_config(AVFormatContext *s)
536 {
537     AVFContext *ctx = (AVFContext*)s->priv_data;
538     CVImageBufferRef image_buffer;
539     CGSize image_buffer_size;
540     AVStream* stream = avformat_new_stream(s, NULL);
541
542     if (!stream) {
543         return 1;
544     }
545
546     // Take stream info from the first frame.
547     while (ctx->frames_captured < 1) {
548         CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES);
549     }
550
551     lock_frames(ctx);
552
553     ctx->video_stream_index = stream->index;
554
555     avpriv_set_pts_info(stream, 64, 1, avf_time_base);
556
557     image_buffer      = CMSampleBufferGetImageBuffer(ctx->current_frame);
558     image_buffer_size = CVImageBufferGetEncodedSize(image_buffer);
559
560     stream->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
561     stream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
562     stream->codec->width      = (int)image_buffer_size.width;
563     stream->codec->height     = (int)image_buffer_size.height;
564     stream->codec->pix_fmt    = ctx->pixel_format;
565
566     CFRelease(ctx->current_frame);
567     ctx->current_frame = nil;
568
569     unlock_frames(ctx);
570
571     return 0;
572 }
573
574 static int get_audio_config(AVFormatContext *s)
575 {
576     AVFContext *ctx = (AVFContext*)s->priv_data;
577     CMFormatDescriptionRef format_desc;
578     AVStream* stream = avformat_new_stream(s, NULL);
579
580     if (!stream) {
581         return 1;
582     }
583
584     // Take stream info from the first frame.
585     while (ctx->audio_frames_captured < 1) {
586         CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES);
587     }
588
589     lock_frames(ctx);
590
591     ctx->audio_stream_index = stream->index;
592
593     avpriv_set_pts_info(stream, 64, 1, avf_time_base);
594
595     format_desc = CMSampleBufferGetFormatDescription(ctx->current_audio_frame);
596     const AudioStreamBasicDescription *basic_desc = CMAudioFormatDescriptionGetStreamBasicDescription(format_desc);
597
598     if (!basic_desc) {
599         av_log(s, AV_LOG_ERROR, "audio format not available\n");
600         return 1;
601     }
602
603     stream->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
604     stream->codec->sample_rate    = basic_desc->mSampleRate;
605     stream->codec->channels       = basic_desc->mChannelsPerFrame;
606     stream->codec->channel_layout = av_get_default_channel_layout(stream->codec->channels);
607
608     ctx->audio_channels        = basic_desc->mChannelsPerFrame;
609     ctx->audio_bits_per_sample = basic_desc->mBitsPerChannel;
610     ctx->audio_float           = basic_desc->mFormatFlags & kAudioFormatFlagIsFloat;
611     ctx->audio_be              = basic_desc->mFormatFlags & kAudioFormatFlagIsBigEndian;
612     ctx->audio_signed_integer  = basic_desc->mFormatFlags & kAudioFormatFlagIsSignedInteger;
613     ctx->audio_packed          = basic_desc->mFormatFlags & kAudioFormatFlagIsPacked;
614     ctx->audio_non_interleaved = basic_desc->mFormatFlags & kAudioFormatFlagIsNonInterleaved;
615
616     if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
617         ctx->audio_float &&
618         ctx->audio_bits_per_sample == 32 &&
619         ctx->audio_packed) {
620         stream->codec->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
621     } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
622         ctx->audio_signed_integer &&
623         ctx->audio_bits_per_sample == 16 &&
624         ctx->audio_packed) {
625         stream->codec->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
626     } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
627         ctx->audio_signed_integer &&
628         ctx->audio_bits_per_sample == 24 &&
629         ctx->audio_packed) {
630         stream->codec->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
631     } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
632         ctx->audio_signed_integer &&
633         ctx->audio_bits_per_sample == 32 &&
634         ctx->audio_packed) {
635         stream->codec->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
636     } else {
637         av_log(s, AV_LOG_ERROR, "audio format is not supported\n");
638         return 1;
639     }
640
641     if (ctx->audio_non_interleaved) {
642         CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
643         ctx->audio_buffer_size        = CMBlockBufferGetDataLength(block_buffer);
644         ctx->audio_buffer             = av_malloc(ctx->audio_buffer_size);
645         if (!ctx->audio_buffer) {
646             av_log(s, AV_LOG_ERROR, "error allocating audio buffer\n");
647             return 1;
648         }
649     }
650
651     CFRelease(ctx->current_audio_frame);
652     ctx->current_audio_frame = nil;
653
654     unlock_frames(ctx);
655
656     return 0;
657 }
658
659 static int avf_read_header(AVFormatContext *s)
660 {
661     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
662     int capture_screen      = 0;
663     uint32_t num_screens    = 0;
664     AVFContext *ctx         = (AVFContext*)s->priv_data;
665     AVCaptureDevice *video_device = nil;
666     AVCaptureDevice *audio_device = nil;
667     // Find capture device
668     NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
669     ctx->num_video_devices = [devices count];
670
671     ctx->first_pts          = av_gettime();
672     ctx->first_audio_pts    = av_gettime();
673
674     pthread_mutex_init(&ctx->frame_lock, NULL);
675     pthread_cond_init(&ctx->frame_wait_cond, NULL);
676
677 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
678     CGGetActiveDisplayList(0, NULL, &num_screens);
679 #endif
680
681     // List devices if requested
682     if (ctx->list_devices) {
683         int index = 0;
684         av_log(ctx, AV_LOG_INFO, "AVFoundation video devices:\n");
685         for (AVCaptureDevice *device in devices) {
686             const char *name = [[device localizedName] UTF8String];
687             index            = [devices indexOfObject:device];
688             av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name);
689             index++;
690         }
691 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
692         if (num_screens > 0) {
693             CGDirectDisplayID screens[num_screens];
694             CGGetActiveDisplayList(num_screens, screens, &num_screens);
695             for (int i = 0; i < num_screens; i++) {
696                 av_log(ctx, AV_LOG_INFO, "[%d] Capture screen %d\n", index + i, i);
697             }
698         }
699 #endif
700
701         av_log(ctx, AV_LOG_INFO, "AVFoundation audio devices:\n");
702         devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
703         for (AVCaptureDevice *device in devices) {
704             const char *name = [[device localizedName] UTF8String];
705             int index  = [devices indexOfObject:device];
706             av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name);
707         }
708          goto fail;
709     }
710
711     // parse input filename for video and audio device
712     parse_device_name(s);
713
714     // check for device index given in filename
715     if (ctx->video_device_index == -1 && ctx->video_filename) {
716         sscanf(ctx->video_filename, "%d", &ctx->video_device_index);
717     }
718     if (ctx->audio_device_index == -1 && ctx->audio_filename) {
719         sscanf(ctx->audio_filename, "%d", &ctx->audio_device_index);
720     }
721
722     if (ctx->video_device_index >= 0) {
723         if (ctx->video_device_index < ctx->num_video_devices) {
724             video_device = [devices objectAtIndex:ctx->video_device_index];
725         } else if (ctx->video_device_index < ctx->num_video_devices + num_screens) {
726 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
727             CGDirectDisplayID screens[num_screens];
728             CGGetActiveDisplayList(num_screens, screens, &num_screens);
729             AVCaptureScreenInput* capture_screen_input = [[[AVCaptureScreenInput alloc] initWithDisplayID:screens[ctx->video_device_index - ctx->num_video_devices]] autorelease];
730
731             if (ctx->framerate.num > 0) {
732                 capture_screen_input.minFrameDuration = CMTimeMake(ctx->framerate.den, ctx->framerate.num);
733             }
734
735             video_device = (AVCaptureDevice*) capture_screen_input;
736             capture_screen = 1;
737 #endif
738          } else {
739             av_log(ctx, AV_LOG_ERROR, "Invalid device index\n");
740             goto fail;
741         }
742     } else if (ctx->video_filename &&
743                strncmp(ctx->video_filename, "none", 4)) {
744         if (!strncmp(ctx->video_filename, "default", 7)) {
745             video_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
746         } else {
747         // looking for video inputs
748         for (AVCaptureDevice *device in devices) {
749             if (!strncmp(ctx->video_filename, [[device localizedName] UTF8String], strlen(ctx->video_filename))) {
750                 video_device = device;
751                 break;
752             }
753         }
754
755 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
756         // looking for screen inputs
757         if (!video_device) {
758             int idx;
759             if(sscanf(ctx->video_filename, "Capture screen %d", &idx) && idx < num_screens) {
760                 CGDirectDisplayID screens[num_screens];
761                 CGGetActiveDisplayList(num_screens, screens, &num_screens);
762                 AVCaptureScreenInput* capture_screen_input = [[[AVCaptureScreenInput alloc] initWithDisplayID:screens[idx]] autorelease];
763                 video_device = (AVCaptureDevice*) capture_screen_input;
764                 ctx->video_device_index = ctx->num_video_devices + idx;
765                 capture_screen = 1;
766
767                 if (ctx->framerate.num > 0) {
768                     capture_screen_input.minFrameDuration = CMTimeMake(ctx->framerate.den, ctx->framerate.num);
769                 }
770             }
771         }
772 #endif
773         }
774
775         if (!video_device) {
776             av_log(ctx, AV_LOG_ERROR, "Video device not found\n");
777             goto fail;
778         }
779     }
780
781     // get audio device
782     if (ctx->audio_device_index >= 0) {
783         NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
784
785         if (ctx->audio_device_index >= [devices count]) {
786             av_log(ctx, AV_LOG_ERROR, "Invalid audio device index\n");
787             goto fail;
788         }
789
790         audio_device = [devices objectAtIndex:ctx->audio_device_index];
791     } else if (ctx->audio_filename &&
792                strncmp(ctx->audio_filename, "none", 4)) {
793         if (!strncmp(ctx->audio_filename, "default", 7)) {
794             audio_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
795         } else {
796         NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
797
798         for (AVCaptureDevice *device in devices) {
799             if (!strncmp(ctx->audio_filename, [[device localizedName] UTF8String], strlen(ctx->audio_filename))) {
800                 audio_device = device;
801                 break;
802             }
803         }
804         }
805
806         if (!audio_device) {
807             av_log(ctx, AV_LOG_ERROR, "Audio device not found\n");
808              goto fail;
809         }
810     }
811
812     // Video nor Audio capture device not found, looking for AVMediaTypeVideo/Audio
813     if (!video_device && !audio_device) {
814         av_log(s, AV_LOG_ERROR, "No AV capture device found\n");
815         goto fail;
816     }
817
818     if (video_device) {
819         if (ctx->video_device_index < ctx->num_video_devices) {
820             av_log(s, AV_LOG_DEBUG, "'%s' opened\n", [[video_device localizedName] UTF8String]);
821         } else {
822             av_log(s, AV_LOG_DEBUG, "'%s' opened\n", [[video_device description] UTF8String]);
823         }
824     }
825     if (audio_device) {
826         av_log(s, AV_LOG_DEBUG, "audio device '%s' opened\n", [[audio_device localizedName] UTF8String]);
827     }
828
829     // Initialize capture session
830     ctx->capture_session = [[AVCaptureSession alloc] init];
831
832     if (video_device && add_video_device(s, video_device)) {
833         goto fail;
834     }
835     if (audio_device && add_audio_device(s, audio_device)) {
836     }
837
838     [ctx->capture_session startRunning];
839
840     /* Unlock device configuration only after the session is started so it
841      * does not reset the capture formats */
842     if (!capture_screen) {
843         [video_device unlockForConfiguration];
844     }
845
846     if (video_device && get_video_config(s)) {
847         goto fail;
848     }
849
850     // set audio stream
851     if (audio_device && get_audio_config(s)) {
852         goto fail;
853     }
854
855     [pool release];
856     return 0;
857
858 fail:
859     [pool release];
860     destroy_context(ctx);
861     return AVERROR(EIO);
862 }
863
864 static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)
865 {
866     AVFContext* ctx = (AVFContext*)s->priv_data;
867
868     do {
869         CVImageBufferRef image_buffer;
870         lock_frames(ctx);
871
872         image_buffer = CMSampleBufferGetImageBuffer(ctx->current_frame);
873
874         if (ctx->current_frame != nil) {
875             void *data;
876             if (av_new_packet(pkt, (int)CVPixelBufferGetDataSize(image_buffer)) < 0) {
877                 return AVERROR(EIO);
878             }
879
880             pkt->pts = pkt->dts = av_rescale_q(av_gettime() - ctx->first_pts,
881                                                AV_TIME_BASE_Q,
882                                                avf_time_base_q);
883             pkt->stream_index  = ctx->video_stream_index;
884             pkt->flags        |= AV_PKT_FLAG_KEY;
885
886             CVPixelBufferLockBaseAddress(image_buffer, 0);
887
888             data = CVPixelBufferGetBaseAddress(image_buffer);
889             memcpy(pkt->data, data, pkt->size);
890
891             CVPixelBufferUnlockBaseAddress(image_buffer, 0);
892             CFRelease(ctx->current_frame);
893             ctx->current_frame = nil;
894         } else if (ctx->current_audio_frame != nil) {
895             CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
896             int block_buffer_size         = CMBlockBufferGetDataLength(block_buffer);
897
898             if (!block_buffer || !block_buffer_size) {
899                 return AVERROR(EIO);
900             }
901
902             if (ctx->audio_non_interleaved && block_buffer_size > ctx->audio_buffer_size) {
903                 return AVERROR_BUFFER_TOO_SMALL;
904             }
905
906             if (av_new_packet(pkt, block_buffer_size) < 0) {
907                 return AVERROR(EIO);
908             }
909
910             pkt->pts = pkt->dts = av_rescale_q(av_gettime() - ctx->first_audio_pts,
911                                                AV_TIME_BASE_Q,
912                                                avf_time_base_q);
913
914             pkt->stream_index  = ctx->audio_stream_index;
915             pkt->flags        |= AV_PKT_FLAG_KEY;
916
917             if (ctx->audio_non_interleaved) {
918                 int sample, c, shift, num_samples;
919
920                 OSStatus ret = CMBlockBufferCopyDataBytes(block_buffer, 0, pkt->size, ctx->audio_buffer);
921                 if (ret != kCMBlockBufferNoErr) {
922                     return AVERROR(EIO);
923                 }
924
925                 num_samples = pkt->size / (ctx->audio_channels * (ctx->audio_bits_per_sample >> 3));
926
927                 // transform decoded frame into output format
928                 #define INTERLEAVE_OUTPUT(bps)                                         \
929                 {                                                                      \
930                     int##bps##_t **src;                                                \
931                     int##bps##_t *dest;                                                \
932                     src = av_malloc(ctx->audio_channels * sizeof(int##bps##_t*));      \
933                     if (!src) return AVERROR(EIO);                                     \
934                     for (c = 0; c < ctx->audio_channels; c++) {                        \
935                         src[c] = ((int##bps##_t*)ctx->audio_buffer) + c * num_samples; \
936                     }                                                                  \
937                     dest  = (int##bps##_t*)pkt->data;                                  \
938                     shift = bps - ctx->audio_bits_per_sample;                          \
939                     for (sample = 0; sample < num_samples; sample++)                   \
940                         for (c = 0; c < ctx->audio_channels; c++)                      \
941                             *dest++ = src[c][sample] << shift;                         \
942                     av_freep(&src);                                                    \
943                 }
944
945                 if (ctx->audio_bits_per_sample <= 16) {
946                     INTERLEAVE_OUTPUT(16)
947                 } else {
948                     INTERLEAVE_OUTPUT(32)
949                 }
950             } else {
951                 OSStatus ret = CMBlockBufferCopyDataBytes(block_buffer, 0, pkt->size, pkt->data);
952                 if (ret != kCMBlockBufferNoErr) {
953                     return AVERROR(EIO);
954                 }
955             }
956
957             CFRelease(ctx->current_audio_frame);
958             ctx->current_audio_frame = nil;
959         } else {
960             pkt->data = NULL;
961             pthread_cond_wait(&ctx->frame_wait_cond, &ctx->frame_lock);
962         }
963
964         unlock_frames(ctx);
965     } while (!pkt->data);
966
967     return 0;
968 }
969
970 static int avf_close(AVFormatContext *s)
971 {
972     AVFContext* ctx = (AVFContext*)s->priv_data;
973     destroy_context(ctx);
974     return 0;
975 }
976
977 static const AVOption options[] = {
978     { "list_devices", "list available devices", offsetof(AVFContext, list_devices), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
979     { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
980     { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
981     { "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 },
982     { "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 },
983     { "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},
984     { "framerate", "set frame rate", offsetof(AVFContext, framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
985     { "video_size", "set video size", offsetof(AVFContext, width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
986     { NULL },
987 };
988
989 static const AVClass avf_class = {
990     .class_name = "AVFoundation input device",
991     .item_name  = av_default_item_name,
992     .option     = options,
993     .version    = LIBAVUTIL_VERSION_INT,
994     .category   = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,
995 };
996
997 AVInputFormat ff_avfoundation_demuxer = {
998     .name           = "avfoundation",
999     .long_name      = NULL_IF_CONFIG_SMALL("AVFoundation input device"),
1000     .priv_data_size = sizeof(AVFContext),
1001     .read_header    = avf_read_header,
1002     .read_packet    = avf_read_packet,
1003     .read_close     = avf_close,
1004     .flags          = AVFMT_NOFILE,
1005     .priv_class     = &avf_class,
1006 };