xref: /aosp_15_r20/external/webrtc/test/mac_capturer.mm (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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