1/* 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 <RTC_OBJC_TYPE (RTCVideoCapturerDelegate)> 19@property(nonatomic) webrtc::test::MacCapturer *capturer; 20@end 21 22@implementation RTCTestVideoSourceAdapter 23@synthesize capturer = _capturer; 24 25- (void)capturer:(RTC_OBJC_TYPE(RTCVideoCapturer) *)capturer 26 didCaptureVideoFrame:(RTC_OBJC_TYPE(RTCVideoFrame) *)frame { 27 const int64_t timestamp_us = frame.timeStampNs / rtc::kNumNanosecsPerMicrosec; 28 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer = 29 rtc::make_ref_counted<webrtc::ObjCFrameBuffer>(frame.buffer); 30 _capturer->OnFrame(webrtc::VideoFrame::Builder() 31 .set_video_frame_buffer(buffer) 32 .set_rotation(webrtc::kVideoRotation_0) 33 .set_timestamp_us(timestamp_us) 34 .build()); 35} 36 37@end 38 39namespace { 40 41AVCaptureDeviceFormat *SelectClosestFormat(AVCaptureDevice *device, size_t width, size_t height) { 42 NSArray<AVCaptureDeviceFormat *> *formats = 43 [RTC_OBJC_TYPE(RTCCameraVideoCapturer) supportedFormatsForDevice:device]; 44 AVCaptureDeviceFormat *selectedFormat = nil; 45 int currentDiff = INT_MAX; 46 for (AVCaptureDeviceFormat *format in formats) { 47 CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription); 48 int diff = 49 std::abs((int64_t)width - dimension.width) + std::abs((int64_t)height - dimension.height); 50 if (diff < currentDiff) { 51 selectedFormat = format; 52 currentDiff = diff; 53 } 54 } 55 return selectedFormat; 56} 57 58} // namespace 59 60namespace webrtc { 61namespace test { 62 63MacCapturer::MacCapturer(size_t width, 64 size_t height, 65 size_t target_fps, 66 size_t capture_device_index) { 67 RTCTestVideoSourceAdapter *adapter = [[RTCTestVideoSourceAdapter alloc] init]; 68 adapter_ = (__bridge_retained void *)adapter; 69 adapter.capturer = this; 70 71 RTC_OBJC_TYPE(RTCCameraVideoCapturer) *capturer = 72 [[RTC_OBJC_TYPE(RTCCameraVideoCapturer) alloc] initWithDelegate:adapter]; 73 capturer_ = (__bridge_retained void *)capturer; 74 75 AVCaptureDevice *device = 76 [[RTC_OBJC_TYPE(RTCCameraVideoCapturer) captureDevices] objectAtIndex:capture_device_index]; 77 AVCaptureDeviceFormat *format = SelectClosestFormat(device, width, height); 78 [capturer startCaptureWithDevice:device format:format fps:target_fps]; 79} 80 81MacCapturer *MacCapturer::Create(size_t width, 82 size_t height, 83 size_t target_fps, 84 size_t capture_device_index) { 85 return new MacCapturer(width, height, target_fps, capture_device_index); 86} 87 88void MacCapturer::Destroy() { 89#pragma clang diagnostic push 90#pragma clang diagnostic ignored "-Wunused-variable" 91 RTCTestVideoSourceAdapter *adapter = (__bridge_transfer RTCTestVideoSourceAdapter *)adapter_; 92 RTC_OBJC_TYPE(RTCCameraVideoCapturer) *capturer = 93 (__bridge_transfer RTC_OBJC_TYPE(RTCCameraVideoCapturer) *)capturer_; 94 [capturer stopCapture]; 95#pragma clang diagnostic pop 96} 97 98MacCapturer::~MacCapturer() { 99 Destroy(); 100} 101 102void MacCapturer::OnFrame(const VideoFrame &frame) { 103 TestVideoCapturer::OnFrame(frame); 104} 105 106} // namespace test 107} // namespace webrtc 108