Rewrite video_loopback to use new mac capturer.

The old one has been deprecated for a long time.

Bug: webrtc:6333, webrtc:6898, webrtc:7861
Change-Id: Ib9b798262817e80019afcacc5b41d18957a28101
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/124827
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Peter Hanspers <peterhanspers@webrtc.org>
Commit-Queue: Kári Helgason <kthelgason@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26993}
diff --git a/examples/BUILD.gn b/examples/BUILD.gn
index 427ddb6..8cb4849 100644
--- a/examples/BUILD.gn
+++ b/examples/BUILD.gn
@@ -695,6 +695,7 @@
       "../rtc_base/third_party/sigslot",
       "../system_wrappers:field_trial",
       "../test:field_trial",
+      "../test:platform_video_capturer",
       "//third_party/abseil-cpp/absl/memory",
       "//third_party/abseil-cpp/absl/types:optional",
     ]
@@ -847,6 +848,7 @@
       "../pc:libjingle_peerconnection",
       "../pc:peerconnection",
       "../rtc_base:rtc_base",
+      "../test:platform_video_capturer",
       "../test:video_test_common",
       "//third_party/abseil-cpp/absl/memory",
     ]
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 03cf0c4..464276c 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -366,6 +366,7 @@
         "..:common_objc",
         ":used_from_extension",
       ]
+      libs = [ "VideoToolbox.framework" ]
     }
 
     rtc_static_library("video_objc") {
diff --git a/test/BUILD.gn b/test/BUILD.gn
index c1e6362..c0b3f17 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -49,8 +49,6 @@
     "frame_utils.h",
     "test_video_capturer.cc",
     "test_video_capturer.h",
-    "vcm_capturer.cc",
-    "vcm_capturer.h",
     "video_codec_settings.h",
   ]
 
@@ -67,7 +65,6 @@
     "../call:video_stream_api",
     "../common_video",
     "../media:rtc_media_base",
-    "../modules/video_capture:video_capture_module",
     "../rtc_base:checks",
     "../rtc_base:rtc_base",
     "../rtc_base:rtc_task_queue",
@@ -78,6 +75,55 @@
   ]
 }
 
+if (!build_with_chromium) {
+  if (is_mac || is_ios) {
+    rtc_source_set("video_test_mac") {
+      testonly = true
+      sources = [
+        "mac_capturer.h",
+        "mac_capturer.mm",
+      ]
+      deps = [
+        ":video_test_common",
+        "../api:libjingle_peerconnection_api",
+        "../api:scoped_refptr",
+        "../modules/video_capture:video_capture_module",
+        "../rtc_base:rtc_base",
+        "../sdk:base_objc",
+        "../sdk:native_api",
+        "../sdk:native_video",
+        "../sdk:videocapture_objc",
+      ]
+    }
+  }
+
+  rtc_source_set("platform_video_capturer") {
+    testonly = true
+    sources = [
+      "platform_video_capturer.cc",
+      "platform_video_capturer.h",
+    ]
+    deps = [
+      ":video_test_common",
+      "//third_party/abseil-cpp/absl/memory",
+    ]
+    if (is_mac || is_ios) {
+      deps += [ ":video_test_mac" ]
+    } else {
+      sources += [
+        "vcm_capturer.cc",
+        "vcm_capturer.h",
+      ]
+      deps += [
+        "../api:scoped_refptr",
+        "../modules/video_capture:video_capture_module",
+        "../rtc_base:checks",
+        "../rtc_base:logging",
+      ]
+    }
+  }
+}
+
 rtc_source_set("rtp_test_utils") {
   testonly = true
   sources = [
@@ -185,9 +231,9 @@
     "gtest.h",
   ]
 
-  public_deps = []
+  public_deps = []  # no-presubmit-check TODO(webrtc:8603)
   if (is_ios) {
-    public_deps += [ ":test_support_objc" ]
+    public_deps += [ ":test_support_objc" ]  # no-presubmit-check TODO(webrtc:8603)
   }
 
   public_configs = [ ":test_main_direct_config" ]
@@ -485,11 +531,11 @@
 rtc_source_set("run_test") {
   testonly = true
   if (is_mac) {
-    public_deps = [
+    public_deps = [  # no-presubmit-check TODO(webrtc:8603)
       ":run_test_objc",
     ]
   } else {
-    public_deps = [
+    public_deps = [  # no-presubmit-check TODO(webrtc:8603)
       ":run_test_generic",
     ]
   }
@@ -560,7 +606,7 @@
     "../system_wrappers",
     "//third_party/abseil-cpp/absl/memory",
   ]
-  public_deps = [
+  public_deps = [  # no-presubmit-check TODO(webrtc:8603)
     ":single_threaded_task_queue",
     "../call:fake_network",
   ]
@@ -719,12 +765,12 @@
 }
 
 rtc_source_set("test_renderer") {
-  public_deps = [
+  public_deps = [  # no-presubmit-check TODO(webrtc:8603)
     ":test_renderer_generic",
   ]
   testonly = true
   if (is_mac) {
-    public_deps += [ ":test_renderer_objc" ]
+    public_deps += [ ":test_renderer_objc" ]  # no-presubmit-check TODO(webrtc:8603)
   }
 }
 
diff --git a/test/mac/Info.plist b/test/mac/Info.plist
new file mode 100644
index 0000000..8a2b5cf
--- /dev/null
+++ b/test/mac/Info.plist
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleIdentifier</key>
+	<string>org.webrtc.video_loopback</string>
+	<key>CFBundleName</key>
+	<string>video_loopback</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>NSCameraUsageDescription</key>
+	<string>Camera access needed for video calling</string>
+	<key>NSMicrophoneUsageDescription</key>
+	<string>Microphone access needed for video calling</string>
+</dict>
+</plist>
diff --git a/test/mac_capturer.h b/test/mac_capturer.h
new file mode 100644
index 0000000..3d7ee77
--- /dev/null
+++ b/test/mac_capturer.h
@@ -0,0 +1,50 @@
+/*
+ *  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.
+ */
+#ifndef TEST_MAC_CAPTURER_H_
+#define TEST_MAC_CAPTURER_H_
+
+#include <memory>
+#include <vector>
+
+#include "api/media_stream_interface.h"
+#include "api/scoped_refptr.h"
+#include "modules/video_capture/video_capture.h"
+#include "rtc_base/thread.h"
+#include "test/test_video_capturer.h"
+
+namespace webrtc {
+namespace test {
+
+class MacCapturer : public TestVideoCapturer,
+                    public rtc::VideoSinkInterface<VideoFrame> {
+ public:
+  static MacCapturer* Create(size_t width,
+                             size_t height,
+                             size_t target_fps,
+                             size_t capture_device_index);
+  ~MacCapturer() override;
+
+  void OnFrame(const VideoFrame& frame) override;
+
+ private:
+  MacCapturer(size_t width,
+              size_t height,
+              size_t target_fps,
+              size_t capture_device_index);
+  void Destroy();
+
+  void* capturer_;
+  void* adapter_;
+};
+
+}  // namespace test
+}  // namespace webrtc
+
+#endif  // TEST_MAC_CAPTURER_H_
diff --git a/test/mac_capturer.mm b/test/mac_capturer.mm
new file mode 100644
index 0000000..004900a
--- /dev/null
+++ b/test/mac_capturer.mm
@@ -0,0 +1,84 @@
+/*
+ *  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 <RTCVideoCapturerDelegate>
+@property(nonatomic) webrtc::test::MacCapturer *capturer;
+@end
+
+@implementation RTCTestVideoSourceAdapter
+@synthesize capturer = _capturer;
+
+- (void)capturer:(RTCVideoCapturer *)capturer didCaptureVideoFrame:(RTCVideoFrame *)frame {
+  const int64_t timestamp_us = frame.timeStampNs / rtc::kNumNanosecsPerMicrosec;
+  rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer =
+      new rtc::RefCountedObject<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 webrtc {
+namespace test {
+
+MacCapturer::MacCapturer(size_t width,
+                         size_t height,
+                         size_t target_fps,
+                         size_t capture_device_index) {
+  RTCTestVideoSourceAdapter *adapter = [[RTCTestVideoSourceAdapter alloc] init];
+  adapter_ = (__bridge_retained void *)adapter;
+  adapter.capturer = this;
+
+  RTCCameraVideoCapturer *capturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:adapter];
+  capturer_ = (__bridge_retained void *)capturer;
+
+  AVCaptureDevice *device =
+      [[RTCCameraVideoCapturer captureDevices] objectAtIndex:capture_device_index];
+  AVCaptureDeviceFormat *format =
+      [[RTCCameraVideoCapturer supportedFormatsForDevice:device] objectAtIndex:0];
+  [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_;
+  RTCCameraVideoCapturer *capturer = (__bridge_transfer RTCCameraVideoCapturer *)capturer_;
+  [capturer stopCapture];
+#pragma clang diagnostic pop
+}
+
+MacCapturer::~MacCapturer() {
+  Destroy();
+}
+
+void MacCapturer::OnFrame(const VideoFrame &frame) {
+  TestVideoCapturer::OnFrame(frame);
+}
+
+}  // namespace test
+}  // namespace webrtc
diff --git a/test/platform_video_capturer.cc b/test/platform_video_capturer.cc
new file mode 100644
index 0000000..fb3392a
--- /dev/null
+++ b/test/platform_video_capturer.cc
@@ -0,0 +1,37 @@
+/*
+ *  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/platform_video_capturer.h"
+
+#include "absl/memory/memory.h"
+#if defined(WEBRTC_MAC)
+#include "test/mac_capturer.h"
+#else
+#include "test/vcm_capturer.h"
+#endif
+
+namespace webrtc {
+namespace test {
+
+std::unique_ptr<TestVideoCapturer> CreateVideoCapturer(
+    size_t width,
+    size_t height,
+    size_t target_fps,
+    size_t capture_device_index) {
+#if defined(WEBRTC_MAC)
+  return absl::WrapUnique<TestVideoCapturer>(test::MacCapturer::Create(
+      width, height, target_fps, capture_device_index));
+#else
+  return absl::WrapUnique<TestVideoCapturer>(test::VcmCapturer::Create(
+      width, height, target_fps, capture_device_index));
+#endif
+}
+
+}  // namespace test
+}  // namespace webrtc
diff --git a/test/platform_video_capturer.h b/test/platform_video_capturer.h
new file mode 100644
index 0000000..241ba87
--- /dev/null
+++ b/test/platform_video_capturer.h
@@ -0,0 +1,29 @@
+/*
+ *  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.
+ */
+#ifndef TEST_PLATFORM_VIDEO_CAPTURER_H_
+#define TEST_PLATFORM_VIDEO_CAPTURER_H_
+
+#include <memory>
+
+#include "test/test_video_capturer.h"
+
+namespace webrtc {
+namespace test {
+
+std::unique_ptr<TestVideoCapturer> CreateVideoCapturer(
+    size_t width,
+    size_t height,
+    size_t target_fps,
+    size_t capture_device_index);
+
+}  // namespace test
+}  // namespace webrtc
+
+#endif  // TEST_PLATFORM_VIDEO_CAPTURER_H_
diff --git a/test/test_video_capturer.h b/test/test_video_capturer.h
index 9c5b498..0f1886b 100644
--- a/test/test_video_capturer.h
+++ b/test/test_video_capturer.h
@@ -25,7 +25,7 @@
 class TestVideoCapturer : public rtc::VideoSourceInterface<VideoFrame> {
  public:
   TestVideoCapturer();
-  virtual ~TestVideoCapturer();
+  ~TestVideoCapturer() override;
 
   void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
                        const rtc::VideoSinkWants& wants) override;
diff --git a/video/BUILD.gn b/video/BUILD.gn
index 17b05de4..5bb0411 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -271,6 +271,7 @@
       "../test:fake_video_codecs",
       "../test:fileutils",
       "../test:perf_test",
+      "../test:platform_video_capturer",
       "../test:rtp_test_utils",
       "../test:test_common",
       "../test:test_renderer",
@@ -280,6 +281,10 @@
       "../test:video_test_support",
       "//third_party/abseil-cpp/absl/memory:memory",
     ]
+
+    if (is_mac || is_ios) {
+      deps += [ "../test:video_test_mac" ]
+    }
   }
 
   rtc_source_set("video_full_stack_tests") {
@@ -309,10 +314,11 @@
     ]
   }
 
-  rtc_executable("video_loopback") {
+  rtc_static_library("video_loopback_lib") {
     testonly = true
     sources = [
       "video_loopback.cc",
+      "video_loopback.h",
     ]
     deps = [
       ":video_quality_test",
@@ -335,6 +341,29 @@
     ]
   }
 
+  if (is_mac) {
+    mac_app_bundle("video_loopback") {
+      testonly = true
+      sources = [
+        "video_loopback_main.mm",
+      ]
+      info_plist = "../test/mac/Info.plist"
+      deps = [
+        ":video_loopback_lib",
+      ]
+    }
+  } else {
+    rtc_executable("video_loopback") {
+      testonly = true
+      sources = [
+        "video_loopback_main.cc",
+      ]
+      deps = [
+        ":video_loopback_lib",
+      ]
+    }
+  }
+
   rtc_executable("screenshare_loopback") {
     testonly = true
     sources = [
diff --git a/video/video_loopback.cc b/video/video_loopback.cc
index ef32ae6..9ceb124 100644
--- a/video/video_loopback.cc
+++ b/video/video_loopback.cc
@@ -7,6 +7,7 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
+#include "video/video_loopback.h"
 
 #include <stdio.h>
 #include <memory>
@@ -389,9 +390,8 @@
     fixture->RunWithRenderers(params);
   }
 }
-}  // namespace webrtc
 
-int main(int argc, char* argv[]) {
+int RunLoopbackTest(int argc, char* argv[]) {
   ::testing::InitGoogleTest(&argc, argv);
   rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
   if (webrtc::flags::FLAG_help) {
@@ -411,3 +411,4 @@
   webrtc::test::RunTest(webrtc::Loopback);
   return 0;
 }
+}  // namespace webrtc
diff --git a/video/video_loopback.h b/video/video_loopback.h
new file mode 100644
index 0000000..51c7707
--- /dev/null
+++ b/video/video_loopback.h
@@ -0,0 +1,19 @@
+/*
+ *  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.
+ */
+
+#ifndef VIDEO_VIDEO_LOOPBACK_H_
+#define VIDEO_VIDEO_LOOPBACK_H_
+
+namespace webrtc {
+// Expose the main test method.
+int RunLoopbackTest(int argc, char* argv[]);
+}  // namespace webrtc
+
+#endif  // VIDEO_VIDEO_LOOPBACK_H_
diff --git a/video/video_loopback_main.cc b/video/video_loopback_main.cc
new file mode 100644
index 0000000..f4e5cdd8
--- /dev/null
+++ b/video/video_loopback_main.cc
@@ -0,0 +1,15 @@
+/*
+ *  Copyright 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 "video/video_loopback.h"
+
+int main(int argc, char* argv[]) {
+  webrtc::RunLoopbackTest(argc, argv);
+}
diff --git a/video/video_loopback_main.mm b/video/video_loopback_main.mm
new file mode 100644
index 0000000..61b47a5
--- /dev/null
+++ b/video/video_loopback_main.mm
@@ -0,0 +1,17 @@
+/*
+ *  Copyright 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.
+ */
+
+#import "video/video_loopback.h"
+
+int main(int argc, char* argv[]) {
+  @autoreleasepool {
+    webrtc::RunLoopbackTest(argc, argv);
+  }
+}
diff --git a/video/video_quality_test.cc b/video/video_quality_test.cc
index 2b20a8d..bdb1035 100644
--- a/video/video_quality_test.cc
+++ b/video/video_quality_test.cc
@@ -35,9 +35,9 @@
 #include "modules/video_coding/codecs/vp9/include/vp9.h"
 #include "modules/video_coding/utility/ivf_file_writer.h"
 #include "rtc_base/strings/string_builder.h"
+#include "test/platform_video_capturer.h"
 #include "test/run_loop.h"
 #include "test/testsupport/file_utils.h"
-#include "test/vcm_capturer.h"
 #include "test/video_renderer.h"
 #include "video/frame_dumping_decoder.h"
 #ifdef WEBRTC_WIN
@@ -1076,10 +1076,10 @@
             test::FrameGenerator::OutputType::I010, absl::nullopt,
             params_.video[video_idx].fps, clock_));
       } else if (params_.video[video_idx].clip_name.empty()) {
-        video_sources_[video_idx].reset(test::VcmCapturer::Create(
+        video_sources_[video_idx] = test::CreateVideoCapturer(
             params_.video[video_idx].width, params_.video[video_idx].height,
             params_.video[video_idx].fps,
-            params_.video[video_idx].capture_device_index));
+            params_.video[video_idx].capture_device_index);
         if (!video_sources_[video_idx]) {
           // Failed to get actual camera, use chroma generator as backup.
           video_sources_[video_idx].reset(test::FrameGeneratorCapturer::Create(