/* * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "test/mac_capturer.h" #import "sdk/objc/base/RTCVideoCapturer.h" #import "sdk/objc/components/capturer/RTCCameraVideoCapturer.h" #import "sdk/objc/native/api/video_capturer.h" #import "sdk/objc/native/src/objc_frame_buffer.h" @interface RTCTestVideoSourceAdapter : NSObject @property(nonatomic) webrtc::test::MacCapturer *capturer; @end @implementation RTCTestVideoSourceAdapter @synthesize capturer = _capturer; - (void)capturer:(RTC_OBJC_TYPE(RTCVideoCapturer) *)capturer didCaptureVideoFrame:(RTC_OBJC_TYPE(RTCVideoFrame) *)frame { const int64_t timestamp_us = frame.timeStampNs / rtc::kNumNanosecsPerMicrosec; rtc::scoped_refptr buffer = rtc::make_ref_counted(frame.buffer); _capturer->OnFrame(webrtc::VideoFrame::Builder() .set_video_frame_buffer(buffer) .set_rotation(webrtc::kVideoRotation_0) .set_timestamp_us(timestamp_us) .build()); } @end namespace { AVCaptureDeviceFormat *SelectClosestFormat(AVCaptureDevice *device, size_t width, size_t height) { NSArray *formats = [RTC_OBJC_TYPE(RTCCameraVideoCapturer) supportedFormatsForDevice:device]; AVCaptureDeviceFormat *selectedFormat = nil; int currentDiff = INT_MAX; for (AVCaptureDeviceFormat *format in formats) { CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription); int diff = std::abs((int64_t)width - dimension.width) + std::abs((int64_t)height - dimension.height); if (diff < currentDiff) { selectedFormat = format; currentDiff = diff; } } return selectedFormat; } } // namespace namespace webrtc { namespace test { MacCapturer::MacCapturer(size_t width, size_t height, size_t target_fps, size_t capture_device_index) { width_ = width; height_ = height; RTCTestVideoSourceAdapter *adapter = [[RTCTestVideoSourceAdapter alloc] init]; adapter_ = (__bridge_retained void *)adapter; adapter.capturer = this; RTC_OBJC_TYPE(RTCCameraVideoCapturer) *capturer = [[RTC_OBJC_TYPE(RTCCameraVideoCapturer) alloc] initWithDelegate:adapter]; capturer_ = (__bridge_retained void *)capturer; AVCaptureDevice *device = [[RTC_OBJC_TYPE(RTCCameraVideoCapturer) captureDevices] objectAtIndex:capture_device_index]; AVCaptureDeviceFormat *format = SelectClosestFormat(device, width, height); [capturer startCaptureWithDevice:device format:format fps:target_fps]; } MacCapturer *MacCapturer::Create(size_t width, size_t height, size_t target_fps, size_t capture_device_index) { return new MacCapturer(width, height, target_fps, capture_device_index); } void MacCapturer::Destroy() { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-variable" RTCTestVideoSourceAdapter *adapter = (__bridge_transfer RTCTestVideoSourceAdapter *)adapter_; RTC_OBJC_TYPE(RTCCameraVideoCapturer) *capturer = (__bridge_transfer RTC_OBJC_TYPE(RTCCameraVideoCapturer) *)capturer_; [capturer stopCapture]; #pragma clang diagnostic pop } MacCapturer::~MacCapturer() { Destroy(); } void MacCapturer::OnFrame(const VideoFrame &frame) { TestVideoCapturer::OnFrame(frame); } } // namespace test } // namespace webrtc