| /* | 
 |  *  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 <RTC_OBJC_TYPE (RTCVideoCapturerDelegate)> | 
 | @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 / webrtc::kNumNanosecsPerMicrosec; | 
 |   webrtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer = | 
 |       webrtc::make_ref_counted<webrtc::ObjCFrameBuffer>(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<AVCaptureDeviceFormat *> *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 |