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 #import <AVFoundation/AVFoundation.h>
29 #include <pthread.h>
30 
32 #include "libavutil/mem.h"
33 #include "libavutil/pixdesc.h"
34 #include "libavutil/opt.h"
35 #include "libavutil/avstring.h"
36 #include "libavformat/demux.h"
37 #include "libavformat/internal.h"
38 #include "libavutil/internal.h"
39 #include "libavutil/parseutils.h"
40 #include "libavutil/time.h"
41 #include "libavutil/imgutils.h"
42 #include "avdevice.h"
43 
44 static const int avf_time_base = 1000000;
45 
46 static const AVRational avf_time_base_q = {
47  .num = 1,
48  .den = avf_time_base
49 };
50 
53  OSType avf_id;
54 };
55 
56 static const struct AVFPixelFormatSpec avf_pixel_formats[] = {
57  { AV_PIX_FMT_MONOBLACK, kCVPixelFormatType_1Monochrome },
58  { AV_PIX_FMT_RGB555BE, kCVPixelFormatType_16BE555 },
59  { AV_PIX_FMT_RGB555LE, kCVPixelFormatType_16LE555 },
60  { AV_PIX_FMT_RGB565BE, kCVPixelFormatType_16BE565 },
61  { AV_PIX_FMT_RGB565LE, kCVPixelFormatType_16LE565 },
62  { AV_PIX_FMT_RGB24, kCVPixelFormatType_24RGB },
63  { AV_PIX_FMT_BGR24, kCVPixelFormatType_24BGR },
64  { AV_PIX_FMT_0RGB, kCVPixelFormatType_32ARGB },
65  { AV_PIX_FMT_BGR0, kCVPixelFormatType_32BGRA },
66  { AV_PIX_FMT_0BGR, kCVPixelFormatType_32ABGR },
67  { AV_PIX_FMT_RGB0, kCVPixelFormatType_32RGBA },
68  { AV_PIX_FMT_BGR48BE, kCVPixelFormatType_48RGB },
69  { AV_PIX_FMT_UYVY422, kCVPixelFormatType_422YpCbCr8 },
70  { AV_PIX_FMT_YUVA444P, kCVPixelFormatType_4444YpCbCrA8R },
71  { AV_PIX_FMT_YUVA444P16LE, kCVPixelFormatType_4444AYpCbCr16 },
72  { AV_PIX_FMT_YUV444P, kCVPixelFormatType_444YpCbCr8 },
73  { AV_PIX_FMT_YUV422P16, kCVPixelFormatType_422YpCbCr16 },
74  { AV_PIX_FMT_YUV422P10, kCVPixelFormatType_422YpCbCr10 },
75  { AV_PIX_FMT_YUV444P10, kCVPixelFormatType_444YpCbCr10 },
76  { AV_PIX_FMT_YUV420P, kCVPixelFormatType_420YpCbCr8Planar },
77  { AV_PIX_FMT_NV12, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange },
78  { AV_PIX_FMT_YUYV422, kCVPixelFormatType_422YpCbCr8_yuvs },
79 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
80  { AV_PIX_FMT_GRAY8, kCVPixelFormatType_OneComponent8 },
81 #endif
82  { AV_PIX_FMT_NONE, 0 }
83 };
84 
85 typedef struct
86 {
87  AVClass* class;
88 
96 
98  int width, height;
99 
106 
112 
113  char *url;
116 
118 
122  int audio_be;
126 
129 
130  enum AVPixelFormat pixel_format;
131 
132  AVCaptureSession *capture_session;
133  AVCaptureVideoDataOutput *video_output;
134  AVCaptureAudioDataOutput *audio_output;
135  CMSampleBufferRef current_frame;
136  CMSampleBufferRef current_audio_frame;
137 
138  AVCaptureDevice *observed_device;
139 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
140  AVCaptureDeviceTransportControlsPlaybackMode observed_mode;
141 #endif
143 } AVFContext;
144 
146 {
147  pthread_mutex_lock(&ctx->frame_lock);
148 }
149 
151 {
152  pthread_cond_broadcast(&ctx->frame_wait_cond);
153  pthread_mutex_unlock(&ctx->frame_lock);
154 }
155 
156 /** FrameReceiver class - delegate for AVCaptureSession
157  */
158 @interface AVFFrameReceiver : NSObject
159 {
161 }
162 
163 - (id)initWithContext:(AVFContext*)context;
164 
165 - (void) captureOutput:(AVCaptureOutput *)captureOutput
166  didOutputSampleBuffer:(CMSampleBufferRef)videoFrame
167  fromConnection:(AVCaptureConnection *)connection;
168 
169 @end
170 
171 @implementation AVFFrameReceiver
172 
173 - (id)initWithContext:(AVFContext*)context
174 {
175  if (self = [super init]) {
176  _context = context;
177 
178  // start observing if a device is set for it
179 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
180  if (_context->observed_device) {
181  NSString *keyPath = NSStringFromSelector(@selector(transportControlsPlaybackMode));
182  NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew;
183 
184  [_context->observed_device addObserver: self
185  forKeyPath: keyPath
186  options: options
187  context: _context];
188  }
189 #endif
190  }
191  return self;
192 }
193 
194 - (void)dealloc {
195  // stop observing if a device is set for it
196 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
197  if (_context->observed_device) {
198  NSString *keyPath = NSStringFromSelector(@selector(transportControlsPlaybackMode));
199  [_context->observed_device removeObserver: self forKeyPath: keyPath];
200  }
201 #endif
202  [super dealloc];
203 }
204 
205 - (void)observeValueForKeyPath:(NSString *)keyPath
206  ofObject:(id)object
207  change:(NSDictionary *)change
208  context:(void *)context {
209  if (context == _context) {
210 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
211  AVCaptureDeviceTransportControlsPlaybackMode mode =
212  [change[NSKeyValueChangeNewKey] integerValue];
213 
214  if (mode != _context->observed_mode) {
215  if (mode == AVCaptureDeviceTransportControlsNotPlayingMode) {
216  // Set under the lock and broadcast so a reader blocked in
217  // avf_read_packet() wakes up and returns EOF instead of
218  // hanging once the device stops delivering frames.
220  _context->observed_quit = 1;
222  }
223  _context->observed_mode = mode;
224  }
225 #endif
226  } else {
227  [super observeValueForKeyPath: keyPath
228  ofObject: object
229  change: change
230  context: context];
231  }
232 }
233 
234 - (void) captureOutput:(AVCaptureOutput *)captureOutput
235  didOutputSampleBuffer:(CMSampleBufferRef)videoFrame
236  fromConnection:(AVCaptureConnection *)connection
237 {
239 
240  while ((_context->current_frame != nil) && !_context->is_stopping) {
242  }
243 
244  if (_context->is_stopping) {
246  return;
247  }
248 
249  _context->current_frame = (CMSampleBufferRef)CFRetain(videoFrame);
250 
252 
254 }
255 
256 @end
257 
258 /** AudioReceiver class - delegate for AVCaptureSession
259  */
260 @interface AVFAudioReceiver : NSObject
261 {
263 }
264 
265 - (id)initWithContext:(AVFContext*)context;
266 
267 - (void) captureOutput:(AVCaptureOutput *)captureOutput
268  didOutputSampleBuffer:(CMSampleBufferRef)audioFrame
269  fromConnection:(AVCaptureConnection *)connection;
270 
271 @end
272 
273 @implementation AVFAudioReceiver
274 
275 - (id)initWithContext:(AVFContext*)context
276 {
277  if (self = [super init]) {
278  _context = context;
279  }
280  return self;
281 }
282 
283 - (void) captureOutput:(AVCaptureOutput *)captureOutput
284  didOutputSampleBuffer:(CMSampleBufferRef)audioFrame
285  fromConnection:(AVCaptureConnection *)connection
286 {
288 
289  while ((_context->current_audio_frame != nil) && !_context->is_stopping) {
291  }
292 
293  if (_context->is_stopping) {
295  return;
296  }
297 
298  _context->current_audio_frame = (CMSampleBufferRef)CFRetain(audioFrame);
299 
301 
303 }
304 
305 @end
306 
308 {
309  // Wake any capture callback blocked waiting for the consumer and make it
310  // bail out, so stopRunning() can drain the session without a deadlock.
311  lock_frames(ctx);
312  ctx->is_stopping = 1;
314 
315  [ctx->capture_session stopRunning];
316 
317  [ctx->capture_session release];
318  [ctx->video_output release];
319  [ctx->audio_output release];
320  [ctx->avf_delegate release];
321  [ctx->avf_audio_delegate release];
322 
323  ctx->capture_session = NULL;
324  ctx->video_output = NULL;
325  ctx->audio_output = NULL;
326  ctx->avf_delegate = NULL;
327  ctx->avf_audio_delegate = NULL;
328 
329  av_freep(&ctx->url);
330  av_freep(&ctx->audio_buffer);
331 
332  pthread_cond_destroy(&ctx->frame_wait_cond);
333  pthread_mutex_destroy(&ctx->frame_lock);
334 
335  if (ctx->current_frame) {
336  CFRelease(ctx->current_frame);
337  ctx->current_frame = nil;
338  }
339 
340  if (ctx->current_audio_frame) {
341  CFRelease(ctx->current_audio_frame);
342  ctx->current_audio_frame = nil;
343  }
344 }
345 
347 {
348  AVFContext *ctx = (AVFContext*)s->priv_data;
349  char *save;
350 
351  ctx->url = av_strdup(s->url);
352 
353  if (!ctx->url)
354  return AVERROR(ENOMEM);
355  if (ctx->url[0] != ':') {
356  ctx->video_filename = av_strtok(ctx->url, ":", &save);
357  ctx->audio_filename = av_strtok(NULL, ":", &save);
358  } else {
359  ctx->audio_filename = av_strtok(ctx->url, ":", &save);
360  }
361  return 0;
362 }
363 
364 /**
365  * Configure the video device.
366  *
367  * Configure the video device using a run-time approach to access properties
368  * since formats, activeFormat are available since iOS >= 7.0 or OSX >= 10.7
369  * and activeVideoMaxFrameDuration is available since i0S >= 7.0 and OSX >= 10.9.
370  *
371  * The NSUndefinedKeyException must be handled by the caller of this function.
372  *
373  */
374 static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
375 {
376  AVFContext *ctx = (AVFContext*)s->priv_data;
377 
378  double framerate = av_q2d(ctx->framerate);
379  NSObject *range = nil;
380  NSObject *format = nil;
381  NSObject *selected_range = nil;
382  NSObject *selected_format = nil;
383 
384  // try to configure format by formats list
385  // might raise an exception if no format list is given
386  // (then fallback to default, no configuration)
387  @try {
388  for (format in [video_device valueForKey:@"formats"]) {
389  CMFormatDescriptionRef formatDescription;
390  CMVideoDimensions dimensions;
391 
392  formatDescription = (CMFormatDescriptionRef) [format performSelector:@selector(formatDescription)];
393  dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
394 
395  if ((ctx->width == 0 && ctx->height == 0) ||
396  (dimensions.width == ctx->width && dimensions.height == ctx->height)) {
397 
398  selected_format = format;
399 
400  for (range in [format valueForKey:@"videoSupportedFrameRateRanges"]) {
401  double max_framerate;
402 
403  [[range valueForKey:@"maxFrameRate"] getValue:&max_framerate];
404  if (fabs (framerate - max_framerate) < 0.01) {
405  selected_range = range;
406  break;
407  }
408  }
409  }
410  }
411 
412  if (!selected_format) {
413  av_log(s, AV_LOG_ERROR, "Selected video size (%dx%d) is not supported by the device.\n",
414  ctx->width, ctx->height);
415  goto unsupported_format;
416  }
417 
418  if (!selected_range) {
419  av_log(s, AV_LOG_ERROR, "Selected framerate (%f) is not supported by the device.\n",
420  framerate);
421  if (ctx->video_is_muxed) {
422  av_log(s, AV_LOG_ERROR, "Falling back to default.\n");
423  } else {
424  goto unsupported_format;
425  }
426  }
427 
428  if ([video_device lockForConfiguration:NULL] == YES) {
429  if (selected_format) {
430  [video_device setValue:selected_format forKey:@"activeFormat"];
431  }
432  if (selected_range) {
433  NSValue *min_frame_duration = [selected_range valueForKey:@"minFrameDuration"];
434  [video_device setValue:min_frame_duration forKey:@"activeVideoMinFrameDuration"];
435  [video_device setValue:min_frame_duration forKey:@"activeVideoMaxFrameDuration"];
436  }
437  } else {
438  av_log(s, AV_LOG_ERROR, "Could not lock device for configuration.\n");
439  return AVERROR(EINVAL);
440  }
441  } @catch(NSException *e) {
442  av_log(ctx, AV_LOG_WARNING, "Configuration of video device failed, falling back to default.\n");
443  }
444 
445  return 0;
446 
447 unsupported_format:
448 
449  av_log(s, AV_LOG_ERROR, "Supported modes:\n");
450  for (format in [video_device valueForKey:@"formats"]) {
451  CMFormatDescriptionRef formatDescription;
452  CMVideoDimensions dimensions;
453 
454  formatDescription = (CMFormatDescriptionRef) [format performSelector:@selector(formatDescription)];
455  dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
456 
457  for (range in [format valueForKey:@"videoSupportedFrameRateRanges"]) {
458  double min_framerate;
459  double max_framerate;
460 
461  [[range valueForKey:@"minFrameRate"] getValue:&min_framerate];
462  [[range valueForKey:@"maxFrameRate"] getValue:&max_framerate];
463  av_log(s, AV_LOG_ERROR, " %dx%d@[%f %f]fps\n",
464  dimensions.width, dimensions.height,
465  min_framerate, max_framerate);
466  }
467  }
468  return AVERROR(EINVAL);
469 }
470 
471 static int add_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
472 {
473  AVFContext *ctx = (AVFContext*)s->priv_data;
474  int ret;
475  NSError *error = nil;
476  AVCaptureInput* capture_input = nil;
477  struct AVFPixelFormatSpec pxl_fmt_spec;
478  NSNumber *pixel_format;
479  NSDictionary *capture_dict;
480  dispatch_queue_t queue;
481 
482  if (ctx->video_device_index < ctx->num_video_devices) {
483  capture_input = (AVCaptureInput*) [[[AVCaptureDeviceInput alloc] initWithDevice:video_device error:&error] autorelease];
484  } else {
485  capture_input = (AVCaptureInput*) video_device;
486  }
487 
488  if (!capture_input) {
489  av_log(s, AV_LOG_ERROR, "Failed to create AV capture input device: %s\n",
490  [[error localizedDescription] UTF8String]);
491  return 1;
492  }
493 
494  if ([ctx->capture_session canAddInput:capture_input]) {
495  [ctx->capture_session addInput:capture_input];
496  } else {
497  av_log(s, AV_LOG_ERROR, "can't add video input to capture session\n");
498  return 1;
499  }
500 
501  // Attaching output
502  ctx->video_output = [[AVCaptureVideoDataOutput alloc] init];
503 
504  if (!ctx->video_output) {
505  av_log(s, AV_LOG_ERROR, "Failed to init AV video output\n");
506  return 1;
507  }
508 
509  // Configure device framerate and video size
510  @try {
511  if ((ret = configure_video_device(s, video_device)) < 0) {
512  return ret;
513  }
514  } @catch (NSException *exception) {
515  if (![[exception name] isEqualToString:NSUndefinedKeyException]) {
516  av_log (s, AV_LOG_ERROR, "An error occurred: %s", [exception.reason UTF8String]);
517  return AVERROR_EXTERNAL;
518  }
519  }
520 
521  // select pixel format
522  pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE;
523 
524  for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE; i++) {
525  if (ctx->pixel_format == avf_pixel_formats[i].ff_id) {
526  pxl_fmt_spec = avf_pixel_formats[i];
527  break;
528  }
529  }
530 
531  // check if selected pixel format is supported by AVFoundation
532  if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
533  av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by AVFoundation.\n",
534  av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
535  return 1;
536  }
537 
538  // check if the pixel format is available for this device
539  if ([[ctx->video_output availableVideoCVPixelFormatTypes] indexOfObject:[NSNumber numberWithInt:pxl_fmt_spec.avf_id]] == NSNotFound) {
540  av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by the input device.\n",
541  av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
542 
543  pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE;
544 
545  av_log(s, AV_LOG_ERROR, "Supported pixel formats:\n");
546  for (NSNumber *pxl_fmt in [ctx->video_output availableVideoCVPixelFormatTypes]) {
547  struct AVFPixelFormatSpec pxl_fmt_dummy;
548  pxl_fmt_dummy.ff_id = AV_PIX_FMT_NONE;
549  for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE; i++) {
550  if ([pxl_fmt intValue] == avf_pixel_formats[i].avf_id) {
551  pxl_fmt_dummy = avf_pixel_formats[i];
552  break;
553  }
554  }
555 
556  if (pxl_fmt_dummy.ff_id != AV_PIX_FMT_NONE) {
557  av_log(s, AV_LOG_ERROR, " %s\n", av_get_pix_fmt_name(pxl_fmt_dummy.ff_id));
558 
559  // select first supported pixel format instead of user selected (or default) pixel format
560  if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
561  pxl_fmt_spec = pxl_fmt_dummy;
562  }
563  }
564  }
565 
566  // fail if there is no appropriate pixel format or print a warning about overriding the pixel format
567  if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
568  return 1;
569  } else {
570  av_log(s, AV_LOG_WARNING, "Overriding selected pixel format to use %s instead.\n",
571  av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
572  }
573  }
574 
575  // set videoSettings to an empty dict for receiving raw data of muxed devices
576  if (ctx->capture_raw_data) {
577  ctx->pixel_format = pxl_fmt_spec.ff_id;
578  ctx->video_output.videoSettings = @{ };
579  } else {
580  ctx->pixel_format = pxl_fmt_spec.ff_id;
581  pixel_format = [NSNumber numberWithUnsignedInt:pxl_fmt_spec.avf_id];
582  capture_dict = [NSDictionary dictionaryWithObject:pixel_format
583  forKey:(id)kCVPixelBufferPixelFormatTypeKey];
584 
585  [ctx->video_output setVideoSettings:capture_dict];
586  }
587  [ctx->video_output setAlwaysDiscardsLateVideoFrames:ctx->drop_late_frames];
588 
589 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
590  // check for transport control support and set observer device if supported
591  if (!ctx->video_is_screen) {
592  int trans_ctrl = [video_device transportControlsSupported];
593  AVCaptureDeviceTransportControlsPlaybackMode trans_mode = [video_device transportControlsPlaybackMode];
594 
595  if (trans_ctrl) {
596  ctx->observed_mode = trans_mode;
597  ctx->observed_device = video_device;
598  }
599  }
600 #endif
601 
602  ctx->avf_delegate = [[AVFFrameReceiver alloc] initWithContext:ctx];
603 
604  queue = dispatch_queue_create("avf_queue", NULL);
605  [ctx->video_output setSampleBufferDelegate:ctx->avf_delegate queue:queue];
606  dispatch_release(queue);
607 
608  if ([ctx->capture_session canAddOutput:ctx->video_output]) {
609  [ctx->capture_session addOutput:ctx->video_output];
610  } else {
611  av_log(s, AV_LOG_ERROR, "can't add video output to capture session\n");
612  return 1;
613  }
614 
615  return 0;
616 }
617 
618 static int add_audio_device(AVFormatContext *s, AVCaptureDevice *audio_device)
619 {
620  AVFContext *ctx = (AVFContext*)s->priv_data;
621  NSError *error = nil;
622  AVCaptureDeviceInput* audio_dev_input = [[[AVCaptureDeviceInput alloc] initWithDevice:audio_device error:&error] autorelease];
623  dispatch_queue_t queue;
624 
625  if (!audio_dev_input) {
626  av_log(s, AV_LOG_ERROR, "Failed to create AV capture input device: %s\n",
627  [[error localizedDescription] UTF8String]);
628  return 1;
629  }
630 
631  if ([ctx->capture_session canAddInput:audio_dev_input]) {
632  [ctx->capture_session addInput:audio_dev_input];
633  } else {
634  av_log(s, AV_LOG_ERROR, "can't add audio input to capture session\n");
635  return 1;
636  }
637 
638  // Attaching output
639  ctx->audio_output = [[AVCaptureAudioDataOutput alloc] init];
640 
641  if (!ctx->audio_output) {
642  av_log(s, AV_LOG_ERROR, "Failed to init AV audio output\n");
643  return 1;
644  }
645 
646  ctx->avf_audio_delegate = [[AVFAudioReceiver alloc] initWithContext:ctx];
647 
648  queue = dispatch_queue_create("avf_audio_queue", NULL);
649  [ctx->audio_output setSampleBufferDelegate:ctx->avf_audio_delegate queue:queue];
650  dispatch_release(queue);
651 
652  if ([ctx->capture_session canAddOutput:ctx->audio_output]) {
653  [ctx->capture_session addOutput:ctx->audio_output];
654  } else {
655  av_log(s, AV_LOG_ERROR, "adding audio output to capture session failed\n");
656  return 1;
657  }
658 
659  return 0;
660 }
661 
663 {
664  AVFContext *ctx = (AVFContext*)s->priv_data;
665  CVImageBufferRef image_buffer;
666  CGSize image_buffer_size;
667  AVStream* stream = avformat_new_stream(s, NULL);
668 
669  if (!stream) {
670  return 1;
671  }
672 
673  // Take stream info from the first frame.
674  while (ctx->frames_captured < 1) {
675  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES);
676  }
677 
678  lock_frames(ctx);
679 
680  ctx->video_stream_index = stream->index;
681 
682  avpriv_set_pts_info(stream, 64, 1, avf_time_base);
683 
684  image_buffer = CMSampleBufferGetImageBuffer(ctx->current_frame);
685 
686  if (image_buffer) {
687  image_buffer_size = CVImageBufferGetEncodedSize(image_buffer);
688 
689  stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
690  stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
691  stream->codecpar->width = (int)image_buffer_size.width;
692  stream->codecpar->height = (int)image_buffer_size.height;
693  stream->codecpar->format = ctx->pixel_format;
694  } else {
695  stream->codecpar->codec_id = AV_CODEC_ID_DVVIDEO;
696  stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
697  stream->codecpar->format = ctx->pixel_format;
698  }
699 
700  CFRelease(ctx->current_frame);
701  ctx->current_frame = nil;
702 
704 
705  return 0;
706 }
707 
709 {
710  AVFContext *ctx = (AVFContext*)s->priv_data;
711  CMFormatDescriptionRef format_desc;
712  AVStream* stream = avformat_new_stream(s, NULL);
713 
714  if (!stream) {
715  return 1;
716  }
717 
718  // Take stream info from the first frame.
719  while (ctx->audio_frames_captured < 1) {
720  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES);
721  }
722 
723  lock_frames(ctx);
724 
725  ctx->audio_stream_index = stream->index;
726 
727  avpriv_set_pts_info(stream, 64, 1, avf_time_base);
728 
729  format_desc = CMSampleBufferGetFormatDescription(ctx->current_audio_frame);
730  const AudioStreamBasicDescription *basic_desc = CMAudioFormatDescriptionGetStreamBasicDescription(format_desc);
731 
732  if (!basic_desc) {
734  av_log(s, AV_LOG_ERROR, "audio format not available\n");
735  return 1;
736  }
737 
738  stream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
739  stream->codecpar->sample_rate = basic_desc->mSampleRate;
740  av_channel_layout_default(&stream->codecpar->ch_layout, basic_desc->mChannelsPerFrame);
741 
742  ctx->audio_channels = basic_desc->mChannelsPerFrame;
743  ctx->audio_bits_per_sample = basic_desc->mBitsPerChannel;
744  ctx->audio_float = basic_desc->mFormatFlags & kAudioFormatFlagIsFloat;
745  ctx->audio_be = basic_desc->mFormatFlags & kAudioFormatFlagIsBigEndian;
746  ctx->audio_signed_integer = basic_desc->mFormatFlags & kAudioFormatFlagIsSignedInteger;
747  ctx->audio_packed = basic_desc->mFormatFlags & kAudioFormatFlagIsPacked;
748  ctx->audio_non_interleaved = basic_desc->mFormatFlags & kAudioFormatFlagIsNonInterleaved;
749 
750  if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
751  ctx->audio_float &&
752  ctx->audio_bits_per_sample == 32 &&
753  ctx->audio_packed) {
754  stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
755  } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
756  ctx->audio_signed_integer &&
757  ctx->audio_bits_per_sample == 16 &&
758  ctx->audio_packed) {
759  stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
760  } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
761  ctx->audio_signed_integer &&
762  ctx->audio_bits_per_sample == 24 &&
763  ctx->audio_packed) {
764  stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
765  } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
766  ctx->audio_signed_integer &&
767  ctx->audio_bits_per_sample == 32 &&
768  ctx->audio_packed) {
769  stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
770  } else {
772  av_log(s, AV_LOG_ERROR, "audio format is not supported\n");
773  return 1;
774  }
775 
776  if (ctx->audio_non_interleaved) {
777  CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
778  ctx->audio_buffer_size = CMBlockBufferGetDataLength(block_buffer);
779  ctx->audio_buffer = av_malloc(ctx->audio_buffer_size);
780  if (!ctx->audio_buffer) {
782  av_log(s, AV_LOG_ERROR, "error allocating audio buffer\n");
783  return 1;
784  }
785  }
786 
787  CFRelease(ctx->current_audio_frame);
788  ctx->current_audio_frame = nil;
789 
791 
792  return 0;
793 }
794 
795 static NSArray* getDevicesWithMediaType(AVMediaType mediaType) {
796 #if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500))
797  NSMutableArray *deviceTypes = nil;
798  if (mediaType == AVMediaTypeVideo) {
799  deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeBuiltInWideAngleCamera]];
800  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
801  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInDualCamera];
802  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTelephotoCamera];
803  #endif
804  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110100)
805  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTrueDepthCamera];
806  #endif
807  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)
808  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTripleCamera];
809  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInDualWideCamera];
810  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInUltraWideCamera];
811  #endif
812  #if (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 130000)
813  [deviceTypes addObject: AVCaptureDeviceTypeDeskViewCamera];
814  #endif
815  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 150400)
816  [deviceTypes addObject: AVCaptureDeviceTypeBuiltInLiDARDepthCamera];
817  #endif
818  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 170000 || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000))
819  [deviceTypes addObject: AVCaptureDeviceTypeContinuityCamera];
820  [deviceTypes addObject: AVCaptureDeviceTypeExternal];
821  #elif (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 140000)
822  [deviceTypes addObject: AVCaptureDeviceTypeExternalUnknown];
823  #endif
824  } else if (mediaType == AVMediaTypeAudio) {
825  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 170000 || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000))
826  deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeMicrophone]];
827  #else
828  deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeBuiltInMicrophone]];
829  #endif
830  } else if (mediaType == AVMediaTypeMuxed) {
831  #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 170000 || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000))
832  deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeExternal]];
833  #elif (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 140000)
834  deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeExternalUnknown]];
835  #else
836  return nil;
837  #endif
838  } else {
839  return nil;
840  }
841 
842  AVCaptureDeviceDiscoverySession *captureDeviceDiscoverySession =
843  [AVCaptureDeviceDiscoverySession
844  discoverySessionWithDeviceTypes:deviceTypes
845  mediaType:mediaType
846  position:AVCaptureDevicePositionUnspecified];
847  return [captureDeviceDiscoverySession devices];
848 #elif TARGET_OS_OSX
849  return [AVCaptureDevice devicesWithMediaType:mediaType];
850 #else
851  return nil;
852 #endif
853 }
854 
856 {
857  int ret = 0;
858  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
859  uint32_t num_screens = 0;
860  AVFContext *ctx = (AVFContext*)s->priv_data;
861  AVCaptureDevice *video_device = nil;
862  AVCaptureDevice *audio_device = nil;
863  // Find capture device
864  NSArray *devices = getDevicesWithMediaType(AVMediaTypeVideo);
865  NSArray *devices_muxed = getDevicesWithMediaType(AVMediaTypeMuxed);
866 
867  ctx->num_video_devices = [devices count] + [devices_muxed count];
868 
869  pthread_mutex_init(&ctx->frame_lock, NULL);
870  pthread_cond_init(&ctx->frame_wait_cond, NULL);
871  ctx->is_stopping = 0;
872 
873 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
874  CGGetActiveDisplayList(0, NULL, &num_screens);
875 #endif
876 
877  // List devices if requested
878  if (ctx->list_devices) {
879  int index = 0;
880  av_log(ctx, AV_LOG_INFO, "AVFoundation video devices:\n");
881  for (AVCaptureDevice *device in devices) {
882  const char *name = [[device localizedName] UTF8String];
883  index = [devices indexOfObject:device];
884  av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name);
885  }
886  for (AVCaptureDevice *device in devices_muxed) {
887  const char *name = [[device localizedName] UTF8String];
888  index = [devices count] + [devices_muxed indexOfObject:device];
889  av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name);
890  }
891 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
892  if (num_screens > 0) {
893  CGDirectDisplayID screens[num_screens];
894  CGGetActiveDisplayList(num_screens, screens, &num_screens);
895  for (int i = 0; i < num_screens; i++) {
896  av_log(ctx, AV_LOG_INFO, "[%d] Capture screen %d\n", ctx->num_video_devices + i, i);
897  }
898  }
899 #endif
900 
901  av_log(ctx, AV_LOG_INFO, "AVFoundation audio devices:\n");
902  devices = getDevicesWithMediaType(AVMediaTypeAudio);
903  for (AVCaptureDevice *device in devices) {
904  const char *name = [[device localizedName] UTF8String];
905  int index = [devices indexOfObject:device];
906  av_log(ctx, AV_LOG_INFO, "[%d] %s\n", index, name);
907  }
908  goto fail;
909  }
910 
911  // parse input filename for video and audio device
913  if (ret)
914  goto fail;
915 
916  // check for device index given in filename
917  if (ctx->video_device_index == -1 && ctx->video_filename) {
918  sscanf(ctx->video_filename, "%d", &ctx->video_device_index);
919  }
920  if (ctx->audio_device_index == -1 && ctx->audio_filename) {
921  sscanf(ctx->audio_filename, "%d", &ctx->audio_device_index);
922  }
923 
924  if (ctx->video_device_index >= 0) {
925  if (ctx->video_device_index < ctx->num_video_devices) {
926  if (ctx->video_device_index < [devices count]) {
927  video_device = [devices objectAtIndex:ctx->video_device_index];
928  } else {
929  video_device = [devices_muxed objectAtIndex:(ctx->video_device_index - [devices count])];
930  ctx->video_is_muxed = 1;
931  }
932  } else if (ctx->video_device_index < ctx->num_video_devices + num_screens) {
933 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
934  CGDirectDisplayID screens[num_screens];
935  CGGetActiveDisplayList(num_screens, screens, &num_screens);
936  AVCaptureScreenInput* capture_screen_input = [[[AVCaptureScreenInput alloc] initWithDisplayID:screens[ctx->video_device_index - ctx->num_video_devices]] autorelease];
937 
938  if (ctx->framerate.num > 0) {
939  capture_screen_input.minFrameDuration = CMTimeMake(ctx->framerate.den, ctx->framerate.num);
940  }
941 
942 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
943  if (ctx->capture_cursor) {
944  capture_screen_input.capturesCursor = YES;
945  } else {
946  capture_screen_input.capturesCursor = NO;
947  }
948 #endif
949 
950  if (ctx->capture_mouse_clicks) {
951  capture_screen_input.capturesMouseClicks = YES;
952  } else {
953  capture_screen_input.capturesMouseClicks = NO;
954  }
955 
956  video_device = (AVCaptureDevice*) capture_screen_input;
957  ctx->video_is_screen = 1;
958 #endif
959  } else {
960  av_log(ctx, AV_LOG_ERROR, "Invalid device index\n");
961  goto fail;
962  }
963  } else if (ctx->video_filename &&
964  strncmp(ctx->video_filename, "none", 4)) {
965  if (!strncmp(ctx->video_filename, "default", 7)) {
966  video_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
967  } else {
968  // looking for video inputs
969  for (AVCaptureDevice *device in devices) {
970  if (!strncmp(ctx->video_filename, [[device localizedName] UTF8String], strlen(ctx->video_filename))) {
971  video_device = device;
972  break;
973  }
974  }
975  // looking for muxed inputs
976  for (AVCaptureDevice *device in devices_muxed) {
977  if (!strncmp(ctx->video_filename, [[device localizedName] UTF8String], strlen(ctx->video_filename))) {
978  video_device = device;
979  ctx->video_is_muxed = 1;
980  break;
981  }
982  }
983 
984 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
985  // looking for screen inputs
986  if (!video_device) {
987  int idx;
988  if(sscanf(ctx->video_filename, "Capture screen %d", &idx) && idx < num_screens) {
989  CGDirectDisplayID screens[num_screens];
990  CGGetActiveDisplayList(num_screens, screens, &num_screens);
991  AVCaptureScreenInput* capture_screen_input = [[[AVCaptureScreenInput alloc] initWithDisplayID:screens[idx]] autorelease];
992  video_device = (AVCaptureDevice*) capture_screen_input;
993  ctx->video_device_index = ctx->num_video_devices + idx;
994  ctx->video_is_screen = 1;
995 
996  if (ctx->framerate.num > 0) {
997  capture_screen_input.minFrameDuration = CMTimeMake(ctx->framerate.den, ctx->framerate.num);
998  }
999 
1000 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
1001  if (ctx->capture_cursor) {
1002  capture_screen_input.capturesCursor = YES;
1003  } else {
1004  capture_screen_input.capturesCursor = NO;
1005  }
1006 #endif
1007 
1008  if (ctx->capture_mouse_clicks) {
1009  capture_screen_input.capturesMouseClicks = YES;
1010  } else {
1011  capture_screen_input.capturesMouseClicks = NO;
1012  }
1013  }
1014  }
1015 #endif
1016  }
1017 
1018  if (!video_device) {
1019  av_log(ctx, AV_LOG_ERROR, "Video device not found\n");
1020  goto fail;
1021  }
1022  }
1023 
1024  // get audio device
1025  if (ctx->audio_device_index >= 0) {
1026  NSArray *devices = getDevicesWithMediaType(AVMediaTypeAudio);
1027 
1028  if (ctx->audio_device_index >= [devices count]) {
1029  av_log(ctx, AV_LOG_ERROR, "Invalid audio device index\n");
1030  goto fail;
1031  }
1032 
1033  audio_device = [devices objectAtIndex:ctx->audio_device_index];
1034  } else if (ctx->audio_filename &&
1035  strncmp(ctx->audio_filename, "none", 4)) {
1036  if (!strncmp(ctx->audio_filename, "default", 7)) {
1037  audio_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
1038  } else {
1039  NSArray *devices = getDevicesWithMediaType(AVMediaTypeAudio);
1040 
1041  for (AVCaptureDevice *device in devices) {
1042  if (!strncmp(ctx->audio_filename, [[device localizedName] UTF8String], strlen(ctx->audio_filename))) {
1043  audio_device = device;
1044  break;
1045  }
1046  }
1047  }
1048 
1049  if (!audio_device) {
1050  av_log(ctx, AV_LOG_ERROR, "Audio device not found\n");
1051  goto fail;
1052  }
1053  }
1054 
1055  // Video nor Audio capture device not found, looking for AVMediaTypeVideo/Audio
1056  if (!video_device && !audio_device) {
1057  av_log(s, AV_LOG_ERROR, "No AV capture device found\n");
1058  goto fail;
1059  }
1060 
1061  if (video_device) {
1062  if (ctx->video_device_index < ctx->num_video_devices) {
1063  av_log(s, AV_LOG_DEBUG, "'%s' opened\n", [[video_device localizedName] UTF8String]);
1064  } else {
1065  av_log(s, AV_LOG_DEBUG, "'%s' opened\n", [[video_device description] UTF8String]);
1066  }
1067  }
1068  if (audio_device) {
1069  av_log(s, AV_LOG_DEBUG, "audio device '%s' opened\n", [[audio_device localizedName] UTF8String]);
1070  }
1071 
1072  // Initialize capture session
1073  ctx->capture_session = [[AVCaptureSession alloc] init];
1074 
1075  if (video_device && add_video_device(s, video_device)) {
1076  goto fail;
1077  }
1078  if (audio_device && add_audio_device(s, audio_device)) {
1079  }
1080 
1081  [ctx->capture_session startRunning];
1082 
1083  /* Unlock device configuration only after the session is started so it
1084  * does not reset the capture formats */
1085  if (!ctx->video_is_screen) {
1086  [video_device unlockForConfiguration];
1087  }
1088 
1089  if (video_device && get_video_config(s)) {
1090  goto fail;
1091  }
1092 
1093  // set audio stream
1094  if (audio_device && get_audio_config(s)) {
1095  goto fail;
1096  }
1097 
1098  [pool release];
1099  return 0;
1100 
1101 fail:
1102  [pool release];
1104  if (ret)
1105  return ret;
1106  return AVERROR(EIO);
1107 }
1108 
1110  CVPixelBufferRef image_buffer,
1111  AVPacket *pkt)
1112 {
1113  AVFContext *ctx = s->priv_data;
1114  int src_linesize[4];
1115  const uint8_t *src_data[4];
1116  int width = CVPixelBufferGetWidth(image_buffer);
1117  int height = CVPixelBufferGetHeight(image_buffer);
1118  int status;
1119 
1120  memset(src_linesize, 0, sizeof(src_linesize));
1121  memset(src_data, 0, sizeof(src_data));
1122 
1123  status = CVPixelBufferLockBaseAddress(image_buffer, 0);
1124  if (status != kCVReturnSuccess) {
1125  av_log(s, AV_LOG_ERROR, "Could not lock base address: %d (%dx%d)\n", status, width, height);
1126  return AVERROR_EXTERNAL;
1127  }
1128 
1129  if (CVPixelBufferIsPlanar(image_buffer)) {
1130  size_t plane_count = CVPixelBufferGetPlaneCount(image_buffer);
1131  int i;
1132  for(i = 0; i < plane_count; i++){
1133  src_linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(image_buffer, i);
1134  src_data[i] = CVPixelBufferGetBaseAddressOfPlane(image_buffer, i);
1135  }
1136  } else {
1137  src_linesize[0] = CVPixelBufferGetBytesPerRow(image_buffer);
1138  src_data[0] = CVPixelBufferGetBaseAddress(image_buffer);
1139  }
1140 
1142  src_data, src_linesize,
1143  ctx->pixel_format, width, height, 1);
1144 
1145 
1146 
1147  CVPixelBufferUnlockBaseAddress(image_buffer, 0);
1148 
1149  return status;
1150 }
1151 
1153 {
1154  AVFContext* ctx = (AVFContext*)s->priv_data;
1155 
1156  lock_frames(ctx);
1157  do {
1158  CVImageBufferRef image_buffer;
1159  CMBlockBufferRef block_buffer;
1160 
1161  if (ctx->current_frame != nil) {
1162  int status;
1163  int length = 0;
1164 
1165  image_buffer = CMSampleBufferGetImageBuffer(ctx->current_frame);
1166  block_buffer = CMSampleBufferGetDataBuffer(ctx->current_frame);
1167 
1168  if (image_buffer != nil) {
1169  length = (int)CVPixelBufferGetDataSize(image_buffer);
1170  } else if (block_buffer != nil) {
1171  length = (int)CMBlockBufferGetDataLength(block_buffer);
1172  } else {
1173  unlock_frames(ctx);
1174  return AVERROR(EINVAL);
1175  }
1176 
1177  if (av_new_packet(pkt, length) < 0) {
1178  unlock_frames(ctx);
1179  return AVERROR(EIO);
1180  }
1181 
1182  CMItemCount count;
1183  CMSampleTimingInfo timing_info;
1184 
1185  if (CMSampleBufferGetOutputSampleTimingInfoArray(ctx->current_frame, 1, &timing_info, &count) == noErr) {
1186  AVRational timebase_q = av_make_q(1, timing_info.presentationTimeStamp.timescale);
1187  pkt->pts = pkt->dts = av_rescale_q(timing_info.presentationTimeStamp.value, timebase_q, avf_time_base_q);
1188  }
1189 
1190  pkt->stream_index = ctx->video_stream_index;
1192 
1193  if (image_buffer) {
1194  status = copy_cvpixelbuffer(s, image_buffer, pkt);
1195  } else {
1196  status = 0;
1197  OSStatus ret = CMBlockBufferCopyDataBytes(block_buffer, 0, pkt->size, pkt->data);
1198  if (ret != kCMBlockBufferNoErr) {
1199  status = AVERROR(EIO);
1200  }
1201  }
1202  CFRelease(ctx->current_frame);
1203  ctx->current_frame = nil;
1204 
1205  if (status < 0) {
1206  unlock_frames(ctx);
1207  return status;
1208  }
1209  } else if (ctx->current_audio_frame != nil) {
1210  CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(ctx->current_audio_frame);
1211  int block_buffer_size = CMBlockBufferGetDataLength(block_buffer);
1212 
1213  if (!block_buffer || !block_buffer_size) {
1214  unlock_frames(ctx);
1215  return AVERROR(EIO);
1216  }
1217 
1218  if (ctx->audio_non_interleaved && block_buffer_size > ctx->audio_buffer_size) {
1219  unlock_frames(ctx);
1220  return AVERROR_BUFFER_TOO_SMALL;
1221  }
1222 
1223  if (av_new_packet(pkt, block_buffer_size) < 0) {
1224  unlock_frames(ctx);
1225  return AVERROR(EIO);
1226  }
1227 
1228  CMItemCount count;
1229  CMSampleTimingInfo timing_info;
1230 
1231  if (CMSampleBufferGetOutputSampleTimingInfoArray(ctx->current_audio_frame, 1, &timing_info, &count) == noErr) {
1232  AVRational timebase_q = av_make_q(1, timing_info.presentationTimeStamp.timescale);
1233  pkt->pts = pkt->dts = av_rescale_q(timing_info.presentationTimeStamp.value, timebase_q, avf_time_base_q);
1234  }
1235 
1236  pkt->stream_index = ctx->audio_stream_index;
1238 
1239  if (ctx->audio_non_interleaved) {
1240  int sample, c, shift, num_samples;
1241 
1242  OSStatus ret = CMBlockBufferCopyDataBytes(block_buffer, 0, pkt->size, ctx->audio_buffer);
1243  if (ret != kCMBlockBufferNoErr) {
1244  unlock_frames(ctx);
1245  return AVERROR(EIO);
1246  }
1247 
1248  num_samples = pkt->size / (ctx->audio_channels * (ctx->audio_bits_per_sample >> 3));
1249 
1250  // transform decoded frame into output format
1251  #define INTERLEAVE_OUTPUT(bps) \
1252  { \
1253  int##bps##_t **src; \
1254  int##bps##_t *dest; \
1255  src = av_malloc(ctx->audio_channels * sizeof(int##bps##_t*)); \
1256  if (!src) { \
1257  unlock_frames(ctx); \
1258  return AVERROR(EIO); \
1259  } \
1260  \
1261  for (c = 0; c < ctx->audio_channels; c++) { \
1262  src[c] = ((int##bps##_t*)ctx->audio_buffer) + c * num_samples; \
1263  } \
1264  dest = (int##bps##_t*)pkt->data; \
1265  shift = bps - ctx->audio_bits_per_sample; \
1266  for (sample = 0; sample < num_samples; sample++) \
1267  for (c = 0; c < ctx->audio_channels; c++) \
1268  *dest++ = src[c][sample] << shift; \
1269  av_freep(&src); \
1270  }
1271 
1272  if (ctx->audio_bits_per_sample <= 16) {
1273  INTERLEAVE_OUTPUT(16)
1274  } else {
1275  INTERLEAVE_OUTPUT(32)
1276  }
1277  } else {
1278  OSStatus ret = CMBlockBufferCopyDataBytes(block_buffer, 0, pkt->size, pkt->data);
1279  if (ret != kCMBlockBufferNoErr) {
1280  unlock_frames(ctx);
1281  return AVERROR(EIO);
1282  }
1283  }
1284 
1285  CFRelease(ctx->current_audio_frame);
1286  ctx->current_audio_frame = nil;
1287  } else {
1288  pkt->data = NULL;
1289  if (ctx->observed_quit) {
1290  unlock_frames(ctx);
1291  return AVERROR_EOF;
1292  }
1293  // No frame available yet: wait until a capture callback delivers
1294  // one (or until the device is being torn down).
1295  pthread_cond_wait(&ctx->frame_wait_cond, &ctx->frame_lock);
1296  }
1297  } while (!pkt->data && !ctx->is_stopping);
1298 
1299  if (ctx->is_stopping) {
1300  unlock_frames(ctx);
1301  return AVERROR_EOF;
1302  }
1303  unlock_frames(ctx);
1304 
1305  return 0;
1306 }
1307 
1309 {
1310  AVFContext* ctx = (AVFContext*)s->priv_data;
1312  return 0;
1313 }
1314 
1315 static const AVOption options[] = {
1316  { "list_devices", "list available devices", offsetof(AVFContext, list_devices), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
1317  { "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 },
1318  { "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 },
1319  { "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},
1320  { "framerate", "set frame rate", offsetof(AVFContext, framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
1321  { "video_size", "set video size", offsetof(AVFContext, width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
1322  { "capture_cursor", "capture the screen cursor", offsetof(AVFContext, capture_cursor), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
1323  { "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 },
1324  { "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 },
1325  { "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 },
1326 
1327  { NULL },
1328 };
1329 
1330 static const AVClass avf_class = {
1331  .class_name = "AVFoundation indev",
1332  .item_name = av_default_item_name,
1333  .option = options,
1334  .version = LIBAVUTIL_VERSION_INT,
1336 };
1337 
1339  .p.name = "avfoundation",
1340  .p.long_name = NULL_IF_CONFIG_SMALL("AVFoundation input device"),
1341  .p.flags = AVFMT_NOFILE,
1342  .p.priv_class = &avf_class,
1343  .priv_data_size = sizeof(AVFContext),
1346  .read_close = avf_close,
1347 };
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
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:128
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
opt.h
AVFContext::audio_float
int audio_float
Definition: avfoundation.m:121
AVFContext::observed_quit
int observed_quit
Definition: avfoundation.m:142
unlock_frames
static void unlock_frames(AVFContext *ctx)
Definition: avfoundation.m:150
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
AV_CODEC_ID_RAWVIDEO
@ AV_CODEC_ID_RAWVIDEO
Definition: codec_id.h:63
AVFContext::current_audio_frame
CMSampleBufferRef current_audio_frame
Definition: avfoundation.m:136
mode
Definition: swscale.c:71
pixdesc.h
AVFContext::audio_frames_captured
int audio_frames_captured
Definition: avfoundation.m:90
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
AVFContext::is_stopping
int is_stopping
Definition: avfoundation.m:93
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:346
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:119
AVFContext::video_filename
char * video_filename
Definition: avfoundation.m:114
AVFPixelFormatSpec::avf_id
OSType avf_id
Definition: avfoundation.m:53
AVFContext::audio_be
int audio_be
Definition: avfoundation.m:122
AVFContext::capture_cursor
int capture_cursor
Definition: avfoundation.m:100
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:829
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:1308
avf_time_base
static const int avf_time_base
Definition: avfoundation.m:44
read_close
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:143
AVFContext::current_frame
CMSampleBufferRef current_frame
Definition: avfoundation.m:135
AVFPixelFormatSpec::ff_id
enum AVPixelFormat ff_id
Definition: avfoundation.m:52
AVFContext::observed_device
AVCaptureDevice * observed_device
Definition: avfoundation.m:138
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:97
AV_PIX_FMT_YUV444P10
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:542
description
Tag description
Definition: snow.txt:206
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:46
AV_PIX_FMT_YUV422P16
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:551
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:117
INTERLEAVE_OUTPUT
#define INTERLEAVE_OUTPUT(bps)
getDevicesWithMediaType
static NSArray * getDevicesWithMediaType(AVMediaType mediaType)
Definition: avfoundation.m:795
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
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:551
AVFAudioReceiver::_context
AVFContext * _context
Definition: avfoundation.m:262
options
static const AVOption options[]
Definition: avfoundation.m:1315
add_audio_device
static int add_audio_device(AVFormatContext *s, AVCaptureDevice *audio_device)
Definition: avfoundation.m:618
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:101
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:91
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:102
AVFContext::list_devices
int list_devices
Definition: avfoundation.m:107
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:51
get_video_config
static int get_video_config(AVFormatContext *s)
Definition: avfoundation.m:662
if
if(ret)
Definition: filter_design.txt:179
AVFContext::audio_packed
int audio_packed
Definition: avfoundation.m:124
AVFFrameReceiver::_context
AVFContext * _context
Definition: avfoundation.m:160
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:1314
fail
#define fail
Definition: test.h:478
internal.h
AVFContext::video_output
AVCaptureVideoDataOutput * video_output
Definition: avfoundation.m:133
framerate
float framerate
Definition: av1_levels.c:29
AVFContext::audio_signed_integer
int audio_signed_integer
Definition: avfoundation.m:123
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:103
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:471
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AVFFrameReceiver
FrameReceiver class - delegate for AVCaptureSession.
Definition: avfoundation.m:158
ff_avfoundation_demuxer
const FFInputFormat ff_avfoundation_demuxer
Definition: avfoundation.m:1338
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
AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:540
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:1152
AVFContext::width
int width
Definition: avfoundation.m:98
configure_video_device
static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
Configure the video device.
Definition: avfoundation.m:374
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:127
AVFContext::video_stream_index
int video_stream_index
Definition: avfoundation.m:109
AV_CODEC_ID_PCM_S24LE
@ AV_CODEC_ID_PCM_S24LE
Definition: codec_id.h:342
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:579
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:307
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:113
AVFormatContext::url
char * url
input or output URL.
Definition: avformat.h:1430
sample
#define sample
Definition: flacdsp_template.c:44
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:469
AVFContext::audio_non_interleaved
int audio_non_interleaved
Definition: avfoundation.m:125
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:574
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:145
AVFContext::audio_stream_index
int audio_stream_index
Definition: avfoundation.m:111
copy_cvpixelbuffer
static int copy_cvpixelbuffer(AVFormatContext *s, CVPixelBufferRef image_buffer, AVPacket *pkt)
Definition: avfoundation.m:1109
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:120
av_malloc
#define av_malloc(s)
Definition: ops_asmgen.c:44
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:855
internal.h
s
uint8_t s
Definition: llvidencdsp.c:39
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:89
AVFContext::video_is_muxed
int video_is_muxed
Definition: avfoundation.m:104
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:747
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:110
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:56
AVFContext::audio_output
AVCaptureAudioDataOutput * audio_output
Definition: avfoundation.m:134
id
enum AVCodecID id
Definition: dts2pts.c:578
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:100
AVFContext::avf_audio_delegate
id avf_audio_delegate
Definition: avfoundation.m:95
channel_layout.h
AVFContext::video_is_screen
int video_is_screen
Definition: avfoundation.m:105
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
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:115
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
av_strdup
#define av_strdup(s)
Definition: ops_asmgen.c:47
get_audio_config
static int get_audio_config(AVFormatContext *s)
Definition: avfoundation.m:708
AVFContext
Definition: avfoundation.m:85
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:108
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
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVFAudioReceiver
AudioReceiver class - delegate for AVCaptureSession.
Definition: avfoundation.m:260
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:94
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
width
#define width
Definition: dsp.h:89
avf_class
static const AVClass avf_class
Definition: avfoundation.m:1330
AVFContext::frame_wait_cond
pthread_cond_t frame_wait_cond
Definition: avfoundation.m:92
AVFContext::capture_session
AVCaptureSession * capture_session
Definition: avfoundation.m:132
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:3376
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