You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

687 lines
24KB

  1. /*
  2. * AVFoundation input device
  3. * Copyright (c) 2015 Luca Barbato
  4. * Alexandre Lision
  5. *
  6. * This file is part of Libav.
  7. *
  8. * Libav is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * Libav is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with Libav; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #import <AVFoundation/AVFoundation.h>
  23. #include <pthread.h>
  24. #include "libavformat/avformat.h"
  25. #include "libavformat/internal.h"
  26. #include "libavutil/log.h"
  27. #include "libavutil/mathematics.h"
  28. #include "libavutil/opt.h"
  29. #include "libavutil/parseutils.h"
  30. #include "libavutil/pixdesc.h"
  31. #include "libavutil/time.h"
  32. #include "avdevice.h"
  33. struct AVPixelFormatMap {
  34. enum AVPixelFormat pix_fmt;
  35. OSType core_video_fmt;
  36. };
  37. static const struct AVPixelFormatMap pixel_format_map[] = {
  38. { AV_PIX_FMT_ABGR, kCVPixelFormatType_32ABGR },
  39. { AV_PIX_FMT_ARGB, kCVPixelFormatType_32ARGB },
  40. { AV_PIX_FMT_BGR24, kCVPixelFormatType_24BGR },
  41. { AV_PIX_FMT_BGR48BE, kCVPixelFormatType_48RGB },
  42. { AV_PIX_FMT_BGRA, kCVPixelFormatType_32BGRA },
  43. { AV_PIX_FMT_MONOBLACK, kCVPixelFormatType_1Monochrome },
  44. { AV_PIX_FMT_NV12, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange },
  45. { AV_PIX_FMT_RGB24, kCVPixelFormatType_24RGB },
  46. { AV_PIX_FMT_RGB555BE, kCVPixelFormatType_16BE555 },
  47. { AV_PIX_FMT_RGB555LE, kCVPixelFormatType_16LE555 },
  48. { AV_PIX_FMT_RGB565BE, kCVPixelFormatType_16BE565 },
  49. { AV_PIX_FMT_RGB565LE, kCVPixelFormatType_16LE565 },
  50. { AV_PIX_FMT_RGBA, kCVPixelFormatType_32RGBA },
  51. { AV_PIX_FMT_UYVY422, kCVPixelFormatType_422YpCbCr8 },
  52. { AV_PIX_FMT_YUV420P, kCVPixelFormatType_420YpCbCr8Planar },
  53. { AV_PIX_FMT_YUV422P10, kCVPixelFormatType_422YpCbCr10 },
  54. { AV_PIX_FMT_YUV422P16, kCVPixelFormatType_422YpCbCr16 },
  55. { AV_PIX_FMT_YUV444P, kCVPixelFormatType_444YpCbCr8 },
  56. { AV_PIX_FMT_YUV444P10, kCVPixelFormatType_444YpCbCr10 },
  57. { AV_PIX_FMT_YUVA444P, kCVPixelFormatType_4444YpCbCrA8R },
  58. { AV_PIX_FMT_YUVA444P16LE, kCVPixelFormatType_4444AYpCbCr16 },
  59. { AV_PIX_FMT_YUYV422, kCVPixelFormatType_422YpCbCr8_yuvs },
  60. #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
  61. { AV_PIX_FMT_GRAY8, kCVPixelFormatType_OneComponent8 },
  62. #endif
  63. { AV_PIX_FMT_NONE, 0 }
  64. };
  65. static enum AVPixelFormat core_video_to_pix_fmt(OSType core_video_fmt)
  66. {
  67. int i;
  68. for (i = 0; pixel_format_map[i].pix_fmt != AV_PIX_FMT_NONE; i++)
  69. if (core_video_fmt == pixel_format_map[i].core_video_fmt)
  70. return pixel_format_map[i].pix_fmt;
  71. return AV_PIX_FMT_NONE;
  72. }
  73. static OSType pix_fmt_to_core_video(enum AVPixelFormat pix_fmt)
  74. {
  75. int i;
  76. for (i = 0; pixel_format_map[i].pix_fmt != AV_PIX_FMT_NONE; i++)
  77. if (pix_fmt == pixel_format_map[i].pix_fmt)
  78. return pixel_format_map[i].core_video_fmt;
  79. return 0;
  80. }
  81. typedef struct AVFoundationCaptureContext {
  82. AVClass *class;
  83. /* AVOptions */
  84. int list_devices;
  85. int list_formats;
  86. char *pixel_format;
  87. char *video_size; /* String describing video size */
  88. char *framerate; /* String describing the framerate */
  89. int video_stream_index;
  90. int width, height;
  91. AVRational internal_framerate;
  92. int64_t first_pts;
  93. int frames_captured;
  94. pthread_mutex_t frame_lock;
  95. pthread_cond_t frame_wait_cond;
  96. /* ARC-compatible pointers to ObjC objects */
  97. CFTypeRef session; /* AVCaptureSession */
  98. CFTypeRef video_output;
  99. CFTypeRef video_delegate;
  100. CVImageBufferRef current_frame;
  101. } AVFoundationCaptureContext;
  102. #define AUDIO_DEVICES 1
  103. #define VIDEO_DEVICES 2
  104. #define ALL_DEVICES AUDIO_DEVICES | VIDEO_DEVICES
  105. #define OFFSET(x) offsetof(AVFoundationCaptureContext, x)
  106. #define DEC AV_OPT_FLAG_DECODING_PARAM
  107. static const AVOption options[] = {
  108. { "list_devices", "List available devices and exit", OFFSET(list_devices), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, DEC, "list_devices" },
  109. { "all", "Show all the supported devices", OFFSET(list_devices), AV_OPT_TYPE_CONST, { .i64 = ALL_DEVICES }, 0, INT_MAX, DEC, "list_devices" },
  110. { "audio", "Show only the audio devices", OFFSET(list_devices), AV_OPT_TYPE_CONST, { .i64 = AUDIO_DEVICES }, 0, INT_MAX, DEC, "list_devices" },
  111. { "video", "Show only the video devices", OFFSET(list_devices), AV_OPT_TYPE_CONST, { .i64 = VIDEO_DEVICES }, 0, INT_MAX, DEC, "list_devices" },
  112. { "list_formats", "List available formats and exit", OFFSET(list_formats), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, DEC, "list_formats" },
  113. { "pixel_format", "Preferred pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, DEC },
  114. { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, DEC },
  115. { "framerate", "A string representing desired framerate", OFFSET(framerate), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, DEC },
  116. { NULL },
  117. };
  118. static void list_capture_devices_by_type(AVFormatContext *s, NSString *type)
  119. {
  120. NSArray *devices = [AVCaptureDevice devicesWithMediaType:type];
  121. av_log(s, AV_LOG_INFO, "Type: %s\n", [type UTF8String]);
  122. for (AVCaptureDevice *device in devices) {
  123. av_log(s, AV_LOG_INFO, "uniqueID: %s\nname: %s\nformat:\n",
  124. [[device uniqueID] UTF8String],
  125. [[device localizedName] UTF8String]);
  126. for (AVCaptureDeviceFormat *format in device.formats)
  127. av_log(s, AV_LOG_INFO, "\t%s\n",
  128. [[NSString stringWithFormat: @ "%@", format] UTF8String]);
  129. }
  130. }
  131. static int avfoundation_list_capture_devices(AVFormatContext *s)
  132. {
  133. AVFoundationCaptureContext *ctx = s->priv_data;
  134. if (ctx->list_devices & AUDIO_DEVICES)
  135. list_capture_devices_by_type(s, AVMediaTypeAudio);
  136. if (ctx->list_devices & VIDEO_DEVICES)
  137. list_capture_devices_by_type(s, AVMediaTypeVideo);
  138. return AVERROR_EXIT;
  139. }
  140. static int list_formats(AVFormatContext *s)
  141. {
  142. av_log(s, AV_LOG_VERBOSE, "Supported pixel formats (first is more efficient):\n");
  143. AVCaptureVideoDataOutput *out = [[AVCaptureVideoDataOutput alloc] init];
  144. for (NSNumber *cv_pixel_format in[out availableVideoCVPixelFormatTypes]) {
  145. OSType cv_fmt = [cv_pixel_format intValue];
  146. enum AVPixelFormat pix_fmt = core_video_to_pix_fmt(cv_fmt);
  147. if (pix_fmt != AV_PIX_FMT_NONE) {
  148. av_log(s, AV_LOG_VERBOSE, " %s: %d\n",
  149. av_get_pix_fmt_name(pix_fmt),
  150. cv_fmt);
  151. }
  152. }
  153. return AVERROR_EXIT;
  154. }
  155. static void lock_frames(AVFoundationCaptureContext *ctx)
  156. {
  157. pthread_mutex_lock(&ctx->frame_lock);
  158. }
  159. static void unlock_frames(AVFoundationCaptureContext *ctx)
  160. {
  161. pthread_mutex_unlock(&ctx->frame_lock);
  162. }
  163. @interface VideoCapture : NSObject <AVCaptureVideoDataOutputSampleBufferDelegate>
  164. {
  165. AVFoundationCaptureContext *_context;
  166. }
  167. - (id)initWithContext:(AVFoundationCaptureContext *)context;
  168. - (void)captureOutput:(AVCaptureOutput *)captureOutput
  169. didOutputSampleBuffer:(CMSampleBufferRef)videoFrame
  170. fromConnection:(AVCaptureConnection *)connection;
  171. @end
  172. @implementation VideoCapture
  173. - (id)initWithContext:(AVFoundationCaptureContext *)context
  174. {
  175. if (self = [super init]) {
  176. _context = context;
  177. }
  178. return self;
  179. }
  180. - (void)captureOutput:(AVCaptureOutput *)captureOutput
  181. didOutputSampleBuffer:(CMSampleBufferRef)videoFrame
  182. fromConnection:(AVCaptureConnection *)connection
  183. {
  184. CVImageBufferRef buf;
  185. lock_frames(_context);
  186. if (_context->current_frame != nil) {
  187. CFRelease(_context->current_frame);
  188. }
  189. buf = CMSampleBufferGetImageBuffer(videoFrame);
  190. if (!buf)
  191. return;
  192. CFRetain(buf);
  193. _context->current_frame = buf;
  194. pthread_cond_signal(&_context->frame_wait_cond);
  195. unlock_frames(_context);
  196. ++_context->frames_captured;
  197. }
  198. @end
  199. /**
  200. * Configure the video device.
  201. */
  202. static bool configure_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
  203. {
  204. AVFoundationCaptureContext *ctx = s->priv_data;
  205. AVCaptureDeviceFormat *selected_format = nil;
  206. AVFrameRateRange *selected_range = nil;
  207. double framerate = av_q2d(ctx->internal_framerate);
  208. double epsilon = 0.00000001;
  209. for (AVCaptureDeviceFormat *format in[video_device formats]) {
  210. CMFormatDescriptionRef formatDescription;
  211. CMVideoDimensions dimensions;
  212. formatDescription = (CMFormatDescriptionRef)format.formatDescription;
  213. dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
  214. if ((ctx->width == 0 && ctx->height == 0) ||
  215. (dimensions.width == ctx->width && dimensions.height == ctx->height)) {
  216. av_log(s, AV_LOG_VERBOSE, "Trying video size %dx%d\n",
  217. dimensions.width, dimensions.height);
  218. ctx->width = dimensions.width;
  219. ctx->height = dimensions.height;
  220. selected_format = format;
  221. if (framerate) {
  222. av_log(s, AV_LOG_VERBOSE, "Checking support for framerate %f\n",
  223. framerate);
  224. for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges)
  225. if (range.minFrameRate <= (framerate + epsilon) &&
  226. range.maxFrameRate >= (framerate - epsilon)) {
  227. selected_range = range;
  228. break;
  229. }
  230. } else {
  231. selected_range = format.videoSupportedFrameRateRanges[0];
  232. framerate = selected_range.maxFrameRate;
  233. break;
  234. }
  235. if (selected_format && selected_range)
  236. break;
  237. }
  238. }
  239. if (!selected_format) {
  240. av_log(s, AV_LOG_ERROR, "Selected video size (%dx%d) is not supported by the device\n",
  241. ctx->width, ctx->height);
  242. return false;
  243. } else {
  244. av_log(s, AV_LOG_VERBOSE, "Setting video size to %dx%d\n",
  245. ctx->width, ctx->height);
  246. }
  247. if (framerate && !selected_range) {
  248. av_log(s, AV_LOG_ERROR, "Selected framerate (%f) is not supported by the device\n",
  249. framerate);
  250. return false;
  251. } else {
  252. av_log(s, AV_LOG_VERBOSE, "Setting framerate to %f\n",
  253. framerate);
  254. }
  255. if ([video_device lockForConfiguration : NULL] == YES) {
  256. [video_device setActiveFormat : selected_format];
  257. [video_device setActiveVideoMinFrameDuration : CMTimeMake(1, framerate)];
  258. [video_device setActiveVideoMaxFrameDuration : CMTimeMake(1, framerate)];
  259. } else {
  260. av_log(s, AV_LOG_ERROR, "Could not lock device for configuration\n");
  261. return false;
  262. }
  263. return true;
  264. }
  265. static void print_supported_formats(AVFormatContext *s, AVCaptureDevice *device)
  266. {
  267. av_log(s, AV_LOG_WARNING, "Supported modes:\n");
  268. for (AVCaptureDeviceFormat *format in[device formats]) {
  269. CMFormatDescriptionRef formatDescription;
  270. CMVideoDimensions dimensions;
  271. formatDescription = (CMFormatDescriptionRef)format.formatDescription;
  272. dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
  273. for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges)
  274. av_log(s, AV_LOG_WARNING, " %dx%d@[%f %f]fps\n",
  275. dimensions.width, dimensions.height,
  276. range.minFrameRate, range.maxFrameRate);
  277. }
  278. }
  279. static int setup_stream(AVFormatContext *s, AVCaptureDevice *device)
  280. {
  281. AVFoundationCaptureContext *ctx = s->priv_data;
  282. NSError *__autoreleasing error = nil;
  283. AVCaptureDeviceInput *input;
  284. AVCaptureSession *session = (__bridge AVCaptureSession *)ctx->session;
  285. av_log(s, AV_LOG_VERBOSE, "Setting up stream for device %s\n", [[device uniqueID] UTF8String]);
  286. if (!configure_video_device(s, device)) {
  287. av_log(s, AV_LOG_ERROR, "device configuration failed\n");
  288. print_supported_formats(s, device);
  289. return AVERROR(EINVAL);
  290. }
  291. // add the input devices
  292. input = [AVCaptureDeviceInput deviceInputWithDevice:device
  293. error:&error];
  294. if (!input) {
  295. av_log(s, AV_LOG_ERROR, "%s\n",
  296. [[error localizedDescription] UTF8String]);
  297. return AVERROR_UNKNOWN;
  298. }
  299. if ([session canAddInput : input]) {
  300. [session addInput : input];
  301. } else {
  302. av_log(s, AV_LOG_ERROR, "Cannot add video input to capture session\n");
  303. return AVERROR(EINVAL);
  304. }
  305. // add the output devices
  306. if ([device hasMediaType : AVMediaTypeVideo]) {
  307. AVCaptureVideoDataOutput *out = [[AVCaptureVideoDataOutput alloc] init];
  308. NSNumber *core_video_fmt = nil;
  309. if (!out) {
  310. av_log(s, AV_LOG_ERROR, "Failed to init AV video output\n");
  311. return AVERROR(EINVAL);
  312. }
  313. [out setAlwaysDiscardsLateVideoFrames : YES];
  314. if (ctx->pixel_format) {
  315. // Try to use specified pixel format
  316. core_video_fmt = [NSNumber numberWithInt:pix_fmt_to_core_video(av_get_pix_fmt(ctx->pixel_format))];
  317. if ([[out availableVideoCVPixelFormatTypes] indexOfObject : core_video_fmt] != NSNotFound) {
  318. av_log(s, AV_LOG_VERBOSE, "Pixel format %s supported!\n", ctx->pixel_format);
  319. } else {
  320. core_video_fmt = nil;
  321. }
  322. }
  323. if (!ctx->pixel_format || !core_video_fmt) {
  324. av_log(s, AV_LOG_VERBOSE, "Pixel format not supported or not provided, overriding...\n");
  325. for (NSNumber *cv_pixel_format in[out availableVideoCVPixelFormatTypes]) {
  326. OSType cv_fmt = [cv_pixel_format intValue];
  327. enum AVPixelFormat pix_fmt = core_video_to_pix_fmt(cv_fmt);
  328. // Use the first one in the list, it will be the most effective
  329. if (pix_fmt != AV_PIX_FMT_NONE) {
  330. core_video_fmt = cv_pixel_format;
  331. ctx->pixel_format = av_strdup(av_get_pix_fmt_name(pix_fmt));
  332. break;
  333. }
  334. }
  335. }
  336. // fail if there is no appropriate pixel format
  337. if (!core_video_fmt) {
  338. return AVERROR(EINVAL);
  339. } else {
  340. av_log(s, AV_LOG_VERBOSE, "Using %s.\n",
  341. ctx->pixel_format);
  342. }
  343. NSDictionary *capture_dict = [NSDictionary dictionaryWithObject:core_video_fmt
  344. forKey:(const NSString *)kCVPixelBufferPixelFormatTypeKey];
  345. [out setVideoSettings : capture_dict];
  346. VideoCapture *delegate = [[VideoCapture alloc] initWithContext:ctx];
  347. dispatch_queue_t queue = dispatch_queue_create("avf_queue", NULL);
  348. [out setSampleBufferDelegate : delegate queue : queue];
  349. if ([session canAddOutput : out]) {
  350. [session addOutput : out];
  351. ctx->video_output = (__bridge_retained CFTypeRef)out;
  352. ctx->video_delegate = (__bridge_retained CFTypeRef)delegate;
  353. } else {
  354. av_log(s, AV_LOG_ERROR, "can't add video output to capture session\n");
  355. return AVERROR(EINVAL);
  356. }
  357. }
  358. return 0;
  359. }
  360. static int get_video_config(AVFormatContext *s)
  361. {
  362. AVFoundationCaptureContext *ctx = (AVFoundationCaptureContext *)s->priv_data;
  363. CVImageBufferRef image_buffer;
  364. CGSize image_buffer_size;
  365. AVStream *stream = avformat_new_stream(s, NULL);
  366. if (!stream) {
  367. av_log(s, AV_LOG_ERROR, "Failed to create AVStream\n");
  368. return AVERROR(EINVAL);
  369. }
  370. // Take stream info from the first frame.
  371. while (ctx->frames_captured < 1)
  372. CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES);
  373. lock_frames(ctx);
  374. ctx->video_stream_index = stream->index;
  375. avpriv_set_pts_info(stream, 64, 1, 1000000);
  376. image_buffer = ctx->current_frame;
  377. image_buffer_size = CVImageBufferGetEncodedSize(image_buffer);
  378. stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
  379. stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
  380. stream->codecpar->width = (int)image_buffer_size.width;
  381. stream->codecpar->height = (int)image_buffer_size.height;
  382. stream->codecpar->format = av_get_pix_fmt(ctx->pixel_format);
  383. CFRelease(ctx->current_frame);
  384. ctx->current_frame = nil;
  385. unlock_frames(ctx);
  386. return 0;
  387. }
  388. static void destroy_context(AVFoundationCaptureContext *ctx)
  389. {
  390. AVCaptureSession *session = (__bridge AVCaptureSession *)ctx->session;
  391. [session stopRunning];
  392. ctx->session = NULL;
  393. pthread_mutex_destroy(&ctx->frame_lock);
  394. pthread_cond_destroy(&ctx->frame_wait_cond);
  395. if (ctx->current_frame) {
  396. CFRelease(ctx->current_frame);
  397. }
  398. }
  399. static int setup_default_stream(AVFormatContext *s)
  400. {
  401. AVCaptureDevice *device;
  402. for (NSString *type in @[AVMediaTypeVideo]) {
  403. device = [AVCaptureDevice defaultDeviceWithMediaType:type];
  404. if (device) {
  405. av_log(s, AV_LOG_VERBOSE, "Using default device %s\n",
  406. [[device uniqueID] UTF8String]);
  407. return setup_stream(s, device);
  408. }
  409. }
  410. return AVERROR(EINVAL);
  411. }
  412. /**
  413. * Try to open device given in filename
  414. * Two supported formats: "device_unique_id" or "[device_unique_id]"
  415. */
  416. static AVCaptureDevice *create_device(AVFormatContext *s)
  417. {
  418. NSString *filename;
  419. NSError *__autoreleasing error = nil;
  420. NSRegularExpression *exp;
  421. NSArray *matches;
  422. AVCaptureDevice *device;
  423. filename = [NSString stringWithFormat:@ "%s", s->filename];
  424. if ((device = [AVCaptureDevice deviceWithUniqueID:filename])) {
  425. av_log(s, AV_LOG_VERBOSE, "Device with name %s found\n", [filename UTF8String]);
  426. return device;
  427. }
  428. // Remove '[]' from the device name
  429. NSString *pat = @"(?<=\\[).*?(?=\\])";
  430. exp = [NSRegularExpression regularExpressionWithPattern:pat
  431. options:0
  432. error:&error];
  433. if (!exp) {
  434. av_log(s, AV_LOG_ERROR, "%s\n",
  435. [[error localizedDescription] UTF8String]);
  436. return NULL;
  437. }
  438. matches = [exp matchesInString:filename options:0
  439. range:NSMakeRange(0, [filename length])];
  440. if (matches.count > 0) {
  441. for (NSTextCheckingResult *match in matches) {
  442. NSRange range = [match rangeAtIndex:0];
  443. NSString *uniqueID = [filename substringWithRange:NSMakeRange(range.location, range.length)];
  444. av_log(s, AV_LOG_VERBOSE, "opening device with ID: %s\n", [uniqueID UTF8String]);
  445. if (!(device = [AVCaptureDevice deviceWithUniqueID:uniqueID])) {
  446. av_log(s, AV_LOG_ERROR, "Device with name %s not found", [filename UTF8String]);
  447. return NULL;
  448. }
  449. return device;
  450. }
  451. }
  452. return NULL;
  453. }
  454. static int setup_streams(AVFormatContext *s)
  455. {
  456. AVFoundationCaptureContext *ctx = s->priv_data;
  457. int ret;
  458. AVCaptureDevice *device;
  459. pthread_mutex_init(&ctx->frame_lock, NULL);
  460. pthread_cond_init(&ctx->frame_wait_cond, NULL);
  461. ctx->session = (__bridge_retained CFTypeRef)[[AVCaptureSession alloc] init];
  462. if (!strncmp(s->filename, "default", 7)) {
  463. ret = setup_default_stream(s);
  464. } else {
  465. device = create_device(s);
  466. if (device) {
  467. ret = setup_stream(s, device);
  468. } else {
  469. av_log(s, AV_LOG_ERROR, "No matches for %s\n", s->filename);
  470. ret = setup_default_stream(s);
  471. }
  472. }
  473. if (ret < 0) {
  474. av_log(s, AV_LOG_ERROR, "No device could be added\n");
  475. return ret;
  476. }
  477. av_log(s, AV_LOG_VERBOSE, "Starting session!\n");
  478. [(__bridge AVCaptureSession *)ctx->session startRunning];
  479. // Session is started, unlock device
  480. [device unlockForConfiguration];
  481. av_log(s, AV_LOG_VERBOSE, "Checking video config\n");
  482. if (get_video_config(s)) {
  483. destroy_context(ctx);
  484. return AVERROR(EIO);
  485. }
  486. return 0;
  487. }
  488. static int avfoundation_read_header(AVFormatContext *s)
  489. {
  490. AVFoundationCaptureContext *ctx = s->priv_data;
  491. ctx->first_pts = av_gettime();
  492. AVRational framerate_q = { 0, 1 };
  493. ctx->internal_framerate = framerate_q;
  494. if (ctx->list_devices)
  495. return avfoundation_list_capture_devices(s);
  496. if (ctx->list_formats) {
  497. return list_formats(s);
  498. }
  499. if (ctx->pixel_format) {
  500. if (av_get_pix_fmt(ctx->pixel_format) == AV_PIX_FMT_NONE) {
  501. av_log(s, AV_LOG_ERROR, "No such input format: %s.\n",
  502. ctx->pixel_format);
  503. return AVERROR(EINVAL);
  504. }
  505. }
  506. if (ctx->video_size &&
  507. (av_parse_video_size(&ctx->width, &ctx->height, ctx->video_size)) < 0) {
  508. av_log(s, AV_LOG_ERROR, "Could not parse video size '%s'.\n",
  509. ctx->video_size);
  510. return AVERROR(EINVAL);
  511. }
  512. if (ctx->framerate &&
  513. (av_parse_video_rate(&ctx->internal_framerate, ctx->framerate)) < 0) {
  514. av_log(s, AV_LOG_ERROR, "Could not parse framerate '%s'.\n",
  515. ctx->framerate);
  516. return AVERROR(EINVAL);
  517. }
  518. return setup_streams(s);
  519. }
  520. static int avfoundation_read_packet(AVFormatContext *s, AVPacket *pkt)
  521. {
  522. AVFoundationCaptureContext *ctx = (AVFoundationCaptureContext *)s->priv_data;
  523. do {
  524. lock_frames(ctx);
  525. if (ctx->current_frame != nil) {
  526. if (av_new_packet(pkt, (int)CVPixelBufferGetDataSize(ctx->current_frame)) < 0) {
  527. return AVERROR(EIO);
  528. }
  529. pkt->pts = pkt->dts = av_rescale_q(av_gettime() - ctx->first_pts,
  530. AV_TIME_BASE_Q,
  531. (AVRational) {1, 1000000 });
  532. pkt->stream_index = ctx->video_stream_index;
  533. pkt->flags |= AV_PKT_FLAG_KEY;
  534. CVPixelBufferLockBaseAddress(ctx->current_frame, 0);
  535. void *data = CVPixelBufferGetBaseAddress(ctx->current_frame);
  536. memcpy(pkt->data, data, pkt->size);
  537. CVPixelBufferUnlockBaseAddress(ctx->current_frame, 0);
  538. CFRelease(ctx->current_frame);
  539. ctx->current_frame = nil;
  540. } else {
  541. pkt->data = NULL;
  542. pthread_cond_wait(&ctx->frame_wait_cond, &ctx->frame_lock);
  543. }
  544. unlock_frames(ctx);
  545. } while (!pkt->data);
  546. return 0;
  547. }
  548. static int avfoundation_read_close(AVFormatContext *s)
  549. {
  550. av_log(s, AV_LOG_VERBOSE, "Closing session...\n");
  551. AVFoundationCaptureContext *ctx = s->priv_data;
  552. destroy_context(ctx);
  553. return 0;
  554. }
  555. static const AVClass avfoundation_class = {
  556. .class_name = "AVFoundation AVCaptureDevice indev",
  557. .item_name = av_default_item_name,
  558. .option = options,
  559. .version = LIBAVUTIL_VERSION_INT,
  560. };
  561. AVInputFormat ff_avfoundation_demuxer = {
  562. .name = "avfoundation",
  563. .long_name = NULL_IF_CONFIG_SMALL("AVFoundation AVCaptureDevice grab"),
  564. .priv_data_size = sizeof(AVFoundationCaptureContext),
  565. .read_header = avfoundation_read_header,
  566. .read_packet = avfoundation_read_packet,
  567. .read_close = avfoundation_read_close,
  568. .flags = AVFMT_NOFILE,
  569. .priv_class = &avfoundation_class,
  570. };