FFmpeg
avfoundation.m
Go to the documentation of this file.
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 #include "config.h"
29 
30 #import <AVFoundation/AVFoundation.h>
31 #if HAVE_IOKIT
32 # import <IOKit/IOKitLib.h>
33  /* kIOMainPortDefault replaced kIOMasterPortDefault in the macOS 12 SDK. */
34 # if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 120000
35 # define AVF_IO_MAIN_PORT_DEFAULT kIOMainPortDefault
36 # else
37 # define AVF_IO_MAIN_PORT_DEFAULT kIOMasterPortDefault
38 # endif
39 #endif
40 
41 #include <pthread.h>
42 
44 #include "libavutil/mem.h"
45 #include "libavutil/pixdesc.h"
46 #include "libavutil/opt.h"
47 #include "libavutil/avstring.h"
48 #include "libavformat/demux.h"
49 #include "libavformat/internal.h"
50 #include "libavutil/internal.h"
51 #include "libavutil/parseutils.h"
52 #include "libavutil/time.h"
53 #include "libavutil/imgutils.h"
54 #include "avdevice.h"
55 
56 static const int avf_time_base = 1000000;
57 
58 static const AVRational avf_time_base_q = {
59  .num = 1,
60  .den = avf_time_base
61 };
62 
65  OSType avf_id;
66 };
67 
68 static const struct AVFPixelFormatSpec avf_pixel_formats[] = {
69  { AV_PIX_FMT_MONOBLACK, kCVPixelFormatType_1Monochrome },
70  { AV_PIX_FMT_RGB555BE, kCVPixelFormatType_16BE555 },
71  { AV_PIX_FMT_RGB555LE, kCVPixelFormatType_16LE555 },
72  { AV_PIX_FMT_RGB565BE, kCVPixelFormatType_16BE565 },
73  { AV_PIX_FMT_RGB565LE, kCVPixelFormatType_16LE565 },
74  { AV_PIX_FMT_RGB24, kCVPixelFormatType_24RGB },
75  { AV_PIX_FMT_BGR24, kCVPixelFormatType_24BGR },
76  { AV_PIX_FMT_0RGB, kCVPixelFormatType_32ARGB },
77  { AV_PIX_FMT_BGR0, kCVPixelFormatType_32BGRA },
78  { AV_PIX_FMT_0BGR, kCVPixelFormatType_32ABGR },
79  { AV_PIX_FMT_RGB0, kCVPixelFormatType_32RGBA },
80  { AV_PIX_FMT_BGR48BE, kCVPixelFormatType_48RGB },
81  { AV_PIX_FMT_UYVY422, kCVPixelFormatType_422YpCbCr8 },
82  { AV_PIX_FMT_YUVA444P, kCVPixelFormatType_4444YpCbCrA8R },
83  { AV_PIX_FMT_YUVA444P16LE, kCVPixelFormatType_4444AYpCbCr16 },
84  { AV_PIX_FMT_YUV444P, kCVPixelFormatType_444YpCbCr8 },
85  { AV_PIX_FMT_YUV422P16, kCVPixelFormatType_422YpCbCr16 },
86  { AV_PIX_FMT_YUV422P10, kCVPixelFormatType_422YpCbCr10 },
87  { AV_PIX_FMT_YUV444P10, kCVPixelFormatType_444YpCbCr10 },
88  { AV_PIX_FMT_YUV420P, kCVPixelFormatType_420YpCbCr8Planar },
89  { AV_PIX_FMT_NV12, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange },
90  { AV_PIX_FMT_YUYV422, kCVPixelFormatType_422YpCbCr8_yuvs },
91 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
92  { AV_PIX_FMT_GRAY8, kCVPixelFormatType_OneComponent8 },
93 #endif
94  { AV_PIX_FMT_NONE, 0 }
95 };
96 
97 typedef struct
98 {
99  AVClass* class;
100 
108 
110  int width, height;
111 
118 
124 
125  char *url;
130 
132 
136  int audio_be;
140 
143 
144  enum AVPixelFormat pixel_format;
145 
146  AVCaptureSession *capture_session;
147  AVCaptureVideoDataOutput *video_output;
148  AVCaptureAudioDataOutput *audio_output;
149  CMSampleBufferRef current_frame;
150  CMSampleBufferRef current_audio_frame;
151 
152  AVCaptureDevice *observed_device;
153 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
154  AVCaptureDeviceTransportControlsPlaybackMode observed_mode;
155 #endif
157 } AVFContext;
158 
160 {
161  pthread_mutex_lock(&ctx->frame_lock);
162 }
163 
165 {
166  pthread_cond_broadcast(&ctx->frame_wait_cond);
167  pthread_mutex_unlock(&ctx->frame_lock);
168 }
169 
170 /** FrameReceiver class - delegate for AVCaptureSession
171  */
172 @interface AVFFrameReceiver : NSObject
173 {
175 }
176 
177 - (id)initWithContext:(AVFContext*)context;
178 
179 - (void) captureOutput:(AVCaptureOutput *)captureOutput
180  didOutputSampleBuffer:(CMSampleBufferRef)videoFrame
181  fromConnection:(AVCaptureConnection *)connection;
182 
183 @end
184 
185 @implementation AVFFrameReceiver
186 
187 - (id)initWithContext:(AVFContext*)context
188 {
189  if (self = [super init]) {
190  _context = context;
191 
192  // start observing if a device is set for it
193 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
194  if (_context->observed_device) {
195  NSString *keyPath = NSStringFromSelector(@selector(transportControlsPlaybackMode));
196  NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew;
197 
198  [_context->observed_device addObserver: self
199  forKeyPath: keyPath
200  options: options
201  context: _context];
202  }
203 #endif
204  }
205  return self;
206 }
207 
208 - (void)dealloc {
209  // stop observing if a device is set for it
210 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
211  if (_context->observed_device) {
212  NSString *keyPath = NSStringFromSelector(@selector(transportControlsPlaybackMode));
213  [_context->observed_device removeObserver: self forKeyPath: keyPath];
214  }
215 #endif
216  [super dealloc];
217 }
218 
219 - (void)observeValueForKeyPath:(NSString *)keyPath
220  ofObject:(id)object
221  change:(NSDictionary *)change
222  context:(void *)context {
223  if (context == _context) {
224 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
225  AVCaptureDeviceTransportControlsPlaybackMode mode =
226  [change[NSKeyValueChangeNewKey] integerValue];
227 
228  if (mode != _context->observed_mode) {
229  if (mode == AVCaptureDeviceTransportControlsNotPlayingMode) {
230  // Set under the lock and broadcast so a reader blocked in
231  // avf_read_packet() wakes up and returns EOF instead of
232  // hanging once the device stops delivering frames.
234  _context->observed_quit = 1;
236  }
237  _context->observed_mode = mode;
238  }
239 #endif
240  } else {
241  [super observeValueForKeyPath: keyPath
242  ofObject: object
243  change: change
244  context: context];
245  }
246 }
247 
248 - (void) captureOutput:(AVCaptureOutput *)captureOutput
249  didOutputSampleBuffer:(CMSampleBufferRef)videoFrame
250  fromConnection:(AVCaptureConnection *)connection
251 {
253 
254  while ((_context->current_frame != nil) && !_context->is_stopping) {
256  }
257 
258  if (_context->is_stopping) {
260  return;
261  }
262 
263  _context->current_frame = (CMSampleBufferRef)CFRetain(videoFrame);
264 
266 
268 }
269 
270 @end
271 
272 /** AudioReceiver class - delegate for AVCaptureSession
273  */
274 @interface AVFAudioReceiver : NSObject
275 {
277 }
278 
279 - (id)initWithContext:(AVFContext*)context;
280 
281 - (void) captureOutput:(AVCaptureOutput *)captureOutput
282  didOutputSampleBuffer:(CMSampleBufferRef)audioFrame
283  fromConnection:(AVCaptureConnection *)connection;
284 
285 @end
286 
287 @implementation AVFAudioReceiver
288 
289 - (id)initWithContext:(AVFContext*)context
290 {
291  if (self = [super init]) {
292  _context = context;
293  }
294  return self;
295 }
296 
297 - (void) captureOutput:(AVCaptureOutput *)captureOutput
298  didOutputSampleBuffer:(CMSampleBufferRef)audioFrame
299  fromConnection:(AVCaptureConnection *)connection
300 {
302 
303  while ((_context->current_audio_frame != nil) && !_context->is_stopping) {
305  }
306 
307  if (_context->is_stopping) {
309  return;
310  }
311 
312  _context->current_audio_frame = (CMSampleBufferRef)CFRetain(audioFrame);
313 
315 
317 }
318 
319 @end
320 
322 {
323  // Wake any capture callback blocked waiting for the consumer and make it
324  // bail out, so stopRunning() can drain the session without a deadlock.
325  lock_frames(ctx);
326  ctx->is_stopping = 1;
328 
329  [ctx->capture_session stopRunning];
330 
331  [ctx->capture_session release];
332  [ctx->video_output release];
333  [ctx->audio_output release];
334  [ctx->avf_delegate release];
335  [ctx->avf_audio_delegate release];
336 
337  ctx->capture_session = NULL;
338  ctx->video_output = NULL;
339  ctx->audio_output = NULL;
340  ctx->avf_delegate = NULL;
341  ctx->avf_audio_delegate = NULL;
342 
343  av_freep(&ctx->url);
344  av_freep(&ctx->audio_buffer);
345 
346  pthread_cond_destroy(&ctx->frame_wait_cond);
347  pthread_mutex_destroy(&ctx->frame_lock);
348 
349  if (ctx->current_frame) {
350  CFRelease(ctx->current_frame);
351  ctx->current_frame = nil;
352  }
353 
354  if (ctx->current_audio_frame) {
355  CFRelease(ctx->current_audio_frame);
356  ctx->current_audio_frame = nil;
357  }
358 }
359 
361 {
362  AVFContext *ctx = (AVFContext*)s->priv_data;
363  char *save;
364 
365  ctx->url = av_strdup(s->url);
366 
367  if (!ctx->url)
368  return AVERROR(ENOMEM);
369  if (ctx->url[0] != ':') {
370  ctx->video_filename = av_strtok(ctx->url, ":", &save);
371  ctx->audio_filename = av_strtok(NULL, ":", &save);
372  } else {
373  ctx->audio_filename = av_strtok(ctx->url, ":", &save);
374  }
375  return 0;
376 }
377 
378 /**
379  * Configure the video device.
380  *
381  * Configure the video device using a run-time approach to access properties
382  * since formats, activeFormat are available since iOS >= 7.0 or OSX >= 10.7
383  * and activeVideoMaxFrameDuration is available since i0S >= 7.0 and OSX >= 10.9.
384  *
385  * The NSUndefinedKeyException must be handled by the caller of this function.
386  *
387  */
388 static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
389 {
390  AVFContext *ctx = (AVFContext*)s->priv_data;
391 
392  double framerate = av_q2d(ctx->framerate);
393  NSObject *range = nil;
394  NSObject *format = nil;
395  NSObject *selected_range = nil;
396  NSObject *selected_format = nil;
397 
398  // try to configure format by formats list
399  // might raise an exception if no format list is given
400  // (then fallback to default, no configuration)
401  @try {
402  for (format in [video_device valueForKey:@"formats"]) {
403  CMFormatDescriptionRef formatDescription;
404  CMVideoDimensions dimensions;
405 
406  formatDescription = (CMFormatDescriptionRef) [format performSelector:@selector(formatDescription)];
407  dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
408 
409  if ((ctx->width == 0 && ctx->height == 0) ||
410  (dimensions.width == ctx->width && dimensions.height == ctx->height)) {
411 
412  selected_format = format;
413 
414  for (range in [format valueForKey:@"videoSupportedFrameRateRanges"]) {
415  double max_framerate;
416 
417  [[range valueForKey:@"maxFrameRate"] getValue:&max_framerate];
418  if (fabs (framerate - max_framerate) < 0.01) {
419  selected_range = range;
420  break;
421  }
422  }
423  }
424  }
425 
426  if (!selected_format) {
427  av_log(s, AV_LOG_ERROR, "Selected video size (%dx%d) is not supported by the device.\n",
428  ctx->width, ctx->height);
429  goto unsupported_format;
430  }
431 
432  if (!selected_range) {
433  av_log(s, AV_LOG_ERROR, "Selected framerate (%f) is not supported by the device.\n",
434  framerate);
435  if (ctx->video_is_muxed) {
436  av_log(s, AV_LOG_ERROR, "Falling back to default.\n");
437  } else {
438  goto unsupported_format;
439  }
440  }
441 
442  if ([video_device lockForConfiguration:NULL] == YES) {
443  if (selected_format) {
444  [video_device setValue:selected_format forKey:@"activeFormat"];
445  }
446  if (selected_range) {
447  NSValue *min_frame_duration = [selected_range valueForKey:@"minFrameDuration"];
448  [video_device setValue:min_frame_duration forKey:@"activeVideoMinFrameDuration"];
449  [video_device setValue:min_frame_duration forKey:@"activeVideoMaxFrameDuration"];
450  }
451  } else {
452  av_log(s, AV_LOG_ERROR, "Could not lock device for configuration.\n");
453  return AVERROR(EINVAL);
454  }
455  } @catch(NSException *e) {
456  av_log(ctx, AV_LOG_WARNING, "Configuration of video device failed, falling back to default.\n");
457  }
458 
459  return 0;
460 
461 unsupported_format:
462 
463  av_log(s, AV_LOG_ERROR, "Supported modes:\n");
464  for (format in [video_device valueForKey:@"formats"]) {
465  CMFormatDescriptionRef formatDescription;
466  CMVideoDimensions dimensions;
467 
468  formatDescription = (CMFormatDescriptionRef) [format performSelector:@selector(formatDescription)];
469  dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
470 
471  for (range in [format valueForKey:@"videoSupportedFrameRateRanges"]) {
472  double min_framerate;
473  double max_framerate;
474 
475  [[range valueForKey:@"minFrameRate"] getValue:&min_framerate];
476  [[range valueForKey:@"maxFrameRate"] getValue:&max_framerate];
477  av_log(s, AV_LOG_ERROR, " %dx%d@[%f %f]fps\n",
478  dimensions.width, dimensions.height,
479  min_framerate, max_framerate);
480  }
481  }
482  return AVERROR(EINVAL);
483 }
484 
485 static int add_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
486 {
487  AVFContext *ctx = (AVFContext*)s->priv_data;
488  int ret;
489  NSError *error = nil;
490  AVCaptureInput* capture_input = nil;
491  struct AVFPixelFormatSpec pxl_fmt_spec;
492  NSNumber *pixel_format;
493  NSDictionary *capture_dict;
494  dispatch_queue_t queue;
495 
496  if (!ctx->video_is_screen) {
497  capture_input = (AVCaptureInput*) [[[AVCaptureDeviceInput alloc] initWithDevice:video_device error:&error] autorelease];
498  } else {
499  capture_input = (AVCaptureInput*) video_device;
500  }
501 
502  if (!capture_input) {
503  av_log(s, AV_LOG_ERROR, "Failed to create AV capture input device: %s\n",
504  [[error localizedDescription] UTF8String]);
505  return 1;
506  }
507 
508  if ([ctx->capture_session canAddInput:capture_input]) {
509  [ctx->capture_session addInput:capture_input];
510  } else {
511  av_log(s, AV_LOG_ERROR, "can't add video input to capture session\n");
512  return 1;
513  }
514 
515  // Attaching output
516  ctx->video_output = [[AVCaptureVideoDataOutput alloc] init];
517 
518  if (!ctx->video_output) {
519  av_log(s, AV_LOG_ERROR, "Failed to init AV video output\n");
520  return 1;
521  }
522 
523  // Configure device framerate and video size
524  @try {
525  if ((ret = configure_video_device(s, video_device)) < 0) {
526  return ret;
527  }
528  } @catch (NSException *exception) {
529  if (![[exception name] isEqualToString:NSUndefinedKeyException]) {
530  av_log (s, AV_LOG_ERROR, "An error occurred: %s", [exception.reason UTF8String]);
531  return AVERROR_EXTERNAL;
532  }
533  }
534 
535  // select pixel format
536  pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE;
537 
538  for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE; i++) {
539  if (ctx->pixel_format == avf_pixel_formats[i].ff_id) {
540  pxl_fmt_spec = avf_pixel_formats[i];
541  break;
542  }
543  }
544 
545  // check if selected pixel format is supported by AVFoundation
546  if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
547  av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by AVFoundation.\n",
548  av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
549  return 1;
550  }
551 
552  // check if the pixel format is available for this device
553  if ([[ctx->video_output availableVideoCVPixelFormatTypes] indexOfObject:[NSNumber numberWithInt:pxl_fmt_spec.avf_id]] == NSNotFound) {
554  av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by the input device.\n",
555  av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
556 
557  pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE;
558 
559  av_log(s, AV_LOG_ERROR, "Supported pixel formats:\n");
560  for (NSNumber *pxl_fmt in [ctx->video_output availableVideoCVPixelFormatTypes]) {
561  struct AVFPixelFormatSpec pxl_fmt_dummy;
562  pxl_fmt_dummy.ff_id = AV_PIX_FMT_NONE;
563  for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE; i++) {
564  if ([pxl_fmt intValue] == avf_pixel_formats[i].avf_id) {
565  pxl_fmt_dummy = avf_pixel_formats[i];
566  break;
567  }
568  }
569 
570  if (pxl_fmt_dummy.ff_id != AV_PIX_FMT_NONE) {
571  av_log(s, AV_LOG_ERROR, " %s\n", av_get_pix_fmt_name(pxl_fmt_dummy.ff_id));
572 
573  // select first supported pixel format instead of user selected (or default) pixel format
574  if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
575  pxl_fmt_spec = pxl_fmt_dummy;
576  }
577  }
578  }
579 
580  // fail if there is no appropriate pixel format or print a warning about overriding the pixel format
581  if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
582  return 1;
583  } else {
584  av_log(s, AV_LOG_WARNING, "Overriding selected pixel format to use %s instead.\n",
585  av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
586  }
587  }
588 
589  // set videoSettings to an empty dict for receiving raw data of muxed devices
590  if (ctx->capture_raw_data) {
591  ctx->pixel_format = pxl_fmt_spec.ff_id;
592  ctx->video_output.videoSettings = @{ };
593  } else {
594  ctx->pixel_format = pxl_fmt_spec.ff_id;
595  pixel_format = [NSNumber numberWithUnsignedInt:pxl_fmt_spec.avf_id];
596  capture_dict = [NSDictionary dictionaryWithObject:pixel_format
597  forKey:(id)kCVPixelBufferPixelFormatTypeKey];
598 
599  [ctx->video_output setVideoSettings:capture_dict];
600  }
601  [ctx->video_output setAlwaysDiscardsLateVideoFrames:ctx->drop_late_frames];
602 
603 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
604  // check for transport control support and set observer device if supported
605  if (!ctx->video_is_screen) {
606  int trans_ctrl = [video_device transportControlsSupported];
607  AVCaptureDeviceTransportControlsPlaybackMode trans_mode = [video_device transportControlsPlaybackMode];
608 
609  if (trans_ctrl) {
610  ctx->observed_mode = trans_mode;
611  ctx->observed_device = video_device;
612  }
613  }
614 #endif
615 
616  ctx->avf_delegate = [[AVFFrameReceiver alloc] initWithContext:ctx];
617 
618  queue = dispatch_queue_create("avf_queue", NULL);
619  [ctx->video_output setSampleBufferDelegate:ctx->avf_delegate queue:queue];
620  dispatch_release(queue);
621 
622  if ([ctx->capture_session canAddOutput:ctx->video_output]) {
623  [ctx->capture_session addOutput:ctx->video_output];
624  } else {
625  av_log(s, AV_LOG_ERROR, "can't add video output to capture session\n");
626  return 1;
627  }
628 
629  return 0;
630 }
631 
632 static int add_audio_device(AVFormatContext *s, AVCaptureDevice *audio_device)
633 {
634  AVFContext *ctx = (AVFContext*)s->priv_data;
635  NSError *error = nil;
636  AVCaptureDeviceInput* audio_dev_input = [[[AVCaptureDeviceInput alloc] initWithDevice:audio_device error:&error] autorelease];
637  dispatch_queue_t queue;
638 
639  if (!audio_dev_input) {
640  av_log(s, AV_LOG_ERROR, "Failed to create AV capture input device: %s\n",
641  [[error localizedDescription] UTF8String]);
642  return 1;
643  }
644 
645  if ([ctx->capture_session canAddInput:audio_dev_input]) {
646  [ctx->capture_session addInput:audio_dev_input];
647  } else {
648  av_log(s, AV_LOG_ERROR, "can't add audio input to capture session\n");
649  return 1;
650  }
651 
652  // Attaching output
653  ctx->audio_output = [[AVCaptureAudioDataOutput alloc] init];
654 
655  if (!ctx->audio_output) {
656  av_log(s, AV_LOG_ERROR, "Failed to init AV audio output\n");
657  return 1;
658  }
659 
660  ctx->avf_audio_delegate = [[AVFAudioReceiver alloc] initWithContext:ctx];
661 
662  queue = dispatch_queue_create("avf_audio_queue", NULL);
663  [ctx->audio_output setSampleBufferDelegate:ctx->avf_audio_delegate queue:queue];
664  dispatch_release(queue);
665 
666  if ([ctx->capture_session canAddOutput:ctx->audio_output]) {
667  [ctx->capture_session addOutput:ctx->audio_output];
668  } else {
669  av_log(s, AV_LOG_ERROR, "adding audio output to capture session failed\n");
670  return 1;
671  }
672 
673  return 0;
674 }
675 
677 {
678  AVFContext *ctx = (AVFContext*)s->priv_data;
679  CVImageBufferRef image_buffer;
680  CGSize image_buffer_size;
681  AVStream* stream = avformat_new_stream(s, NULL);
682 
683  if (!stream) {
684  return 1;
685  }
686 
687  // Take stream info from the first frame.
688  while (ctx->frames_captured < 1) {
689  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES);
690  }
691 
692  lock_frames(ctx);
693 
694  ctx->video_stream_index = stream->index;
695 
696  avpriv_set_pts_info(stream, 64, 1, avf_time_base);
697 
698  image_buffer = CMSampleBufferGetImageBuffer(ctx->current_frame);
699 
700  if (image_buffer) {
701  image_buffer_size = CVImageBufferGetEncodedSize(image_buffer);
702 
703  stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
704  stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
705  stream->codecpar->width = (int)image_buffer_size.width;
706  stream->codecpar->height = (int)image_buffer_size.height;
707  stream->codecpar->format = ctx->pixel_format;
708  } else {
709  stream->codecpar->codec_id = AV_CODEC_ID_DVVIDEO;
710  stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
711  stream->codecpar->format = ctx->pixel_format;
712  }
713 
714  CFRelease(ctx->current_frame);
715  ctx->current_frame = nil;
716 
718 
719  return 0;
720 }
721 
723 {
724  AVFContext *ctx = (AVFContext*)s->priv_data;
725  CMFormatDescriptionRef format_desc;
726  AVStream* stream = avformat_new_stream(s, NULL);
727 
728  if (!stream) {
729  return 1;
730  }
731 
732  // Take stream info from the first frame.
733  while (ctx->audio_frames_captured < 1) {
734  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES);
735  }
736 
737  lock_frames(ctx);
738 
739  ctx->audio_stream_index = stream->index;
740 
741  avpriv_set_pts_info(stream, 64, 1, avf_time_base);
742 
743  format_desc = CMSampleBufferGetFormatDescription(ctx->current_audio_frame);
744  const AudioStreamBasicDescription *basic_desc = CMAudioFormatDescriptionGetStreamBasicDescription(format_desc);
745 
746  if (!basic_desc) {
748  av_log(s, AV_LOG_ERROR, "audio format not available\n");
749  return 1;
750  }
751 
752  stream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
753  stream->codecpar->sample_rate = basic_desc->mSampleRate;
754  av_channel_layout_default(&stream->codecpar->ch_layout, basic_desc->mChannelsPerFrame);
755 
756  ctx->audio_channels = basic_desc->mChannelsPerFrame;
757  ctx->audio_bits_per_sample = basic_desc->mBitsPerChannel;
758  ctx->audio_float = basic_desc->mFormatFlags & kAudioFormatFlagIsFloat;
759  ctx->audio_be = basic_desc->mFormatFlags & kAudioFormatFlagIsBigEndian;
760  ctx->audio_signed_integer = basic_desc->mFormatFlags & kAudioFormatFlagIsSignedInteger;
761  ctx->audio_packed = basic_desc->mFormatFlags & kAudioFormatFlagIsPacked;
762  ctx->audio_non_interleaved = basic_desc->mFormatFlags & kAudioFormatFlagIsNonInterleaved;
763 
764  if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
765  ctx->audio_float &&
766  ctx->audio_bits_per_sample == 32 &&
767  ctx->audio_packed) {
768  stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
769  } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
770  ctx->audio_signed_integer &&
771  ctx->audio_bits_per_sample == 16 &&
772  ctx->audio_packed) {
773  stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
774  } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
775  ctx->audio_signed_integer &&
776  ctx->audio_bits_per_sample == 24 &&
777  ctx->audio_packed) {
778  stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
779  } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
780  ctx->audio_signed_integer &&
781  ctx->audio_bits_per_sample == 32 &&
782  ctx->audio_packed) {
783  stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
784  } else {
786  av_log(s, AV_LOG_ERROR, "audio format is not supported\n");
787  return 1;
788  }
789 
790  if (ctx->audio_non_interleaved) {
791  CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
792  ctx->audio_buffer_size = CMBlockBufferGetDataLength(block_buffer);
793  ctx->audio_buffer = av_malloc(ctx->audio_buffer_size);
794  if (!ctx->audio_buffer) {
796  av_log(s, AV_LOG_ERROR, "error allocating audio buffer\n");
797  return 1;
798  }
799  }
800 
801  CFRelease(ctx->current_audio_frame);
802  ctx->current_audio_frame = nil;
803 
805 
806  return 0;
807 }
808 
809 static NSArray* getDevicesWithMediaType(AVMediaType mediaType) {
810 #if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500))
811  NSMutableArray *deviceTypes = nil;
812  if (mediaType == AVMediaTypeVideo) {
813  deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeBuiltInWideAngleCamera]];
814  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
815  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInDualCamera];
816  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTelephotoCamera];
817  #endif
818  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110100)
819  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTrueDepthCamera];
820  #endif
821  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)
822  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTripleCamera];
823  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInDualWideCamera];
824  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInUltraWideCamera];
825  #endif
826  #if (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 130000)
827  [deviceTypes addObject: AVCaptureDeviceTypeDeskViewCamera];
828  #endif
829  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 150400)
830  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInLiDARDepthCamera];
831  #endif
832  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 170000 || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000))
833  [deviceTypes addObject: AVCaptureDeviceTypeContinuityCamera];
834  [deviceTypes addObject: AVCaptureDeviceTypeExternal];
835  #elif (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 140000)
836  [deviceTypes addObject: AVCaptureDeviceTypeExternalUnknown];
837  #endif
838  } else if (mediaType == AVMediaTypeAudio) {
839  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 170000 || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000))
840  deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeMicrophone]];
841  #else
842  deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeBuiltInMicrophone]];
843  #endif
844  } else if (mediaType == AVMediaTypeMuxed) {
845  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 170000 || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000))
846  deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeExternal]];
847  #elif (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 140000)
848  deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeExternalUnknown]];
849  #else
850  return nil;
851  #endif
852  } else {
853  return nil;
854  }
855 
856  AVCaptureDeviceDiscoverySession *captureDeviceDiscoverySession =
857  [AVCaptureDeviceDiscoverySession
858  discoverySessionWithDeviceTypes:deviceTypes
859  mediaType:mediaType
860  position:AVCaptureDevicePositionUnspecified];
861  return [captureDeviceDiscoverySession devices];
862 #elif TARGET_OS_OSX
863  return [AVCaptureDevice devicesWithMediaType:mediaType];
864 #else
865  return nil;
866 #endif
867 }
868 
869 #if HAVE_IOKIT
870 static int avf_io_get_string(io_service_t service, CFStringRef key, char *buf, size_t size)
871 {
872  CFTypeRef ref = IORegistryEntryCreateCFProperty(service, key, kCFAllocatorDefault, 0);
873  int ok = ref && CFGetTypeID(ref) == CFStringGetTypeID() && CFStringGetCString(ref, buf, size, kCFStringEncodingUTF8);
874  if (ref)
875  CFRelease(ref);
876  return ok;
877 }
878 
879 static int avf_io_get_uint32(io_service_t service, CFStringRef key, uint32_t *out)
880 {
881  CFTypeRef ref = IORegistryEntryCreateCFProperty(service, key, kCFAllocatorDefault, 0);
882  int ok = ref && CFGetTypeID(ref) == CFNumberGetTypeID() && CFNumberGetValue(ref, kCFNumberSInt32Type, out);
883  if (ref)
884  CFRelease(ref);
885  return ok;
886 }
887 #endif
888 
889 #if HAVE_IOKIT
890 static int64_t avf_usb_location_for_serial(const char *serial)
891 {
892  int64_t location = -1;
893  io_iterator_t iterator = 0;
894  io_service_t service;
895 
896  if (IOServiceGetMatchingServices(AVF_IO_MAIN_PORT_DEFAULT,
897  IOServiceMatching("IOUSBHostDevice"), &iterator) != KERN_SUCCESS)
898  return -1;
899 
900  while (location < 0 && (service = IOIteratorNext(iterator))) {
901  char found[512];
902  uint32_t loc;
903  if (avf_io_get_string(service, CFSTR("USB Serial Number"), found, sizeof(found)) &&
904  !strcmp(found, serial) &&
905  avf_io_get_uint32(service, CFSTR("locationID"), &loc))
906  location = loc;
907  IOObjectRelease(service);
908  }
909  IOObjectRelease(iterator);
910 
911  return location;
912 }
913 #else
914 static int64_t avf_usb_location_for_serial(const char *serial)
915 {
916  return -1;
917 }
918 #endif
919 
920 #if HAVE_IOKIT
921 static NSString *avf_usb_serial_for_location(uint32_t location)
922 {
923  NSString *serial = nil;
924  io_iterator_t iterator = 0;
925  io_service_t service;
926 
927  if (IOServiceGetMatchingServices(AVF_IO_MAIN_PORT_DEFAULT,
928  IOServiceMatching("IOUSBHostDevice"), &iterator) != KERN_SUCCESS)
929  return nil;
930 
931  while (!serial && (service = IOIteratorNext(iterator))) {
932  char found[512];
933  uint32_t loc;
934  if (avf_io_get_uint32(service, CFSTR("locationID"), &loc) && loc == location &&
935  avf_io_get_string(service, CFSTR("USB Serial Number"), found, sizeof(found)))
936  serial = [NSString stringWithUTF8String:found];
937  IOObjectRelease(service);
938  }
939  IOObjectRelease(iterator);
940 
941  return serial;
942 }
943 #else
944 static NSString *avf_usb_serial_for_location(uint32_t location)
945 {
946  return nil;
947 }
948 #endif
949 
950 // USB video uniqueID = locationID<<32 | VID<<16 | PID; match on the locationID.
951 static AVCaptureDevice *avf_video_device_with_serial(const char *serial,
952  NSArray *devices, NSArray *devices_muxed, int *is_muxed)
953 {
954  int64_t location = avf_usb_location_for_serial(serial);
955  NSArray *lists[2] = { devices, devices_muxed };
956 
957  if (location < 0)
958  return nil;
959 
960  for (int i = 0; i < 2; i++) {
961  for (AVCaptureDevice *device in lists[i]) {
962  NSString *uid = [device uniqueID];
963  if ([uid hasPrefix:@"0x"] &&
964  (uint32_t)(strtoull([uid UTF8String], NULL, 16) >> 32) == (uint32_t)location) {
965  *is_muxed = (i == 1);
966  return device;
967  }
968  }
969  }
970 
971  return nil;
972 }
973 
974 // CoreAudio USB-audio UID: AppleUSBAudioEngine:manufacturer:device:serial:interfaces
975 #if HAVE_IOKIT
976 static NSString *avf_audio_serial_for_uid(NSString *uid)
977 {
978  if (![uid hasPrefix:@"AppleUSBAudioEngine:"])
979  return nil;
980  NSArray<NSString *> *fields = [uid componentsSeparatedByString:@":"];
981  if (fields.count < 5)
982  return nil;
983  NSString *serial = fields[fields.count - 2];
984  if (serial.length && avf_usb_location_for_serial([serial UTF8String]) >= 0)
985  return serial;
986  return nil;
987 }
988 #else
989 static NSString *avf_audio_serial_for_uid(NSString *uid)
990 {
991  return nil;
992 }
993 #endif
994 
995 static AVCaptureDevice *avf_audio_device_with_serial(const char *serial, NSArray *devices)
996 {
997  NSString *want = [NSString stringWithUTF8String:serial];
998 
999  for (AVCaptureDevice *device in devices)
1000  if ([avf_audio_serial_for_uid([device uniqueID]) isEqualToString:want])
1001  return device;
1002 
1003  return nil;
1004 }
1005 
1006 static AVCaptureDevice *avf_device_with_uid(const char *uid,
1007  NSArray *devices, NSArray *devices_muxed, int *is_muxed)
1008 {
1009  NSString *want = [NSString stringWithUTF8String:uid];
1010  NSArray *lists[2] = { devices, devices_muxed };
1011 
1012  for (int i = 0; i < 2; i++) {
1013  for (AVCaptureDevice *device in lists[i]) {
1014  if ([[device uniqueID] isEqualToString:want]) {
1015  if (is_muxed)
1016  *is_muxed = (i == 1);
1017  return device;
1018  }
1019  }
1020  }
1021 
1022  return nil;
1023 }
1024 
1025 // Best-effort serial string for -list_devices, or nil.
1026 static NSString *avf_device_listing_serial(AVCaptureDevice *device)
1027 {
1028  NSString *uid = [device uniqueID];
1029 
1030  if ([uid hasPrefix:@"0x"]) {
1031  unsigned long long value = strtoull([uid UTF8String], NULL, 16);
1032  NSString *serial = avf_usb_serial_for_location((uint32_t)(value >> 32));
1033  return serial.length ? serial : nil;
1034  }
1035  return avf_audio_serial_for_uid(uid);
1036 }
1037 
1038 static void avf_log_device_entry(AVFContext *ctx, int index, AVCaptureDevice *device)
1039 {
1040  NSString *serial = avf_device_listing_serial(device);
1041 
1042  if (serial)
1043  av_log(ctx, AV_LOG_INFO, "[%d] %s [uid:%s] [serial:%s]\n", index,
1044  [[device localizedName] UTF8String], [[device uniqueID] UTF8String],
1045  [serial UTF8String]);
1046  else
1047  av_log(ctx, AV_LOG_INFO, "[%d] %s [uid:%s]\n", index,
1048  [[device localizedName] UTF8String], [[device uniqueID] UTF8String]);
1049 }
1050 
1051 // Returns 1 if a device id was set (*device = match, or nil after logging on miss), else 0.
1053  NSArray *devices, NSArray *devices_muxed,
1054  const char *id, AVCaptureDevice **device, int *is_muxed)
1055 {
1056  BOOL is_audio = [media_type isEqualToString:AVMediaTypeAudio];
1057  const char *kind = is_audio ? "Audio" : "Video";
1058  const char *value = NULL;
1059 
1060  if (!id)
1061  return 0;
1062 
1063  if (av_strstart(id, "serial:", &value)) {
1064  if (is_audio)
1065  *device = avf_audio_device_with_serial(value, devices);
1066  else
1067  *device = avf_video_device_with_serial(value, devices, devices_muxed, is_muxed);
1068  if (!*device)
1070  "%s capture device with serial number '%s' not found\n", kind, value);
1071  } else if (av_strstart(id, "uid:", &value)) {
1072  *device = avf_device_with_uid(value, devices, devices_muxed, is_muxed);
1073  if (!*device)
1075  "%s capture device with unique ID '%s' not found\n", kind, value);
1076  } else {
1078  "Invalid %s device id '%s': expected 'uid:<unique ID>' or 'serial:<serial number>'\n",
1079  is_audio ? "audio" : "video", id);
1080  }
1081  return 1;
1082 }
1083 
1085 {
1086  int ret = 0;
1087  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1088  uint32_t num_screens = 0;
1089  AVFContext *ctx = (AVFContext*)s->priv_data;
1090  AVCaptureDevice *video_device = nil;
1091  AVCaptureDevice *audio_device = nil;
1092  // Find capture device
1093  NSArray *devices = getDevicesWithMediaType(AVMediaTypeVideo);
1094  NSArray *devices_muxed = getDevicesWithMediaType(AVMediaTypeMuxed);
1095  NSArray *audio_devices = getDevicesWithMediaType(AVMediaTypeAudio);
1096 
1097  ctx->num_video_devices = [devices count] + [devices_muxed count];
1098 
1099  pthread_mutex_init(&ctx->frame_lock, NULL);
1100  pthread_cond_init(&ctx->frame_wait_cond, NULL);
1101  ctx->is_stopping = 0;
1102 
1103 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
1104  CGGetActiveDisplayList(0, NULL, &num_screens);
1105 #endif
1106 
1107  // List devices if requested
1108  if (ctx->list_devices) {
1109  int index = 0;
1110  av_log(ctx, AV_LOG_INFO, "AVFoundation video devices:\n");
1111  for (AVCaptureDevice *device in devices) {
1112  index = [devices indexOfObject:device];
1113  avf_log_device_entry(ctx, index, device);
1114  }
1115  for (AVCaptureDevice *device in devices_muxed) {
1116  index = [devices count] + [devices_muxed indexOfObject:device];
1117  avf_log_device_entry(ctx, index, device);
1118  }
1119 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
1120  if (num_screens > 0) {
1121  CGDirectDisplayID screens[num_screens];
1122  CGGetActiveDisplayList(num_screens, screens, &num_screens);
1123  for (int i = 0; i < num_screens; i++) {
1124  av_log(ctx, AV_LOG_INFO, "[%d] Capture screen %d\n", ctx->num_video_devices + i, i);
1125  }
1126  }
1127 #endif
1128 
1129  av_log(ctx, AV_LOG_INFO, "AVFoundation audio devices:\n");
1130  devices = getDevicesWithMediaType(AVMediaTypeAudio);
1131  for (AVCaptureDevice *device in devices) {
1132  int index = [devices indexOfObject:device];
1133  avf_log_device_entry(ctx, index, device);
1134  }
1135  goto fail;
1136  }
1137 
1138  // parse input filename for video and audio device
1139  ret = parse_device_name(s);
1140  if (ret)
1141  goto fail;
1142 
1143  // check for device index given in filename
1144  if (ctx->video_device_index == -1 && ctx->video_filename) {
1145  sscanf(ctx->video_filename, "%d", &ctx->video_device_index);
1146  }
1147  if (ctx->audio_device_index == -1 && ctx->audio_filename) {
1148  sscanf(ctx->audio_filename, "%d", &ctx->audio_device_index);
1149  }
1150 
1151  if (avf_device_from_id(ctx, AVMediaTypeVideo, devices, devices_muxed,
1152  ctx->video_device_id, &video_device, &ctx->video_is_muxed)) {
1153  if (!video_device)
1154  goto fail;
1155  } else if (ctx->video_device_index >= 0) {
1156  if (ctx->video_device_index < ctx->num_video_devices) {
1157  if (ctx->video_device_index < [devices count]) {
1158  video_device = [devices objectAtIndex:ctx->video_device_index];
1159  } else {
1160  video_device = [devices_muxed objectAtIndex:(ctx->video_device_index - [devices count])];
1161  ctx->video_is_muxed = 1;
1162  }
1163  } else if (ctx->video_device_index < ctx->num_video_devices + num_screens) {
1164 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
1165  CGDirectDisplayID screens[num_screens];
1166  CGGetActiveDisplayList(num_screens, screens, &num_screens);
1167  AVCaptureScreenInput* capture_screen_input = [[[AVCaptureScreenInput alloc] initWithDisplayID:screens[ctx->video_device_index - ctx->num_video_devices]] autorelease];
1168 
1169  if (ctx->framerate.num > 0) {
1170  capture_screen_input.minFrameDuration = CMTimeMake(ctx->framerate.den, ctx->framerate.num);
1171  }
1172 
1173 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
1174  if (ctx->capture_cursor) {
1175  capture_screen_input.capturesCursor = YES;
1176  } else {
1177  capture_screen_input.capturesCursor = NO;
1178  }
1179 #endif
1180 
1181  if (ctx->capture_mouse_clicks) {
1182  capture_screen_input.capturesMouseClicks = YES;
1183  } else {
1184  capture_screen_input.capturesMouseClicks = NO;
1185  }
1186 
1187  video_device = (AVCaptureDevice*) capture_screen_input;
1188  ctx->video_is_screen = 1;
1189 #endif
1190  } else {
1191  av_log(ctx, AV_LOG_ERROR, "Invalid device index\n");
1192  goto fail;
1193  }
1194  } else if (ctx->video_filename &&
1195  strncmp(ctx->video_filename, "none", 4)) {
1196  if (!strncmp(ctx->video_filename, "default", 7)) {
1197  video_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
1198  } else {
1199  // looking for video inputs
1200  for (AVCaptureDevice *device in devices) {
1201  if (!strncmp(ctx->video_filename, [[device localizedName] UTF8String], strlen(ctx->video_filename))) {
1202  video_device = device;
1203  break;
1204  }
1205  }
1206  // looking for muxed inputs
1207  for (AVCaptureDevice *device in devices_muxed) {
1208  if (!strncmp(ctx->video_filename, [[device localizedName] UTF8String], strlen(ctx->video_filename))) {
1209  video_device = device;
1210  ctx->video_is_muxed = 1;
1211  break;
1212  }
1213  }
1214 
1215 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
1216  // looking for screen inputs
1217  if (!video_device) {
1218  int idx;
1219  if(sscanf(ctx->video_filename, "Capture screen %d", &idx) && idx < num_screens) {
1220  CGDirectDisplayID screens[num_screens];
1221  CGGetActiveDisplayList(num_screens, screens, &num_screens);
1222  AVCaptureScreenInput* capture_screen_input = [[[AVCaptureScreenInput alloc] initWithDisplayID:screens[idx]] autorelease];
1223  video_device = (AVCaptureDevice*) capture_screen_input;
1224  ctx->video_device_index = ctx->num_video_devices + idx;
1225  ctx->video_is_screen = 1;
1226 
1227  if (ctx->framerate.num > 0) {
1228  capture_screen_input.minFrameDuration = CMTimeMake(ctx->framerate.den, ctx->framerate.num);
1229  }
1230 
1231 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
1232  if (ctx->capture_cursor) {
1233  capture_screen_input.capturesCursor = YES;
1234  } else {
1235  capture_screen_input.capturesCursor = NO;
1236  }
1237 #endif
1238 
1239  if (ctx->capture_mouse_clicks) {
1240  capture_screen_input.capturesMouseClicks = YES;
1241  } else {
1242  capture_screen_input.capturesMouseClicks = NO;
1243  }
1244  }
1245  }
1246 #endif
1247  }
1248 
1249  if (!video_device) {
1250  av_log(ctx, AV_LOG_ERROR, "Video device not found\n");
1251  goto fail;
1252  }
1253  }
1254 
1255  // get audio device
1256  if (avf_device_from_id(ctx, AVMediaTypeAudio, audio_devices, nil,
1257  ctx->audio_device_id, &audio_device, NULL)) {
1258  if (!audio_device)
1259  goto fail;
1260  } else if (ctx->audio_device_index >= 0) {
1261  if (ctx->audio_device_index >= [audio_devices count]) {
1262  av_log(ctx, AV_LOG_ERROR, "Invalid audio device index\n");
1263  goto fail;
1264  }
1265 
1266  audio_device = [audio_devices objectAtIndex:ctx->audio_device_index];
1267  } else if (ctx->audio_filename &&
1268  strncmp(ctx->audio_filename, "none", 4)) {
1269  if (!strncmp(ctx->audio_filename, "default", 7)) {
1270  audio_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
1271  } else {
1272  for (AVCaptureDevice *device in audio_devices) {
1273  if (!strncmp(ctx->audio_filename, [[device localizedName] UTF8String], strlen(ctx->audio_filename))) {
1274  audio_device = device;
1275  break;
1276  }
1277  }
1278  }
1279 
1280  if (!audio_device) {
1281  av_log(ctx, AV_LOG_ERROR, "Audio device not found\n");
1282  goto fail;
1283  }
1284  }
1285 
1286  // Video nor Audio capture device not found, looking for AVMediaTypeVideo/Audio
1287  if (!video_device && !audio_device) {
1288  av_log(s, AV_LOG_ERROR, "No AV capture device found\n");
1289  goto fail;
1290  }
1291 
1292  if (video_device) {
1293  if (!ctx->video_is_screen) {
1294  av_log(s, AV_LOG_DEBUG, "'%s' opened\n", [[video_device localizedName] UTF8String]);
1295  } else {
1296  av_log(s, AV_LOG_DEBUG, "'%s' opened\n", [[video_device description] UTF8String]);
1297  }
1298  }
1299  if (audio_device) {
1300  av_log(s, AV_LOG_DEBUG, "audio device '%s' opened\n", [[audio_device localizedName] UTF8String]);
1301  }
1302 
1303  // Initialize capture session
1304  ctx->capture_session = [[AVCaptureSession alloc] init];
1305 
1306  if (video_device && add_video_device(s, video_device)) {
1307  goto fail;
1308  }
1309  if (audio_device && add_audio_device(s, audio_device)) {
1310  }
1311 
1312  [ctx->capture_session startRunning];
1313 
1314  /* Unlock device configuration only after the session is started so it
1315  * does not reset the capture formats */
1316  if (!ctx->video_is_screen) {
1317  [video_device unlockForConfiguration];
1318  }
1319 
1320  if (video_device && get_video_config(s)) {
1321  goto fail;
1322  }
1323 
1324  // set audio stream
1325  if (audio_device && get_audio_config(s)) {
1326  goto fail;
1327  }
1328 
1329  [pool release];
1330  return 0;
1331 
1332 fail:
1333  [pool release];
1335  if (ret)
1336  return ret;
1337  return AVERROR(EIO);
1338 }
1339 
1341  CVPixelBufferRef image_buffer,
1342  AVPacket *pkt)
1343 {
1344  AVFContext *ctx = s->priv_data;
1345  int src_linesize[4];
1346  const uint8_t *src_data[4];
1347  int width = CVPixelBufferGetWidth(image_buffer);
1348  int height = CVPixelBufferGetHeight(image_buffer);
1349  int status;
1350 
1351  memset(src_linesize, 0, sizeof(src_linesize));
1352  memset(src_data, 0, sizeof(src_data));
1353 
1354  status = CVPixelBufferLockBaseAddress(image_buffer, 0);
1355  if (status != kCVReturnSuccess) {
1356  av_log(s, AV_LOG_ERROR, "Could not lock base address: %d (%dx%d)\n", status, width, height);
1357  return AVERROR_EXTERNAL;
1358  }
1359 
1360  if (CVPixelBufferIsPlanar(image_buffer)) {
1361  size_t plane_count = CVPixelBufferGetPlaneCount(image_buffer);
1362  int i;
1363  for(i = 0; i < plane_count; i++){
1364  src_linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(image_buffer, i);
1365  src_data[i] = CVPixelBufferGetBaseAddressOfPlane(image_buffer, i);
1366  }
1367  } else {
1368  src_linesize[0] = CVPixelBufferGetBytesPerRow(image_buffer);
1369  src_data[0] = CVPixelBufferGetBaseAddress(image_buffer);
1370  }
1371 
1373  src_data, src_linesize,
1374  ctx->pixel_format, width, height, 1);
1375 
1376 
1377 
1378  CVPixelBufferUnlockBaseAddress(image_buffer, 0);
1379 
1380  return status;
1381 }
1382 
1384 {
1385  AVFContext* ctx = (AVFContext*)s->priv_data;
1386 
1387  lock_frames(ctx);
1388  do {
1389  CVImageBufferRef image_buffer;
1390  CMBlockBufferRef block_buffer;
1391 
1392  if (ctx->current_frame != nil) {
1393  int status;
1394  int length = 0;
1395 
1396  image_buffer = CMSampleBufferGetImageBuffer(ctx->current_frame);
1397  block_buffer = CMSampleBufferGetDataBuffer(ctx->current_frame);
1398 
1399  if (image_buffer != nil) {
1400  length = (int)CVPixelBufferGetDataSize(image_buffer);
1401  } else if (block_buffer != nil) {
1402  length = (int)CMBlockBufferGetDataLength(block_buffer);
1403  } else {
1404  unlock_frames(ctx);
1405  return AVERROR(EINVAL);
1406  }
1407 
1408  if (av_new_packet(pkt, length) < 0) {
1409  unlock_frames(ctx);
1410  return AVERROR(EIO);
1411  }
1412 
1413  CMItemCount count;
1414  CMSampleTimingInfo timing_info;
1415 
1416  if (CMSampleBufferGetOutputSampleTimingInfoArray(ctx->current_frame, 1, &timing_info, &count) == noErr) {
1417  AVRational timebase_q = av_make_q(1, timing_info.presentationTimeStamp.timescale);
1418  pkt->pts = pkt->dts = av_rescale_q(timing_info.presentationTimeStamp.value, timebase_q, avf_time_base_q);
1419  }
1420 
1421  pkt->stream_index = ctx->video_stream_index;
1423 
1424  if (image_buffer) {
1425  status = copy_cvpixelbuffer(s, image_buffer, pkt);
1426  } else {
1427  status = 0;
1428  OSStatus ret = CMBlockBufferCopyDataBytes(block_buffer, 0, pkt->size, pkt->data);
1429  if (ret != kCMBlockBufferNoErr) {
1430  status = AVERROR(EIO);
1431  }
1432  }
1433  CFRelease(ctx->current_frame);
1434  ctx->current_frame = nil;
1435 
1436  if (status < 0) {
1437  unlock_frames(ctx);
1438  return status;
1439  }
1440  } else if (ctx->current_audio_frame != nil) {
1441  CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
1442  int block_buffer_size = CMBlockBufferGetDataLength(block_buffer);
1443 
1444  if (!block_buffer || !block_buffer_size) {
1445  unlock_frames(ctx);
1446  return AVERROR(EIO);
1447  }
1448 
1449  if (ctx->audio_non_interleaved && block_buffer_size > ctx->audio_buffer_size) {
1450  unlock_frames(ctx);
1451  return AVERROR_BUFFER_TOO_SMALL;
1452  }
1453 
1454  if (av_new_packet(pkt, block_buffer_size) < 0) {
1455  unlock_frames(ctx);
1456  return AVERROR(EIO);
1457  }
1458 
1459  CMItemCount count;
1460  CMSampleTimingInfo timing_info;
1461 
1462  if (CMSampleBufferGetOutputSampleTimingInfoArray(ctx->current_audio_frame, 1, &timing_info, &count) == noErr) {
1463  AVRational timebase_q = av_make_q(1, timing_info.presentationTimeStamp.timescale);
1464  pkt->pts = pkt->dts = av_rescale_q(timing_info.presentationTimeStamp.value, timebase_q, avf_time_base_q);
1465  }
1466 
1467  pkt->stream_index = ctx->audio_stream_index;
1469 
1470  if (ctx->audio_non_interleaved) {
1471  int sample, c, shift, num_samples;
1472 
1473  OSStatus ret = CMBlockBufferCopyDataBytes(block_buffer, 0, pkt->size, ctx->audio_buffer);
1474  if (ret != kCMBlockBufferNoErr) {
1475  unlock_frames(ctx);
1476  return AVERROR(EIO);
1477  }
1478 
1479  num_samples = pkt->size / (ctx->audio_channels * (ctx->audio_bits_per_sample >> 3));
1480 
1481  // transform decoded frame into output format
1482  #define INTERLEAVE_OUTPUT(bps) \
1483  { \
1484  int##bps##_t **src; \
1485  int##bps##_t *dest; \
1486  src = av_malloc(ctx->audio_channels * sizeof(int##bps##_t*)); \
1487  if (!src) { \
1488  unlock_frames(ctx); \
1489  return AVERROR(EIO); \
1490  } \
1491  \
1492  for (c = 0; c < ctx->audio_channels; c++) { \
1493  src[c] = ((int##bps##_t*)ctx->audio_buffer) + c * num_samples; \
1494  } \
1495  dest = (int##bps##_t*)pkt->data; \
1496  shift = bps - ctx->audio_bits_per_sample; \
1497  for (sample = 0; sample < num_samples; sample++) \
1498  for (c = 0; c < ctx->audio_channels; c++) \
1499  *dest++ = src[c][sample] << shift; \
1500  av_freep(&src); \
1501  }
1502 
1503  if (ctx->audio_bits_per_sample <= 16) {
1504  INTERLEAVE_OUTPUT(16)
1505  } else {
1506  INTERLEAVE_OUTPUT(32)
1507  }
1508  } else {
1509  OSStatus ret = CMBlockBufferCopyDataBytes(block_buffer, 0, pkt->size, pkt->data);
1510  if (ret != kCMBlockBufferNoErr) {
1511  unlock_frames(ctx);
1512  return AVERROR(EIO);
1513  }
1514  }
1515 
1516  CFRelease(ctx->current_audio_frame);
1517  ctx->current_audio_frame = nil;
1518  } else {
1519  pkt->data = NULL;
1520  if (ctx->observed_quit) {
1521  unlock_frames(ctx);
1522  return AVERROR_EOF;
1523  }
1524  // No frame available yet: wait until a capture callback delivers
1525  // one (or until the device is being torn down).
1526  pthread_cond_wait(&ctx->frame_wait_cond, &ctx->frame_lock);
1527  }
1528  } while (!pkt->data && !ctx->is_stopping);
1529 
1530  if (ctx->is_stopping) {
1531  unlock_frames(ctx);
1532  return AVERROR_EOF;
1533  }
1534  unlock_frames(ctx);
1535 
1536  return 0;
1537 }
1538 
1540 {
1541  AVFContext* ctx = (AVFContext*)s->priv_data;
1543  return 0;
1544 }
1545 
1546 static const AVOption options[] = {
1547  { "list_devices", "list available devices", offsetof(AVFContext, list_devices), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
1548  { "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 },
1549  { "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 },
1550  { "video_device_id", "select video device by prefixed id (uid:<unique ID> or serial:<USB serial number>)", offsetof(AVFContext, video_device_id), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
1551  { "audio_device_id", "select audio device by prefixed id (uid:<unique ID> or serial:<USB serial number>)", offsetof(AVFContext, audio_device_id), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
1552  { "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},
1553  { "framerate", "set frame rate", offsetof(AVFContext, framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
1554  { "video_size", "set video size", offsetof(AVFContext, width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
1555  { "capture_cursor", "capture the screen cursor", offsetof(AVFContext, capture_cursor), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
1556  { "capture_mouse_clicks", "capture the screen mouse clicks", offsetof(AVFContext, capture_mouse_clicks), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
1557  { "capture_raw_data", "capture the raw data from device connection", offsetof(AVFContext, capture_raw_data), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
1558  { "drop_late_frames", "drop frames that are available later than expected", offsetof(AVFContext, drop_late_frames), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
1559 
1560  { NULL },
1561 };
1562 
1563 static const AVClass avf_class = {
1564  .class_name = "AVFoundation indev",
1565  .item_name = av_default_item_name,
1566  .option = options,
1567  .version = LIBAVUTIL_VERSION_INT,
1569 };
1570 
1572  .p.name = "avfoundation",
1573  .p.long_name = NULL_IF_CONFIG_SMALL("AVFoundation input device"),
1574  .p.flags = AVFMT_NOFILE,
1575  .p.priv_class = &avf_class,
1576  .priv_data_size = sizeof(AVFContext),
1579  .read_close = avf_close,
1580 };
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:32
AV_CODEC_ID_PCM_S16LE
@ AV_CODEC_ID_PCM_S16LE
Definition: codec_id.h:330
av_strdup
#define av_strdup(s)
Definition: ops_static.c:47
pthread_mutex_t
_fmutex pthread_mutex_t
Definition: os2threads.h:53
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AV_CODEC_ID_PCM_F32BE
@ AV_CODEC_ID_PCM_F32BE
Definition: codec_id.h:350
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
AVFContext::audio_buffer_size
int audio_buffer_size
Definition: avfoundation.m:142
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
uid
UID uid
Definition: mxfenc.c:2488
opt.h
AVFContext::audio_float
int audio_float
Definition: avfoundation.m:135
AVFContext::observed_quit
int observed_quit
Definition: avfoundation.m:156
unlock_frames
static void unlock_frames(AVFContext *ctx)
Definition: avfoundation.m:164
out
static FILE * out
Definition: movenc.c:55
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
AV_OPT_TYPE_VIDEO_RATE
@ AV_OPT_TYPE_VIDEO_RATE
Underlying C type is AVRational.
Definition: opt.h:314
pthread_mutex_init
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
int64_t
long long int64_t
Definition: coverity.c:34
AV_CODEC_ID_RAWVIDEO
@ AV_CODEC_ID_RAWVIDEO
Definition: codec_id.h:63
AVFContext::current_audio_frame
CMSampleBufferRef current_audio_frame
Definition: avfoundation.m:150
mode
Definition: swscale.c:71
pixdesc.h
AVFContext::audio_frames_captured
int audio_frames_captured
Definition: avfoundation.m:102
AVPacket::data
uint8_t * data
Definition: packet.h:603
pthread_mutex_lock
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
Definition: os2threads.h:119
AVOption
AVOption.
Definition: opt.h:428
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:76
avf_audio_device_with_serial
static AVCaptureDevice * avf_audio_device_with_serial(const char *serial, NSArray *devices)
Definition: avfoundation.m:995
key
const char * key
Definition: ffmpeg_mux_init.c:2971
AVFContext::is_stopping
int is_stopping
Definition: avfoundation.m:105
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:650
parse_device_name
static int parse_device_name(AVFormatContext *s)
Definition: avfoundation.m:360
AV_PIX_FMT_RGB555BE
@ AV_PIX_FMT_RGB555BE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
Definition: pixfmt.h:114
AVFContext::audio_channels
int audio_channels
Definition: avfoundation.m:133
AVFContext::video_filename
char * video_filename
Definition: avfoundation.m:126
AVFPixelFormatSpec::avf_id
OSType avf_id
Definition: avfoundation.m:65
AVFContext::audio_be
int audio_be
Definition: avfoundation.m:136
avf_audio_serial_for_uid
static NSString * avf_audio_serial_for_uid(NSString *uid)
Definition: avfoundation.m:989
AVFContext::capture_cursor
int capture_cursor
Definition: avfoundation.m:112
avpriv_set_pts_info
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: avformat.c:834
avf_device_with_uid
static AVCaptureDevice * avf_device_with_uid(const char *uid, NSArray *devices, NSArray *devices_muxed, int *is_muxed)
Definition: avfoundation.m:1006
AV_CODEC_ID_PCM_S16BE
@ AV_CODEC_ID_PCM_S16BE
Definition: codec_id.h:331
avf_close
static int avf_close(AVFormatContext *s)
Definition: avfoundation.m:1539
avf_time_base
static const int avf_time_base
Definition: avfoundation.m:56
read_close
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:143
AVFContext::current_frame
CMSampleBufferRef current_frame
Definition: avfoundation.m:149
AVFPixelFormatSpec::ff_id
enum AVPixelFormat ff_id
Definition: avfoundation.m:64
AVFContext::observed_device
AVCaptureDevice * observed_device
Definition: avfoundation.m:152
AVERROR_BUFFER_TOO_SMALL
#define AVERROR_BUFFER_TOO_SMALL
Buffer too small.
Definition: error.h:53
AVRational::num
int num
Numerator.
Definition: rational.h:59
AVFContext::framerate
AVRational framerate
Definition: avfoundation.m:109
AV_PIX_FMT_YUV444P10
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:548
description
Tag description
Definition: snow.txt:206
avf_video_device_with_serial
static AVCaptureDevice * avf_video_device_with_serial(const char *serial, NSArray *devices, NSArray *devices_muxed, int *is_muxed)
Definition: avfoundation.m:951
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
avf_time_base_q
static const AVRational avf_time_base_q
Definition: avfoundation.m:58
AV_PIX_FMT_YUV422P16
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:557
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_read_callback.c:42
AVFContext::num_video_devices
int num_video_devices
Definition: avfoundation.m:131
INTERLEAVE_OUTPUT
#define INTERLEAVE_OUTPUT(bps)
getDevicesWithMediaType
static NSArray * getDevicesWithMediaType(AVMediaType mediaType)
Definition: avfoundation.m:809
av_new_packet
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: packet.c:98
avf_device_from_id
static int avf_device_from_id(AVFContext *ctx, AVMediaType media_type, NSArray *devices, NSArray *devices_muxed, const char *id, AVCaptureDevice **device, int *is_muxed)
Definition: avfoundation.m:1052
pthread_mutex_unlock
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
Definition: os2threads.h:126
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:570
AVFAudioReceiver::_context
AVFContext * _context
Definition: avfoundation.m:276
options
static const AVOption options[]
Definition: avfoundation.m:1546
add_audio_device
static int add_audio_device(AVFormatContext *s, AVCaptureDevice *audio_device)
Definition: avfoundation.m:632
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:201
av_q2d
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
av_strtok
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition: avstring.c:179
AVFContext::capture_mouse_clicks
int capture_mouse_clicks
Definition: avfoundation.m:113
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
AVFContext::frame_lock
pthread_mutex_t frame_lock
Definition: avfoundation.m:103
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
AVFContext::capture_raw_data
int capture_raw_data
Definition: avfoundation.m:114
AVFContext::list_devices
int list_devices
Definition: avfoundation.m:119
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
pthread_cond_broadcast
static av_always_inline int pthread_cond_broadcast(pthread_cond_t *cond)
Definition: os2threads.h:162
AVFPixelFormatSpec
Definition: avfoundation.m:63
get_video_config
static int get_video_config(AVFormatContext *s)
Definition: avfoundation.m:676
fields
the definition of that something depends on the semantic of the filter The callback must examine the status of the filter s links and proceed accordingly The status of output links is stored in the status_in and status_out fields and tested by the then the processing requires a frame on this link and the filter is expected to make efforts in that direction The status of input links is stored by the fifo and status_out fields
Definition: filter_design.txt:155
if
if(ret)
Definition: filter_design.txt:179
AVFContext::audio_packed
int audio_packed
Definition: avfoundation.m:138
AVFFrameReceiver::_context
AVFContext * _context
Definition: avfoundation.m:174
context
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option keep it simple and lowercase description are in without and describe what they for example set the foo of the bar offset is the offset of the field in your context
Definition: writing_filters.txt:91
AVFormatContext
Format I/O context.
Definition: avformat.h:1333
fail
#define fail
Definition: test.h:478
internal.h
AVFContext::video_output
AVCaptureVideoDataOutput * video_output
Definition: avfoundation.m:147
framerate
float framerate
Definition: av1_levels.c:29
AVFContext::audio_signed_integer
int audio_signed_integer
Definition: avfoundation.m:137
AV_PIX_FMT_RGB565LE
@ AV_PIX_FMT_RGB565LE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
Definition: pixfmt.h:113
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
fabs
static __device__ float fabs(float a)
Definition: cuda_runtime.h:182
NULL
#define NULL
Definition: coverity.c:32
format
New swscale design to change SwsGraph is what coordinates multiple passes These can include cascaded scaling error diffusion and so on Or we could have separate passes for the vertical and horizontal scaling In between each SwsPass lies a fully allocated image buffer Graph passes may have different levels of e g we can have a single threaded error diffusion pass following a multi threaded scaling pass SwsGraph is internally recreated whenever the image format
Definition: swscale-v2.txt:14
AVFContext::drop_late_frames
int drop_late_frames
Definition: avfoundation.m:115
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:74
add_video_device
static int add_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
Definition: avfoundation.m:485
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AVFFrameReceiver
FrameReceiver class - delegate for AVCaptureSession.
Definition: avfoundation.m:172
AVFContext::video_device_id
char * video_device_id
Definition: avfoundation.m:128
ff_avfoundation_demuxer
const FFInputFormat ff_avfoundation_demuxer
Definition: avfoundation.m:1571
AV_PIX_FMT_MONOBLACK
@ AV_PIX_FMT_MONOBLACK
Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb.
Definition: pixfmt.h:83
AV_OPT_TYPE_IMAGE_SIZE
@ AV_OPT_TYPE_IMAGE_SIZE
Underlying C type is two consecutive integers.
Definition: opt.h:302
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:242
parseutils.h
options
Definition: swscale.c:50
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:265
time.h
AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
@ AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
Definition: log.h:42
AVFContext::audio_device_id
char * audio_device_id
Definition: avfoundation.m:129
AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:546
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
avf_read_packet
static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: avfoundation.m:1383
AVFContext::width
int width
Definition: avfoundation.m:110
configure_video_device
static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
Configure the video device.
Definition: avfoundation.m:388
index
int index
Definition: gxfenc.c:90
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AVFContext::audio_buffer
int32_t * audio_buffer
Definition: avfoundation.m:141
AVFContext::video_stream_index
int video_stream_index
Definition: avfoundation.m:121
AV_CODEC_ID_PCM_S24LE
@ AV_CODEC_ID_PCM_S24LE
Definition: codec_id.h:342
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:608
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:75
AVMediaType
AVMediaType
Definition: avutil.h:198
AVPacket::size
int size
Definition: packet.h:604
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:88
height
#define height
Definition: dsp.h:89
destroy_context
static void destroy_context(AVFContext *ctx)
Definition: avfoundation.m:321
shift
static int shift(int a, int b)
Definition: bonk.c:261
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
AVFContext::url
char * url
Definition: avfoundation.m:125
AVFormatContext::url
char * url
input or output URL.
Definition: avformat.h:1449
sample
#define sample
Definition: flacdsp_template.c:44
size
int size
Definition: twinvq_data.h:10344
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
av_malloc
#define av_malloc(s)
Definition: ops_static.c:44
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:488
AVFContext::audio_non_interleaved
int audio_non_interleaved
Definition: avfoundation.m:139
range
enum AVColorRange range
Definition: mediacodec_wrapper.c:2594
avdevice.h
FFInputFormat::p
AVInputFormat p
The public AVInputFormat.
Definition: demux.h:70
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:602
AV_PIX_FMT_YUVA444P
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:174
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:609
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:263
read_header
static int read_header(FFV1Context *f, RangeCoder *c)
Definition: ffv1dec.c:578
av_strstart
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:36
pthread_cond_destroy
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
Definition: os2threads.h:144
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
pthread_mutex_destroy
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:112
av_channel_layout_default
void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels)
Get the default channel layout for a given number of channels.
Definition: channel_layout.c:841
lock_frames
static void lock_frames(AVFContext *ctx)
Definition: avfoundation.m:159
AVFContext::audio_stream_index
int audio_stream_index
Definition: avfoundation.m:123
copy_cvpixelbuffer
static int copy_cvpixelbuffer(AVFormatContext *s, CVPixelBufferRef image_buffer, AVPacket *pkt)
Definition: avfoundation.m:1340
AV_PIX_FMT_RGB555LE
@ AV_PIX_FMT_RGB555LE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
Definition: pixfmt.h:115
AVFContext::audio_bits_per_sample
int audio_bits_per_sample
Definition: avfoundation.m:134
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:596
avf_read_header
static int avf_read_header(AVFormatContext *s)
Definition: avfoundation.m:1084
internal.h
s
uint8_t s
Definition: llvidencdsp.c:39
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
AV_CODEC_ID_DVVIDEO
@ AV_CODEC_ID_DVVIDEO
Definition: codec_id.h:74
AV_CODEC_ID_PCM_S32BE
@ AV_CODEC_ID_PCM_S32BE
Definition: codec_id.h:339
demux.h
pthread_cond_t
Definition: os2threads.h:58
AVFContext::frames_captured
int frames_captured
Definition: avfoundation.m:101
avf_device_listing_serial
static NSString * avf_device_listing_serial(AVCaptureDevice *device)
Definition: avfoundation.m:1026
avf_usb_location_for_serial
static int64_t avf_usb_location_for_serial(const char *serial)
Definition: avfoundation.m:914
AVFContext::video_is_muxed
int video_is_muxed
Definition: avfoundation.m:116
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:766
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:264
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:96
AVFContext::audio_device_index
int audio_device_index
Definition: avfoundation.m:122
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:81
avf_pixel_formats
static const struct AVFPixelFormatSpec avf_pixel_formats[]
Definition: avfoundation.m:68
AVFContext::audio_output
AVCaptureAudioDataOutput * audio_output
Definition: avfoundation.m:148
id
enum AVCodecID id
Definition: dts2pts.c:607
AV_PIX_FMT_UYVY422
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:88
status
ov_status_e status
Definition: dnn_backend_openvino.c:99
AVFContext::avf_audio_delegate
id avf_audio_delegate
Definition: avfoundation.m:107
channel_layout.h
AVFContext::video_is_screen
int video_is_screen
Definition: avfoundation.m:117
mode
mode
Definition: ebur128.h:83
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:258
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
AV_OPT_TYPE_PIXEL_FMT
@ AV_OPT_TYPE_PIXEL_FMT
Underlying C type is enum AVPixelFormat.
Definition: opt.h:306
AVPacket::stream_index
int stream_index
Definition: packet.h:605
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:78
AVFContext::audio_filename
char * audio_filename
Definition: avfoundation.m:127
AV_PIX_FMT_RGB565BE
@ AV_PIX_FMT_RGB565BE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
Definition: pixfmt.h:112
pthread_cond_wait
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Definition: os2threads.h:192
AV_OPT_FLAG_DECODING_PARAM
#define AV_OPT_FLAG_DECODING_PARAM
A generic parameter which can be set by the user for demuxing or decoding.
Definition: opt.h:355
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
AV_CODEC_ID_PCM_S32LE
@ AV_CODEC_ID_PCM_S32LE
Definition: codec_id.h:338
mem.h
get_audio_config
static int get_audio_config(AVFormatContext *s)
Definition: avfoundation.m:722
AVFContext
Definition: avfoundation.m:97
timing_info
static int FUNC() timing_info(CodedBitstreamContext *ctx, RWContext *rw, AV1RawTimingInfo *current)
Definition: cbs_av1_syntax_template.c:158
av_image_copy_to_buffer
int av_image_copy_to_buffer(uint8_t *dst, int dst_size, const uint8_t *const src_data[4], const int src_linesize[4], enum AVPixelFormat pix_fmt, int width, int height, int align)
Copy image data from an image into a buffer.
Definition: imgutils.c:501
AVPacket
This structure stores compressed data.
Definition: packet.h:580
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:326
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
FFInputFormat
Definition: demux.h:66
int32_t
int32_t
Definition: audioconvert.c:56
imgutils.h
AVFContext::video_device_index
int video_device_index
Definition: avfoundation.m:120
AV_PIX_FMT_0RGB
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:262
AV_CODEC_ID_PCM_F32LE
@ AV_CODEC_ID_PCM_F32LE
Definition: codec_id.h:351
avf_log_device_entry
static void avf_log_device_entry(AVFContext *ctx, int index, AVCaptureDevice *device)
Definition: avfoundation.m:1038
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVFAudioReceiver
AudioReceiver class - delegate for AVCaptureSession.
Definition: avfoundation.m:274
pthread_cond_init
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
Definition: os2threads.h:133
pkt
static AVPacket * pkt
Definition: demux_decode.c:55
avstring.h
AVFContext::avf_delegate
id avf_delegate
Definition: avfoundation.m:106
AV_PIX_FMT_YUVA444P16LE
@ AV_PIX_FMT_YUVA444P16LE
planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)
Definition: pixfmt.h:192
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:275
width
#define width
Definition: dsp.h:89
avf_class
static const AVClass avf_class
Definition: avfoundation.m:1563
AVFContext::frame_wait_cond
pthread_cond_t frame_wait_cond
Definition: avfoundation.m:104
AVFContext::capture_session
AVCaptureSession * capture_session
Definition: avfoundation.m:146
AV_CODEC_ID_PCM_S24BE
@ AV_CODEC_ID_PCM_S24BE
Definition: codec_id.h:343
av_get_pix_fmt_name
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:3380
AV_PIX_FMT_BGR48BE
@ AV_PIX_FMT_BGR48BE
packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big...
Definition: pixfmt.h:145
avf_usb_serial_for_location
static NSString * avf_usb_serial_for_location(uint32_t location)
Definition: avfoundation.m:944