blob: 8d50a804f98294397d55fdb6cdc2fc0afd08d48c [file] [log] [blame]
Kári Tristan Helgasonede7cb22019-03-06 10:34:09 +01001/*
2 * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "test/mac_capturer.h"
12
13#import "sdk/objc/base/RTCVideoCapturer.h"
14#import "sdk/objc/components/capturer/RTCCameraVideoCapturer.h"
15#import "sdk/objc/native/api/video_capturer.h"
16#import "sdk/objc/native/src/objc_frame_buffer.h"
17
18@interface RTCTestVideoSourceAdapter : NSObject <RTCVideoCapturerDelegate>
19@property(nonatomic) webrtc::test::MacCapturer *capturer;
20@end
21
22@implementation RTCTestVideoSourceAdapter
23@synthesize capturer = _capturer;
24
25- (void)capturer:(RTCVideoCapturer *)capturer didCaptureVideoFrame:(RTCVideoFrame *)frame {
26 const int64_t timestamp_us = frame.timeStampNs / rtc::kNumNanosecsPerMicrosec;
27 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer =
28 new rtc::RefCountedObject<webrtc::ObjCFrameBuffer>(frame.buffer);
29 _capturer->OnFrame(webrtc::VideoFrame::Builder()
30 .set_video_frame_buffer(buffer)
31 .set_rotation(webrtc::kVideoRotation_0)
32 .set_timestamp_us(timestamp_us)
33 .build());
34}
35
36@end
37
Kári Tristan Helgason10db5972019-03-13 11:18:44 +010038namespace {
39
40AVCaptureDeviceFormat *SelectClosestFormat(AVCaptureDevice *device, size_t width, size_t height) {
41 NSArray<AVCaptureDeviceFormat *> *formats =
42 [RTCCameraVideoCapturer supportedFormatsForDevice:device];
43 AVCaptureDeviceFormat *selectedFormat = nil;
44 int currentDiff = INT_MAX;
45 for (AVCaptureDeviceFormat *format in formats) {
46 CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
47 int diff =
48 std::abs((int64_t)width - dimension.width) + std::abs((int64_t)height - dimension.height);
49 if (diff < currentDiff) {
50 selectedFormat = format;
51 currentDiff = diff;
52 }
53 }
54 return selectedFormat;
55}
56
57} // namespace
58
Kári Tristan Helgasonede7cb22019-03-06 10:34:09 +010059namespace webrtc {
60namespace test {
61
62MacCapturer::MacCapturer(size_t width,
63 size_t height,
64 size_t target_fps,
65 size_t capture_device_index) {
66 RTCTestVideoSourceAdapter *adapter = [[RTCTestVideoSourceAdapter alloc] init];
67 adapter_ = (__bridge_retained void *)adapter;
68 adapter.capturer = this;
69
70 RTCCameraVideoCapturer *capturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:adapter];
71 capturer_ = (__bridge_retained void *)capturer;
72
73 AVCaptureDevice *device =
74 [[RTCCameraVideoCapturer captureDevices] objectAtIndex:capture_device_index];
Kári Tristan Helgason10db5972019-03-13 11:18:44 +010075 AVCaptureDeviceFormat *format = SelectClosestFormat(device, width, height);
Kári Tristan Helgasonede7cb22019-03-06 10:34:09 +010076 [capturer startCaptureWithDevice:device format:format fps:target_fps];
77}
78
79MacCapturer *MacCapturer::Create(size_t width,
80 size_t height,
81 size_t target_fps,
82 size_t capture_device_index) {
83 return new MacCapturer(width, height, target_fps, capture_device_index);
84}
85
86void MacCapturer::Destroy() {
87#pragma clang diagnostic push
88#pragma clang diagnostic ignored "-Wunused-variable"
89 RTCTestVideoSourceAdapter *adapter = (__bridge_transfer RTCTestVideoSourceAdapter *)adapter_;
90 RTCCameraVideoCapturer *capturer = (__bridge_transfer RTCCameraVideoCapturer *)capturer_;
91 [capturer stopCapture];
92#pragma clang diagnostic pop
93}
94
95MacCapturer::~MacCapturer() {
96 Destroy();
97}
98
99void MacCapturer::OnFrame(const VideoFrame &frame) {
100 TestVideoCapturer::OnFrame(frame);
101}
102
103} // namespace test
104} // namespace webrtc