summaryrefslogtreecommitdiff
path: root/chromium/media/capture
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 15:28:34 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:54:51 +0000
commit2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch)
treeeb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/media/capture
parentb014812705fc80bff0a5c120dfcef88f349816dc (diff)
downloadqtwebengine-chromium-2a19c63448c84c1805fb1a585c3651318bb86ca7.tar.gz
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/media/capture')
-rw-r--r--chromium/media/capture/BUILD.gn110
-rw-r--r--chromium/media/capture/DEPS2
-rw-r--r--chromium/media/capture/content/android/BUILD.gn4
-rw-r--r--chromium/media/capture/content/android/screen_capture_machine_android.cc38
-rw-r--r--chromium/media/capture/content/android/screen_capture_machine_android.h24
-rw-r--r--chromium/media/capture/content/android/thread_safe_capture_oracle.cc (renamed from chromium/media/capture/content/thread_safe_capture_oracle.cc)17
-rw-r--r--chromium/media/capture/content/android/thread_safe_capture_oracle.h (renamed from chromium/media/capture/content/thread_safe_capture_oracle.h)30
-rw-r--r--chromium/media/capture/content/screen_capture_device_core.cc172
-rw-r--r--chromium/media/capture/content/screen_capture_device_core.h122
-rw-r--r--chromium/media/capture/mojom/video_capture_types.mojom27
-rw-r--r--chromium/media/capture/mojom/video_capture_types.typemap1
-rw-r--r--chromium/media/capture/mojom/video_capture_types_mojom_traits.cc87
-rw-r--r--chromium/media/capture/mojom/video_capture_types_mojom_traits.h28
-rw-r--r--chromium/media/capture/run_all_unittests.cc12
-rw-r--r--chromium/media/capture/video/android/video_capture_device_factory_android.cc10
-rw-r--r--chromium/media/capture/video/chromeos/DEPS1
-rw-r--r--chromium/media/capture/video/chromeos/camera_device_delegate.cc11
-rw-r--r--chromium/media/capture/video/chromeos/camera_device_delegate_unittest.cc2
-rw-r--r--chromium/media/capture/video/chromeos/camera_hal_delegate.cc73
-rw-r--r--chromium/media/capture/video/chromeos/camera_hal_delegate.h7
-rw-r--r--chromium/media/capture/video/chromeos/camera_hal_delegate_unittest.cc2
-rw-r--r--chromium/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc66
-rw-r--r--chromium/media/capture/video/chromeos/camera_hal_dispatcher_impl.h8
-rw-r--r--chromium/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc4
-rw-r--r--chromium/media/capture/video/chromeos/mojo/camera_metadata_tags.mojom64
-rw-r--r--chromium/media/capture/video/chromeos/pixel_format_utils.cc2
-rw-r--r--chromium/media/capture/video/chromeos/public/BUILD.gn14
-rw-r--r--chromium/media/capture/video/chromeos/public/cros_features.cc19
-rw-r--r--chromium/media/capture/video/chromeos/public/cros_features.h16
-rw-r--r--chromium/media/capture/video/chromeos/stream_buffer_manager.cc31
-rw-r--r--chromium/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc63
-rw-r--r--chromium/media/capture/video/chromeos/video_capture_device_factory_chromeos.h17
-rw-r--r--chromium/media/capture/video/create_video_capture_device_factory.cc91
-rw-r--r--chromium/media/capture/video/create_video_capture_device_factory.h22
-rw-r--r--chromium/media/capture/video/linux/camera_config_chromeos.h10
-rw-r--r--chromium/media/capture/video/linux/fake_v4l2_impl.cc198
-rw-r--r--chromium/media/capture/video/linux/fake_v4l2_impl.h62
-rw-r--r--chromium/media/capture/video/linux/v4l2_capture_delegate.cc447
-rw-r--r--chromium/media/capture/video/linux/v4l2_capture_delegate.h37
-rw-r--r--chromium/media/capture/video/linux/v4l2_capture_delegate_unittest.cc3
-rw-r--r--chromium/media/capture/video/linux/v4l2_capture_device.h44
-rw-r--r--chromium/media/capture/video/linux/v4l2_capture_device_impl.cc48
-rw-r--r--chromium/media/capture/video/linux/v4l2_capture_device_impl.h39
-rw-r--r--chromium/media/capture/video/linux/video_capture_device_chromeos.cc29
-rw-r--r--chromium/media/capture/video/linux/video_capture_device_chromeos.h26
-rw-r--r--chromium/media/capture/video/linux/video_capture_device_factory_linux.cc341
-rw-r--r--chromium/media/capture/video/linux/video_capture_device_factory_linux.h38
-rw-r--r--chromium/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc107
-rw-r--r--chromium/media/capture/video/linux/video_capture_device_linux.cc5
-rw-r--r--chromium/media/capture/video/linux/video_capture_device_linux.h4
-rw-r--r--chromium/media/capture/video/mac/video_capture_device_factory_mac.mm10
-rw-r--r--chromium/media/capture/video/mock_gpu_memory_buffer_manager.cc4
-rw-r--r--chromium/media/capture/video/shared_memory_buffer_tracker.cc4
-rw-r--r--chromium/media/capture/video/shared_memory_buffer_tracker.h1
-rw-r--r--chromium/media/capture/video/shared_memory_handle_provider.cc23
-rw-r--r--chromium/media/capture/video/shared_memory_handle_provider.h10
-rw-r--r--chromium/media/capture/video/video_capture_buffer_pool.h4
-rw-r--r--chromium/media/capture/video/video_capture_buffer_pool_impl.cc28
-rw-r--r--chromium/media/capture/video/video_capture_buffer_pool_impl.h2
-rw-r--r--chromium/media/capture/video/video_capture_buffer_tracker.h1
-rw-r--r--chromium/media/capture/video/video_capture_device_client.cc42
-rw-r--r--chromium/media/capture/video/video_capture_device_client.h19
-rw-r--r--chromium/media/capture/video/video_capture_device_client_unittest.cc4
-rw-r--r--chromium/media/capture/video/video_capture_device_descriptor.cc10
-rw-r--r--chromium/media/capture/video/video_capture_device_descriptor.h1
-rw-r--r--chromium/media/capture/video/video_capture_device_factory.cc49
-rw-r--r--chromium/media/capture/video/video_capture_device_factory.h12
-rw-r--r--chromium/media/capture/video/video_capture_device_unittest.cc38
-rw-r--r--chromium/media/capture/video/video_capture_jpeg_decoder.h4
-rw-r--r--chromium/media/capture/video/video_capture_jpeg_decoder_impl.cc260
-rw-r--r--chromium/media/capture/video/video_capture_jpeg_decoder_impl.h119
-rw-r--r--chromium/media/capture/video/win/video_capture_device_factory_win.cc25
-rw-r--r--chromium/media/capture/video/win/video_capture_device_factory_win_unittest.cc30
-rw-r--r--chromium/media/capture/video/win/video_capture_device_win.cc8
-rw-r--r--chromium/media/capture/video_capture_types.cc3
-rw-r--r--chromium/media/capture/video_capture_types.h8
76 files changed, 2262 insertions, 1092 deletions
diff --git a/chromium/media/capture/BUILD.gn b/chromium/media/capture/BUILD.gn
index be5925b27b6..f9e2ccbb4f1 100644
--- a/chromium/media/capture/BUILD.gn
+++ b/chromium/media/capture/BUILD.gn
@@ -53,12 +53,8 @@ source_set("capture_device_specific") {
"content/animated_content_sampler.h",
"content/capture_resolution_chooser.cc",
"content/capture_resolution_chooser.h",
- "content/screen_capture_device_core.cc",
- "content/screen_capture_device_core.h",
"content/smooth_event_sampler.cc",
"content/smooth_event_sampler.h",
- "content/thread_safe_capture_oracle.cc",
- "content/thread_safe_capture_oracle.h",
"content/video_capture_oracle.cc",
"content/video_capture_oracle.h",
"video/blob_utils.cc",
@@ -97,24 +93,8 @@ source_set("capture_device_specific") {
component("capture_lib") {
defines = [ "CAPTURE_IMPLEMENTATION" ]
sources = [
- "video/linux/camera_config_chromeos.cc",
- "video/linux/camera_config_chromeos.h",
- "video/linux/v4l2_capture_delegate.cc",
- "video/linux/v4l2_capture_delegate.h",
- "video/linux/video_capture_device_chromeos.cc",
- "video/linux/video_capture_device_chromeos.h",
- "video/linux/video_capture_device_factory_linux.cc",
- "video/linux/video_capture_device_factory_linux.h",
- "video/linux/video_capture_device_linux.cc",
- "video/linux/video_capture_device_linux.h",
- "video/mac/video_capture_device_avfoundation_mac.h",
- "video/mac/video_capture_device_avfoundation_mac.mm",
- "video/mac/video_capture_device_decklink_mac.h",
- "video/mac/video_capture_device_decklink_mac.mm",
- "video/mac/video_capture_device_factory_mac.h",
- "video/mac/video_capture_device_factory_mac.mm",
- "video/mac/video_capture_device_mac.h",
- "video/mac/video_capture_device_mac.mm",
+ "video/create_video_capture_device_factory.cc",
+ "video/create_video_capture_device_factory.h",
"video/scoped_buffer_pool_reservation.h",
"video/shared_memory_buffer_tracker.cc",
"video/shared_memory_buffer_tracker.h",
@@ -130,33 +110,14 @@ component("capture_lib") {
"video/video_capture_device_client.cc",
"video/video_capture_device_client.h",
"video/video_capture_jpeg_decoder.h",
+ "video/video_capture_jpeg_decoder_impl.cc",
+ "video/video_capture_jpeg_decoder_impl.h",
"video/video_capture_system.h",
"video/video_capture_system_impl.cc",
"video/video_capture_system_impl.h",
"video/video_frame_receiver.h",
"video/video_frame_receiver_on_task_runner.cc",
"video/video_frame_receiver_on_task_runner.h",
- "video/win/capability_list_win.cc",
- "video/win/capability_list_win.h",
- "video/win/filter_base_win.cc",
- "video/win/filter_base_win.h",
- "video/win/metrics.cc",
- "video/win/metrics.h",
- "video/win/pin_base_win.cc",
- "video/win/pin_base_win.h",
- "video/win/sink_filter_observer_win.h",
- "video/win/sink_filter_win.cc",
- "video/win/sink_filter_win.h",
- "video/win/sink_input_pin_win.cc",
- "video/win/sink_input_pin_win.h",
- "video/win/video_capture_device_factory_win.cc",
- "video/win/video_capture_device_factory_win.h",
- "video/win/video_capture_device_mf_win.cc",
- "video/win/video_capture_device_mf_win.h",
- "video/win/video_capture_device_utils_win.cc",
- "video/win/video_capture_device_utils_win.h",
- "video/win/video_capture_device_win.cc",
- "video/win/video_capture_device_win.h",
"video_capturer_source.cc",
"video_capturer_source.h",
]
@@ -173,6 +134,7 @@ component("capture_lib") {
"//media/capture/mojom:image_capture",
"//media/capture/mojom:image_capture_types",
"//media/capture/mojom:video_capture",
+ "//media/mojo/clients:jpeg_decode_accelerator",
"//media/mojo/interfaces:interfaces",
"//services/service_manager/public/cpp",
"//third_party/libyuv",
@@ -192,6 +154,16 @@ component("capture_lib") {
}
if (is_mac) {
+ sources += [
+ "video/mac/video_capture_device_avfoundation_mac.h",
+ "video/mac/video_capture_device_avfoundation_mac.mm",
+ "video/mac/video_capture_device_decklink_mac.h",
+ "video/mac/video_capture_device_decklink_mac.mm",
+ "video/mac/video_capture_device_factory_mac.h",
+ "video/mac/video_capture_device_factory_mac.mm",
+ "video/mac/video_capture_device_mac.h",
+ "video/mac/video_capture_device_mac.mm",
+ ]
deps += [ "//third_party/decklink" ]
libs = [
"AVFoundation.framework",
@@ -204,6 +176,29 @@ component("capture_lib") {
}
if (is_win) {
+ sources += [
+ "video/win/capability_list_win.cc",
+ "video/win/capability_list_win.h",
+ "video/win/filter_base_win.cc",
+ "video/win/filter_base_win.h",
+ "video/win/metrics.cc",
+ "video/win/metrics.h",
+ "video/win/pin_base_win.cc",
+ "video/win/pin_base_win.h",
+ "video/win/sink_filter_observer_win.h",
+ "video/win/sink_filter_win.cc",
+ "video/win/sink_filter_win.h",
+ "video/win/sink_input_pin_win.cc",
+ "video/win/sink_input_pin_win.h",
+ "video/win/video_capture_device_factory_win.cc",
+ "video/win/video_capture_device_factory_win.h",
+ "video/win/video_capture_device_mf_win.cc",
+ "video/win/video_capture_device_mf_win.h",
+ "video/win/video_capture_device_utils_win.cc",
+ "video/win/video_capture_device_utils_win.h",
+ "video/win/video_capture_device_win.cc",
+ "video/win/video_capture_device_win.h",
+ ]
deps += [ "//media/base/win" ]
libs = [
"mf.lib",
@@ -221,6 +216,25 @@ component("capture_lib") {
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
}
+ # This includes the case of ChromeOS
+ if (is_linux) {
+ sources += [
+ "video/linux/camera_config_chromeos.cc",
+ "video/linux/camera_config_chromeos.h",
+ "video/linux/v4l2_capture_delegate.cc",
+ "video/linux/v4l2_capture_delegate.h",
+ "video/linux/v4l2_capture_device.h",
+ "video/linux/v4l2_capture_device_impl.cc",
+ "video/linux/v4l2_capture_device_impl.h",
+ "video/linux/video_capture_device_chromeos.cc",
+ "video/linux/video_capture_device_chromeos.h",
+ "video/linux/video_capture_device_factory_linux.cc",
+ "video/linux/video_capture_device_factory_linux.h",
+ "video/linux/video_capture_device_linux.cc",
+ "video/linux/video_capture_device_linux.h",
+ ]
+ }
+
if (is_chromeos) {
sources += [
"video/chromeos/camera_3a_controller.cc",
@@ -248,10 +262,11 @@ component("capture_lib") {
"video/chromeos/video_capture_device_factory_chromeos.cc",
"video/chromeos/video_capture_device_factory_chromeos.h",
]
+ public_deps += [ "//media/capture/video/chromeos/public" ]
deps += [
"//chromeos:chromeos",
"//media/capture/video/chromeos/mojo:cros_camera",
- "//mojo/edk",
+ "//third_party/libdrm",
"//third_party/libsync",
]
}
@@ -286,7 +301,10 @@ test("capture_unittests") {
"video/fake_video_capture_device_unittest.cc",
"video/file_video_capture_device_unittest.cc",
"video/linux/camera_config_chromeos_unittest.cc",
+ "video/linux/fake_v4l2_impl.cc",
+ "video/linux/fake_v4l2_impl.h",
"video/linux/v4l2_capture_delegate_unittest.cc",
+ "video/linux/video_capture_device_factory_linux_unittest.cc",
"video/mac/video_capture_device_factory_mac_unittest.mm",
"video/mock_gpu_memory_buffer_manager.cc",
"video/mock_gpu_memory_buffer_manager.h",
@@ -308,7 +326,7 @@ test("capture_unittests") {
"//media:test_support",
"//media/capture/mojom:image_capture",
"//media/capture/mojom:image_capture_types",
- "//mojo/edk",
+ "//mojo/core/embedder",
"//testing/gmock",
"//testing/gtest",
"//ui/gfx:test_support",
@@ -358,7 +376,7 @@ test("capture_unittests") {
deps += [
"//chromeos:chromeos",
"//media/capture/video/chromeos/mojo:cros_camera",
- "//mojo/edk",
+ "//mojo/core/embedder",
"//third_party/libdrm",
"//third_party/libsync",
"//third_party/minigbm",
diff --git a/chromium/media/capture/DEPS b/chromium/media/capture/DEPS
index d415fec5261..809f1c1109f 100644
--- a/chromium/media/capture/DEPS
+++ b/chromium/media/capture/DEPS
@@ -1,3 +1,3 @@
specific_include_rules = {
- "run_all_unittests.cc": [ "+mojo/edk/embedder" ],
+ "run_all_unittests.cc": [ "+mojo/core/embedder" ],
}
diff --git a/chromium/media/capture/content/android/BUILD.gn b/chromium/media/capture/content/android/BUILD.gn
index 92ff80e2ea3..521a0f0a51f 100644
--- a/chromium/media/capture/content/android/BUILD.gn
+++ b/chromium/media/capture/content/android/BUILD.gn
@@ -14,14 +14,18 @@ source_set("android") {
sources = [
"screen_capture_machine_android.cc",
"screen_capture_machine_android.h",
+ "thread_safe_capture_oracle.cc",
+ "thread_safe_capture_oracle.h",
]
configs += [ "//media:media_config" ]
deps = [
":screen_capture_jni_headers",
+ "//media",
"//media/capture:capture_device_specific",
"//media/capture/mojom:image_capture",
"//third_party/libyuv",
"//ui/gfx:color_space",
+ "//ui/gfx/geometry",
]
}
diff --git a/chromium/media/capture/content/android/screen_capture_machine_android.cc b/chromium/media/capture/content/android/screen_capture_machine_android.cc
index 734048e68ac..be83b1379e5 100644
--- a/chromium/media/capture/content/android/screen_capture_machine_android.cc
+++ b/chromium/media/capture/content/android/screen_capture_machine_android.cc
@@ -4,10 +4,15 @@
#include "media/capture/content/android/screen_capture_machine_android.h"
+#include <utility>
+
#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
#include "jni/ScreenCapture_jni.h"
+#include "media/base/video_frame.h"
+#include "media/capture/content/android/thread_safe_capture_oracle.h"
#include "media/capture/content/video_capture_oracle.h"
+#include "media/capture/video_capture_types.h"
#include "third_party/libyuv/include/libyuv.h"
using base::android::AttachCurrentThread;
@@ -94,7 +99,7 @@ void ScreenCaptureMachineAndroid::OnRGBAFrameAvailable(
frame->visible_rect().height(), libyuv::kFilterBilinear);
}
- capture_frame_cb.Run(frame, start_time, true);
+ std::move(capture_frame_cb).Run(frame, start_time, true);
lastFrame_ = frame;
}
@@ -177,7 +182,7 @@ void ScreenCaptureMachineAndroid::OnI420FrameAvailable(
frame->visible_rect().height(), libyuv::kFilterBilinear);
}
- capture_frame_cb.Run(frame, start_time, true);
+ std::move(capture_frame_cb).Run(frame, start_time, true);
lastFrame_ = frame;
}
@@ -225,20 +230,18 @@ void ScreenCaptureMachineAndroid::OnOrientationChange(
}
}
-void ScreenCaptureMachineAndroid::Start(
- const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
- const VideoCaptureParams& params,
- const base::Callback<void(bool)> callback) {
+bool ScreenCaptureMachineAndroid::Start(
+ scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy,
+ const VideoCaptureParams& params) {
DCHECK(oracle_proxy.get());
- oracle_proxy_ = oracle_proxy;
+ oracle_proxy_ = std::move(oracle_proxy);
j_capture_.Reset(
createScreenCaptureMachineAndroid(reinterpret_cast<intptr_t>(this)));
if (j_capture_.obj() == nullptr) {
DLOG(ERROR) << "Failed to createScreenCaptureAndroid";
- callback.Run(false);
- return;
+ return false;
}
DCHECK(params.requested_format.frame_size.GetArea());
@@ -251,24 +254,19 @@ void ScreenCaptureMachineAndroid::Start(
params.requested_format.frame_size.height());
if (!ret) {
DLOG(ERROR) << "Failed to init ScreenCaptureAndroid";
- callback.Run(ret);
- return;
+ return false;
}
ret = Java_ScreenCapture_startPrompt(AttachCurrentThread(), j_capture_);
- // Must wait for user input to start capturing before we can report back
- // device started state. However, if the user-prompt failed to show, report
- // a failed start immediately.
- if (!ret)
- callback.Run(ret);
+ // NOTE: Result of user prompt will be delivered to OnActivityResult(), and
+ // this will report the device started/error state via the |oracle_proxy_|.
+ return !!ret;
}
-void ScreenCaptureMachineAndroid::Stop(const base::Closure& callback) {
+void ScreenCaptureMachineAndroid::Stop() {
if (j_capture_.obj() != nullptr) {
Java_ScreenCapture_stopCapture(AttachCurrentThread(), j_capture_);
}
-
- callback.Run();
}
// ScreenCapture on Android works in a passive way and there are no captured
@@ -306,7 +304,7 @@ void ScreenCaptureMachineAndroid::MaybeCaptureForRefresh() {
frame->stride(VideoFrame::kVPlane), frame->visible_rect().width(),
frame->visible_rect().height(), libyuv::kFilterBilinear);
- capture_frame_cb.Run(frame, start_time, true);
+ std::move(capture_frame_cb).Run(frame, start_time, true);
}
} // namespace media
diff --git a/chromium/media/capture/content/android/screen_capture_machine_android.h b/chromium/media/capture/content/android/screen_capture_machine_android.h
index 775e6d6c00c..4b118341f62 100644
--- a/chromium/media/capture/content/android/screen_capture_machine_android.h
+++ b/chromium/media/capture/content/android/screen_capture_machine_android.h
@@ -9,16 +9,20 @@
#include <memory>
#include "base/android/scoped_java_ref.h"
+#include "base/memory/scoped_refptr.h"
#include "media/capture/capture_export.h"
-#include "media/capture/content/screen_capture_device_core.h"
namespace media {
+class ThreadSafeCaptureOracle;
+struct VideoCaptureParams;
+class VideoFrame;
+
// ScreenCaptureMachineAndroid captures 32bit RGB or YUV420 triplanar.
-class CAPTURE_EXPORT ScreenCaptureMachineAndroid : public VideoCaptureMachine {
+class CAPTURE_EXPORT ScreenCaptureMachineAndroid {
public:
ScreenCaptureMachineAndroid();
- ~ScreenCaptureMachineAndroid() override;
+ virtual ~ScreenCaptureMachineAndroid();
static base::android::ScopedJavaLocalRef<jobject>
createScreenCaptureMachineAndroid(jlong nativeScreenCaptureMachineAndroid);
@@ -58,12 +62,14 @@ class CAPTURE_EXPORT ScreenCaptureMachineAndroid : public VideoCaptureMachine {
const base::android::JavaRef<jobject>& obj,
jint rotation);
- // VideoCaptureMachine overrides.
- void Start(const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
- const media::VideoCaptureParams& params,
- const base::Callback<void(bool)> callback) override;
- void Stop(const base::Closure& callback) override;
- void MaybeCaptureForRefresh() override;
+ // Starts/Stops capturing.
+ bool Start(scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy,
+ const VideoCaptureParams& params);
+ void Stop();
+
+ // If there is a cached frame, and the oracle allows sending another frame
+ // right now, the cached captured frame is redelivered.
+ void MaybeCaptureForRefresh();
private:
// Indicates the orientation of the device.
diff --git a/chromium/media/capture/content/thread_safe_capture_oracle.cc b/chromium/media/capture/content/android/thread_safe_capture_oracle.cc
index 4d07bb7cdf6..ef8732f591b 100644
--- a/chromium/media/capture/content/thread_safe_capture_oracle.cc
+++ b/chromium/media/capture/content/android/thread_safe_capture_oracle.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "media/capture/content/thread_safe_capture_oracle.h"
+#include "media/capture/content/android/thread_safe_capture_oracle.h"
#include <stdint.h>
@@ -13,7 +13,6 @@
#include "base/bits.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
-#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "media/base/video_frame.h"
@@ -44,11 +43,8 @@ struct ThreadSafeCaptureOracle::InFlightFrameCapture {
ThreadSafeCaptureOracle::ThreadSafeCaptureOracle(
std::unique_ptr<VideoCaptureDevice::Client> client,
- const VideoCaptureParams& params,
- bool enable_auto_throttling)
- : client_(std::move(client)),
- oracle_(enable_auto_throttling),
- params_(params) {
+ const VideoCaptureParams& params)
+ : client_(std::move(client)), oracle_(false), params_(params) {
DCHECK_GE(params.requested_format.frame_rate, 1e-6f);
oracle_.SetMinCapturePeriod(base::TimeDelta::FromMicroseconds(
static_cast<int64_t>(1000000.0 / params.requested_format.frame_rate +
@@ -168,8 +164,8 @@ bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
return false;
}
- *callback = base::Bind(&ThreadSafeCaptureOracle::DidCaptureFrame, this,
- base::Passed(&capture));
+ *callback = base::BindOnce(&ThreadSafeCaptureOracle::DidCaptureFrame, this,
+ base::Passed(&capture));
return true;
}
@@ -217,9 +213,6 @@ void ThreadSafeCaptureOracle::DidCaptureFrame(
const bool should_deliver_frame =
oracle_.CompleteCapture(capture->frame_number, success, &reference_time);
- // The following is used by
- // chrome/browser/extension/api/cast_streaming/performance_test.cc, in
- // addition to the usual runtime tracing.
TRACE_EVENT_ASYNC_END2("gpu.capture", "Capture", capture->buffer.id,
"success", should_deliver_frame, "timestamp",
(reference_time - base::TimeTicks()).InMicroseconds());
diff --git a/chromium/media/capture/content/thread_safe_capture_oracle.h b/chromium/media/capture/content/android/thread_safe_capture_oracle.h
index cab73733cae..65e62f66044 100644
--- a/chromium/media/capture/content/thread_safe_capture_oracle.h
+++ b/chromium/media/capture/content/android/thread_safe_capture_oracle.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MEDIA_CAPTURE_CONTENT_THREAD_SAFE_CAPTURE_ORACLE_H_
-#define MEDIA_CAPTURE_CONTENT_THREAD_SAFE_CAPTURE_ORACLE_H_
+#ifndef MEDIA_CAPTURE_CONTENT_ANDROID_THREAD_SAFE_CAPTURE_ORACLE_H_
+#define MEDIA_CAPTURE_CONTENT_ANDROID_THREAD_SAFE_CAPTURE_ORACLE_H_
#include <memory>
#include <string>
#include "base/memory/ref_counted.h"
-#include "media/base/video_frame.h"
+#include "base/synchronization/lock.h"
#include "media/capture/capture_export.h"
#include "media/capture/content/video_capture_oracle.h"
#include "media/capture/video/video_capture_buffer_handle.h"
@@ -23,6 +23,7 @@ namespace media {
struct VideoCaptureParams;
class VideoFrame;
+class VideoFrameMetadata;
// Thread-safe, refcounted proxy to the VideoCaptureOracle. This proxy wraps
// the VideoCaptureOracle, which decides which frames to capture, and a
@@ -32,16 +33,15 @@ class CAPTURE_EXPORT ThreadSafeCaptureOracle
: public base::RefCountedThreadSafe<ThreadSafeCaptureOracle> {
public:
ThreadSafeCaptureOracle(std::unique_ptr<VideoCaptureDevice::Client> client,
- const VideoCaptureParams& params,
- bool enable_auto_throttling);
+ const VideoCaptureParams& params);
// Called when a captured frame is available or an error has occurred.
// If |success| is true then |frame| is valid and |timestamp| indicates when
// the frame was painted.
// If |success| is false, all other parameters are invalid.
- typedef base::Callback<void(scoped_refptr<VideoFrame> frame,
- base::TimeTicks timestamp,
- bool success)>
+ typedef base::OnceCallback<void(scoped_refptr<VideoFrame> frame,
+ base::TimeTicks timestamp,
+ bool success)>
CaptureFrameCallback;
// Record a change |event| along with its |damage_rect| and |event_time|, and
@@ -60,18 +60,6 @@ class CAPTURE_EXPORT ThreadSafeCaptureOracle
scoped_refptr<VideoFrame>* storage,
CaptureFrameCallback* callback);
- base::TimeDelta min_capture_period() const {
- return oracle_.min_capture_period();
- }
-
- base::TimeTicks last_time_animation_was_detected() const {
- return oracle_.last_time_animation_was_detected();
- }
-
- gfx::Size max_frame_size() const {
- return params_.requested_format.frame_size;
- }
-
// Returns the current capture resolution.
gfx::Size GetCaptureSize() const;
@@ -125,4 +113,4 @@ class CAPTURE_EXPORT ThreadSafeCaptureOracle
} // namespace media
-#endif // MEDIA_CAPTURE_CONTENT_THREAD_SAFE_CAPTURE_ORACLE_H_
+#endif // MEDIA_CAPTURE_CONTENT_ANDROID_THREAD_SAFE_CAPTURE_ORACLE_H_
diff --git a/chromium/media/capture/content/screen_capture_device_core.cc b/chromium/media/capture/content/screen_capture_device_core.cc
deleted file mode 100644
index 5ae39399c9e..00000000000
--- a/chromium/media/capture/content/screen_capture_device_core.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/capture/content/screen_capture_device_core.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/threading/thread_checker.h"
-
-namespace media {
-
-namespace {
-
-void DeleteCaptureMachine(
- std::unique_ptr<VideoCaptureMachine> capture_machine) {
- capture_machine.reset();
-}
-
-} // namespace
-
-VideoCaptureMachine::VideoCaptureMachine() = default;
-
-VideoCaptureMachine::~VideoCaptureMachine() = default;
-
-bool VideoCaptureMachine::IsAutoThrottlingEnabled() const {
- return false;
-}
-
-void ScreenCaptureDeviceCore::AllocateAndStart(
- const VideoCaptureParams& params,
- std::unique_ptr<VideoCaptureDevice::Client> client) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (state_ != kIdle) {
- DVLOG(1) << "Allocate() invoked when not in state Idle.";
- return;
- }
-
- if (params.requested_format.pixel_format != PIXEL_FORMAT_I420) {
- client->OnError(
- FROM_HERE,
- base::StringPrintf(
- "unsupported format: %s",
- VideoCaptureFormat::ToString(params.requested_format).c_str()));
- return;
- }
-
- oracle_proxy_ = new ThreadSafeCaptureOracle(
- std::move(client), params, capture_machine_->IsAutoThrottlingEnabled());
-
- capture_machine_->Start(
- oracle_proxy_, params,
- base::Bind(&ScreenCaptureDeviceCore::CaptureStarted, AsWeakPtr()));
-
- TransitionStateTo(kCapturing);
-}
-
-void ScreenCaptureDeviceCore::RequestRefreshFrame() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (state_ != kCapturing)
- return;
-
- capture_machine_->MaybeCaptureForRefresh();
-}
-
-void ScreenCaptureDeviceCore::Suspend() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (state_ != kCapturing)
- return;
-
- TransitionStateTo(kSuspended);
-
- capture_machine_->Suspend();
-}
-
-void ScreenCaptureDeviceCore::Resume() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (state_ != kSuspended)
- return;
-
- TransitionStateTo(kCapturing);
-
- capture_machine_->Resume();
-}
-
-void ScreenCaptureDeviceCore::StopAndDeAllocate() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (state_ != kCapturing && state_ != kSuspended)
- return;
-
- oracle_proxy_->Stop();
- oracle_proxy_ = NULL;
-
- TransitionStateTo(kIdle);
-
- capture_machine_->Stop(base::DoNothing());
-}
-
-void ScreenCaptureDeviceCore::OnConsumerReportingUtilization(
- int frame_feedback_id,
- double utilization) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(oracle_proxy_);
- oracle_proxy_->OnConsumerReportingUtilization(frame_feedback_id, utilization);
-}
-
-void ScreenCaptureDeviceCore::CaptureStarted(bool success) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!success)
- Error(FROM_HERE, "Failed to start capture machine.");
- else if (oracle_proxy_)
- oracle_proxy_->ReportStarted();
-}
-
-ScreenCaptureDeviceCore::ScreenCaptureDeviceCore(
- std::unique_ptr<VideoCaptureMachine> capture_machine)
- : state_(kIdle), capture_machine_(std::move(capture_machine)) {
- DCHECK(capture_machine_.get());
-}
-
-ScreenCaptureDeviceCore::~ScreenCaptureDeviceCore() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(state_ != kCapturing && state_ != kSuspended);
- if (capture_machine_) {
- capture_machine_->Stop(
- base::Bind(&DeleteCaptureMachine, base::Passed(&capture_machine_)));
- }
- DVLOG(1) << "ScreenCaptureDeviceCore@" << this << " destroying.";
-}
-
-void ScreenCaptureDeviceCore::TransitionStateTo(State next_state) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
-#ifndef NDEBUG
- static const char* kStateNames[] = {"Idle", "Capturing", "Suspended",
- "Error"};
- static_assert(arraysize(kStateNames) == kLastCaptureState,
- "Different number of states and textual descriptions");
- DVLOG(1) << "State change: " << kStateNames[state_] << " --> "
- << kStateNames[next_state];
-#endif
-
- state_ = next_state;
-}
-
-void ScreenCaptureDeviceCore::Error(const base::Location& from_here,
- const std::string& reason) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (state_ == kIdle)
- return;
-
- if (oracle_proxy_)
- oracle_proxy_->ReportError(from_here, reason);
-
- StopAndDeAllocate();
- TransitionStateTo(kError);
-}
-
-} // namespace media
diff --git a/chromium/media/capture/content/screen_capture_device_core.h b/chromium/media/capture/content/screen_capture_device_core.h
deleted file mode 100644
index 5f5bdcbc32f..00000000000
--- a/chromium/media/capture/content/screen_capture_device_core.h
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_CAPTURE_CONTENT_SCREEN_CAPTURE_DEVICE_CORE_H_
-#define MEDIA_CAPTURE_CONTENT_SCREEN_CAPTURE_DEVICE_CORE_H_
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "media/capture/capture_export.h"
-#include "media/capture/content/thread_safe_capture_oracle.h"
-#include "media/capture/video/video_capture_device.h"
-
-namespace base {
-class Location;
-} // namespace base
-
-namespace media {
-
-struct VideoCaptureParams;
-
-class ThreadSafeCaptureOracle;
-
-// Keeps track of the video capture source frames and executes copying.
-class CAPTURE_EXPORT VideoCaptureMachine {
- public:
- VideoCaptureMachine();
- virtual ~VideoCaptureMachine();
-
- // Starts capturing.
- // |callback| is invoked with true if succeeded. Otherwise, with false.
- virtual void Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
- const VideoCaptureParams& params,
- const base::Callback<void(bool)> callback) = 0;
-
- // Suspend/Resume frame delivery. Implementations of these are optional.
- virtual void Suspend() {}
- virtual void Resume() {}
-
- // Stops capturing.
- // |callback| is invoked after the capturing has stopped.
- virtual void Stop(const base::Closure& callback) = 0;
-
- // Returns true if the video capture is configured to monitor end-to-end
- // system utilization, and alter frame sizes and/or frame rates to mitigate
- // overloading or under-utilization.
- virtual bool IsAutoThrottlingEnabled() const;
-
- // The implementation of this method should consult the oracle, using the
- // kRefreshRequest event type, to decide whether to initiate a new frame
- // capture, and then do so if the oracle agrees.
- virtual void MaybeCaptureForRefresh() = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(VideoCaptureMachine);
-};
-
-// The "meat" of a content video capturer.
-//
-// Separating this from the "shell classes" WebContentsVideoCaptureDevice and
-// DesktopCaptureDeviceAura allows safe destruction without needing to block any
-// threads, as well as code sharing.
-//
-// ScreenCaptureDeviceCore manages a simple state machine and the pipeline
-// (see notes at top of this file). It times the start of successive captures
-// and facilitates the processing of each through the stages of the
-// pipeline.
-class CAPTURE_EXPORT ScreenCaptureDeviceCore
- : public base::SupportsWeakPtr<ScreenCaptureDeviceCore> {
- public:
- ScreenCaptureDeviceCore(std::unique_ptr<VideoCaptureMachine> capture_machine);
- virtual ~ScreenCaptureDeviceCore();
-
- // Asynchronous requests to change ScreenCaptureDeviceCore state.
- void AllocateAndStart(const VideoCaptureParams& params,
- std::unique_ptr<VideoCaptureDevice::Client> client);
- void RequestRefreshFrame();
- void Suspend();
- void Resume();
- void StopAndDeAllocate();
- void OnConsumerReportingUtilization(int frame_feedback_id,
- double utilization);
-
- private:
- // Flag indicating current state.
- enum State { kIdle, kCapturing, kSuspended, kError, kLastCaptureState };
-
- void TransitionStateTo(State next_state);
-
- // Called back in response to StartCaptureMachine(). |success| is true if
- // capture machine succeeded to start.
- void CaptureStarted(bool success);
-
- // Stops capturing and notifies client_ of an error state.
- void Error(const base::Location& from_here, const std::string& reason);
-
- // Tracks that all activity occurs on the media stream manager's thread.
- base::ThreadChecker thread_checker_;
-
- // Current lifecycle state.
- State state_;
-
- // Tracks the CaptureMachine that's doing work on our behalf
- // on the device thread or UI thread.
- // This value should never be dereferenced by this class.
- std::unique_ptr<VideoCaptureMachine> capture_machine_;
-
- // Our thread-safe capture oracle which serves as the gateway to the video
- // capture pipeline. Besides the VideoCaptureDevice itself, it is the only
- // component of the system with direct access to |client_|.
- scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_;
-
- DISALLOW_COPY_AND_ASSIGN(ScreenCaptureDeviceCore);
-};
-
-} // namespace media
-
-#endif // MEDIA_CAPTURE_CONTENT_SCREEN_CAPTURE_DEVICE_CORE_H_
diff --git a/chromium/media/capture/mojom/video_capture_types.mojom b/chromium/media/capture/mojom/video_capture_types.mojom
index 414b5ca327f..b59c87abfcb 100644
--- a/chromium/media/capture/mojom/video_capture_types.mojom
+++ b/chromium/media/capture/mojom/video_capture_types.mojom
@@ -50,6 +50,12 @@ enum PowerLineFrequency {
HZ_60
};
+enum VideoFacingMode {
+ NONE,
+ USER,
+ ENVIRONMENT
+};
+
enum VideoCaptureApi {
LINUX_V4L2_SINGLE_PLANE,
WIN_MEDIA_FOUNDATION,
@@ -61,6 +67,7 @@ enum VideoCaptureApi {
ANDROID_API2_LEGACY,
ANDROID_API2_FULL,
ANDROID_API2_LIMITED,
+ VIRTUAL_DEVICE,
UNKNOWN
};
@@ -70,6 +77,18 @@ enum VideoCaptureTransportType {
OTHER_TRANSPORT
};
+enum VideoCaptureBufferType {
+ kSharedMemory,
+
+ // Warning: This case is a workaround for compatibility with an older version
+ // of Mojo only and will be deleted as soon as the Mojo version of ChromiumOS
+ // becomes compatible with the |kSharedMemory|.
+ // TODO(chfremer): Remove this when https://crbug.com/857537 is resolved.
+ kSharedMemoryViaRawFileDescriptor,
+
+ kMailboxHolder
+};
+
struct VideoCaptureFormat {
gfx.mojom.Size frame_size;
float frame_rate;
@@ -78,6 +97,7 @@ struct VideoCaptureFormat {
struct VideoCaptureParams {
VideoCaptureFormat requested_format;
+ VideoCaptureBufferType buffer_type;
ResolutionChangePolicy resolution_change_policy;
PowerLineFrequency power_line_frequency;
};
@@ -101,6 +121,7 @@ struct VideoCaptureDeviceDescriptor {
string display_name;
string device_id;
string model_id;
+ VideoFacingMode facing_mode;
VideoCaptureApi capture_api;
VideoCaptureTransportType transport_type;
VideoCaptureDeviceDescriptorCameraCalibration? camera_calibration;
@@ -116,8 +137,14 @@ struct MailboxBufferHandleSet {
array<gpu.mojom.MailboxHolder, 4> mailbox_holder;
};
+struct SharedMemoryViaRawFileDescriptor {
+ handle file_descriptor_handle;
+ uint32 shared_memory_size_in_bytes;
+};
+
union VideoBufferHandle {
handle<shared_buffer> shared_buffer_handle;
+ SharedMemoryViaRawFileDescriptor shared_memory_via_raw_file_descriptor;
MailboxBufferHandleSet mailbox_handles;
};
diff --git a/chromium/media/capture/mojom/video_capture_types.typemap b/chromium/media/capture/mojom/video_capture_types.typemap
index 27b85993df2..cec8543cd92 100644
--- a/chromium/media/capture/mojom/video_capture_types.typemap
+++ b/chromium/media/capture/mojom/video_capture_types.typemap
@@ -33,6 +33,7 @@ type_mappings = [
"media.mojom.ResolutionChangePolicy=media::ResolutionChangePolicy",
"media.mojom.PowerLineFrequency=media::PowerLineFrequency",
"media.mojom.VideoCapturePixelFormat=media::VideoPixelFormat",
+ "media.mojom.VideoCaptureBufferType=media::VideoCaptureBufferType",
"media.mojom.VideoCaptureFormat=media::VideoCaptureFormat",
"media.mojom.VideoCaptureParams=media::VideoCaptureParams",
"media.mojom.VideoCaptureDeviceDescriptorCameraCalibration=media::VideoCaptureDeviceDescriptor::CameraCalibration",
diff --git a/chromium/media/capture/mojom/video_capture_types_mojom_traits.cc b/chromium/media/capture/mojom/video_capture_types_mojom_traits.cc
index 396b0139456..f02c0ac60c3 100644
--- a/chromium/media/capture/mojom/video_capture_types_mojom_traits.cc
+++ b/chromium/media/capture/mojom/video_capture_types_mojom_traits.cc
@@ -234,6 +234,84 @@ bool EnumTraits<media::mojom::VideoCapturePixelFormat,
}
// static
+media::mojom::VideoCaptureBufferType
+EnumTraits<media::mojom::VideoCaptureBufferType,
+ media::VideoCaptureBufferType>::ToMojom(media::VideoCaptureBufferType
+ input) {
+ switch (input) {
+ case media::VideoCaptureBufferType::kSharedMemory:
+ return media::mojom::VideoCaptureBufferType::kSharedMemory;
+ case media::VideoCaptureBufferType::kSharedMemoryViaRawFileDescriptor:
+ return media::mojom::VideoCaptureBufferType::
+ kSharedMemoryViaRawFileDescriptor;
+ case media::VideoCaptureBufferType::kMailboxHolder:
+ return media::mojom::VideoCaptureBufferType::kMailboxHolder;
+ }
+ NOTREACHED();
+ return media::mojom::VideoCaptureBufferType::kSharedMemory;
+}
+
+// static
+bool EnumTraits<media::mojom::VideoCaptureBufferType,
+ media::VideoCaptureBufferType>::
+ FromMojom(media::mojom::VideoCaptureBufferType input,
+ media::VideoCaptureBufferType* output) {
+ switch (input) {
+ case media::mojom::VideoCaptureBufferType::kSharedMemory:
+ *output = media::VideoCaptureBufferType::kSharedMemory;
+ return true;
+ case media::mojom::VideoCaptureBufferType::
+ kSharedMemoryViaRawFileDescriptor:
+ *output =
+ media::VideoCaptureBufferType::kSharedMemoryViaRawFileDescriptor;
+ return true;
+ case media::mojom::VideoCaptureBufferType::kMailboxHolder:
+ *output = media::VideoCaptureBufferType::kMailboxHolder;
+ return true;
+ }
+ NOTREACHED();
+ return false;
+}
+
+// static
+media::mojom::VideoFacingMode
+EnumTraits<media::mojom::VideoFacingMode, media::VideoFacingMode>::ToMojom(
+ media::VideoFacingMode input) {
+ switch (input) {
+ case media::VideoFacingMode::MEDIA_VIDEO_FACING_NONE:
+ return media::mojom::VideoFacingMode::NONE;
+ case media::VideoFacingMode::MEDIA_VIDEO_FACING_USER:
+ return media::mojom::VideoFacingMode::USER;
+ case media::VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT:
+ return media::mojom::VideoFacingMode::ENVIRONMENT;
+ case media::VideoFacingMode::NUM_MEDIA_VIDEO_FACING_MODES:
+ NOTREACHED();
+ return media::mojom::VideoFacingMode::NONE;
+ }
+ NOTREACHED();
+ return media::mojom::VideoFacingMode::NONE;
+}
+
+// static
+bool EnumTraits<media::mojom::VideoFacingMode, media::VideoFacingMode>::
+ FromMojom(media::mojom::VideoFacingMode input,
+ media::VideoFacingMode* output) {
+ switch (input) {
+ case media::mojom::VideoFacingMode::NONE:
+ *output = media::VideoFacingMode::MEDIA_VIDEO_FACING_NONE;
+ return true;
+ case media::mojom::VideoFacingMode::USER:
+ *output = media::VideoFacingMode::MEDIA_VIDEO_FACING_USER;
+ return true;
+ case media::mojom::VideoFacingMode::ENVIRONMENT:
+ *output = media::VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT;
+ return true;
+ }
+ NOTREACHED();
+ return false;
+}
+
+// static
media::mojom::VideoCaptureApi
EnumTraits<media::mojom::VideoCaptureApi, media::VideoCaptureApi>::ToMojom(
media::VideoCaptureApi input) {
@@ -258,6 +336,8 @@ EnumTraits<media::mojom::VideoCaptureApi, media::VideoCaptureApi>::ToMojom(
return media::mojom::VideoCaptureApi::ANDROID_API2_FULL;
case media::VideoCaptureApi::ANDROID_API2_LIMITED:
return media::mojom::VideoCaptureApi::ANDROID_API2_LIMITED;
+ case media::VideoCaptureApi::VIRTUAL_DEVICE:
+ return media::mojom::VideoCaptureApi::VIRTUAL_DEVICE;
case media::VideoCaptureApi::UNKNOWN:
return media::mojom::VideoCaptureApi::UNKNOWN;
}
@@ -300,6 +380,9 @@ bool EnumTraits<media::mojom::VideoCaptureApi, media::VideoCaptureApi>::
case media::mojom::VideoCaptureApi::ANDROID_API2_LIMITED:
*output = media::VideoCaptureApi::ANDROID_API2_LIMITED;
return true;
+ case media::mojom::VideoCaptureApi::VIRTUAL_DEVICE:
+ *output = media::VideoCaptureApi::VIRTUAL_DEVICE;
+ return true;
case media::mojom::VideoCaptureApi::UNKNOWN:
*output = media::VideoCaptureApi::UNKNOWN;
return true;
@@ -360,6 +443,8 @@ bool StructTraits<media::mojom::VideoCaptureParamsDataView,
media::VideoCaptureParams* out) {
if (!data.ReadRequestedFormat(&out->requested_format))
return false;
+ if (!data.ReadBufferType(&out->buffer_type))
+ return false;
if (!data.ReadResolutionChangePolicy(&out->resolution_change_policy))
return false;
if (!data.ReadPowerLineFrequency(&out->power_line_frequency))
@@ -394,6 +479,8 @@ bool StructTraits<media::mojom::VideoCaptureDeviceDescriptorDataView,
return false;
if (!data.ReadModelId(&(output->model_id)))
return false;
+ if (!data.ReadFacingMode(&(output->facing)))
+ return false;
if (!data.ReadCaptureApi(&(output->capture_api)))
return false;
if (!data.ReadTransportType(&(output->transport_type)))
diff --git a/chromium/media/capture/mojom/video_capture_types_mojom_traits.h b/chromium/media/capture/mojom/video_capture_types_mojom_traits.h
index 4c9283c48da..1b7649a2c4a 100644
--- a/chromium/media/capture/mojom/video_capture_types_mojom_traits.h
+++ b/chromium/media/capture/mojom/video_capture_types_mojom_traits.h
@@ -5,6 +5,7 @@
#ifndef MEDIA_CAPTURE_MOJOM_VIDEO_CAPTURE_TYPES_MOJOM_TRAITS_H_
#define MEDIA_CAPTURE_MOJOM_VIDEO_CAPTURE_TYPES_MOJOM_TRAITS_H_
+#include "media/base/video_facing.h"
#include "media/capture/mojom/video_capture_types.mojom.h"
#include "media/capture/video/video_capture_device_descriptor.h"
#include "media/capture/video/video_capture_device_info.h"
@@ -41,6 +42,23 @@ struct EnumTraits<media::mojom::VideoCapturePixelFormat,
};
template <>
+struct EnumTraits<media::mojom::VideoCaptureBufferType,
+ media::VideoCaptureBufferType> {
+ static media::mojom::VideoCaptureBufferType ToMojom(
+ media::VideoCaptureBufferType buffer_type);
+
+ static bool FromMojom(media::mojom::VideoCaptureBufferType input,
+ media::VideoCaptureBufferType* out);
+};
+
+template <>
+struct EnumTraits<media::mojom::VideoFacingMode, media::VideoFacingMode> {
+ static media::mojom::VideoFacingMode ToMojom(media::VideoFacingMode input);
+ static bool FromMojom(media::mojom::VideoFacingMode input,
+ media::VideoFacingMode* output);
+};
+
+template <>
struct EnumTraits<media::mojom::VideoCaptureApi, media::VideoCaptureApi> {
static media::mojom::VideoCaptureApi ToMojom(media::VideoCaptureApi input);
static bool FromMojom(media::mojom::VideoCaptureApi input,
@@ -84,6 +102,11 @@ struct StructTraits<media::mojom::VideoCaptureParamsDataView,
return params.requested_format;
}
+ static media::VideoCaptureBufferType buffer_type(
+ const media::VideoCaptureParams& params) {
+ return params.buffer_type;
+ }
+
static media::ResolutionChangePolicy resolution_change_policy(
const media::VideoCaptureParams& params) {
return params.resolution_change_policy;
@@ -145,6 +168,11 @@ struct StructTraits<media::mojom::VideoCaptureDeviceDescriptorDataView,
return input.model_id;
}
+ static media::VideoFacingMode facing_mode(
+ const media::VideoCaptureDeviceDescriptor& input) {
+ return input.facing;
+ }
+
static media::VideoCaptureApi capture_api(
const media::VideoCaptureDeviceDescriptor& input) {
return input.capture_api;
diff --git a/chromium/media/capture/run_all_unittests.cc b/chromium/media/capture/run_all_unittests.cc
index d196bb67efc..9c4b2770c53 100644
--- a/chromium/media/capture/run_all_unittests.cc
+++ b/chromium/media/capture/run_all_unittests.cc
@@ -9,8 +9,8 @@
#include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_suite.h"
#include "base/threading/thread.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/scoped_ipc_support.h"
+#include "mojo/core/embedder/embedder.h"
+#include "mojo/core/embedder/scoped_ipc_support.h"
#include "testing/gtest/include/gtest/gtest.h"
class MojoEnabledTestEnvironment final : public testing::Environment {
@@ -20,12 +20,12 @@ class MojoEnabledTestEnvironment final : public testing::Environment {
~MojoEnabledTestEnvironment() final = default;
void SetUp() final {
- mojo::edk::Init();
+ mojo::core::Init();
mojo_ipc_thread_.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
- mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport(
+ mojo_ipc_support_.reset(new mojo::core::ScopedIPCSupport(
mojo_ipc_thread_.task_runner(),
- mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST));
+ mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST));
VLOG(1) << "Mojo initialized";
}
@@ -36,7 +36,7 @@ class MojoEnabledTestEnvironment final : public testing::Environment {
private:
base::Thread mojo_ipc_thread_;
- std::unique_ptr<mojo::edk::ScopedIPCSupport> mojo_ipc_support_;
+ std::unique_ptr<mojo::core::ScopedIPCSupport> mojo_ipc_support_;
};
int main(int argc, char* argv[]) {
diff --git a/chromium/media/capture/video/android/video_capture_device_factory_android.cc b/chromium/media/capture/video/android/video_capture_device_factory_android.cc
index e1a0cba1908..ae4e875731b 100644
--- a/chromium/media/capture/video/android/video_capture_device_factory_android.cc
+++ b/chromium/media/capture/video/android/video_capture_device_factory_android.cc
@@ -154,14 +154,4 @@ bool VideoCaptureDeviceFactoryAndroid::IsLegacyOrDeprecatedDevice(
AttachCurrentThread(), id));
}
-// static
-VideoCaptureDeviceFactory*
-VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
- return new VideoCaptureDeviceFactoryAndroid();
-}
-
} // namespace media
diff --git a/chromium/media/capture/video/chromeos/DEPS b/chromium/media/capture/video/chromeos/DEPS
index fe2df0dba85..f1958045109 100644
--- a/chromium/media/capture/video/chromeos/DEPS
+++ b/chromium/media/capture/video/chromeos/DEPS
@@ -1,5 +1,4 @@
include_rules = [
"+chromeos/dbus",
- "+mojo/edk/embedder",
"+third_party/libsync",
]
diff --git a/chromium/media/capture/video/chromeos/camera_device_delegate.cc b/chromium/media/capture/video/chromeos/camera_device_delegate.cc
index 8505fcf230b..ad245ae399b 100644
--- a/chromium/media/capture/video/chromeos/camera_device_delegate.cc
+++ b/chromium/media/capture/video/chromeos/camera_device_delegate.cc
@@ -9,6 +9,7 @@
#include <utility>
#include <vector>
+#include "base/posix/safe_strerror.h"
#include "media/base/bind_to_current_loop.h"
#include "media/capture/mojom/image_capture_types.h"
#include "media/capture/video/blob_utils.h"
@@ -18,8 +19,6 @@
#include "media/capture/video/chromeos/camera_hal_delegate.h"
#include "media/capture/video/chromeos/camera_metadata_utils.h"
#include "media/capture/video/chromeos/stream_buffer_manager.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
namespace media {
@@ -288,7 +287,7 @@ void CameraDeviceDelegate::OnClosed(int32_t result) {
device_context_->SetState(CameraDeviceContext::State::kStopped);
if (result) {
device_context_->LogToClient(std::string("Failed to close device: ") +
- std::string(strerror(result)));
+ base::safe_strerror(-result));
}
ResetMojoInterface();
device_context_ = nullptr;
@@ -397,8 +396,8 @@ void CameraDeviceDelegate::OnInitialized(int32_t result) {
}
if (result) {
device_context_->SetErrorState(
- FROM_HERE, std::string("Failed to initialize camera device") +
- std::string(strerror(result)));
+ FROM_HERE, std::string("Failed to initialize camera device: ") +
+ base::safe_strerror(-result));
return;
}
device_context_->SetState(CameraDeviceContext::State::kInitialized);
@@ -471,7 +470,7 @@ void CameraDeviceDelegate::OnConfiguredStreams(
if (result) {
device_context_->SetErrorState(
FROM_HERE, std::string("Failed to configure streams: ") +
- std::string(strerror(result)));
+ base::safe_strerror(-result));
return;
}
if (!updated_config ||
diff --git a/chromium/media/capture/video/chromeos/camera_device_delegate_unittest.cc b/chromium/media/capture/video/chromeos/camera_device_delegate_unittest.cc
index aa0f3c91fcc..aad0c9bac8b 100644
--- a/chromium/media/capture/video/chromeos/camera_device_delegate_unittest.cc
+++ b/chromium/media/capture/video/chromeos/camera_device_delegate_unittest.cc
@@ -128,7 +128,7 @@ class CameraDeviceDelegateTest : public ::testing::Test {
hal_delegate_thread_("HalDelegateThread") {}
void SetUp() override {
- VideoCaptureDeviceFactoryChromeOS::SetBufferManagerForTesting(
+ VideoCaptureDeviceFactoryChromeOS::SetGpuBufferManager(
&mock_gpu_memory_buffer_manager_);
hal_delegate_thread_.Start();
camera_hal_delegate_ =
diff --git a/chromium/media/capture/video/chromeos/camera_hal_delegate.cc b/chromium/media/capture/video/chromeos/camera_hal_delegate.cc
index 3a33d9b8f89..a47b75b4332 100644
--- a/chromium/media/capture/video/chromeos/camera_hal_delegate.cc
+++ b/chromium/media/capture/video/chromeos/camera_hal_delegate.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/posix/safe_strerror.h"
#include "base/strings/string_piece.h"
#include "media/capture/video/chromeos/camera_buffer_factory.h"
#include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
@@ -85,6 +86,7 @@ std::unique_ptr<VideoCaptureDevice> CameraHalDelegate::CreateDevice(
if (!UpdateBuiltInCameraInfo()) {
return capture_device;
}
+ base::AutoLock lock(camera_info_lock_);
if (camera_info_.find(device_descriptor.device_id) == camera_info_.end()) {
LOG(ERROR) << "Invalid camera device: " << device_descriptor.device_id;
return capture_device;
@@ -103,6 +105,7 @@ void CameraHalDelegate::GetSupportedFormats(
return;
}
std::string camera_id = device_descriptor.device_id;
+ base::AutoLock lock(camera_info_lock_);
if (camera_info_.find(camera_id) == camera_info_.end() ||
camera_info_[camera_id].is_null()) {
LOG(ERROR) << "Invalid camera_id: " << camera_id;
@@ -168,13 +171,14 @@ void CameraHalDelegate::GetDeviceDescriptors(
if (!UpdateBuiltInCameraInfo()) {
return;
}
- for (size_t id = 0; id < num_builtin_cameras_; ++id) {
- VideoCaptureDeviceDescriptor desc;
- std::string camera_id = std::to_string(id);
- const cros::mojom::CameraInfoPtr& camera_info = camera_info_[camera_id];
+ base::AutoLock lock(camera_info_lock_);
+ for (const auto& it : camera_info_) {
+ const std::string& camera_id = it.first;
+ const cros::mojom::CameraInfoPtr& camera_info = it.second;
if (!camera_info) {
continue;
}
+ VideoCaptureDeviceDescriptor desc;
desc.device_id = camera_id;
desc.capture_api = VideoCaptureApi::ANDROID_API2_LIMITED;
desc.transport_type = VideoCaptureTransportType::OTHER_TRANSPORT;
@@ -196,6 +200,7 @@ void CameraHalDelegate::GetDeviceDescriptors(
}
device_descriptors->push_back(desc);
}
+ // TODO(shik): Report external camera first when lid is closed.
// TODO(jcliang): Remove this after JS API supports query camera facing
// (http://crbug.com/543997).
std::sort(device_descriptors->begin(), device_descriptors->end());
@@ -248,6 +253,9 @@ void CameraHalDelegate::ResetMojoInterfaceOnIpcThread() {
}
builtin_camera_info_updated_.Reset();
camera_module_has_been_set_.Reset();
+
+ // Clear all cached camera info, especially external cameras.
+ camera_info_.clear();
}
bool CameraHalDelegate::UpdateBuiltInCameraInfo() {
@@ -279,7 +287,7 @@ void CameraHalDelegate::UpdateBuiltInCameraInfoOnIpcThread() {
void CameraHalDelegate::OnGotNumberOfCamerasOnIpcThread(int32_t num_cameras) {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- if (num_cameras <= 0) {
+ if (num_cameras < 0) {
builtin_camera_info_updated_.Signal();
LOG(ERROR) << "Failed to get number of cameras: " << num_cameras;
return;
@@ -303,9 +311,16 @@ void CameraHalDelegate::OnSetCallbacksOnIpcThread(int32_t result) {
if (result) {
num_builtin_cameras_ = 0;
builtin_camera_info_updated_.Signal();
- LOG(ERROR) << "Failed to set camera module callbacks: " << strerror(result);
+ LOG(ERROR) << "Failed to set camera module callbacks: "
+ << base::safe_strerror(-result);
+ return;
+ }
+
+ if (num_builtin_cameras_ == 0) {
+ builtin_camera_info_updated_.Signal();
return;
}
+
for (size_t camera_id = 0; camera_id < num_builtin_cameras_; ++camera_id) {
GetCameraInfoOnIpcThread(
camera_id,
@@ -332,9 +347,25 @@ void CameraHalDelegate::OnGotCameraInfoOnIpcThread(
}
// In case of error |camera_info| is empty.
SortCameraMetadata(&camera_info->static_camera_characteristics);
+
+ base::AutoLock lock(camera_info_lock_);
camera_info_[std::to_string(camera_id)] = std::move(camera_info);
- if (camera_info_.size() == num_builtin_cameras_) {
- builtin_camera_info_updated_.Signal();
+
+ if (camera_id < base::checked_cast<int32_t>(num_builtin_cameras_)) {
+ // |camera_info_| might contain some entries for external cameras as well,
+ // we should check all built-in cameras explicitly.
+ bool all_updated = [&]() {
+ for (size_t i = 0; i < num_builtin_cameras_; i++) {
+ if (camera_info_.find(std::to_string(i)) == camera_info_.end()) {
+ return false;
+ }
+ }
+ return true;
+ }();
+
+ if (all_updated) {
+ builtin_camera_info_updated_.Signal();
+ }
}
}
@@ -352,8 +383,30 @@ void CameraHalDelegate::CameraDeviceStatusChange(
int32_t camera_id,
cros::mojom::CameraDeviceStatus new_status) {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
- // TODO(jcliang): Handle status change for external cameras.
- NOTIMPLEMENTED() << "CameraDeviceStatusChange is not implemented";
+ VLOG(1) << "camera_id = " << camera_id << ", new_status = " << new_status;
+ base::AutoLock lock(camera_info_lock_);
+ auto it = camera_info_.find(std::to_string(camera_id));
+ switch (new_status) {
+ case cros::mojom::CameraDeviceStatus::CAMERA_DEVICE_STATUS_PRESENT:
+ if (it == camera_info_.end()) {
+ GetCameraInfoOnIpcThread(
+ camera_id,
+ base::BindOnce(&CameraHalDelegate::OnGotCameraInfoOnIpcThread, this,
+ camera_id));
+ } else {
+ LOG(WARNING) << "Ignore duplicated camera_id = " << camera_id;
+ }
+ break;
+ case cros::mojom::CameraDeviceStatus::CAMERA_DEVICE_STATUS_NOT_PRESENT:
+ if (it != camera_info_.end()) {
+ camera_info_.erase(it);
+ } else {
+ LOG(WARNING) << "Ignore nonexistent camera_id = " << camera_id;
+ }
+ break;
+ default:
+ NOTREACHED() << "Unexpected new status " << new_status;
+ }
}
void CameraHalDelegate::TorchModeStatusChange(
diff --git a/chromium/media/capture/video/chromeos/camera_hal_delegate.h b/chromium/media/capture/video/chromeos/camera_hal_delegate.h
index b8c0745e063..19050a1d91b 100644
--- a/chromium/media/capture/video/chromeos/camera_hal_delegate.h
+++ b/chromium/media/capture/video/chromeos/camera_hal_delegate.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "media/capture/video/chromeos/mojo/camera3.mojom.h"
@@ -129,9 +130,11 @@ class CAPTURE_EXPORT CameraHalDelegate final
// reported by the camera HAL, and |camera_info_| stores the camera info of
// each camera device. They are modified only on |ipc_task_runner_|. They
// are also read in GetSupportedFormats and GetDeviceDescriptors, in which the
- // access is sequenced through UpdateBuiltInCameraInfo and
- // |builtin_camera_info_updated_| to avoid race conditions.
+ // access is protected by |camera_info_lock_| and sequenced through
+ // UpdateBuiltInCameraInfo and |builtin_camera_info_updated_| to avoid race
+ // conditions.
size_t num_builtin_cameras_;
+ base::Lock camera_info_lock_;
std::unordered_map<std::string, cros::mojom::CameraInfoPtr> camera_info_;
SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromium/media/capture/video/chromeos/camera_hal_delegate_unittest.cc b/chromium/media/capture/video/chromeos/camera_hal_delegate_unittest.cc
index 33349860f1c..4f1f101aa1a 100644
--- a/chromium/media/capture/video/chromeos/camera_hal_delegate_unittest.cc
+++ b/chromium/media/capture/video/chromeos/camera_hal_delegate_unittest.cc
@@ -31,7 +31,7 @@ class CameraHalDelegateTest : public ::testing::Test {
hal_delegate_thread_("HalDelegateThread") {}
void SetUp() override {
- VideoCaptureDeviceFactoryChromeOS::SetBufferManagerForTesting(
+ VideoCaptureDeviceFactoryChromeOS::SetGpuBufferManager(
&mock_gpu_memory_buffer_manager_);
hal_delegate_thread_.Start();
camera_hal_delegate_ =
diff --git a/chromium/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc b/chromium/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
index 50eb9cb16a8..ade9c3e55ce 100644
--- a/chromium/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
+++ b/chromium/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
@@ -14,15 +14,14 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/posix/eintr_wrapper.h"
+#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/named_platform_handle.h"
-#include "mojo/edk/embedder/named_platform_handle_utils.h"
-#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/platform_channel_utils_posix.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/public/cpp/platform/named_platform_channel.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+#include "mojo/public/cpp/platform/socket_utils_posix.h"
+#include "mojo/public/cpp/system/invitation.h"
namespace media {
@@ -32,6 +31,12 @@ const base::FilePath::CharType kArcCamera3SocketPath[] =
"/var/run/camera/camera3.sock";
const char kArcCameraGroup[] = "arc-camera";
+std::string GenerateRandomToken() {
+ char random_bytes[16];
+ base::RandBytes(random_bytes, 16);
+ return base::HexEncode(random_bytes, 16);
+}
+
// Creates a pipe. Returns true on success, otherwise false.
// On success, |read_fd| will be set to the fd of the read side, and
// |write_fd| will be set to the one of write side.
@@ -211,10 +216,10 @@ void CameraHalDispatcherImpl::CreateSocket(base::WaitableEvent* started) {
DCHECK(blocking_io_task_runner_->BelongsToCurrentThread());
base::FilePath socket_path(kArcCamera3SocketPath);
- mojo::edk::ScopedInternalPlatformHandle socket_fd =
- mojo::edk::CreateServerHandle(
- mojo::edk::NamedPlatformHandle(socket_path.value()));
- if (!socket_fd.is_valid()) {
+ mojo::NamedPlatformChannel::Options options;
+ options.server_name = socket_path.value();
+ mojo::NamedPlatformChannel channel(options);
+ if (!channel.server_endpoint().is_valid()) {
LOG(ERROR) << "Failed to create the socket file: " << kArcCamera3SocketPath;
started->Signal();
return;
@@ -253,13 +258,13 @@ void CameraHalDispatcherImpl::CreateSocket(base::WaitableEvent* started) {
blocking_io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&CameraHalDispatcherImpl::StartServiceLoop,
- base::Unretained(this), base::Passed(&socket_fd),
+ base::Unretained(this),
+ channel.TakeServerEndpoint().TakePlatformHandle().TakeFD(),
base::Unretained(started)));
}
-void CameraHalDispatcherImpl::StartServiceLoop(
- mojo::edk::ScopedInternalPlatformHandle socket_fd,
- base::WaitableEvent* started) {
+void CameraHalDispatcherImpl::StartServiceLoop(base::ScopedFD socket_fd,
+ base::WaitableEvent* started) {
DCHECK(blocking_io_task_runner_->BelongsToCurrentThread());
DCHECK(!proxy_fd_.is_valid());
DCHECK(!cancel_pipe_.is_valid());
@@ -277,34 +282,35 @@ void CameraHalDispatcherImpl::StartServiceLoop(
VLOG(1) << "CameraHalDispatcherImpl started; waiting for incoming connection";
while (true) {
- if (!WaitForSocketReadable(proxy_fd_.get().handle, cancel_fd.get())) {
+ if (!WaitForSocketReadable(proxy_fd_.get(), cancel_fd.get())) {
VLOG(1) << "Quit CameraHalDispatcherImpl IO thread";
return;
}
- mojo::edk::ScopedInternalPlatformHandle accepted_fd;
- if (mojo::edk::ServerAcceptConnection(proxy_fd_, &accepted_fd, false) &&
+ base::ScopedFD accepted_fd;
+ if (mojo::AcceptSocketConnection(proxy_fd_.get(), &accepted_fd, false) &&
accepted_fd.is_valid()) {
VLOG(1) << "Accepted a connection";
// Hardcode pid 0 since it is unused in mojo.
const base::ProcessHandle kUnusedChildProcessHandle = 0;
- mojo::edk::PlatformChannelPair channel_pair;
- mojo::edk::OutgoingBrokerClientInvitation invitation;
+ mojo::PlatformChannel channel;
+ mojo::OutgoingInvitation invitation;
- std::string token = mojo::edk::GenerateRandomToken();
+ // Generate an arbitrary 32-byte string, as we use this length as a
+ // protocol version identifier.
+ std::string token = GenerateRandomToken();
mojo::ScopedMessagePipeHandle pipe = invitation.AttachMessagePipe(token);
+ mojo::OutgoingInvitation::Send(std::move(invitation),
+ kUnusedChildProcessHandle,
+ channel.TakeLocalEndpoint());
- invitation.Send(
- kUnusedChildProcessHandle,
- mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy,
- channel_pair.PassServerHandle()));
-
- std::vector<mojo::edk::ScopedInternalPlatformHandle> handles;
- handles.emplace_back(channel_pair.PassClientHandle());
+ auto remote_endpoint = channel.TakeRemoteEndpoint();
+ std::vector<base::ScopedFD> fds;
+ fds.emplace_back(remote_endpoint.TakePlatformHandle().TakeFD());
struct iovec iov = {const_cast<char*>(token.c_str()), token.length()};
- ssize_t result = mojo::edk::PlatformChannelSendmsgWithHandles(
- accepted_fd, &iov, 1, handles);
+ ssize_t result =
+ mojo::SendmsgWithHandles(accepted_fd.get(), &iov, 1, fds);
if (result == -1) {
PLOG(ERROR) << "sendmsg()";
} else {
diff --git a/chromium/media/capture/video/chromeos/camera_hal_dispatcher_impl.h b/chromium/media/capture/video/chromeos/camera_hal_dispatcher_impl.h
index 7470f777b4b..1eecadcc781 100644
--- a/chromium/media/capture/video/chromeos/camera_hal_dispatcher_impl.h
+++ b/chromium/media/capture/video/chromeos/camera_hal_dispatcher_impl.h
@@ -8,14 +8,15 @@
#include <memory>
#include <set>
+#include "base/files/scoped_file.h"
#include "base/memory/singleton.h"
#include "base/threading/thread.h"
#include "media/capture/capture_export.h"
#include "media/capture/video/chromeos/mojo/cros_camera_service.mojom.h"
#include "media/capture/video/video_capture_device_factory.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/platform/platform_channel_server_endpoint.h"
namespace base {
@@ -78,8 +79,7 @@ class CAPTURE_EXPORT CameraHalDispatcherImpl final
// Waits for incoming connections (from HAL process or from client processes).
// Runs on |blocking_io_thread_|.
- void StartServiceLoop(mojo::edk::ScopedInternalPlatformHandle socket_fd,
- base::WaitableEvent* started);
+ void StartServiceLoop(base::ScopedFD socket_fd, base::WaitableEvent* started);
void AddClientObserverOnProxyThread(
std::unique_ptr<CameraClientObserver> observer);
@@ -95,7 +95,7 @@ class CAPTURE_EXPORT CameraHalDispatcherImpl final
void StopOnProxyThread();
- mojo::edk::ScopedInternalPlatformHandle proxy_fd_;
+ base::ScopedFD proxy_fd_;
base::ScopedFD cancel_pipe_;
base::Thread proxy_thread_;
diff --git a/chromium/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc b/chromium/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc
index 020ca137016..eab11a8e646 100644
--- a/chromium/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc
+++ b/chromium/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc
@@ -150,7 +150,9 @@ class GpuMemoryBufferImplGbm : public gfx::GpuMemoryBuffer {
gfx::GpuMemoryBufferId GetId() const override { return handle_.id; }
- gfx::GpuMemoryBufferHandle GetHandle() const override { return handle_; }
+ gfx::GpuMemoryBufferHandle GetHandle() const override {
+ return gfx::CloneHandleForIPC(handle_);
+ }
ClientBuffer AsClientBuffer() override {
return reinterpret_cast<ClientBuffer>(this);
diff --git a/chromium/media/capture/video/chromeos/mojo/camera_metadata_tags.mojom b/chromium/media/capture/video/chromeos/mojo/camera_metadata_tags.mojom
index d4543e7bb73..4fcfad8dcd7 100644
--- a/chromium/media/capture/video/chromeos/mojo/camera_metadata_tags.mojom
+++ b/chromium/media/capture/video/chromeos/mojo/camera_metadata_tags.mojom
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,7 +55,9 @@ enum CameraMetadataSection {
ANDROID_SYNC = 0x17,
ANDROID_REPROCESS = 0x18,
ANDROID_DEPTH = 0x19,
- ANDROID_SECTION_COUNT = 0x1A,
+ ANDROID_LOGICAL_MULTI_CAMERA = 0x1A,
+ ANDROID_DISTORTION_CORRECTION = 0x1B,
+ ANDROID_SECTION_COUNT = 0x1C,
VENDOR_SECTION = 0x8000
};
@@ -92,6 +94,10 @@ enum CameraMetadataSectionStart {
ANDROID_SYNC_START = 0x170000,
ANDROID_REPROCESS_START = 0x180000,
ANDROID_DEPTH_START = 0x190000,
+ ANDROID_LOGICAL_MULTI_CAMERA_START
+ = 0x1A0000,
+ ANDROID_DISTORTION_CORRECTION_START
+ = 0x1B0000,
// Mojom maps enum to int32_t in C++. This causes problem on the VENDOR_SECTION_START
// below as 0x80000000 would generate -Wc++11-narrowing warnings while compiling the
@@ -155,6 +161,7 @@ enum CameraMetadataTag {
ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE,
ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
ANDROID_CONTROL_ENABLE_ZSL,
+ ANDROID_CONTROL_AF_SCENE_CHANGE,
ANDROID_CONTROL_END,
ANDROID_DEMOSAIC_MODE = 0x20000, // ANDROID_DEMOSAIC_START,
ANDROID_DEMOSAIC_END,
@@ -198,6 +205,8 @@ enum CameraMetadataTag {
ANDROID_LENS_STATE,
ANDROID_LENS_INTRINSIC_CALIBRATION,
ANDROID_LENS_RADIAL_DISTORTION,
+ ANDROID_LENS_POSE_REFERENCE,
+ ANDROID_LENS_DISTORTION,
ANDROID_LENS_END,
ANDROID_LENS_INFO_AVAILABLE_APERTURES = 0x90000, // ANDROID_LENS_INFO_START,
ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
@@ -234,6 +243,8 @@ enum CameraMetadataTag {
ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
+ ANDROID_REQUEST_AVAILABLE_SESSION_KEYS,
+ ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS,
ANDROID_REQUEST_END,
ANDROID_SCALER_CROP_REGION = 0xD0000, // ANDROID_SCALER_START,
ANDROID_SCALER_AVAILABLE_FORMATS,
@@ -315,6 +326,10 @@ enum CameraMetadataTag {
ANDROID_STATISTICS_SCENE_FLICKER,
ANDROID_STATISTICS_HOT_PIXEL_MAP,
ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+ ANDROID_STATISTICS_OIS_DATA_MODE,
+ ANDROID_STATISTICS_OIS_TIMESTAMPS,
+ ANDROID_STATISTICS_OIS_X_SHIFTS,
+ ANDROID_STATISTICS_OIS_Y_SHIFTS,
ANDROID_STATISTICS_END,
ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES =
0x120000, // ANDROID_STATISTICS_INFO_START,
@@ -325,6 +340,7 @@ enum CameraMetadataTag {
ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE,
ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
+ ANDROID_STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES,
ANDROID_STATISTICS_INFO_END,
ANDROID_TONEMAP_CURVE_BLUE = 0x130000, // ANDROID_TONEMAP_START,
ANDROID_TONEMAP_CURVE_GREEN,
@@ -339,6 +355,7 @@ enum CameraMetadataTag {
ANDROID_LED_AVAILABLE_LEDS,
ANDROID_LED_END,
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL = 0x150000, // ANDROID_INFO_START,
+ ANDROID_INFO_VERSION,
ANDROID_INFO_END,
ANDROID_BLACK_LEVEL_LOCK = 0x160000, // ANDROID_BLACK_LEVEL_START,
ANDROID_BLACK_LEVEL_END,
@@ -354,6 +371,12 @@ enum CameraMetadataTag {
ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS,
ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE,
ANDROID_DEPTH_END,
+ ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS = 0x1A0000, // ANDROID_LOGICAL_MULTI_CAMERA_START,
+ ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE,
+ ANDROID_LOGICAL_MULTI_CAMERA_END,
+ ANDROID_DISTORTION_CORRECTION_MODE = 0x1B0000, // ANDROID_DISTORTION_CORRECTION_START,
+ ANDROID_DISTORTION_CORRECTION_AVAILABLE_MODES,
+ ANDROID_DISTORTION_CORRECTION_END,
};
/**
@@ -395,6 +418,7 @@ enum AndroidControlAeMode {
ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH,
ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH,
ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE,
+ ANDROID_CONTROL_AE_MODE_ON_EXTERNAL_FLASH,
};
// ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER
@@ -449,6 +473,7 @@ enum AndroidControlCaptureIntent {
ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT,
ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG,
ANDROID_CONTROL_CAPTURE_INTENT_MANUAL,
+ ANDROID_CONTROL_CAPTURE_INTENT_MOTION_TRACKING,
};
// ANDROID_CONTROL_EFFECT_MODE
@@ -551,6 +576,12 @@ enum AndroidControlEnableZsl {
ANDROID_CONTROL_ENABLE_ZSL_TRUE,
};
+// ANDROID_CONTROL_AF_SCENE_CHANGE
+enum AndroidControlAfSceneChange {
+ ANDROID_CONTROL_AF_SCENE_CHANGE_NOT_DETECTED,
+ ANDROID_CONTROL_AF_SCENE_CHANGE_DETECTED,
+};
+
// ANDROID_DEMOSAIC_MODE
enum AndroidDemosaicMode {
ANDROID_DEMOSAIC_MODE_FAST,
@@ -613,6 +644,12 @@ enum AndroidLensState {
ANDROID_LENS_STATE_MOVING,
};
+// ANDROID_LENS_POSE_REFERENCE
+enum AndroidLensPoseReference {
+ ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA,
+ ANDROID_LENS_POSE_REFERENCE_GYROSCOPE,
+};
+
// ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION
enum AndroidLensInfoFocusDistanceCalibration {
ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED,
@@ -659,6 +696,9 @@ enum AndroidRequestAvailableCapabilities {
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME,
};
// ANDROID_SCALER_AVAILABLE_FORMATS
@@ -783,6 +823,12 @@ enum AndroidStatisticsLensShadingMapMode {
ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON,
};
+// ANDROID_STATISTICS_OIS_DATA_MODE
+enum AndroidStatisticsOisDataMode {
+ ANDROID_STATISTICS_OIS_DATA_MODE_OFF,
+ ANDROID_STATISTICS_OIS_DATA_MODE_ON,
+};
+
// ANDROID_TONEMAP_MODE
enum AndroidTonemapMode {
ANDROID_TONEMAP_MODE_CONTRAST_CURVE,
@@ -815,6 +861,7 @@ enum AndroidInfoSupportedHardwareLevel {
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3,
+ ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL,
};
// ANDROID_BLACK_LEVEL_LOCK
@@ -846,3 +893,16 @@ enum AndroidDepthDepthIsExclusive {
ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_FALSE,
ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_TRUE,
};
+
+// ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
+enum AndroidLogicalMultiCameraSensorSyncType {
+ ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE,
+ ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED,
+};
+
+// ANDROID_DISTORTION_CORRECTION_MODE
+enum AndroidDistortionCorrectionMode {
+ ANDROID_DISTORTION_CORRECTION_MODE_OFF,
+ ANDROID_DISTORTION_CORRECTION_MODE_FAST,
+ ANDROID_DISTORTION_CORRECTION_MODE_HIGH_QUALITY,
+};
diff --git a/chromium/media/capture/video/chromeos/pixel_format_utils.cc b/chromium/media/capture/video/chromeos/pixel_format_utils.cc
index 6f9d4e3645c..a4197a81921 100644
--- a/chromium/media/capture/video/chromeos/pixel_format_utils.cc
+++ b/chromium/media/capture/video/chromeos/pixel_format_utils.cc
@@ -4,7 +4,7 @@
#include "media/capture/video/chromeos/pixel_format_utils.h"
-#include <libdrm/drm_fourcc.h>
+#include <drm_fourcc.h>
namespace media {
diff --git a/chromium/media/capture/video/chromeos/public/BUILD.gn b/chromium/media/capture/video/chromeos/public/BUILD.gn
new file mode 100644
index 00000000000..092ba2c6fc2
--- /dev/null
+++ b/chromium/media/capture/video/chromeos/public/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("public") {
+ sources = [
+ "cros_features.cc",
+ "cros_features.h",
+ ]
+
+ public_deps = [
+ "//base",
+ ]
+}
diff --git a/chromium/media/capture/video/chromeos/public/cros_features.cc b/chromium/media/capture/video/chromeos/public/cros_features.cc
new file mode 100644
index 00000000000..4658f93134c
--- /dev/null
+++ b/chromium/media/capture/video/chromeos/public/cros_features.cc
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/capture/video/chromeos/public/cros_features.h"
+
+#include "base/files/file_util.h"
+
+namespace media {
+
+bool ShouldUseCrosCameraService() {
+ // Checks whether the Chrome OS binary which provides the HAL v3 camera
+ // service is installed on the device. If the binary exists we assume the
+ // device is using the new camera HAL v3 stack.
+ const base::FilePath kCrosCameraService("/usr/bin/cros_camera_service");
+ return base::PathExists(kCrosCameraService);
+}
+
+} // namespace media
diff --git a/chromium/media/capture/video/chromeos/public/cros_features.h b/chromium/media/capture/video/chromeos/public/cros_features.h
new file mode 100644
index 00000000000..94797d4d8a5
--- /dev/null
+++ b/chromium/media/capture/video/chromeos/public/cros_features.h
@@ -0,0 +1,16 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAPTURE_VIDEO_CHROMEOS_PUBLIC_CROS_FEATURES_H_
+#define MEDIA_CAPTURE_VIDEO_CHROMEOS_PUBLIC_CROS_FEATURES_H_
+
+namespace media {
+
+// A run-time check for whether or not we should use the OS-level camera
+// service on ChromeOS for video capture.
+bool ShouldUseCrosCameraService();
+
+} // namespace media
+
+#endif // MEDIA_CAPTURE_VIDEO_CHROMEOS_PUBLIC_CROS_FEATURES_H_
diff --git a/chromium/media/capture/video/chromeos/stream_buffer_manager.cc b/chromium/media/capture/video/chromeos/stream_buffer_manager.cc
index 2cd54bb1114..ad4af81973f 100644
--- a/chromium/media/capture/video/chromeos/stream_buffer_manager.cc
+++ b/chromium/media/capture/video/chromeos/stream_buffer_manager.cc
@@ -7,11 +7,12 @@
#include <sync/sync.h>
#include <memory>
+#include "base/posix/safe_strerror.h"
#include "media/capture/video/chromeos/camera_buffer_factory.h"
#include "media/capture/video/chromeos/camera_device_context.h"
#include "media/capture/video/chromeos/camera_metadata_utils.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/public/cpp/platform/platform_handle.h"
+#include "mojo/public/cpp/system/platform_handle.h"
namespace media {
@@ -318,24 +319,19 @@ void StreamBufferManager::RegisterBuffer(StreamType stream_type) {
size_t num_planes = buffer_handle.planes.size();
std::vector<StreamCaptureInterface::Plane> planes(num_planes);
for (size_t i = 0; i < num_planes; ++i) {
- // Wrap the platform handle.
- MojoHandle wrapped_handle;
// There is only one fd.
int dup_fd = dup(buffer_handle.fds[0].fd);
if (dup_fd == -1) {
device_context_->SetErrorState(FROM_HERE, "Failed to dup fd");
return;
}
- MojoResult result = mojo::edk::CreateInternalPlatformHandleWrapper(
- mojo::edk::ScopedInternalPlatformHandle(
- mojo::edk::InternalPlatformHandle(dup_fd)),
- &wrapped_handle);
- if (result != MOJO_RESULT_OK) {
+ planes[i].fd =
+ mojo::WrapPlatformHandle(mojo::PlatformHandle(base::ScopedFD(dup_fd)));
+ if (!planes[i].fd.is_valid()) {
device_context_->SetErrorState(FROM_HERE,
"Failed to wrap gpu memory handle");
return;
}
- planes[i].fd.reset(mojo::Handle(wrapped_handle));
planes[i].stride = buffer_handle.planes[i].stride;
planes[i].offset = buffer_handle.planes[i].offset;
}
@@ -367,7 +363,7 @@ void StreamBufferManager::OnRegisteredBuffer(StreamType stream_type,
if (result) {
device_context_->SetErrorState(FROM_HERE,
std::string("Failed to register buffer: ") +
- std::string(strerror(result)));
+ base::safe_strerror(-result));
return;
}
stream_context_[stream_type]->registered_buffers.push(buffer_id);
@@ -439,8 +435,8 @@ void StreamBufferManager::OnProcessedCaptureRequest(int32_t result) {
}
if (result) {
device_context_->SetErrorState(
- FROM_HERE, std::string("Process capture request failed") +
- std::string(strerror(result)));
+ FROM_HERE, std::string("Process capture request failed: ") +
+ base::safe_strerror(-result));
return;
}
// Keeps the preview stream going.
@@ -702,15 +698,14 @@ void StreamBufferManager::SubmitCaptureResult(uint32_t frame_number,
// Wait on release fence before delivering the result buffer to client.
if (stream_buffer->release_fence.is_valid()) {
const int kSyncWaitTimeoutMs = 1000;
- mojo::edk::ScopedInternalPlatformHandle fence;
- MojoResult result = mojo::edk::PassWrappedInternalPlatformHandle(
- stream_buffer->release_fence.release().value(), &fence);
- if (result != MOJO_RESULT_OK) {
+ mojo::PlatformHandle fence =
+ mojo::UnwrapPlatformHandle(std::move(stream_buffer->release_fence));
+ if (!fence.is_valid()) {
device_context_->SetErrorState(FROM_HERE,
"Failed to unwrap release fence fd");
return;
}
- if (!sync_wait(fence.get().handle, kSyncWaitTimeoutMs)) {
+ if (!sync_wait(fence.GetFD().get(), kSyncWaitTimeoutMs)) {
device_context_->SetErrorState(FROM_HERE,
"Sync wait on release fence timed out");
return;
diff --git a/chromium/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc b/chromium/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc
index dbd982e71b5..6fb9ccac642 100644
--- a/chromium/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc
+++ b/chromium/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc
@@ -4,10 +4,8 @@
#include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h"
-#include "base/files/file_util.h"
#include "base/memory/ptr_util.h"
#include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
-#include "media/capture/video/linux/video_capture_device_factory_linux.h"
namespace media {
@@ -18,20 +16,14 @@ gpu::GpuMemoryBufferManager* g_gpu_buffer_manager = nullptr;
} // namespace
VideoCaptureDeviceFactoryChromeOS::VideoCaptureDeviceFactoryChromeOS(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer,
- gpu::GpuMemoryBufferManager* gpu_buffer_manager,
- MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory)
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer)
: task_runner_for_screen_observer_(task_runner_for_screen_observer),
camera_hal_ipc_thread_("CameraHalIpcThread"),
- initialized_(Init(std::move(jda_factory), std::move(jea_factory))) {
- g_gpu_buffer_manager = gpu_buffer_manager;
-}
+ initialized_(Init()) {}
VideoCaptureDeviceFactoryChromeOS::~VideoCaptureDeviceFactoryChromeOS() {
camera_hal_delegate_->Reset();
camera_hal_ipc_thread_.Stop();
- g_gpu_buffer_manager = nullptr;
}
std::unique_ptr<VideoCaptureDevice>
@@ -49,9 +41,6 @@ void VideoCaptureDeviceFactoryChromeOS::GetSupportedFormats(
const VideoCaptureDeviceDescriptor& device_descriptor,
VideoCaptureFormats* supported_formats) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (!initialized_) {
- return;
- }
camera_hal_delegate_->GetSupportedFormats(device_descriptor,
supported_formats);
}
@@ -66,38 +55,25 @@ void VideoCaptureDeviceFactoryChromeOS::GetDeviceDescriptors(
}
// static
-bool VideoCaptureDeviceFactoryChromeOS::ShouldEnable() {
- // Checks whether the Chrome OS binary which provides the HAL v3 camera
- // service is installed on the device. If the binary exists we assume the
- // device is using the new camera HAL v3 stack.
- const base::FilePath kCrosCameraService("/usr/bin/cros_camera_service");
- return base::PathExists(kCrosCameraService);
-}
-
-// static
gpu::GpuMemoryBufferManager*
VideoCaptureDeviceFactoryChromeOS::GetBufferManager() {
return g_gpu_buffer_manager;
}
// static
-void VideoCaptureDeviceFactoryChromeOS::SetBufferManagerForTesting(
+void VideoCaptureDeviceFactoryChromeOS::SetGpuBufferManager(
gpu::GpuMemoryBufferManager* buffer_manager) {
g_gpu_buffer_manager = buffer_manager;
}
-bool VideoCaptureDeviceFactoryChromeOS::Init(
- MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
+bool VideoCaptureDeviceFactoryChromeOS::Init() {
if (!camera_hal_ipc_thread_.Start()) {
LOG(ERROR) << "Module thread failed to start";
return false;
}
- if (!CameraHalDispatcherImpl::GetInstance()->IsStarted() &&
- !CameraHalDispatcherImpl::GetInstance()->Start(std::move(jda_factory),
- std::move(jea_factory))) {
- LOG(ERROR) << "Failed to start CameraHalDispatcherImpl";
+ if (!CameraHalDispatcherImpl::GetInstance()->IsStarted()) {
+ LOG(ERROR) << "CameraHalDispatcherImpl is not started";
return false;
}
@@ -107,31 +83,4 @@ bool VideoCaptureDeviceFactoryChromeOS::Init(
return true;
}
-#if defined(OS_CHROMEOS)
-// static
-VideoCaptureDeviceFactory*
-VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer,
- gpu::GpuMemoryBufferManager* gpu_buffer_manager,
- MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
- // On Chrome OS we have to support two use cases:
- //
- // 1. For devices that have the camera HAL v3 service running on Chrome OS,
- // we use the HAL v3 capture device which VideoCaptureDeviceFactoryChromeOS
- // provides.
- // 2. Existing devices that use UVC cameras need to use the V4L2 capture
- // device which VideoCaptureDeviceFacotoryLinux provides; there are also
- // some special devices that may never be able to implement a camera HAL
- // v3.
- if (VideoCaptureDeviceFactoryChromeOS::ShouldEnable()) {
- return new VideoCaptureDeviceFactoryChromeOS(
- task_runner_for_screen_observer, gpu_buffer_manager,
- std::move(jda_factory), std::move(jea_factory));
- } else {
- return new VideoCaptureDeviceFactoryLinux(task_runner_for_screen_observer);
- }
-}
-#endif
-
} // namespace media
diff --git a/chromium/media/capture/video/chromeos/video_capture_device_factory_chromeos.h b/chromium/media/capture/video/chromeos/video_capture_device_factory_chromeos.h
index 4507469bb03..bc452c30b03 100644
--- a/chromium/media/capture/video/chromeos/video_capture_device_factory_chromeos.h
+++ b/chromium/media/capture/video/chromeos/video_capture_device_factory_chromeos.h
@@ -19,10 +19,7 @@ class CAPTURE_EXPORT VideoCaptureDeviceFactoryChromeOS final
public:
explicit VideoCaptureDeviceFactoryChromeOS(
scoped_refptr<base::SingleThreadTaskRunner>
- task_runner_for_screen_observer,
- gpu::GpuMemoryBufferManager* gpu_buffer_manager,
- MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory);
+ task_runner_for_screen_observer);
~VideoCaptureDeviceFactoryChromeOS() override;
@@ -35,21 +32,13 @@ class CAPTURE_EXPORT VideoCaptureDeviceFactoryChromeOS final
void GetDeviceDescriptors(
VideoCaptureDeviceDescriptors* device_descriptors) final;
- // A run-time check for whether we should enable
- // VideoCaptureDeviceFactoryChromeOS on the device.
- static bool ShouldEnable();
-
static gpu::GpuMemoryBufferManager* GetBufferManager();
-
- // For testing purpose only.
- static void SetBufferManagerForTesting(
- gpu::GpuMemoryBufferManager* buffer_manager);
+ static void SetGpuBufferManager(gpu::GpuMemoryBufferManager* buffer_manager);
private:
// Initializes the factory. The factory is functional only after this call
// succeeds.
- bool Init(MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory);
+ bool Init();
const scoped_refptr<base::SingleThreadTaskRunner>
task_runner_for_screen_observer_;
diff --git a/chromium/media/capture/video/create_video_capture_device_factory.cc b/chromium/media/capture/video/create_video_capture_device_factory.cc
new file mode 100644
index 00000000000..9ca6f8c3e1a
--- /dev/null
+++ b/chromium/media/capture/video/create_video_capture_device_factory.cc
@@ -0,0 +1,91 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/capture/video/create_video_capture_device_factory.h"
+
+#include "base/command_line.h"
+#include "build/build_config.h"
+#include "media/base/media_switches.h"
+#include "media/capture/video/fake_video_capture_device_factory.h"
+#include "media/capture/video/file_video_capture_device_factory.h"
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#include "media/capture/video/linux/video_capture_device_factory_linux.h"
+#elif defined(OS_CHROMEOS)
+#include "media/capture/video/chromeos/public/cros_features.h"
+#include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h"
+#include "media/capture/video/linux/video_capture_device_factory_linux.h"
+#elif defined(OS_WIN)
+#include "media/capture/video/win/video_capture_device_factory_win.h"
+#elif defined(OS_MACOSX)
+#include "media/capture/video/mac/video_capture_device_factory_mac.h"
+#elif defined(OS_ANDROID)
+#include "media/capture/video/android/video_capture_device_factory_android.h"
+#endif
+
+namespace media {
+
+namespace {
+
+std::unique_ptr<VideoCaptureDeviceFactory>
+CreatePlatformSpecificVideoCaptureDeviceFactory(
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ return std::make_unique<VideoCaptureDeviceFactoryLinux>(ui_task_runner);
+#elif defined(OS_CHROMEOS)
+ // On Chrome OS we have to support two use cases:
+ //
+ // 1. For devices that have the camera HAL v3 service running on Chrome OS,
+ // we use the HAL v3 capture device which VideoCaptureDeviceFactoryChromeOS
+ // provides.
+ // 2. Existing devices that use UVC cameras need to use the V4L2 capture
+ // device which VideoCaptureDeviceFacotoryLinux provides; there are also
+ // some special devices that may never be able to implement a camera HAL
+ // v3.
+ if (ShouldUseCrosCameraService()) {
+ return std::make_unique<VideoCaptureDeviceFactoryChromeOS>(ui_task_runner);
+ } else {
+ return std::make_unique<VideoCaptureDeviceFactoryLinux>(ui_task_runner);
+ }
+#elif defined(OS_WIN)
+ return std::make_unique<VideoCaptureDeviceFactoryWin>();
+#elif defined(OS_MACOSX)
+ return std::make_unique<VideoCaptureDeviceFactoryMac>();
+#elif defined(OS_ANDROID)
+ return std::make_unique<VideoCaptureDeviceFactoryAndroid>();
+#else
+ NOTIMPLEMENTED();
+ return nullptr;
+#endif
+}
+
+} // anonymous namespace
+
+std::unique_ptr<VideoCaptureDeviceFactory> CreateVideoCaptureDeviceFactory(
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ // Use a Fake or File Video Device Factory if the command line flags are
+ // present, otherwise use the normal, platform-dependent, device factory.
+ if (command_line->HasSwitch(switches::kUseFakeDeviceForMediaStream)) {
+ if (command_line->HasSwitch(switches::kUseFileForFakeVideoCapture)) {
+ return std::make_unique<FileVideoCaptureDeviceFactory>();
+ } else {
+ std::vector<FakeVideoCaptureDeviceSettings> config;
+ FakeVideoCaptureDeviceFactory::ParseFakeDevicesConfigFromOptionsString(
+ command_line->GetSwitchValueASCII(
+ switches::kUseFakeDeviceForMediaStream),
+ &config);
+ auto result = std::make_unique<FakeVideoCaptureDeviceFactory>();
+ result->SetToCustomDevicesConfig(config);
+ return std::move(result);
+ }
+ } else {
+ // |ui_task_runner| is needed for the Linux ChromeOS factory to retrieve
+ // screen rotations.
+ return CreatePlatformSpecificVideoCaptureDeviceFactory(ui_task_runner);
+ }
+}
+
+} // namespace media
diff --git a/chromium/media/capture/video/create_video_capture_device_factory.h b/chromium/media/capture/video/create_video_capture_device_factory.h
new file mode 100644
index 00000000000..7199bf800e3
--- /dev/null
+++ b/chromium/media/capture/video/create_video_capture_device_factory.h
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAPTURE_VIDEO_CREATE_VIDEO_CAPTURE_DEVICE_FACTORY_H_
+#define MEDIA_CAPTURE_VIDEO_CREATE_VIDEO_CAPTURE_DEVICE_FACTORY_H_
+
+#include <memory>
+
+#include "base/single_thread_task_runner.h"
+#include "media/capture/capture_export.h"
+#include "media/capture/video/video_capture_device_factory.h"
+
+namespace media {
+
+std::unique_ptr<VideoCaptureDeviceFactory> CAPTURE_EXPORT
+CreateVideoCaptureDeviceFactory(
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
+
+} // namespace media
+
+#endif // MEDIA_CAPTURE_VIDEO_CREATE_VIDEO_CAPTURE_DEVICE_FACTORY_H_
diff --git a/chromium/media/capture/video/linux/camera_config_chromeos.h b/chromium/media/capture/video/linux/camera_config_chromeos.h
index 3b3bb395995..df4556e40a2 100644
--- a/chromium/media/capture/video/linux/camera_config_chromeos.h
+++ b/chromium/media/capture/video/linux/camera_config_chromeos.h
@@ -61,16 +61,6 @@ class CAPTURE_EXPORT CameraConfigChromeOS {
CAPTURE_EXPORT VideoFacingMode
GetCameraFacing(const std::string& device_id,
const std::string& model_id) const;
- // Get the orientation of the camera. The value is the angle that the camera
- // image needs to be rotated clockwise so it shows correctly on the display in
- // its natural orientation. It should be 0, 90, 180, or 270.
- //
- // For example, suppose a device has a naturally tall screen. The back-facing
- // camera sensor is mounted in landscape. You are looking at the screen. If
- // the top side of the camera sensor is aligned with the right edge of the
- // screen in natural orientation, the value should be 90. If the top side of a
- // front-facing camera sensor is aligned with the right of the screen, the
- // value should be 270.
int GetOrientation(const std::string& device_id,
const std::string& model_id) const;
diff --git a/chromium/media/capture/video/linux/fake_v4l2_impl.cc b/chromium/media/capture/video/linux/fake_v4l2_impl.cc
new file mode 100644
index 00000000000..2c33b40820a
--- /dev/null
+++ b/chromium/media/capture/video/linux/fake_v4l2_impl.cc
@@ -0,0 +1,198 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/capture/video/linux/fake_v4l2_impl.h"
+
+#include <linux/videodev2.h>
+#include <string.h>
+
+#include "base/stl_util.h"
+
+#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
+
+namespace media {
+
+static const int kInvalidId = -1;
+static const int kSuccessReturnValue = 0;
+static const int kErrorReturnValue = -1;
+
+class FakeV4L2Impl::OpenedDevice {
+ public:
+ explicit OpenedDevice(const std::string& device_id, int open_flags)
+ : device_id_(device_id), open_flags_(open_flags) {}
+
+ const std::string& device_id() const { return device_id_; }
+ int open_flags() const { return open_flags_; }
+
+ private:
+ const std::string device_id_;
+ const int open_flags_;
+};
+
+FakeV4L2Impl::FakeV4L2Impl() : next_id_to_return_from_open_(1) {}
+
+FakeV4L2Impl::~FakeV4L2Impl() = default;
+
+void FakeV4L2Impl::AddDevice(const std::string& device_name,
+ const FakeV4L2DeviceConfig& config) {
+ device_configs_.emplace(device_name, config);
+}
+
+int FakeV4L2Impl::open(const char* device_name, int flags) {
+ std::string device_name_as_string(device_name);
+ if (!base::ContainsKey(device_configs_, device_name_as_string))
+ return kInvalidId;
+
+ auto id_iter = device_name_to_open_id_map_.find(device_name_as_string);
+ if (id_iter != device_name_to_open_id_map_.end()) {
+ // Device is already open
+ return kInvalidId;
+ }
+
+ auto device_id = next_id_to_return_from_open_++;
+ device_name_to_open_id_map_.emplace(device_name_as_string, device_id);
+ opened_devices_.emplace(
+ device_id, std::make_unique<OpenedDevice>(device_name_as_string, flags));
+ return device_id;
+}
+
+int FakeV4L2Impl::close(int fd) {
+ auto device_iter = opened_devices_.find(fd);
+ if (device_iter == opened_devices_.end())
+ return kErrorReturnValue;
+ device_name_to_open_id_map_.erase(device_iter->second->device_id());
+ opened_devices_.erase(device_iter->first);
+ return kSuccessReturnValue;
+}
+
+int FakeV4L2Impl::ioctl(int fd, int request, void* argp) {
+ auto device_iter = opened_devices_.find(fd);
+ if (device_iter == opened_devices_.end())
+ return EBADF;
+ auto& opened_device = device_iter->second;
+ auto& device_config = device_configs_.at(opened_device->device_id());
+
+ switch (request) {
+ case VIDIOC_ENUM_FMT: {
+ auto* fmtdesc = reinterpret_cast<v4l2_fmtdesc*>(argp);
+ if (fmtdesc->index > 0u) {
+ // We only support a single format for now.
+ return EINVAL;
+ }
+ if (fmtdesc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ // We only support video capture.
+ return EINVAL;
+ }
+ fmtdesc->flags = 0u;
+ strcpy(reinterpret_cast<char*>(fmtdesc->description), "YUV420");
+ fmtdesc->pixelformat = V4L2_PIX_FMT_YUV420;
+ memset(fmtdesc->reserved, 0, 4);
+ return kSuccessReturnValue;
+ }
+ case VIDIOC_QUERYCAP: {
+ auto* cap = reinterpret_cast<v4l2_capability*>(argp);
+ strcpy(reinterpret_cast<char*>(cap->driver), "FakeV4L2");
+ CHECK(device_config.descriptor.display_name().size() < 31);
+ strcpy(reinterpret_cast<char*>(cap->driver),
+ device_config.descriptor.display_name().c_str());
+ cap->bus_info[0] = 0;
+ // Provide arbitrary version info
+ cap->version = KERNEL_VERSION(1, 0, 0);
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE;
+ memset(cap->reserved, 0, 4);
+ return kSuccessReturnValue;
+ }
+ case VIDIOC_STREAMON:
+ case VIDIOC_STREAMOFF:
+ NOTIMPLEMENTED();
+ return kSuccessReturnValue;
+ case VIDIOC_CROPCAP:
+ case VIDIOC_DBG_G_REGISTER:
+ case VIDIOC_DBG_S_REGISTER:
+ case VIDIOC_ENCODER_CMD:
+ case VIDIOC_TRY_ENCODER_CMD:
+ case VIDIOC_ENUMAUDIO:
+ case VIDIOC_ENUMAUDOUT:
+ case VIDIOC_ENUM_FRAMESIZES:
+ case VIDIOC_ENUM_FRAMEINTERVALS:
+ case VIDIOC_ENUMINPUT:
+ case VIDIOC_ENUMOUTPUT:
+ case VIDIOC_ENUMSTD:
+ case VIDIOC_G_AUDIO:
+ case VIDIOC_S_AUDIO:
+ case VIDIOC_G_AUDOUT:
+ case VIDIOC_S_AUDOUT:
+ case VIDIOC_G_CROP:
+ case VIDIOC_S_CROP:
+ case VIDIOC_G_CTRL:
+ case VIDIOC_S_CTRL:
+ case VIDIOC_G_ENC_INDEX:
+ case VIDIOC_G_EXT_CTRLS:
+ case VIDIOC_S_EXT_CTRLS:
+ case VIDIOC_TRY_EXT_CTRLS:
+ case VIDIOC_G_FBUF:
+ case VIDIOC_S_FBUF:
+ case VIDIOC_G_FMT:
+ case VIDIOC_S_FMT:
+ case VIDIOC_TRY_FMT:
+ case VIDIOC_G_FREQUENCY:
+ case VIDIOC_S_FREQUENCY:
+ case VIDIOC_G_INPUT:
+ case VIDIOC_S_INPUT:
+ case VIDIOC_G_JPEGCOMP:
+ case VIDIOC_S_JPEGCOMP:
+ case VIDIOC_G_MODULATOR:
+ case VIDIOC_S_MODULATOR:
+ case VIDIOC_G_OUTPUT:
+ case VIDIOC_S_OUTPUT:
+ case VIDIOC_G_PARM:
+ case VIDIOC_S_PARM:
+ case VIDIOC_G_PRIORITY:
+ case VIDIOC_S_PRIORITY:
+ case VIDIOC_G_SLICED_VBI_CAP:
+ case VIDIOC_G_STD:
+ case VIDIOC_S_STD:
+ case VIDIOC_G_TUNER:
+ case VIDIOC_S_TUNER:
+ case VIDIOC_LOG_STATUS:
+ case VIDIOC_OVERLAY:
+ case VIDIOC_QBUF:
+ case VIDIOC_DQBUF:
+ case VIDIOC_QUERYBUF:
+ case VIDIOC_QUERYCTRL:
+ case VIDIOC_QUERYMENU:
+ case VIDIOC_QUERYSTD:
+ case VIDIOC_REQBUFS:
+ case VIDIOC_S_HW_FREQ_SEEK:
+ // Unsupported |request| code.
+ NOTREACHED() << "Unsupported request code " << request;
+ return kErrorReturnValue;
+ }
+
+ // Invalid |request|.
+ NOTREACHED();
+ return kErrorReturnValue;
+}
+
+void* FakeV4L2Impl::mmap(void* start,
+ size_t length,
+ int prot,
+ int flags,
+ int fd,
+ off_t offset) {
+ NOTREACHED();
+ return nullptr;
+}
+
+int FakeV4L2Impl::munmap(void* start, size_t length) {
+ NOTREACHED();
+ return kErrorReturnValue;
+}
+
+int FakeV4L2Impl::poll(struct pollfd* ufds, unsigned int nfds, int timeout) {
+ NOTREACHED();
+ return kErrorReturnValue;
+}
+
+} // namespace media
diff --git a/chromium/media/capture/video/linux/fake_v4l2_impl.h b/chromium/media/capture/video/linux/fake_v4l2_impl.h
new file mode 100644
index 00000000000..1dd4b6c1c0c
--- /dev/null
+++ b/chromium/media/capture/video/linux/fake_v4l2_impl.h
@@ -0,0 +1,62 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAPTURE_VIDEO_LINUX_FAKE_V4L2_IMPL_H_
+#define MEDIA_CAPTURE_VIDEO_LINUX_FAKE_V4L2_IMPL_H_
+
+#include <map>
+#include <string>
+
+#include "media/capture/capture_export.h"
+#include "media/capture/video/linux/v4l2_capture_device.h"
+#include "media/capture/video/video_capture_device_descriptor.h"
+
+namespace media {
+
+struct FakeV4L2DeviceConfig {
+ FakeV4L2DeviceConfig(const VideoCaptureDeviceDescriptor& descriptor)
+ : descriptor(descriptor) {}
+
+ const VideoCaptureDeviceDescriptor descriptor;
+};
+
+// Implementation of V4L2CaptureDevice interface that allows configuring fake
+// devices useful for testing.
+class CAPTURE_EXPORT FakeV4L2Impl : public V4L2CaptureDevice {
+ public:
+ FakeV4L2Impl();
+
+ void AddDevice(const std::string& device_name,
+ const FakeV4L2DeviceConfig& config);
+
+ // Implementation of V4L2CaptureDevice interface:
+ int open(const char* device_name, int flags) override;
+ int close(int fd) override;
+ int ioctl(int fd, int request, void* argp) override;
+ void* mmap(void* start,
+ size_t length,
+ int prot,
+ int flags,
+ int fd,
+ off_t offset) override;
+
+ int munmap(void* start, size_t length) override;
+ int poll(struct pollfd* ufds, unsigned int nfds, int timeout) override;
+
+ protected:
+ ~FakeV4L2Impl() override;
+
+ private:
+ class OpenedDevice;
+
+ int next_id_to_return_from_open_;
+ std::map<std::string, FakeV4L2DeviceConfig> device_configs_;
+ std::map<std::string, int> device_name_to_open_id_map_;
+ std::map<int /*value returned by open()*/, std::unique_ptr<OpenedDevice>>
+ opened_devices_;
+};
+
+} // namespace media
+
+#endif // MEDIA_CAPTURE_VIDEO_LINUX_FAKE_V4L2_IMPL_H_
diff --git a/chromium/media/capture/video/linux/v4l2_capture_delegate.cc b/chromium/media/capture/video/linux/v4l2_capture_delegate.cc
index ce969d7e40a..c152e8c2822 100644
--- a/chromium/media/capture/video/linux/v4l2_capture_delegate.cc
+++ b/chromium/media/capture/video/linux/v4l2_capture_delegate.cc
@@ -55,8 +55,9 @@ const int kMjpegHeight = 480;
// Typical framerate, in fps
const int kTypicalFramerate = 30;
-// V4L2 color formats supported by V4L2CaptureDelegate derived classes.
-// This list is ordered by precedence of use -- but see caveats for MJPEG.
+// V4L2CaptureDevice color formats supported by V4L2CaptureDelegate derived
+// classes. This list is ordered by precedence of use -- but see caveats for
+// MJPEG.
static struct {
uint32_t fourcc;
VideoPixelFormat pixel_format;
@@ -124,44 +125,6 @@ static std::string FourccToString(uint32_t fourcc) {
(fourcc >> 16) & 0xFF, (fourcc >> 24) & 0xFF);
}
-// Running ioctl() on some devices, especially shortly after (re)opening the
-// device file descriptor or (re)starting streaming, can fail but works after
-// retrying (https://crbug.com/670262).
-// Returns false if the |request| ioctl fails too many times.
-static bool RunIoctl(int fd, int request, void* argp) {
- int num_retries = 0;
- for (; HANDLE_EINTR(ioctl(fd, request, argp)) < 0 &&
- num_retries < kMaxIOCtrlRetries;
- ++num_retries) {
- DPLOG(WARNING) << "ioctl";
- }
- DPLOG_IF(ERROR, num_retries != kMaxIOCtrlRetries);
- return num_retries != kMaxIOCtrlRetries;
-}
-
-// Creates a mojom::RangePtr with the (min, max, current, step) values of the
-// control associated with |control_id|. Returns an empty Range otherwise.
-static mojom::RangePtr RetrieveUserControlRange(int device_fd, int control_id) {
- mojom::RangePtr capability = mojom::Range::New();
-
- v4l2_queryctrl range = {};
- range.id = control_id;
- range.type = V4L2_CTRL_TYPE_INTEGER;
- if (!RunIoctl(device_fd, VIDIOC_QUERYCTRL, &range))
- return mojom::Range::New();
- capability->max = range.maximum;
- capability->min = range.minimum;
- capability->step = range.step;
-
- v4l2_control current = {};
- current.id = control_id;
- if (!RunIoctl(device_fd, VIDIOC_G_CTRL, &current))
- return mojom::Range::New();
- capability->current = current.value;
-
- return capability;
-}
-
// Determines if |control_id| is special, i.e. controls another one's state.
static bool IsSpecialControl(int control_id) {
switch (control_id) {
@@ -203,114 +166,12 @@ static bool IsBlacklistedControl(int control_id) {
return false;
}
-// Sets all user control to their default. Some controls are enabled by another
-// flag, usually having the word "auto" in the name, see IsSpecialControl().
-// These flags are preset beforehand, then set to their defaults individually
-// afterwards.
-static void ResetUserAndCameraControlsToDefault(int device_fd) {
- // Set V4L2_CID_AUTO_WHITE_BALANCE to false first.
- v4l2_control auto_white_balance = {};
- auto_white_balance.id = V4L2_CID_AUTO_WHITE_BALANCE;
- auto_white_balance.value = false;
- if (!RunIoctl(device_fd, VIDIOC_S_CTRL, &auto_white_balance))
- return;
-
- std::vector<struct v4l2_ext_control> special_camera_controls;
- // Set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_MANUAL.
- v4l2_ext_control auto_exposure = {};
- auto_exposure.id = V4L2_CID_EXPOSURE_AUTO;
- auto_exposure.value = V4L2_EXPOSURE_MANUAL;
- special_camera_controls.push_back(auto_exposure);
- // Set V4L2_CID_EXPOSURE_AUTO_PRIORITY to false.
- v4l2_ext_control priority_auto_exposure = {};
- priority_auto_exposure.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY;
- priority_auto_exposure.value = false;
- special_camera_controls.push_back(priority_auto_exposure);
- // Set V4L2_CID_FOCUS_AUTO to false.
- v4l2_ext_control auto_focus = {};
- auto_focus.id = V4L2_CID_FOCUS_AUTO;
- auto_focus.value = false;
- special_camera_controls.push_back(auto_focus);
-
- struct v4l2_ext_controls ext_controls = {};
- ext_controls.ctrl_class = V4L2_CID_CAMERA_CLASS;
- ext_controls.count = special_camera_controls.size();
- ext_controls.controls = special_camera_controls.data();
- if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) < 0)
- DPLOG(ERROR) << "VIDIOC_S_EXT_CTRLS";
-
- std::vector<struct v4l2_ext_control> camera_controls;
- for (const auto& control : kControls) {
- std::vector<struct v4l2_ext_control> camera_controls;
-
- v4l2_queryctrl range = {};
- range.id = control.control_base | V4L2_CTRL_FLAG_NEXT_CTRL;
- while (0 == HANDLE_EINTR(ioctl(device_fd, VIDIOC_QUERYCTRL, &range))) {
- if (V4L2_CTRL_ID2CLASS(range.id) != V4L2_CTRL_ID2CLASS(control.class_id))
- break;
- range.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
-
- if (IsSpecialControl(range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL))
- continue;
- if (IsBlacklistedControl(range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL))
- continue;
-
- struct v4l2_ext_control ext_control = {};
- ext_control.id = range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
- ext_control.value = range.default_value;
- camera_controls.push_back(ext_control);
- }
-
- if (!camera_controls.empty()) {
- struct v4l2_ext_controls ext_controls = {};
- ext_controls.ctrl_class = control.class_id;
- ext_controls.count = camera_controls.size();
- ext_controls.controls = camera_controls.data();
- if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) < 0)
- DPLOG(ERROR) << "VIDIOC_S_EXT_CTRLS";
- }
- }
-
- // Now set the special flags to the default values
- v4l2_queryctrl range = {};
- range.id = V4L2_CID_AUTO_WHITE_BALANCE;
- HANDLE_EINTR(ioctl(device_fd, VIDIOC_QUERYCTRL, &range));
- auto_white_balance.value = range.default_value;
- HANDLE_EINTR(ioctl(device_fd, VIDIOC_S_CTRL, &auto_white_balance));
-
- special_camera_controls.clear();
- memset(&range, 0, sizeof(struct v4l2_queryctrl));
- range.id = V4L2_CID_EXPOSURE_AUTO;
- HANDLE_EINTR(ioctl(device_fd, VIDIOC_QUERYCTRL, &range));
- auto_exposure.value = range.default_value;
- special_camera_controls.push_back(auto_exposure);
-
- memset(&range, 0, sizeof(struct v4l2_queryctrl));
- range.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY;
- HANDLE_EINTR(ioctl(device_fd, VIDIOC_QUERYCTRL, &range));
- priority_auto_exposure.value = range.default_value;
- special_camera_controls.push_back(priority_auto_exposure);
-
- memset(&range, 0, sizeof(struct v4l2_queryctrl));
- range.id = V4L2_CID_FOCUS_AUTO;
- HANDLE_EINTR(ioctl(device_fd, VIDIOC_QUERYCTRL, &range));
- auto_focus.value = range.default_value;
- special_camera_controls.push_back(auto_focus);
-
- memset(&ext_controls, 0, sizeof(struct v4l2_ext_controls));
- ext_controls.ctrl_class = V4L2_CID_CAMERA_CLASS;
- ext_controls.count = special_camera_controls.size();
- ext_controls.controls = special_camera_controls.data();
- if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) < 0)
- DPLOG(ERROR) << "VIDIOC_S_EXT_CTRLS";
-}
-
-// Class keeping track of a SPLANE V4L2 buffer, mmap()ed on construction and
-// munmap()ed on destruction.
+// Class keeping track of a SPLANE V4L2CaptureDevice buffer, mmap()ed on
+// construction and munmap()ed on destruction.
class V4L2CaptureDelegate::BufferTracker
: public base::RefCounted<BufferTracker> {
public:
- BufferTracker();
+ BufferTracker(V4L2CaptureDevice* v4l2);
// Abstract method to mmap() given |fd| according to |buffer|.
bool Init(int fd, const v4l2_buffer& buffer);
@@ -325,6 +186,7 @@ class V4L2CaptureDelegate::BufferTracker
friend class base::RefCounted<BufferTracker>;
virtual ~BufferTracker();
+ V4L2CaptureDevice* const v4l2_;
uint8_t* start_;
size_t length_;
size_t payload_size_;
@@ -368,13 +230,39 @@ std::list<uint32_t> V4L2CaptureDelegate::GetListOfUsableFourCcs(
return supported_formats;
}
+V4L2CaptureDelegate::ScopedV4L2DeviceFD::ScopedV4L2DeviceFD(
+ V4L2CaptureDevice* v4l2)
+ : device_fd_(kInvalidId), v4l2_(v4l2) {}
+
+V4L2CaptureDelegate::ScopedV4L2DeviceFD::~ScopedV4L2DeviceFD() {
+ if (is_valid())
+ reset();
+}
+
+int V4L2CaptureDelegate::ScopedV4L2DeviceFD::get() {
+ return device_fd_;
+}
+
+void V4L2CaptureDelegate::ScopedV4L2DeviceFD::reset(int fd /*= kInvalidId*/) {
+ if (is_valid())
+ v4l2_->close(device_fd_);
+ device_fd_ = fd;
+}
+
+bool V4L2CaptureDelegate::ScopedV4L2DeviceFD::is_valid() {
+ return device_fd_ != kInvalidId;
+}
+
V4L2CaptureDelegate::V4L2CaptureDelegate(
+ V4L2CaptureDevice* v4l2,
const VideoCaptureDeviceDescriptor& device_descriptor,
const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner,
int power_line_frequency)
- : v4l2_task_runner_(v4l2_task_runner),
+ : v4l2_(v4l2),
+ v4l2_task_runner_(v4l2_task_runner),
device_descriptor_(device_descriptor),
power_line_frequency_(power_line_frequency),
+ device_fd_(v4l2),
is_capturing_(false),
timeout_count_(0),
rotation_(0),
@@ -391,20 +279,23 @@ void V4L2CaptureDelegate::AllocateAndStart(
// Need to open camera with O_RDWR after Linux kernel 3.3.
device_fd_.reset(
- HANDLE_EINTR(open(device_descriptor_.device_id.c_str(), O_RDWR)));
+ HANDLE_EINTR(v4l2_->open(device_descriptor_.device_id.c_str(), O_RDWR)));
if (!device_fd_.is_valid()) {
- SetErrorState(FROM_HERE, "Failed to open V4L2 device driver file.");
+ SetErrorState(FROM_HERE,
+ "Failed to open V4L2CaptureDevice device driver file.");
return;
}
ResetUserAndCameraControlsToDefault(device_fd_.get());
v4l2_capability cap = {};
- if (!((HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYCAP, &cap)) == 0) &&
+ if (!((HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_QUERYCAP, &cap)) ==
+ 0) &&
((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)))) {
device_fd_.reset();
- SetErrorState(FROM_HERE, "This is not a V4L2 video capture device");
+ SetErrorState(FROM_HERE,
+ "This is not a V4L2CaptureDevice video capture device");
return;
}
@@ -416,7 +307,8 @@ void V4L2CaptureDelegate::AllocateAndStart(
v4l2_fmtdesc fmtdesc = {};
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- for (; HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_ENUM_FMT, &fmtdesc)) == 0;
+ for (; HANDLE_EINTR(
+ v4l2_->ioctl(device_fd_.get(), VIDIOC_ENUM_FMT, &fmtdesc)) == 0;
++fmtdesc.index) {
best = std::find(desired_v4l2_formats.begin(), best, fmtdesc.pixelformat);
}
@@ -428,7 +320,8 @@ void V4L2CaptureDelegate::AllocateAndStart(
DVLOG(1) << "Chosen pixel format is " << FourccToString(*best);
FillV4L2Format(&video_fmt_, width, height, *best);
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_FMT, &video_fmt_)) < 0) {
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_FMT, &video_fmt_)) <
+ 0) {
SetErrorState(FROM_HERE, "Failed to set video capture format");
return;
}
@@ -443,7 +336,8 @@ void V4L2CaptureDelegate::AllocateAndStart(
v4l2_streamparm streamparm = {};
streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
// The following line checks that the driver knows about framerate get/set.
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_PARM, &streamparm)) >= 0) {
+ if (HANDLE_EINTR(
+ v4l2_->ioctl(device_fd_.get(), VIDIOC_G_PARM, &streamparm)) >= 0) {
// Now check if the device is able to accept a capture framerate set.
if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
// |frame_rate| is float, approximate by a fraction.
@@ -452,8 +346,8 @@ void V4L2CaptureDelegate::AllocateAndStart(
(frame_rate) ? (frame_rate * kFrameRatePrecision)
: (kTypicalFramerate * kFrameRatePrecision);
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_PARM, &streamparm)) <
- 0) {
+ if (HANDLE_EINTR(
+ v4l2_->ioctl(device_fd_.get(), VIDIOC_S_PARM, &streamparm)) < 0) {
SetErrorState(FROM_HERE, "Failed to set camera framerate");
return;
}
@@ -474,7 +368,7 @@ void V4L2CaptureDelegate::AllocateAndStart(
control.id = V4L2_CID_POWER_LINE_FREQUENCY;
control.value = power_line_frequency_;
const int retval =
- HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &control));
+ HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &control));
if (retval != 0)
DVLOG(1) << "Error setting power line frequency removal";
}
@@ -486,8 +380,10 @@ void V4L2CaptureDelegate::AllocateAndStart(
v4l2_requestbuffers r_buffer;
FillV4L2RequestBuffer(&r_buffer, kNumVideoBuffers);
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) {
- SetErrorState(FROM_HERE, "Error requesting MMAP buffers from V4L2");
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) <
+ 0) {
+ SetErrorState(FROM_HERE,
+ "Error requesting MMAP buffers from V4L2CaptureDevice");
return;
}
for (unsigned int i = 0; i < r_buffer.count; ++i) {
@@ -498,8 +394,8 @@ void V4L2CaptureDelegate::AllocateAndStart(
}
v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMON, &capture_type)) <
- 0) {
+ if (HANDLE_EINTR(
+ v4l2_->ioctl(device_fd_.get(), VIDIOC_STREAMON, &capture_type)) < 0) {
SetErrorState(FROM_HERE, "VIDIOC_STREAMON failed");
return;
}
@@ -517,8 +413,8 @@ void V4L2CaptureDelegate::StopAndDeAllocate() {
// The order is important: stop streaming, clear |buffer_pool_|,
// thus munmap()ing the v4l2_buffers, and then return them to the OS.
v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &capture_type)) <
- 0) {
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_STREAMOFF,
+ &capture_type)) < 0) {
SetErrorState(FROM_HERE, "VIDIOC_STREAMOFF failed");
return;
}
@@ -527,7 +423,8 @@ void V4L2CaptureDelegate::StopAndDeAllocate() {
v4l2_requestbuffers r_buffer;
FillV4L2RequestBuffer(&r_buffer, 0);
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0)
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) <
+ 0)
SetErrorState(FROM_HERE, "Failed to VIDIOC_REQBUFS with count = 0");
// At this point we can close the device.
@@ -569,8 +466,8 @@ void V4L2CaptureDelegate::GetPhotoState(
photo_capabilities->current_focus_mode = MeteringMode::NONE;
v4l2_control auto_focus_current = {};
auto_focus_current.id = V4L2_CID_FOCUS_AUTO;
- if (HANDLE_EINTR(
- ioctl(device_fd_.get(), VIDIOC_G_CTRL, &auto_focus_current)) >= 0) {
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_G_CTRL,
+ &auto_focus_current)) >= 0) {
photo_capabilities->current_focus_mode = auto_focus_current.value
? MeteringMode::CONTINUOUS
: MeteringMode::MANUAL;
@@ -588,8 +485,8 @@ void V4L2CaptureDelegate::GetPhotoState(
photo_capabilities->current_exposure_mode = MeteringMode::NONE;
v4l2_control exposure_current = {};
exposure_current.id = V4L2_CID_EXPOSURE_AUTO;
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_CTRL, &exposure_current)) >=
- 0) {
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_G_CTRL,
+ &exposure_current)) >= 0) {
photo_capabilities->current_exposure_mode =
exposure_current.value == V4L2_EXPOSURE_MANUAL
? MeteringMode::MANUAL
@@ -616,8 +513,8 @@ void V4L2CaptureDelegate::GetPhotoState(
photo_capabilities->current_white_balance_mode = MeteringMode::NONE;
v4l2_control white_balance_current = {};
white_balance_current.id = V4L2_CID_AUTO_WHITE_BALANCE;
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_CTRL,
- &white_balance_current)) >= 0) {
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_G_CTRL,
+ &white_balance_current)) >= 0) {
photo_capabilities->current_white_balance_mode =
white_balance_current.value ? MeteringMode::CONTINUOUS
: MeteringMode::MANUAL;
@@ -656,7 +553,8 @@ void V4L2CaptureDelegate::SetPhotoOptions(
v4l2_control zoom_current = {};
zoom_current.id = V4L2_CID_ZOOM_ABSOLUTE;
zoom_current.value = settings->zoom;
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &zoom_current)) < 0)
+ if (HANDLE_EINTR(
+ v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &zoom_current)) < 0)
DPLOG(ERROR) << "setting zoom to " << settings->zoom;
}
@@ -667,20 +565,22 @@ void V4L2CaptureDelegate::SetPhotoOptions(
white_balance_set.id = V4L2_CID_AUTO_WHITE_BALANCE;
white_balance_set.value =
settings->white_balance_mode == mojom::MeteringMode::CONTINUOUS;
- HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &white_balance_set));
+ HANDLE_EINTR(
+ v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &white_balance_set));
}
if (settings->has_color_temperature) {
v4l2_control auto_white_balance_current = {};
auto_white_balance_current.id = V4L2_CID_AUTO_WHITE_BALANCE;
- const int result = HANDLE_EINTR(
- ioctl(device_fd_.get(), VIDIOC_G_CTRL, &auto_white_balance_current));
+ const int result = HANDLE_EINTR(v4l2_->ioctl(
+ device_fd_.get(), VIDIOC_G_CTRL, &auto_white_balance_current));
// Color temperature can only be applied if Auto White Balance is off.
if (result >= 0 && !auto_white_balance_current.value) {
v4l2_control set_temperature = {};
set_temperature.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
set_temperature.value = settings->color_temperature;
- HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &set_temperature));
+ HANDLE_EINTR(
+ v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &set_temperature));
}
}
@@ -693,20 +593,22 @@ void V4L2CaptureDelegate::SetPhotoOptions(
settings->exposure_mode == mojom::MeteringMode::CONTINUOUS
? V4L2_EXPOSURE_APERTURE_PRIORITY
: V4L2_EXPOSURE_MANUAL;
- HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &exposure_mode_set));
+ HANDLE_EINTR(
+ v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &exposure_mode_set));
}
if (settings->has_exposure_compensation) {
v4l2_control auto_exposure_current = {};
auto_exposure_current.id = V4L2_CID_EXPOSURE_AUTO;
const int result = HANDLE_EINTR(
- ioctl(device_fd_.get(), VIDIOC_G_CTRL, &auto_exposure_current));
+ v4l2_->ioctl(device_fd_.get(), VIDIOC_G_CTRL, &auto_exposure_current));
// Exposure Compensation can only be applied if Auto Exposure is off.
if (result >= 0 && auto_exposure_current.value == V4L2_EXPOSURE_MANUAL) {
v4l2_control set_exposure = {};
set_exposure.id = V4L2_CID_EXPOSURE_ABSOLUTE;
set_exposure.value = settings->exposure_compensation;
- HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &set_exposure));
+ HANDLE_EINTR(
+ v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &set_exposure));
}
}
@@ -714,28 +616,32 @@ void V4L2CaptureDelegate::SetPhotoOptions(
v4l2_control current = {};
current.id = V4L2_CID_BRIGHTNESS;
current.value = settings->brightness;
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) < 0)
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) <
+ 0)
DPLOG(ERROR) << "setting brightness to " << settings->brightness;
}
if (settings->has_contrast) {
v4l2_control current = {};
current.id = V4L2_CID_CONTRAST;
current.value = settings->contrast;
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) < 0)
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) <
+ 0)
DPLOG(ERROR) << "setting contrast to " << settings->contrast;
}
if (settings->has_saturation) {
v4l2_control current = {};
current.id = V4L2_CID_SATURATION;
current.value = settings->saturation;
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) < 0)
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) <
+ 0)
DPLOG(ERROR) << "setting saturation to " << settings->saturation;
}
if (settings->has_sharpness) {
v4l2_control current = {};
current.id = V4L2_CID_SHARPNESS;
current.value = settings->sharpness;
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) < 0)
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_CTRL, &current)) <
+ 0)
DPLOG(ERROR) << "setting sharpness to " << settings->sharpness;
}
@@ -754,16 +660,162 @@ base::WeakPtr<V4L2CaptureDelegate> V4L2CaptureDelegate::GetWeakPtr() {
V4L2CaptureDelegate::~V4L2CaptureDelegate() = default;
+// Running v4l2_->ioctl() on some devices, especially shortly after (re)opening
+// the device file descriptor or (re)starting streaming, can fail but works
+// after retrying (https://crbug.com/670262). Returns false if the |request|
+// ioctl fails too many times.
+bool V4L2CaptureDelegate::RunIoctl(int fd, int request, void* argp) {
+ int num_retries = 0;
+ for (; HANDLE_EINTR(v4l2_->ioctl(fd, request, argp)) < 0 &&
+ num_retries < kMaxIOCtrlRetries;
+ ++num_retries) {
+ DPLOG(WARNING) << "ioctl";
+ }
+ DPLOG_IF(ERROR, num_retries != kMaxIOCtrlRetries);
+ return num_retries != kMaxIOCtrlRetries;
+}
+
+// Creates a mojom::RangePtr with the (min, max, current, step) values of the
+// control associated with |control_id|. Returns an empty Range otherwise.
+mojom::RangePtr V4L2CaptureDelegate::RetrieveUserControlRange(int device_fd,
+ int control_id) {
+ mojom::RangePtr capability = mojom::Range::New();
+
+ v4l2_queryctrl range = {};
+ range.id = control_id;
+ range.type = V4L2_CTRL_TYPE_INTEGER;
+ if (!RunIoctl(device_fd, VIDIOC_QUERYCTRL, &range))
+ return mojom::Range::New();
+ capability->max = range.maximum;
+ capability->min = range.minimum;
+ capability->step = range.step;
+
+ v4l2_control current = {};
+ current.id = control_id;
+ if (!RunIoctl(device_fd, VIDIOC_G_CTRL, &current))
+ return mojom::Range::New();
+ capability->current = current.value;
+
+ return capability;
+}
+
+// Sets all user control to their default. Some controls are enabled by another
+// flag, usually having the word "auto" in the name, see IsSpecialControl().
+// These flags are preset beforehand, then set to their defaults individually
+// afterwards.
+void V4L2CaptureDelegate::ResetUserAndCameraControlsToDefault(int device_fd) {
+ // Set V4L2_CID_AUTO_WHITE_BALANCE to false first.
+ v4l2_control auto_white_balance = {};
+ auto_white_balance.id = V4L2_CID_AUTO_WHITE_BALANCE;
+ auto_white_balance.value = false;
+ if (!RunIoctl(device_fd, VIDIOC_S_CTRL, &auto_white_balance))
+ return;
+
+ std::vector<struct v4l2_ext_control> special_camera_controls;
+ // Set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_MANUAL.
+ v4l2_ext_control auto_exposure = {};
+ auto_exposure.id = V4L2_CID_EXPOSURE_AUTO;
+ auto_exposure.value = V4L2_EXPOSURE_MANUAL;
+ special_camera_controls.push_back(auto_exposure);
+ // Set V4L2_CID_EXPOSURE_AUTO_PRIORITY to false.
+ v4l2_ext_control priority_auto_exposure = {};
+ priority_auto_exposure.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY;
+ priority_auto_exposure.value = false;
+ special_camera_controls.push_back(priority_auto_exposure);
+ // Set V4L2_CID_FOCUS_AUTO to false.
+ v4l2_ext_control auto_focus = {};
+ auto_focus.id = V4L2_CID_FOCUS_AUTO;
+ auto_focus.value = false;
+ special_camera_controls.push_back(auto_focus);
+
+ struct v4l2_ext_controls ext_controls = {};
+ ext_controls.ctrl_class = V4L2_CID_CAMERA_CLASS;
+ ext_controls.count = special_camera_controls.size();
+ ext_controls.controls = special_camera_controls.data();
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) <
+ 0)
+ DPLOG(ERROR) << "VIDIOC_S_EXT_CTRLS";
+
+ std::vector<struct v4l2_ext_control> camera_controls;
+ for (const auto& control : kControls) {
+ std::vector<struct v4l2_ext_control> camera_controls;
+
+ v4l2_queryctrl range = {};
+ range.id = control.control_base | V4L2_CTRL_FLAG_NEXT_CTRL;
+ while (0 ==
+ HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_QUERYCTRL, &range))) {
+ if (V4L2_CTRL_ID2CLASS(range.id) != V4L2_CTRL_ID2CLASS(control.class_id))
+ break;
+ range.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+
+ if (IsSpecialControl(range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL))
+ continue;
+ if (IsBlacklistedControl(range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL))
+ continue;
+
+ struct v4l2_ext_control ext_control = {};
+ ext_control.id = range.id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
+ ext_control.value = range.default_value;
+ camera_controls.push_back(ext_control);
+ }
+
+ if (!camera_controls.empty()) {
+ struct v4l2_ext_controls ext_controls = {};
+ ext_controls.ctrl_class = control.class_id;
+ ext_controls.count = camera_controls.size();
+ ext_controls.controls = camera_controls.data();
+ if (HANDLE_EINTR(
+ v4l2_->ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) < 0)
+ DPLOG(ERROR) << "VIDIOC_S_EXT_CTRLS";
+ }
+ }
+
+ // Now set the special flags to the default values
+ v4l2_queryctrl range = {};
+ range.id = V4L2_CID_AUTO_WHITE_BALANCE;
+ HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_QUERYCTRL, &range));
+ auto_white_balance.value = range.default_value;
+ HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_S_CTRL, &auto_white_balance));
+
+ special_camera_controls.clear();
+ memset(&range, 0, sizeof(struct v4l2_queryctrl));
+ range.id = V4L2_CID_EXPOSURE_AUTO;
+ HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_QUERYCTRL, &range));
+ auto_exposure.value = range.default_value;
+ special_camera_controls.push_back(auto_exposure);
+
+ memset(&range, 0, sizeof(struct v4l2_queryctrl));
+ range.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY;
+ HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_QUERYCTRL, &range));
+ priority_auto_exposure.value = range.default_value;
+ special_camera_controls.push_back(priority_auto_exposure);
+
+ memset(&range, 0, sizeof(struct v4l2_queryctrl));
+ range.id = V4L2_CID_FOCUS_AUTO;
+ HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_QUERYCTRL, &range));
+ auto_focus.value = range.default_value;
+ special_camera_controls.push_back(auto_focus);
+
+ memset(&ext_controls, 0, sizeof(struct v4l2_ext_controls));
+ ext_controls.ctrl_class = V4L2_CID_CAMERA_CLASS;
+ ext_controls.count = special_camera_controls.size();
+ ext_controls.controls = special_camera_controls.data();
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd, VIDIOC_S_EXT_CTRLS, &ext_controls)) <
+ 0)
+ DPLOG(ERROR) << "VIDIOC_S_EXT_CTRLS";
+}
+
bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
v4l2_buffer buffer;
FillV4L2Buffer(&buffer, index);
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYBUF, &buffer)) < 0) {
- DLOG(ERROR) << "Error querying status of a MMAP V4L2 buffer";
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_QUERYBUF, &buffer)) <
+ 0) {
+ DLOG(ERROR) << "Error querying status of a MMAP V4L2CaptureDevice buffer";
return false;
}
- const scoped_refptr<BufferTracker> buffer_tracker(new BufferTracker());
+ const scoped_refptr<BufferTracker> buffer_tracker(new BufferTracker(v4l2_));
if (!buffer_tracker->Init(device_fd_.get(), buffer)) {
DLOG(ERROR) << "Error creating BufferTracker";
return false;
@@ -771,8 +823,9 @@ bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
buffer_tracker_pool_.push_back(buffer_tracker);
// Enqueue the buffer in the drivers incoming queue.
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) {
- DLOG(ERROR) << "Error enqueuing a V4L2 buffer back into the driver";
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) {
+ DLOG(ERROR)
+ << "Error enqueuing a V4L2CaptureDevice buffer back into the driver";
return false;
}
return true;
@@ -786,7 +839,8 @@ void V4L2CaptureDelegate::DoCapture() {
pollfd device_pfd = {};
device_pfd.fd = device_fd_.get();
device_pfd.events = POLLIN;
- const int result = HANDLE_EINTR(poll(&device_pfd, 1, kCaptureTimeoutMs));
+ const int result =
+ HANDLE_EINTR(v4l2_->poll(&device_pfd, 1, kCaptureTimeoutMs));
if (result < 0) {
SetErrorState(FROM_HERE, "Poll failed");
return;
@@ -810,7 +864,8 @@ void V4L2CaptureDelegate::DoCapture() {
v4l2_buffer buffer;
FillV4L2Buffer(&buffer, 0);
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) < 0) {
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) <
+ 0) {
SetErrorState(FROM_HERE, "Failed to dequeue capture buffer");
return;
}
@@ -856,7 +911,8 @@ void V4L2CaptureDelegate::DoCapture() {
std::move(cb).Run(std::move(blob));
}
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) {
+ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) <
+ 0) {
SetErrorState(FROM_HERE, "Failed to enqueue capture buffer");
return;
}
@@ -873,23 +929,24 @@ void V4L2CaptureDelegate::SetErrorState(const base::Location& from_here,
client_->OnError(from_here, reason);
}
-V4L2CaptureDelegate::BufferTracker::BufferTracker() = default;
+V4L2CaptureDelegate::BufferTracker::BufferTracker(V4L2CaptureDevice* v4l2)
+ : v4l2_(v4l2) {}
V4L2CaptureDelegate::BufferTracker::~BufferTracker() {
if (start_ == nullptr)
return;
- const int result = munmap(start_, length_);
- PLOG_IF(ERROR, result < 0) << "Error munmap()ing V4L2 buffer";
+ const int result = v4l2_->munmap(start_, length_);
+ PLOG_IF(ERROR, result < 0) << "Error munmap()ing V4L2CaptureDevice buffer";
}
bool V4L2CaptureDelegate::BufferTracker::Init(int fd,
const v4l2_buffer& buffer) {
// Some devices require mmap() to be called with both READ and WRITE.
// See http://crbug.com/178582.
- void* const start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, buffer.m.offset);
+ void* const start = v4l2_->mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, buffer.m.offset);
if (start == MAP_FAILED) {
- DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace";
+ DLOG(ERROR) << "Error mmap()ing a V4L2CaptureDevice buffer into userspace";
return false;
}
start_ = static_cast<uint8_t*>(start);
diff --git a/chromium/media/capture/video/linux/v4l2_capture_delegate.h b/chromium/media/capture/video/linux/v4l2_capture_delegate.h
index 37f1964b088..5a246a3b7d0 100644
--- a/chromium/media/capture/video/linux/v4l2_capture_delegate.h
+++ b/chromium/media/capture/video/linux/v4l2_capture_delegate.h
@@ -12,6 +12,7 @@
#include "base/files/scoped_file.h"
#include "base/macros.h"
#include "build/build_config.h"
+#include "media/capture/video/linux/v4l2_capture_device_impl.h"
#include "media/capture/video/video_capture_device.h"
#if defined(OS_OPENBSD)
@@ -26,9 +27,10 @@ class Location;
namespace media {
-// Class doing the actual Linux capture using V4L2 API. V4L2 SPLANE/MPLANE
-// capture specifics are implemented in derived classes. Created on the owner's
-// thread, otherwise living, operating and destroyed on |v4l2_task_runner_|.
+// Class doing the actual Linux capture using V4L2CaptureDevice API.
+// V4L2CaptureDevice SPLANE/MPLANE capture specifics are implemented in derived
+// classes. Created on the owner's thread, otherwise living, operating and
+// destroyed on |v4l2_task_runner_|.
class CAPTURE_EXPORT V4L2CaptureDelegate final {
public:
// Retrieves the #planes for a given |fourcc|, or 0 if unknown.
@@ -42,6 +44,7 @@ class CAPTURE_EXPORT V4L2CaptureDelegate final {
static std::list<uint32_t> GetListOfUsableFourCcs(bool prefer_mjpeg);
V4L2CaptureDelegate(
+ V4L2CaptureDevice* v4l2,
const VideoCaptureDeviceDescriptor& device_descriptor,
const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner,
int power_line_frequency);
@@ -68,9 +71,28 @@ class CAPTURE_EXPORT V4L2CaptureDelegate final {
friend class V4L2CaptureDelegateTest;
class BufferTracker;
-
- // VIDIOC_QUERYBUFs a buffer from V4L2, creates a BufferTracker for it and
- // enqueues it (VIDIOC_QBUF) back into V4L2.
+ class ScopedV4L2DeviceFD {
+ public:
+ static constexpr int kInvalidId = -1;
+ ScopedV4L2DeviceFD(V4L2CaptureDevice* v4l2);
+ ~ScopedV4L2DeviceFD();
+ int get();
+ void reset(int fd = kInvalidId);
+ bool is_valid();
+
+ private:
+ int device_fd_;
+ V4L2CaptureDevice* const v4l2_;
+ };
+
+ bool RunIoctl(int fd, int request, void* argp);
+ mojom::RangePtr RetrieveUserControlRange(int device_fd, int control_id);
+ void ResetUserAndCameraControlsToDefault(int device_fd);
+
+ // void CloseDevice();
+
+ // VIDIOC_QUERYBUFs a buffer from V4L2CaptureDevice, creates a BufferTracker
+ // for it and enqueues it (VIDIOC_QBUF) back into V4L2CaptureDevice.
bool MapAndQueueBuffer(int index);
void DoCapture();
@@ -78,6 +100,7 @@ class CAPTURE_EXPORT V4L2CaptureDelegate final {
void SetErrorState(const base::Location& from_here,
const std::string& reason);
+ V4L2CaptureDevice* const v4l2_;
const scoped_refptr<base::SingleThreadTaskRunner> v4l2_task_runner_;
const VideoCaptureDeviceDescriptor device_descriptor_;
const int power_line_frequency_;
@@ -86,7 +109,7 @@ class CAPTURE_EXPORT V4L2CaptureDelegate final {
VideoCaptureFormat capture_format_;
v4l2_format video_fmt_;
std::unique_ptr<VideoCaptureDevice::Client> client_;
- base::ScopedFD device_fd_;
+ ScopedV4L2DeviceFD device_fd_;
base::queue<VideoCaptureDevice::TakePhotoCallback> take_photo_callbacks_;
diff --git a/chromium/media/capture/video/linux/v4l2_capture_delegate_unittest.cc b/chromium/media/capture/video/linux/v4l2_capture_delegate_unittest.cc
index bbbd9b72b03..446aab373a7 100644
--- a/chromium/media/capture/video/linux/v4l2_capture_delegate_unittest.cc
+++ b/chromium/media/capture/video/linux/v4l2_capture_delegate_unittest.cc
@@ -221,7 +221,9 @@ class V4L2CaptureDelegateTest : public ::testing::Test {
public:
V4L2CaptureDelegateTest()
: device_descriptor_("Device 0", "/dev/video0"),
+ v4l2_(new V4L2CaptureDeviceImpl()),
delegate_(std::make_unique<V4L2CaptureDelegate>(
+ v4l2_.get(),
device_descriptor_,
base::ThreadTaskRunnerHandle::Get(),
50)) {}
@@ -229,6 +231,7 @@ class V4L2CaptureDelegateTest : public ::testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_;
VideoCaptureDeviceDescriptor device_descriptor_;
+ scoped_refptr<V4L2CaptureDevice> v4l2_;
std::unique_ptr<V4L2CaptureDelegate> delegate_;
};
diff --git a/chromium/media/capture/video/linux/v4l2_capture_device.h b/chromium/media/capture/video/linux/v4l2_capture_device.h
new file mode 100644
index 00000000000..2c95357c9a2
--- /dev/null
+++ b/chromium/media/capture/video/linux/v4l2_capture_device.h
@@ -0,0 +1,44 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAPTURE_VIDEO_LINUX_V4L2_CAPTURE_DEVICE_H_
+#define MEDIA_CAPTURE_VIDEO_LINUX_V4L2_CAPTURE_DEVICE_H_
+
+#include <poll.h>
+#include <sys/fcntl.h>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "media/capture/capture_export.h"
+
+namespace media {
+
+// Interface for abstracting out the V4L2 API. This allows using a mock or fake
+// implementation in testing.
+class CAPTURE_EXPORT V4L2CaptureDevice
+ : public base::RefCounted<V4L2CaptureDevice> {
+ public:
+ virtual int open(const char* device_name, int flags) = 0;
+ virtual int close(int fd) = 0;
+ virtual int ioctl(int fd, int request, void* argp) = 0;
+ virtual void* mmap(void* start,
+ size_t length,
+ int prot,
+ int flags,
+ int fd,
+ off_t offset) = 0;
+
+ virtual int munmap(void* start, size_t length) = 0;
+ virtual int poll(struct pollfd* ufds, unsigned int nfds, int timeout) = 0;
+
+ protected:
+ virtual ~V4L2CaptureDevice() {}
+
+ private:
+ friend class base::RefCounted<V4L2CaptureDevice>;
+};
+
+} // namespace media
+
+#endif // MEDIA_CAPTURE_VIDEO_LINUX_V4L2_CAPTURE_DEVICE_H_
diff --git a/chromium/media/capture/video/linux/v4l2_capture_device_impl.cc b/chromium/media/capture/video/linux/v4l2_capture_device_impl.cc
new file mode 100644
index 00000000000..c9040f5dee6
--- /dev/null
+++ b/chromium/media/capture/video/linux/v4l2_capture_device_impl.cc
@@ -0,0 +1,48 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/capture/video/linux/v4l2_capture_device_impl.h"
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <unistd.h>
+
+namespace media {
+
+V4L2CaptureDeviceImpl::~V4L2CaptureDeviceImpl() = default;
+
+int V4L2CaptureDeviceImpl::open(const char* device_name, int flags) {
+ return ::open(device_name, flags);
+}
+
+int V4L2CaptureDeviceImpl::close(int fd) {
+ return ::close(fd);
+}
+
+int V4L2CaptureDeviceImpl::ioctl(int fd, int request, void* argp) {
+ return ::ioctl(fd, request, argp);
+}
+
+void* V4L2CaptureDeviceImpl::mmap(void* start,
+ size_t length,
+ int prot,
+ int flags,
+ int fd,
+ off_t offset) {
+ return ::mmap(start, length, prot, flags, fd, offset);
+}
+
+int V4L2CaptureDeviceImpl::munmap(void* start, size_t length) {
+ return ::munmap(start, length);
+}
+
+int V4L2CaptureDeviceImpl::poll(struct pollfd* ufds,
+ unsigned int nfds,
+ int timeout) {
+ return ::poll(ufds, nfds, timeout);
+}
+
+} // namespace media
diff --git a/chromium/media/capture/video/linux/v4l2_capture_device_impl.h b/chromium/media/capture/video/linux/v4l2_capture_device_impl.h
new file mode 100644
index 00000000000..936c8b0938b
--- /dev/null
+++ b/chromium/media/capture/video/linux/v4l2_capture_device_impl.h
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAPTURE_VIDEO_LINUX_V4L2_CAPTURE_DEVICE_IMPL_H_
+#define MEDIA_CAPTURE_VIDEO_LINUX_V4L2_CAPTURE_DEVICE_IMPL_H_
+
+#include <poll.h>
+#include <sys/fcntl.h>
+
+#include "media/capture/capture_export.h"
+#include "media/capture/video/linux/v4l2_capture_device.h"
+
+namespace media {
+
+// Implementation of V4L2CaptureDevice interface that delegates to the actual
+// V4L2 APIs.
+class CAPTURE_EXPORT V4L2CaptureDeviceImpl : public V4L2CaptureDevice {
+ public:
+ int open(const char* device_name, int flags) override;
+ int close(int fd) override;
+ int ioctl(int fd, int request, void* argp) override;
+ void* mmap(void* start,
+ size_t length,
+ int prot,
+ int flags,
+ int fd,
+ off_t offset) override;
+
+ int munmap(void* start, size_t length) override;
+ int poll(struct pollfd* ufds, unsigned int nfds, int timeout) override;
+
+ private:
+ ~V4L2CaptureDeviceImpl() override;
+};
+
+} // namespace media
+
+#endif // MEDIA_CAPTURE_VIDEO_LINUX_V4L2_CAPTURE_DEVICE_IMPL_H_
diff --git a/chromium/media/capture/video/linux/video_capture_device_chromeos.cc b/chromium/media/capture/video/linux/video_capture_device_chromeos.cc
index 329939be1f9..8d4ba37da13 100644
--- a/chromium/media/capture/video/linux/video_capture_device_chromeos.cc
+++ b/chromium/media/capture/video/linux/video_capture_device_chromeos.cc
@@ -17,36 +17,25 @@
namespace media {
-static CameraConfigChromeOS* GetCameraConfig() {
- static CameraConfigChromeOS* config = new CameraConfigChromeOS();
- return config;
-}
-
VideoCaptureDeviceChromeOS::VideoCaptureDeviceChromeOS(
+ const ChromeOSDeviceCameraConfig& camera_config,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
+ scoped_refptr<V4L2CaptureDevice> v4l2,
const VideoCaptureDeviceDescriptor& device_descriptor)
- : VideoCaptureDeviceLinux(device_descriptor),
+ : VideoCaptureDeviceLinux(std::move(v4l2), device_descriptor),
+ camera_config_(camera_config),
screen_observer_delegate_(
- new ScreenObserverDelegate(this, ui_task_runner)),
- lens_facing_(
- GetCameraConfig()->GetCameraFacing(device_descriptor.device_id,
- device_descriptor.model_id)),
- camera_orientation_(
- GetCameraConfig()->GetOrientation(device_descriptor.device_id,
- device_descriptor.model_id)),
- // External cameras have lens_facing as MEDIA_VIDEO_FACING_NONE.
- // We don't want to rotate the frame even if the device rotates.
- rotates_with_device_(lens_facing_ !=
- VideoFacingMode::MEDIA_VIDEO_FACING_NONE) {}
+ new ScreenObserverDelegate(this, ui_task_runner)) {}
VideoCaptureDeviceChromeOS::~VideoCaptureDeviceChromeOS() {
screen_observer_delegate_->RemoveObserver();
}
void VideoCaptureDeviceChromeOS::SetRotation(int rotation) {
- if (!rotates_with_device_) {
+ if (!camera_config_.rotates_with_device) {
rotation = 0;
- } else if (lens_facing_ == VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT) {
+ } else if (camera_config_.lens_facing ==
+ VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT) {
// Original frame when |rotation| = 0
// -----------------------
// | * |
@@ -82,7 +71,7 @@ void VideoCaptureDeviceChromeOS::SetRotation(int rotation) {
}
// Take into account camera orientation w.r.t. the display. External cameras
// would have camera_orientation_ as 0.
- rotation = (rotation + camera_orientation_) % 360;
+ rotation = (rotation + camera_config_.camera_orientation) % 360;
VideoCaptureDeviceLinux::SetRotation(rotation);
}
diff --git a/chromium/media/capture/video/linux/video_capture_device_chromeos.h b/chromium/media/capture/video/linux/video_capture_device_chromeos.h
index d9e738ed2f2..ffb6a377bc7 100644
--- a/chromium/media/capture/video/linux/video_capture_device_chromeos.h
+++ b/chromium/media/capture/video/linux/video_capture_device_chromeos.h
@@ -8,7 +8,6 @@
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "media/capture/video/chromeos/display_rotation_observer.h"
-#include "media/capture/video/linux/camera_config_chromeos.h"
#include "media/capture/video/linux/video_capture_device_linux.h"
namespace display {
@@ -17,14 +16,32 @@ class Display;
namespace media {
+struct ChromeOSDeviceCameraConfig {
+ ChromeOSDeviceCameraConfig(VideoFacingMode lens_facing,
+ int camera_orientation)
+ : lens_facing(lens_facing),
+ camera_orientation(camera_orientation),
+ // External cameras have lens_facing as MEDIA_VIDEO_FACING_NONE.
+ // We don't want to rotate the frame even if the device rotates.
+ rotates_with_device(lens_facing !=
+ VideoFacingMode::MEDIA_VIDEO_FACING_NONE) {}
+
+ const VideoFacingMode lens_facing;
+ const int camera_orientation;
+ // Whether the incoming frames should rotate when the device rotates.
+ const bool rotates_with_device;
+};
+
// This class is functionally the same as VideoCaptureDeviceLinux, with the
// exception that it is aware of the orientation of the internal Display. When
// the internal Display is rotated, the frames captured are rotated to match.
class VideoCaptureDeviceChromeOS : public VideoCaptureDeviceLinux,
public DisplayRotationObserver {
public:
- explicit VideoCaptureDeviceChromeOS(
+ VideoCaptureDeviceChromeOS(
+ const ChromeOSDeviceCameraConfig& camera_config,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
+ scoped_refptr<V4L2CaptureDevice> v4l2,
const VideoCaptureDeviceDescriptor& device_descriptor);
~VideoCaptureDeviceChromeOS() override;
@@ -34,11 +51,8 @@ class VideoCaptureDeviceChromeOS : public VideoCaptureDeviceLinux,
private:
// DisplayRotationObserver implementation.
void SetDisplayRotation(const display::Display& display) override;
+ const ChromeOSDeviceCameraConfig camera_config_;
scoped_refptr<ScreenObserverDelegate> screen_observer_delegate_;
- const VideoFacingMode lens_facing_;
- const int camera_orientation_;
- // Whether the incoming frames should rotate when the device rotates.
- const bool rotates_with_device_;
DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceChromeOS);
};
diff --git a/chromium/media/capture/video/linux/video_capture_device_factory_linux.cc b/chromium/media/capture/video/linux/video_capture_device_factory_linux.cc
index 3699cb953ec..99c9912010e 100644
--- a/chromium/media/capture/video/linux/video_capture_device_factory_linux.cc
+++ b/chromium/media/capture/video/linux/video_capture_device_factory_linux.cc
@@ -44,6 +44,13 @@ const char kPidPathTemplate[] = "/sys/class/video4linux/%s/device/../idProduct";
const char kInterfacePathTemplate[] =
"/sys/class/video4linux/%s/device/interface";
+#if defined(OS_CHROMEOS)
+static CameraConfigChromeOS* GetCameraConfig() {
+ static CameraConfigChromeOS* config = new CameraConfigChromeOS();
+ return config;
+}
+#endif
+
bool ReadIdFile(const std::string& path, std::string* id) {
char id_buf[kVidPidSize];
FILE* file = fopen(path.c_str(), "rb");
@@ -57,155 +64,110 @@ bool ReadIdFile(const std::string& path, std::string* id) {
return true;
}
-bool HasUsableFormats(int fd, uint32_t capabilities) {
- if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
- return false;
-
- const std::list<uint32_t>& usable_fourccs =
- VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false);
- v4l2_fmtdesc fmtdesc = {};
- fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0;
- ++fmtdesc.index) {
- if (std::find(usable_fourccs.begin(), usable_fourccs.end(),
- fmtdesc.pixelformat) != usable_fourccs.end()) {
- return true;
- }
- }
-
- DLOG(ERROR) << "No usable formats found";
- return false;
+std::string ExtractFileNameFromDeviceId(const std::string& device_id) {
+ // |unique_id| is of the form "/dev/video2". |file_name| is "video2".
+ const char kDevDir[] = "/dev/";
+ DCHECK(base::StartsWith(device_id, kDevDir, base::CompareCase::SENSITIVE));
+ return device_id.substr(strlen(kDevDir), device_id.length());
}
-std::list<float> GetFrameRateList(int fd,
- uint32_t fourcc,
- uint32_t width,
- uint32_t height) {
- std::list<float> frame_rates;
-
- v4l2_frmivalenum frame_interval = {};
- frame_interval.pixel_format = fourcc;
- frame_interval.width = width;
- frame_interval.height = height;
- for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval)) ==
- 0;
- ++frame_interval.index) {
- if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
- if (frame_interval.discrete.numerator != 0) {
- frame_rates.push_back(
- frame_interval.discrete.denominator /
- static_cast<float>(frame_interval.discrete.numerator));
- }
- } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
- frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
- // TODO(mcasas): see http://crbug.com/249953, support these devices.
- NOTIMPLEMENTED_LOG_ONCE();
- break;
+class DevVideoFilePathsDeviceProvider
+ : public VideoCaptureDeviceFactoryLinux::DeviceProvider {
+ public:
+ void GetDeviceIds(std::vector<std::string>* target_container) override {
+ const base::FilePath path("/dev/");
+ base::FileEnumerator enumerator(path, false, base::FileEnumerator::FILES,
+ "video*");
+ while (!enumerator.Next().empty()) {
+ const base::FileEnumerator::FileInfo info = enumerator.GetInfo();
+ target_container->emplace_back(path.value() + info.GetName().value());
}
}
- // Some devices, e.g. Kinect, do not enumerate any frame rates, see
- // http://crbug.com/412284. Set their frame_rate to zero.
- if (frame_rates.empty())
- frame_rates.push_back(0);
- return frame_rates;
-}
-void GetSupportedFormatsForV4L2BufferType(
- int fd,
- VideoCaptureFormats* supported_formats) {
- v4l2_fmtdesc v4l2_format = {};
- v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FMT, &v4l2_format)) == 0;
- ++v4l2_format.index) {
- VideoCaptureFormat supported_format;
- supported_format.pixel_format =
- VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat(
- v4l2_format.pixelformat);
+ std::string GetDeviceModelId(const std::string& device_id) override {
+ const std::string file_name = ExtractFileNameFromDeviceId(device_id);
+ std::string usb_id;
+ const std::string vid_path =
+ base::StringPrintf(kVidPathTemplate, file_name.c_str());
+ if (!ReadIdFile(vid_path, &usb_id))
+ return usb_id;
- if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN)
- continue;
+ usb_id.append(":");
+ const std::string pid_path =
+ base::StringPrintf(kPidPathTemplate, file_name.c_str());
+ if (!ReadIdFile(pid_path, &usb_id))
+ usb_id.clear();
- v4l2_frmsizeenum frame_size = {};
- frame_size.pixel_format = v4l2_format.pixelformat;
- for (; HANDLE_EINTR(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size)) == 0;
- ++frame_size.index) {
- if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
- supported_format.frame_size.SetSize(frame_size.discrete.width,
- frame_size.discrete.height);
- } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE ||
- frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
- // TODO(mcasas): see http://crbug.com/249953, support these devices.
- NOTIMPLEMENTED_LOG_ONCE();
- }
+ return usb_id;
+ }
- const std::list<float> frame_rates = GetFrameRateList(
- fd, v4l2_format.pixelformat, frame_size.discrete.width,
- frame_size.discrete.height);
- for (const auto& frame_rate : frame_rates) {
- supported_format.frame_rate = frame_rate;
- supported_formats->push_back(supported_format);
- DVLOG(1) << VideoCaptureFormat::ToString(supported_format);
- }
+ std::string GetDeviceDisplayName(const std::string& device_id) override {
+ const std::string file_name = ExtractFileNameFromDeviceId(device_id);
+ const std::string interface_path =
+ base::StringPrintf(kInterfacePathTemplate, file_name.c_str());
+ std::string display_name;
+ if (!base::ReadFileToStringWithMaxSize(base::FilePath(interface_path),
+ &display_name,
+ kMaxInterfaceNameSize)) {
+ return std::string();
}
+ return display_name;
}
-}
-std::string ExtractFileNameFromDeviceId(const std::string& device_id) {
- // |unique_id| is of the form "/dev/video2". |file_name| is "video2".
- const char kDevDir[] = "/dev/";
- DCHECK(base::StartsWith(device_id, kDevDir, base::CompareCase::SENSITIVE));
- return device_id.substr(strlen(kDevDir), device_id.length());
-}
-
-std::string GetDeviceModelId(const std::string& device_id) {
- const std::string file_name = ExtractFileNameFromDeviceId(device_id);
- std::string usb_id;
- const std::string vid_path =
- base::StringPrintf(kVidPathTemplate, file_name.c_str());
- if (!ReadIdFile(vid_path, &usb_id))
- return usb_id;
-
- usb_id.append(":");
- const std::string pid_path =
- base::StringPrintf(kPidPathTemplate, file_name.c_str());
- if (!ReadIdFile(pid_path, &usb_id))
- usb_id.clear();
-
- return usb_id;
-}
+ VideoFacingMode GetCameraFacing(const std::string& device_id,
+ const std::string& model_id) override {
+#if defined(OS_CHROMEOS)
+ return GetCameraConfig()->GetCameraFacing(device_id, model_id);
+#else
+ NOTREACHED();
+ return MEDIA_VIDEO_FACING_NONE;
+#endif
+ }
-std::string GetDeviceDisplayName(const std::string& device_id) {
- const std::string file_name = ExtractFileNameFromDeviceId(device_id);
- const std::string interface_path =
- base::StringPrintf(kInterfacePathTemplate, file_name.c_str());
- std::string display_name;
- if (!base::ReadFileToStringWithMaxSize(base::FilePath(interface_path),
- &display_name,
- kMaxInterfaceNameSize)) {
- return std::string();
+ int GetOrientation(const std::string& device_id,
+ const std::string& model_id) override {
+#if defined(OS_CHROMEOS)
+ return GetCameraConfig()->GetOrientation(device_id, model_id);
+#else
+ NOTREACHED();
+ return 0;
+#endif
}
- return display_name;
-}
+};
} // namespace
VideoCaptureDeviceFactoryLinux::VideoCaptureDeviceFactoryLinux(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
- : ui_task_runner_(ui_task_runner) {
-}
+ : v4l2_(new V4L2CaptureDeviceImpl()),
+ device_provider_(new DevVideoFilePathsDeviceProvider()),
+ ui_task_runner_(ui_task_runner) {}
VideoCaptureDeviceFactoryLinux::~VideoCaptureDeviceFactoryLinux() = default;
+void VideoCaptureDeviceFactoryLinux::SetV4L2EnvironmentForTesting(
+ scoped_refptr<V4L2CaptureDevice> v4l2,
+ std::unique_ptr<VideoCaptureDeviceFactoryLinux::DeviceProvider>
+ device_provider) {
+ v4l2_ = std::move(v4l2);
+ device_provider_ = std::move(device_provider);
+}
+
std::unique_ptr<VideoCaptureDevice>
VideoCaptureDeviceFactoryLinux::CreateDevice(
const VideoCaptureDeviceDescriptor& device_descriptor) {
DCHECK(thread_checker_.CalledOnValidThread());
#if defined(OS_CHROMEOS)
- VideoCaptureDeviceChromeOS* self =
- new VideoCaptureDeviceChromeOS(ui_task_runner_, device_descriptor);
+ ChromeOSDeviceCameraConfig camera_config(
+ device_provider_->GetCameraFacing(device_descriptor.device_id,
+ device_descriptor.model_id),
+ device_provider_->GetOrientation(device_descriptor.device_id,
+ device_descriptor.model_id));
+ VideoCaptureDeviceChromeOS* self = new VideoCaptureDeviceChromeOS(
+ camera_config, ui_task_runner_, v4l2_.get(), device_descriptor);
#else
VideoCaptureDeviceLinux* self =
- new VideoCaptureDeviceLinux(device_descriptor);
+ new VideoCaptureDeviceLinux(v4l2_.get(), device_descriptor);
#endif
if (!self)
return std::unique_ptr<VideoCaptureDevice>();
@@ -227,38 +189,36 @@ void VideoCaptureDeviceFactoryLinux::GetDeviceDescriptors(
VideoCaptureDeviceDescriptors* device_descriptors) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(device_descriptors->empty());
- const base::FilePath path("/dev/");
- base::FileEnumerator enumerator(path, false, base::FileEnumerator::FILES,
- "video*");
-
- while (!enumerator.Next().empty()) {
- const base::FileEnumerator::FileInfo info = enumerator.GetInfo();
- const std::string unique_id = path.value() + info.GetName().value();
- const base::ScopedFD fd(HANDLE_EINTR(open(unique_id.c_str(), O_RDONLY)));
+ std::vector<std::string> filepaths;
+ device_provider_->GetDeviceIds(&filepaths);
+ for (auto& unique_id : filepaths) {
+ const base::ScopedFD fd(
+ HANDLE_EINTR(v4l2_->open(unique_id.c_str(), O_RDONLY)));
if (!fd.is_valid()) {
- DLOG(ERROR) << "Couldn't open " << info.GetName().value();
+ DLOG(ERROR) << "Couldn't open " << unique_id;
continue;
}
- // Test if this is a V4L2 capture device and if it has at least one
- // supported capture format. Devices that have capture and output
+ // Test if this is a V4L2CaptureDevice capture device and if it has at least
+ // one supported capture format. Devices that have capture and output
// capabilities at the same time are memory-to-memory and are skipped, see
// http://crbug.com/139356.
v4l2_capability cap;
- if ((HANDLE_EINTR(ioctl(fd.get(), VIDIOC_QUERYCAP, &cap)) == 0) &&
+ if ((HANDLE_EINTR(v4l2_->ioctl(fd.get(), VIDIOC_QUERYCAP, &cap)) == 0) &&
(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE &&
!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) &&
HasUsableFormats(fd.get(), cap.capabilities)) {
- const std::string model_id = GetDeviceModelId(unique_id);
- std::string display_name = GetDeviceDisplayName(unique_id);
+ const std::string model_id =
+ device_provider_->GetDeviceModelId(unique_id);
+ std::string display_name =
+ device_provider_->GetDeviceDisplayName(unique_id);
if (display_name.empty())
display_name = reinterpret_cast<char*>(cap.card);
#if defined(OS_CHROMEOS)
- static CameraConfigChromeOS* config = new CameraConfigChromeOS();
device_descriptors->emplace_back(
display_name, unique_id, model_id,
VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE,
VideoCaptureTransportType::OTHER_TRANSPORT,
- config->GetCameraFacing(unique_id, model_id));
+ device_provider_->GetCameraFacing(unique_id, model_id));
#else
device_descriptors->emplace_back(
display_name, unique_id, model_id,
@@ -278,7 +238,8 @@ void VideoCaptureDeviceFactoryLinux::GetSupportedFormats(
DCHECK(thread_checker_.CalledOnValidThread());
if (device.device_id.empty())
return;
- base::ScopedFD fd(HANDLE_EINTR(open(device.device_id.c_str(), O_RDONLY)));
+ base::ScopedFD fd(
+ HANDLE_EINTR(v4l2_->open(device.device_id.c_str(), O_RDONLY)));
if (!fd.is_valid()) // Failed to open this device.
return;
supported_formats->clear();
@@ -287,16 +248,100 @@ void VideoCaptureDeviceFactoryLinux::GetSupportedFormats(
GetSupportedFormatsForV4L2BufferType(fd.get(), supported_formats);
}
-#if !defined(OS_CHROMEOS)
-// static
-VideoCaptureDeviceFactory*
-VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
- return new VideoCaptureDeviceFactoryLinux(ui_task_runner);
+bool VideoCaptureDeviceFactoryLinux::HasUsableFormats(int fd,
+ uint32_t capabilities) {
+ if (!(capabilities & V4L2_CAP_VIDEO_CAPTURE))
+ return false;
+
+ const std::list<uint32_t>& usable_fourccs =
+ VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false);
+ v4l2_fmtdesc fmtdesc = {};
+ fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ for (; HANDLE_EINTR(v4l2_->ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0;
+ ++fmtdesc.index) {
+ if (std::find(usable_fourccs.begin(), usable_fourccs.end(),
+ fmtdesc.pixelformat) != usable_fourccs.end()) {
+ return true;
+ }
+ }
+
+ DLOG(ERROR) << "No usable formats found";
+ return false;
+}
+
+std::list<float> VideoCaptureDeviceFactoryLinux::GetFrameRateList(
+ int fd,
+ uint32_t fourcc,
+ uint32_t width,
+ uint32_t height) {
+ std::list<float> frame_rates;
+
+ v4l2_frmivalenum frame_interval = {};
+ frame_interval.pixel_format = fourcc;
+ frame_interval.width = width;
+ frame_interval.height = height;
+ for (; HANDLE_EINTR(v4l2_->ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS,
+ &frame_interval)) == 0;
+ ++frame_interval.index) {
+ if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
+ if (frame_interval.discrete.numerator != 0) {
+ frame_rates.push_back(
+ frame_interval.discrete.denominator /
+ static_cast<float>(frame_interval.discrete.numerator));
+ }
+ } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
+ frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
+ // TODO(mcasas): see http://crbug.com/249953, support these devices.
+ NOTIMPLEMENTED_LOG_ONCE();
+ break;
+ }
+ }
+ // Some devices, e.g. Kinect, do not enumerate any frame rates, see
+ // http://crbug.com/412284. Set their frame_rate to zero.
+ if (frame_rates.empty())
+ frame_rates.push_back(0);
+ return frame_rates;
+}
+
+void VideoCaptureDeviceFactoryLinux::GetSupportedFormatsForV4L2BufferType(
+ int fd,
+ VideoCaptureFormats* supported_formats) {
+ v4l2_fmtdesc v4l2_format = {};
+ v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ for (; HANDLE_EINTR(v4l2_->ioctl(fd, VIDIOC_ENUM_FMT, &v4l2_format)) == 0;
+ ++v4l2_format.index) {
+ VideoCaptureFormat supported_format;
+ supported_format.pixel_format =
+ VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat(
+ v4l2_format.pixelformat);
+
+ if (supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN)
+ continue;
+
+ v4l2_frmsizeenum frame_size = {};
+ frame_size.pixel_format = v4l2_format.pixelformat;
+ for (; HANDLE_EINTR(
+ v4l2_->ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size)) == 0;
+ ++frame_size.index) {
+ if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+ supported_format.frame_size.SetSize(frame_size.discrete.width,
+ frame_size.discrete.height);
+ } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE ||
+ frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
+ // TODO(mcasas): see http://crbug.com/249953, support these devices.
+ NOTIMPLEMENTED_LOG_ONCE();
+ }
+
+ const std::list<float> frame_rates = GetFrameRateList(
+ fd, v4l2_format.pixelformat, frame_size.discrete.width,
+ frame_size.discrete.height);
+ for (const auto& frame_rate : frame_rates) {
+ supported_format.frame_rate = frame_rate;
+ supported_formats->push_back(supported_format);
+ DVLOG(1) << VideoCaptureFormat::ToString(supported_format);
+ }
+ }
+ }
}
-#endif
} // namespace media
diff --git a/chromium/media/capture/video/linux/video_capture_device_factory_linux.h b/chromium/media/capture/video/linux/video_capture_device_factory_linux.h
index 50e8db4db88..d3f06f9168e 100644
--- a/chromium/media/capture/video/linux/video_capture_device_factory_linux.h
+++ b/chromium/media/capture/video/linux/video_capture_device_factory_linux.h
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
+#include "media/capture/video/linux/v4l2_capture_device.h"
#include "media/capture/video_capture_types.h"
namespace media {
@@ -20,10 +21,36 @@ namespace media {
class CAPTURE_EXPORT VideoCaptureDeviceFactoryLinux
: public VideoCaptureDeviceFactory {
public:
+ class CAPTURE_EXPORT DeviceProvider {
+ public:
+ virtual ~DeviceProvider() {}
+ virtual void GetDeviceIds(std::vector<std::string>* target_container) = 0;
+ virtual std::string GetDeviceModelId(const std::string& device_id) = 0;
+ virtual std::string GetDeviceDisplayName(const std::string& device_id) = 0;
+ virtual VideoFacingMode GetCameraFacing(const std::string& device_id,
+ const std::string& model_id) = 0;
+ // Get the orientation of the camera. The value is the angle that the camera
+ // image needs to be rotated clockwise so it shows correctly on the display
+ // in its natural orientation. It should be 0, 90, 180, or 270.
+ //
+ // For example, suppose a device has a naturally tall screen. The
+ // back-facing camera sensor is mounted in landscape. You are looking at the
+ // screen. If the top side of the camera sensor is aligned with the right
+ // edge of the screen in natural orientation, the value should be 90. If the
+ // top side of a front-facing camera sensor is aligned with the right of the
+ // screen, the value should be 270.
+ virtual int GetOrientation(const std::string& device_id,
+ const std::string& model_id) = 0;
+ };
+
explicit VideoCaptureDeviceFactoryLinux(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
~VideoCaptureDeviceFactoryLinux() override;
+ void SetV4L2EnvironmentForTesting(
+ scoped_refptr<V4L2CaptureDevice> v4l2,
+ std::unique_ptr<DeviceProvider> device_provider);
+
std::unique_ptr<VideoCaptureDevice> CreateDevice(
const VideoCaptureDeviceDescriptor& device_descriptor) override;
void GetDeviceDescriptors(
@@ -33,6 +60,17 @@ class CAPTURE_EXPORT VideoCaptureDeviceFactoryLinux
VideoCaptureFormats* supported_formats) override;
private:
+ bool HasUsableFormats(int fd, uint32_t capabilities);
+ std::list<float> GetFrameRateList(int fd,
+ uint32_t fourcc,
+ uint32_t width,
+ uint32_t height);
+ void GetSupportedFormatsForV4L2BufferType(
+ int fd,
+ VideoCaptureFormats* supported_formats);
+
+ scoped_refptr<V4L2CaptureDevice> v4l2_;
+ std::unique_ptr<DeviceProvider> device_provider_;
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactoryLinux);
};
diff --git a/chromium/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc b/chromium/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc
new file mode 100644
index 00000000000..aa25be89fb6
--- /dev/null
+++ b/chromium/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc
@@ -0,0 +1,107 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/capture/video/linux/video_capture_device_factory_linux.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "media/capture/video/linux/fake_v4l2_impl.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+namespace media {
+
+class DescriptorDeviceProvider
+ : public VideoCaptureDeviceFactoryLinux::DeviceProvider {
+ public:
+ void AddDevice(const VideoCaptureDeviceDescriptor& descriptor) {
+ descriptors_.emplace_back(descriptor);
+ }
+
+ void GetDeviceIds(std::vector<std::string>* target_container) override {
+ for (const auto& entry : descriptors_) {
+ target_container->emplace_back(entry.device_id);
+ }
+ }
+
+ std::string GetDeviceModelId(const std::string& device_id) override {
+ auto iter =
+ std::find_if(descriptors_.begin(), descriptors_.end(),
+ [&device_id](const VideoCaptureDeviceDescriptor& val) {
+ return val.device_id == device_id;
+ });
+ if (iter == descriptors_.end())
+ CHECK(false) << "Unknown device_id " << device_id;
+
+ return iter->model_id;
+ }
+
+ std::string GetDeviceDisplayName(const std::string& device_id) override {
+ auto iter =
+ std::find_if(descriptors_.begin(), descriptors_.end(),
+ [&device_id](const VideoCaptureDeviceDescriptor& val) {
+ return val.device_id == device_id;
+ });
+ if (iter == descriptors_.end())
+ CHECK(false) << "Unknown device_id " << device_id;
+
+ return iter->display_name();
+ }
+
+ VideoFacingMode GetCameraFacing(const std::string& device_id,
+ const std::string& model_id) override {
+ return MEDIA_VIDEO_FACING_NONE;
+ }
+
+ int GetOrientation(const std::string& device_id,
+ const std::string& model_id) override {
+ return 0;
+ }
+
+ private:
+ std::vector<VideoCaptureDeviceDescriptor> descriptors_;
+};
+
+class VideoCaptureDeviceFactoryLinuxTest : public ::testing::Test {
+ public:
+ VideoCaptureDeviceFactoryLinuxTest() {}
+ ~VideoCaptureDeviceFactoryLinuxTest() override = default;
+
+ void SetUp() override {
+ factory_ = std::make_unique<VideoCaptureDeviceFactoryLinux>(
+ base::ThreadTaskRunnerHandle::Get());
+ scoped_refptr<FakeV4L2Impl> fake_v4l2(new FakeV4L2Impl());
+ fake_v4l2_ = fake_v4l2.get();
+ auto fake_device_provider = std::make_unique<DescriptorDeviceProvider>();
+ fake_device_provider_ = fake_device_provider.get();
+ factory_->SetV4L2EnvironmentForTesting(std::move(fake_v4l2),
+ std::move(fake_device_provider));
+ }
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ FakeV4L2Impl* fake_v4l2_;
+ DescriptorDeviceProvider* fake_device_provider_;
+ std::unique_ptr<VideoCaptureDeviceFactoryLinux> factory_;
+};
+
+TEST_F(VideoCaptureDeviceFactoryLinuxTest, EnumerateSingleFakeV4L2Device) {
+ // Setup
+ const std::string stub_display_name = "Fake Device 0";
+ const std::string stub_device_id = "/dev/video0";
+ VideoCaptureDeviceDescriptor descriptor(stub_display_name, stub_device_id);
+ fake_device_provider_->AddDevice(descriptor);
+ fake_v4l2_->AddDevice(stub_device_id, FakeV4L2DeviceConfig(descriptor));
+
+ // Exercise
+ VideoCaptureDeviceDescriptors descriptors;
+ factory_->GetDeviceDescriptors(&descriptors);
+
+ // Verification
+ ASSERT_EQ(1u, descriptors.size());
+ ASSERT_EQ(stub_device_id, descriptors[0].device_id);
+ ASSERT_EQ(stub_display_name, descriptors[0].display_name());
+}
+
+}; // namespace media
diff --git a/chromium/media/capture/video/linux/video_capture_device_linux.cc b/chromium/media/capture/video/linux/video_capture_device_linux.cc
index 594596a07de..808b74f418d 100644
--- a/chromium/media/capture/video/linux/video_capture_device_linux.cc
+++ b/chromium/media/capture/video/linux/video_capture_device_linux.cc
@@ -37,8 +37,10 @@ std::list<uint32_t> VideoCaptureDeviceLinux::GetListOfUsableFourCCs(
}
VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(
+ scoped_refptr<V4L2CaptureDevice> v4l2,
const VideoCaptureDeviceDescriptor& device_descriptor)
: device_descriptor_(device_descriptor),
+ v4l2_(std::move(v4l2)),
v4l2_thread_("V4L2CaptureThread") {}
VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
@@ -59,7 +61,8 @@ void VideoCaptureDeviceLinux::AllocateAndStart(
const int line_frequency =
TranslatePowerLineFrequencyToV4L2(GetPowerLineFrequency(params));
capture_impl_ = std::make_unique<V4L2CaptureDelegate>(
- device_descriptor_, v4l2_thread_.task_runner(), line_frequency);
+ v4l2_.get(), device_descriptor_, v4l2_thread_.task_runner(),
+ line_frequency);
if (!capture_impl_) {
client->OnError(FROM_HERE, "Failed to create VideoCaptureDelegate");
return;
diff --git a/chromium/media/capture/video/linux/video_capture_device_linux.h b/chromium/media/capture/video/linux/video_capture_device_linux.h
index cd34355e84b..e94cc6ac3e1 100644
--- a/chromium/media/capture/video/linux/video_capture_device_linux.h
+++ b/chromium/media/capture/video/linux/video_capture_device_linux.h
@@ -18,6 +18,7 @@
#include "base/files/scoped_file.h"
#include "base/macros.h"
#include "base/threading/thread.h"
+#include "media/capture/video/linux/v4l2_capture_device_impl.h"
#include "media/capture/video/video_capture_device.h"
#include "media/capture/video_capture_types.h"
@@ -32,6 +33,7 @@ class VideoCaptureDeviceLinux : public VideoCaptureDevice {
static std::list<uint32_t> GetListOfUsableFourCCs(bool favour_mjpeg);
explicit VideoCaptureDeviceLinux(
+ scoped_refptr<V4L2CaptureDevice> v4l2,
const VideoCaptureDeviceDescriptor& device_descriptor);
~VideoCaptureDeviceLinux() override;
@@ -52,6 +54,8 @@ class VideoCaptureDeviceLinux : public VideoCaptureDevice {
private:
static int TranslatePowerLineFrequencyToV4L2(PowerLineFrequency frequency);
+ const scoped_refptr<V4L2CaptureDevice> v4l2_;
+
// Internal delegate doing the actual capture setting, buffer allocation and
// circulation with the V4L2 API. Created in the thread where
// VideoCaptureDeviceLinux lives but otherwise operating and deleted on
diff --git a/chromium/media/capture/video/mac/video_capture_device_factory_mac.mm b/chromium/media/capture/video/mac/video_capture_device_factory_mac.mm
index d240605877f..48d3552524d 100644
--- a/chromium/media/capture/video/mac/video_capture_device_factory_mac.mm
+++ b/chromium/media/capture/video/mac/video_capture_device_factory_mac.mm
@@ -120,14 +120,4 @@ void VideoCaptureDeviceFactoryMac::GetSupportedFormats(
}
}
-// static
-VideoCaptureDeviceFactory*
-VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
- return new VideoCaptureDeviceFactoryMac();
-}
-
} // namespace media
diff --git a/chromium/media/capture/video/mock_gpu_memory_buffer_manager.cc b/chromium/media/capture/video/mock_gpu_memory_buffer_manager.cc
index 69629786d89..9b8befe84bf 100644
--- a/chromium/media/capture/video/mock_gpu_memory_buffer_manager.cc
+++ b/chromium/media/capture/video/mock_gpu_memory_buffer_manager.cc
@@ -93,7 +93,9 @@ class FakeGpuMemoryBuffer : public gfx::GpuMemoryBuffer {
gfx::GpuMemoryBufferId GetId() const override { return handle_.id; }
- gfx::GpuMemoryBufferHandle GetHandle() const override { return handle_; }
+ gfx::GpuMemoryBufferHandle GetHandle() const override {
+ return gfx::CloneHandleForIPC(handle_);
+ }
ClientBuffer AsClientBuffer() override {
NOTREACHED();
diff --git a/chromium/media/capture/video/shared_memory_buffer_tracker.cc b/chromium/media/capture/video/shared_memory_buffer_tracker.cc
index 7cd4a05e580..e375a183c12 100644
--- a/chromium/media/capture/video/shared_memory_buffer_tracker.cc
+++ b/chromium/media/capture/video/shared_memory_buffer_tracker.cc
@@ -39,4 +39,8 @@ SharedMemoryBufferTracker::GetNonOwnedSharedMemoryHandleForLegacyIPC() {
return provider_.GetNonOwnedSharedMemoryHandleForLegacyIPC();
}
+uint32_t SharedMemoryBufferTracker::GetMemorySizeInBytes() {
+ return provider_.GetMemorySizeInBytes();
+}
+
} // namespace media
diff --git a/chromium/media/capture/video/shared_memory_buffer_tracker.h b/chromium/media/capture/video/shared_memory_buffer_tracker.h
index 2c92ca017e2..92abef763c9 100644
--- a/chromium/media/capture/video/shared_memory_buffer_tracker.h
+++ b/chromium/media/capture/video/shared_memory_buffer_tracker.h
@@ -27,6 +27,7 @@ class SharedMemoryBufferTracker final : public VideoCaptureBufferTracker {
std::unique_ptr<VideoCaptureBufferHandle> GetMemoryMappedAccess() override;
mojo::ScopedSharedBufferHandle GetHandleForTransit(bool read_only) override;
base::SharedMemoryHandle GetNonOwnedSharedMemoryHandleForLegacyIPC() override;
+ uint32_t GetMemorySizeInBytes() override;
private:
SharedMemoryHandleProvider provider_;
diff --git a/chromium/media/capture/video/shared_memory_handle_provider.cc b/chromium/media/capture/video/shared_memory_handle_provider.cc
index 72a909337e6..2e2e7e78603 100644
--- a/chromium/media/capture/video/shared_memory_handle_provider.cc
+++ b/chromium/media/capture/video/shared_memory_handle_provider.cc
@@ -63,6 +63,25 @@ bool SharedMemoryHandleProvider::InitFromMojoHandle(
return true;
}
+#if defined(OS_LINUX)
+bool SharedMemoryHandleProvider::InitAsReadOnlyFromRawFileDescriptor(
+ mojo::ScopedHandle fd_handle,
+ uint32_t memory_size_in_bytes) {
+ base::PlatformFile platform_file;
+ const MojoResult result =
+ mojo::UnwrapPlatformFile(std::move(fd_handle), &platform_file);
+ if (result != MOJO_RESULT_OK)
+ return false;
+ base::UnguessableToken guid = base::UnguessableToken::Create();
+ base::SharedMemoryHandle memory_handle(
+ base::FileDescriptor(platform_file, true), 0u, guid);
+ mapped_size_ = memory_size_in_bytes;
+ read_only_flag_ = true;
+ shared_memory_.emplace(memory_handle, read_only_flag_);
+ return true;
+}
+#endif // defined(OS_LINUX)
+
mojo::ScopedSharedBufferHandle
SharedMemoryHandleProvider::GetHandleForInterProcessTransit(bool read_only) {
if (read_only_flag_ && !read_only) {
@@ -88,6 +107,10 @@ SharedMemoryHandleProvider::GetNonOwnedSharedMemoryHandleForLegacyIPC() {
return shared_memory_->handle();
}
+uint32_t SharedMemoryHandleProvider::GetMemorySizeInBytes() {
+ return static_cast<uint32_t>(mapped_size_);
+}
+
std::unique_ptr<VideoCaptureBufferHandle>
SharedMemoryHandleProvider::GetHandleForInProcessAccess() {
{
diff --git a/chromium/media/capture/video/shared_memory_handle_provider.h b/chromium/media/capture/video/shared_memory_handle_provider.h
index 8a14f3a4d35..7cd578bcba6 100644
--- a/chromium/media/capture/video/shared_memory_handle_provider.h
+++ b/chromium/media/capture/video/shared_memory_handle_provider.h
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "base/memory/shared_memory.h"
#include "base/optional.h"
+#include "build/build_config.h"
#include "media/capture/capture_export.h"
#include "media/capture/video/video_capture_buffer_handle.h"
#include "media/capture/video/video_capture_device.h"
@@ -35,6 +36,15 @@ class CAPTURE_EXPORT SharedMemoryHandleProvider
// if the operation failed.
bool InitFromMojoHandle(mojo::ScopedSharedBufferHandle buffer_handle);
+// This requires platforms where base::SharedMemoryHandle is backed by a
+// file descriptor.
+#if defined(OS_LINUX)
+ bool InitAsReadOnlyFromRawFileDescriptor(mojo::ScopedHandle fd_handle,
+ uint32_t memory_size_in_bytes);
+#endif // defined(OS_LINUX)
+
+ uint32_t GetMemorySizeInBytes();
+
// Implementation of Buffer::HandleProvider:
mojo::ScopedSharedBufferHandle GetHandleForInterProcessTransit(
bool read_only) override;
diff --git a/chromium/media/capture/video/video_capture_buffer_pool.h b/chromium/media/capture/video/video_capture_buffer_pool.h
index 1760aea78a4..1c4aa541e93 100644
--- a/chromium/media/capture/video/video_capture_buffer_pool.h
+++ b/chromium/media/capture/video/video_capture_buffer_pool.h
@@ -7,6 +7,7 @@
#include "base/memory/ref_counted.h"
#include "media/capture/capture_export.h"
+#include "media/capture/mojom/video_capture_types.mojom.h"
#include "media/capture/video_capture_types.h"
#include "mojo/public/cpp/system/buffer.h"
#include "ui/gfx/geometry/size.h"
@@ -50,6 +51,9 @@ class CAPTURE_EXPORT VideoCaptureBufferPool
virtual base::SharedMemoryHandle GetNonOwnedSharedMemoryHandleForLegacyIPC(
int buffer_id) = 0;
+ virtual mojom::SharedMemoryViaRawFileDescriptorPtr
+ CreateSharedMemoryViaRawFileDescriptorStruct(int buffer_id) = 0;
+
// Try and obtain a read/write access to the buffer.
virtual std::unique_ptr<VideoCaptureBufferHandle> GetHandleForInProcessAccess(
int buffer_id) = 0;
diff --git a/chromium/media/capture/video/video_capture_buffer_pool_impl.cc b/chromium/media/capture/video/video_capture_buffer_pool_impl.cc
index 477f5697029..9359b38be22 100644
--- a/chromium/media/capture/video/video_capture_buffer_pool_impl.cc
+++ b/chromium/media/capture/video/video_capture_buffer_pool_impl.cc
@@ -11,6 +11,7 @@
#include "build/build_config.h"
#include "media/capture/video/video_capture_buffer_handle.h"
#include "media/capture/video/video_capture_buffer_tracker.h"
+#include "mojo/public/cpp/system/platform_handle.h"
#include "ui/gfx/buffer_format_util.h"
namespace media {
@@ -53,6 +54,33 @@ VideoCaptureBufferPoolImpl::GetNonOwnedSharedMemoryHandleForLegacyIPC(
return tracker->GetNonOwnedSharedMemoryHandleForLegacyIPC();
}
+mojom::SharedMemoryViaRawFileDescriptorPtr
+VideoCaptureBufferPoolImpl::CreateSharedMemoryViaRawFileDescriptorStruct(
+ int buffer_id) {
+// This requires platforms where base::SharedMemoryHandle is backed by a
+// file descriptor.
+#if defined(OS_LINUX)
+ base::AutoLock lock(lock_);
+
+ VideoCaptureBufferTracker* tracker = GetTracker(buffer_id);
+ if (!tracker) {
+ NOTREACHED() << "Invalid buffer_id.";
+ return 0u;
+ }
+
+ auto result = mojom::SharedMemoryViaRawFileDescriptor::New();
+ result->file_descriptor_handle = mojo::WrapPlatformFile(
+ base::SharedMemory::DuplicateHandle(
+ tracker->GetNonOwnedSharedMemoryHandleForLegacyIPC())
+ .GetHandle());
+ result->shared_memory_size_in_bytes = tracker->GetMemorySizeInBytes();
+ return result;
+#else
+ NOTREACHED();
+ return mojom::SharedMemoryViaRawFileDescriptorPtr();
+#endif
+}
+
std::unique_ptr<VideoCaptureBufferHandle>
VideoCaptureBufferPoolImpl::GetHandleForInProcessAccess(int buffer_id) {
base::AutoLock lock(lock_);
diff --git a/chromium/media/capture/video/video_capture_buffer_pool_impl.h b/chromium/media/capture/video/video_capture_buffer_pool_impl.h
index 34b585f0885..2cde52214b3 100644
--- a/chromium/media/capture/video/video_capture_buffer_pool_impl.h
+++ b/chromium/media/capture/video/video_capture_buffer_pool_impl.h
@@ -40,6 +40,8 @@ class CAPTURE_EXPORT VideoCaptureBufferPoolImpl
bool read_only) override;
base::SharedMemoryHandle GetNonOwnedSharedMemoryHandleForLegacyIPC(
int buffer_id) override;
+ mojom::SharedMemoryViaRawFileDescriptorPtr
+ CreateSharedMemoryViaRawFileDescriptorStruct(int buffer_id) override;
std::unique_ptr<VideoCaptureBufferHandle> GetHandleForInProcessAccess(
int buffer_id) override;
int ReserveForProducer(const gfx::Size& dimensions,
diff --git a/chromium/media/capture/video/video_capture_buffer_tracker.h b/chromium/media/capture/video/video_capture_buffer_tracker.h
index 040ff5368bb..a4f7dff560c 100644
--- a/chromium/media/capture/video/video_capture_buffer_tracker.h
+++ b/chromium/media/capture/video/video_capture_buffer_tracker.h
@@ -44,6 +44,7 @@ class CAPTURE_EXPORT VideoCaptureBufferTracker {
bool read_only) = 0;
virtual base::SharedMemoryHandle
GetNonOwnedSharedMemoryHandleForLegacyIPC() = 0;
+ virtual uint32_t GetMemorySizeInBytes() = 0;
private:
// |dimensions_| may change as a VideoCaptureBufferTracker is re-used, but
diff --git a/chromium/media/capture/video/video_capture_device_client.cc b/chromium/media/capture/video/video_capture_device_client.cc
index 1a1bc937b31..64dd779fc2f 100644
--- a/chromium/media/capture/video/video_capture_device_client.cc
+++ b/chromium/media/capture/video/video_capture_device_client.cc
@@ -64,7 +64,8 @@ void GetI420BufferAccess(
*y_plane_stride = dimensions.width();
*uv_plane_stride = *y_plane_stride / 2;
}
-}
+
+} // anonymous namespace
namespace media {
@@ -96,12 +97,14 @@ class BufferPoolBufferHandleProvider
};
VideoCaptureDeviceClient::VideoCaptureDeviceClient(
+ VideoCaptureBufferType target_buffer_type,
std::unique_ptr<VideoFrameReceiver> receiver,
scoped_refptr<VideoCaptureBufferPool> buffer_pool,
- const VideoCaptureJpegDecoderFactoryCB& jpeg_decoder_factory)
- : receiver_(std::move(receiver)),
- jpeg_decoder_factory_callback_(jpeg_decoder_factory),
- external_jpeg_decoder_initialized_(false),
+ VideoCaptureJpegDecoderFactoryCB optional_jpeg_decoder_factory_callback)
+ : target_buffer_type_(target_buffer_type),
+ receiver_(std::move(receiver)),
+ optional_jpeg_decoder_factory_callback_(
+ std::move(optional_jpeg_decoder_factory_callback)),
buffer_pool_(std::move(buffer_pool)),
last_captured_pixel_format_(PIXEL_FORMAT_UNKNOWN) {
on_started_using_gpu_cb_ =
@@ -138,6 +141,7 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData(
base::TimeTicks reference_time,
base::TimeDelta timestamp,
int frame_feedback_id) {
+ DFAKE_SCOPED_RECURSIVE_LOCK(call_from_producer_);
TRACE_EVENT0("media", "VideoCaptureDeviceClient::OnIncomingCapturedData");
if (last_captured_pixel_format_ != format.pixel_format) {
@@ -145,11 +149,11 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData(
last_captured_pixel_format_ = format.pixel_format;
if (format.pixel_format == PIXEL_FORMAT_MJPEG &&
- !external_jpeg_decoder_initialized_) {
- external_jpeg_decoder_initialized_ = true;
- external_jpeg_decoder_ = jpeg_decoder_factory_callback_.Run();
- if (external_jpeg_decoder_)
- external_jpeg_decoder_->Initialize();
+ optional_jpeg_decoder_factory_callback_) {
+ external_jpeg_decoder_ =
+ std::move(optional_jpeg_decoder_factory_callback_).Run();
+ DCHECK(external_jpeg_decoder_);
+ external_jpeg_decoder_->Initialize();
}
}
@@ -400,9 +404,21 @@ VideoCaptureDeviceClient::ReserveOutputBuffer(const gfx::Size& frame_size,
if (!base::ContainsValue(buffer_ids_known_by_receiver_, buffer_id)) {
media::mojom::VideoBufferHandlePtr buffer_handle =
media::mojom::VideoBufferHandle::New();
- buffer_handle->set_shared_buffer_handle(
- buffer_pool_->GetHandleForInterProcessTransit(buffer_id,
- true /*read_only*/));
+ switch (target_buffer_type_) {
+ case VideoCaptureBufferType::kSharedMemory:
+ buffer_handle->set_shared_buffer_handle(
+ buffer_pool_->GetHandleForInterProcessTransit(buffer_id,
+ true /*read_only*/));
+ break;
+ case VideoCaptureBufferType::kSharedMemoryViaRawFileDescriptor:
+ buffer_handle->set_shared_memory_via_raw_file_descriptor(
+ buffer_pool_->CreateSharedMemoryViaRawFileDescriptorStruct(
+ buffer_id));
+ break;
+ case VideoCaptureBufferType::kMailboxHolder:
+ NOTREACHED();
+ break;
+ }
receiver_->OnNewBuffer(buffer_id, std::move(buffer_handle));
buffer_ids_known_by_receiver_.push_back(buffer_id);
}
diff --git a/chromium/media/capture/video/video_capture_device_client.h b/chromium/media/capture/video/video_capture_device_client.h
index 7708de91fc7..01dacc7376c 100644
--- a/chromium/media/capture/video/video_capture_device_client.h
+++ b/chromium/media/capture/video/video_capture_device_client.h
@@ -15,6 +15,7 @@
#include "base/memory/ref_counted.h"
#include "base/threading/thread_collision_warner.h"
#include "media/capture/capture_export.h"
+#include "media/capture/mojom/video_capture_types.mojom.h"
#include "media/capture/video/video_capture_device.h"
namespace media {
@@ -23,11 +24,15 @@ class VideoFrameReceiver;
class VideoCaptureJpegDecoder;
using VideoCaptureJpegDecoderFactoryCB =
- base::Callback<std::unique_ptr<VideoCaptureJpegDecoder>()>;
+ base::OnceCallback<std::unique_ptr<VideoCaptureJpegDecoder>()>;
// Implementation of VideoCaptureDevice::Client that uses a buffer pool
// to provide buffers and converts incoming data to the I420 format for
-// consumption by a given VideoFrameReceiver.
+// consumption by a given VideoFrameReceiver. If
+// |optional_jpeg_decoder_factory_callback| is provided, the
+// VideoCaptureDeviceClient will attempt to use it for decoding of MJPEG frames.
+// Otherwise, it will use libyuv to perform MJPEG to I420 conversion in
+// software.
//
// Methods of this class may be called from any thread, and in practice will
// often be called on some auxiliary thread depending on the platform and the
@@ -39,9 +44,10 @@ class CAPTURE_EXPORT VideoCaptureDeviceClient
: public VideoCaptureDevice::Client {
public:
VideoCaptureDeviceClient(
+ VideoCaptureBufferType target_buffer_type,
std::unique_ptr<VideoFrameReceiver> receiver,
scoped_refptr<VideoCaptureBufferPool> buffer_pool,
- const VideoCaptureJpegDecoderFactoryCB& jpeg_decoder_factory);
+ VideoCaptureJpegDecoderFactoryCB optional_jpeg_decoder_factory_callback);
~VideoCaptureDeviceClient() override;
static Buffer MakeBufferStruct(
@@ -95,15 +101,14 @@ class CAPTURE_EXPORT VideoCaptureDeviceClient
base::TimeDelta timestamp,
int frame_feedback_id);
+ const VideoCaptureBufferType target_buffer_type_;
+
// The receiver to which we post events.
const std::unique_ptr<VideoFrameReceiver> receiver_;
std::vector<int> buffer_ids_known_by_receiver_;
- const VideoCaptureJpegDecoderFactoryCB jpeg_decoder_factory_callback_;
+ VideoCaptureJpegDecoderFactoryCB optional_jpeg_decoder_factory_callback_;
std::unique_ptr<VideoCaptureJpegDecoder> external_jpeg_decoder_;
-
- // Whether |external_jpeg_decoder_| has been initialized.
- bool external_jpeg_decoder_initialized_;
base::OnceClosure on_started_using_gpu_cb_;
// The pool of shared-memory buffers used for capturing.
diff --git a/chromium/media/capture/video/video_capture_device_client_unittest.cc b/chromium/media/capture/video/video_capture_device_client_unittest.cc
index a3467e7e17a..56ada337446 100644
--- a/chromium/media/capture/video/video_capture_device_client_unittest.cc
+++ b/chromium/media/capture/video/video_capture_device_client_unittest.cc
@@ -54,8 +54,8 @@ class VideoCaptureDeviceClientTest : public ::testing::Test {
gpu_memory_buffer_manager_ =
std::make_unique<unittest_internal::MockGpuMemoryBufferManager>();
device_client_ = std::make_unique<VideoCaptureDeviceClient>(
- std::move(controller), buffer_pool,
- base::Bind(&ReturnNullPtrAsJpecDecoder));
+ VideoCaptureBufferType::kSharedMemory, std::move(controller),
+ buffer_pool, base::BindRepeating(&ReturnNullPtrAsJpecDecoder));
}
~VideoCaptureDeviceClientTest() override = default;
diff --git a/chromium/media/capture/video/video_capture_device_descriptor.cc b/chromium/media/capture/video/video_capture_device_descriptor.cc
index 3a718ed8c6c..be6c87ec4ce 100644
--- a/chromium/media/capture/video/video_capture_device_descriptor.cc
+++ b/chromium/media/capture/video/video_capture_device_descriptor.cc
@@ -61,10 +61,10 @@ bool VideoCaptureDeviceDescriptor::operator<(
"FACING_ENVIRONMENT has a wrong value");
static_assert(kFacingMapping[MEDIA_VIDEO_FACING_USER] == 2,
"FACING_USER has a wrong value");
- if (kFacingMapping[facing] > kFacingMapping[other.facing])
- return true;
- if (device_id < other.device_id)
- return true;
+ if (kFacingMapping[facing] != kFacingMapping[other.facing])
+ return kFacingMapping[facing] > kFacingMapping[other.facing];
+ if (device_id != other.device_id)
+ return device_id < other.device_id;
return capture_api < other.capture_api;
}
@@ -90,6 +90,8 @@ const char* VideoCaptureDeviceDescriptor::GetCaptureApiTypeString() const {
return "Camera API2 Full";
case VideoCaptureApi::ANDROID_API2_LIMITED:
return "Camera API2 Limited";
+ case VideoCaptureApi::VIRTUAL_DEVICE:
+ return "Virtual Device";
case VideoCaptureApi::UNKNOWN:
return "Unknown";
}
diff --git a/chromium/media/capture/video/video_capture_device_descriptor.h b/chromium/media/capture/video/video_capture_device_descriptor.h
index 48eed13ece0..c53274df3bf 100644
--- a/chromium/media/capture/video/video_capture_device_descriptor.h
+++ b/chromium/media/capture/video/video_capture_device_descriptor.h
@@ -27,6 +27,7 @@ enum class VideoCaptureApi {
ANDROID_API2_LEGACY,
ANDROID_API2_FULL,
ANDROID_API2_LIMITED,
+ VIRTUAL_DEVICE,
UNKNOWN
};
diff --git a/chromium/media/capture/video/video_capture_device_factory.cc b/chromium/media/capture/video/video_capture_device_factory.cc
index 4dd4f7bde89..4d903b6a714 100644
--- a/chromium/media/capture/video/video_capture_device_factory.cc
+++ b/chromium/media/capture/video/video_capture_device_factory.cc
@@ -14,61 +14,12 @@
namespace media {
-// static
-std::unique_ptr<VideoCaptureDeviceFactory>
-VideoCaptureDeviceFactory::CreateFactory(
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- gpu::GpuMemoryBufferManager* gpu_buffer_manager,
- MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- // Use a Fake or File Video Device Factory if the command line flags are
- // present, otherwise use the normal, platform-dependent, device factory.
- if (command_line->HasSwitch(switches::kUseFakeDeviceForMediaStream)) {
- if (command_line->HasSwitch(switches::kUseFileForFakeVideoCapture)) {
- return std::unique_ptr<VideoCaptureDeviceFactory>(
- new FileVideoCaptureDeviceFactory());
- } else {
- std::vector<FakeVideoCaptureDeviceSettings> config;
- FakeVideoCaptureDeviceFactory::ParseFakeDevicesConfigFromOptionsString(
- command_line->GetSwitchValueASCII(
- switches::kUseFakeDeviceForMediaStream),
- &config);
- auto result = std::make_unique<FakeVideoCaptureDeviceFactory>();
- result->SetToCustomDevicesConfig(config);
- return std::move(result);
- }
- } else {
- // |ui_task_runner| is needed for the Linux ChromeOS factory to retrieve
- // screen rotations.
- return std::unique_ptr<VideoCaptureDeviceFactory>(
- CreateVideoCaptureDeviceFactory(ui_task_runner, gpu_buffer_manager,
- std::move(jda_factory),
- std::move(jea_factory)));
- }
-}
-
VideoCaptureDeviceFactory::VideoCaptureDeviceFactory() {
thread_checker_.DetachFromThread();
}
VideoCaptureDeviceFactory::~VideoCaptureDeviceFactory() = default;
-#if !defined(OS_MACOSX) && !defined(OS_LINUX) && !defined(OS_ANDROID) && \
- !defined(OS_WIN)
-// static
-VideoCaptureDeviceFactory*
-VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- gpu::GpuMemoryBufferManager* gpu_buffer_manager,
- MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
- NOTIMPLEMENTED();
- return NULL;
-}
-#endif
-
void VideoCaptureDeviceFactory::GetCameraLocationsAsync(
std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors,
DeviceDescriptorsCallback result_callback) {
diff --git a/chromium/media/capture/video/video_capture_device_factory.h b/chromium/media/capture/video/video_capture_device_factory.h
index 1cd174ffc75..9ec274265c1 100644
--- a/chromium/media/capture/video/video_capture_device_factory.h
+++ b/chromium/media/capture/video/video_capture_device_factory.h
@@ -34,12 +34,6 @@ using MojoJpegEncodeAcceleratorFactoryCB =
// crbug.com/665065
class CAPTURE_EXPORT VideoCaptureDeviceFactory {
public:
- static std::unique_ptr<VideoCaptureDeviceFactory> CreateFactory(
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- gpu::GpuMemoryBufferManager* gpu_buffer_manager,
- MojoJpegDecodeAcceleratorFactoryCB jpeg_decoder_factory,
- MojoJpegEncodeAcceleratorFactoryCB jpeg_encoder_factory);
-
VideoCaptureDeviceFactory();
virtual ~VideoCaptureDeviceFactory();
@@ -76,12 +70,6 @@ class CAPTURE_EXPORT VideoCaptureDeviceFactory {
base::ThreadChecker thread_checker_;
private:
- static VideoCaptureDeviceFactory* CreateVideoCaptureDeviceFactory(
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- gpu::GpuMemoryBufferManager* gpu_buffer_manager,
- MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory);
-
DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactory);
};
diff --git a/chromium/media/capture/video/video_capture_device_unittest.cc b/chromium/media/capture/video/video_capture_device_unittest.cc
index 21143688320..dbb4f6565f5 100644
--- a/chromium/media/capture/video/video_capture_device_unittest.cc
+++ b/chromium/media/capture/video/video_capture_device_unittest.cc
@@ -21,7 +21,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "media/base/bind_to_current_loop.h"
-#include "media/capture/video/video_capture_device_factory.h"
+#include "media/capture/video/create_video_capture_device_factory.h"
#include "media/capture/video_capture_types.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -49,6 +49,7 @@
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_power_manager_client.h"
#include "media/capture/video/chromeos/camera_buffer_factory.h"
+#include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
#include "media/capture/video/chromeos/local_gpu_memory_buffer_manager.h"
#include "media/capture/video/chromeos/video_capture_device_chromeos_halv3.h"
#include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h"
@@ -287,22 +288,23 @@ class VideoCaptureDeviceTest
video_capture_client_(new MockVideoCaptureClient(
base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured,
base::Unretained(this)))),
- image_capture_client_(new MockImageCaptureClient()),
+ image_capture_client_(new MockImageCaptureClient()) {
#if defined(OS_CHROMEOS)
- local_gpu_memory_buffer_manager_(new LocalGpuMemoryBufferManager()),
- dbus_setter_(chromeos::DBusThreadManager::GetSetterForTesting()),
-#endif
- video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory(
- base::ThreadTaskRunnerHandle::Get(),
-#if defined(OS_CHROMEOS)
- local_gpu_memory_buffer_manager_.get(),
-#else
- nullptr,
+ local_gpu_memory_buffer_manager_ =
+ std::make_unique<LocalGpuMemoryBufferManager>();
+ dbus_setter_ = chromeos::DBusThreadManager::GetSetterForTesting();
+ VideoCaptureDeviceFactoryChromeOS::SetGpuBufferManager(
+ local_gpu_memory_buffer_manager_.get());
+ if (!CameraHalDispatcherImpl::GetInstance()->IsStarted()) {
+ CameraHalDispatcherImpl::GetInstance()->Start(
+ base::DoNothing::Repeatedly<
+ media::mojom::JpegDecodeAcceleratorRequest>(),
+ base::DoNothing::Repeatedly<
+ media::mojom::JpegEncodeAcceleratorRequest>());
+ }
#endif
- base::BindRepeating(
- [](media::mojom::JpegDecodeAcceleratorRequest) {}),
- base::DoNothing::Repeatedly<
- media::mojom::JpegEncodeAcceleratorRequest>())) {
+ video_capture_device_factory_ =
+ CreateVideoCaptureDeviceFactory(base::ThreadTaskRunnerHandle::Get());
}
void SetUp() override {
@@ -435,12 +437,10 @@ class VideoCaptureDeviceTest
const scoped_refptr<MockImageCaptureClient> image_capture_client_;
VideoCaptureFormat last_format_;
#if defined(OS_CHROMEOS)
- const std::unique_ptr<LocalGpuMemoryBufferManager>
- local_gpu_memory_buffer_manager_;
+ std::unique_ptr<LocalGpuMemoryBufferManager> local_gpu_memory_buffer_manager_;
std::unique_ptr<chromeos::DBusThreadManagerSetter> dbus_setter_;
#endif
- const std::unique_ptr<VideoCaptureDeviceFactory>
- video_capture_device_factory_;
+ std::unique_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_;
};
// Cause hangs on Windows Debug. http://crbug.com/417824
diff --git a/chromium/media/capture/video/video_capture_jpeg_decoder.h b/chromium/media/capture/video/video_capture_jpeg_decoder.h
index c5b32cf4519..e2da00d54c8 100644
--- a/chromium/media/capture/video/video_capture_jpeg_decoder.h
+++ b/chromium/media/capture/video/video_capture_jpeg_decoder.h
@@ -13,6 +13,8 @@
namespace media {
+// All methods are allowed to be called from any thread, but calls must be
+// non-concurrently.
class CAPTURE_EXPORT VideoCaptureJpegDecoder {
public:
// Enumeration of decoder status. The enumeration is published for clients to
@@ -24,7 +26,7 @@ class CAPTURE_EXPORT VideoCaptureJpegDecoder {
// decode error.
};
- using DecodeDoneCB = base::Callback<void(
+ using DecodeDoneCB = base::RepeatingCallback<void(
int buffer_id,
int frame_feedback_id,
std::unique_ptr<VideoCaptureDevice::Client::Buffer::
diff --git a/chromium/media/capture/video/video_capture_jpeg_decoder_impl.cc b/chromium/media/capture/video/video_capture_jpeg_decoder_impl.cc
new file mode 100644
index 00000000000..b82bae90b11
--- /dev/null
+++ b/chromium/media/capture/video/video_capture_jpeg_decoder_impl.cc
@@ -0,0 +1,260 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/capture/video/video_capture_jpeg_decoder_impl.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "media/base/media_switches.h"
+
+namespace media {
+
+VideoCaptureJpegDecoderImpl::VideoCaptureJpegDecoderImpl(
+ MojoJpegDecodeAcceleratorFactoryCB jpeg_decoder_factory,
+ scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
+ DecodeDoneCB decode_done_cb,
+ base::RepeatingCallback<void(const std::string&)> send_log_message_cb)
+ : jpeg_decoder_factory_(std::move(jpeg_decoder_factory)),
+ decoder_task_runner_(std::move(decoder_task_runner)),
+ decode_done_cb_(std::move(decode_done_cb)),
+ send_log_message_cb_(std::move(send_log_message_cb)),
+ has_received_decoded_frame_(false),
+ next_bitstream_buffer_id_(0),
+ in_buffer_id_(media::JpegDecodeAccelerator::kInvalidBitstreamBufferId),
+ decoder_status_(INIT_PENDING),
+ weak_ptr_factory_(this) {}
+
+VideoCaptureJpegDecoderImpl::~VideoCaptureJpegDecoderImpl() {
+ // |this| was set as |decoder_|'s client. |decoder_| has to be deleted on
+ // |decoder_task_runner_| before this destructor returns to ensure that it
+ // doesn't call back into its client.
+
+ if (!decoder_)
+ return;
+
+ if (decoder_task_runner_->RunsTasksInCurrentSequence()) {
+ decoder_.reset();
+ return;
+ }
+
+ base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ // base::Unretained is safe because |this| will be valid until |event|
+ // is signaled.
+ decoder_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VideoCaptureJpegDecoderImpl::DestroyDecoderOnIOThread,
+ base::Unretained(this), &event));
+ event.Wait();
+}
+
+void VideoCaptureJpegDecoderImpl::Initialize() {
+ if (!IsVideoCaptureAcceleratedJpegDecodingEnabled()) {
+ decoder_status_ = FAILED;
+ RecordInitDecodeUMA_Locked();
+ return;
+ }
+
+ decoder_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VideoCaptureJpegDecoderImpl::FinishInitialization,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+VideoCaptureJpegDecoderImpl::STATUS VideoCaptureJpegDecoderImpl::GetStatus()
+ const {
+ base::AutoLock lock(lock_);
+ return decoder_status_;
+}
+
+void VideoCaptureJpegDecoderImpl::DecodeCapturedData(
+ const uint8_t* data,
+ size_t in_buffer_size,
+ const media::VideoCaptureFormat& frame_format,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp,
+ media::VideoCaptureDevice::Client::Buffer out_buffer) {
+ DCHECK(decoder_);
+
+ TRACE_EVENT_ASYNC_BEGIN0("jpeg", "VideoCaptureJpegDecoderImpl decoding",
+ next_bitstream_buffer_id_);
+ TRACE_EVENT0("jpeg", "VideoCaptureJpegDecoderImpl::DecodeCapturedData");
+
+ // TODO(kcwu): enqueue decode requests in case decoding is not fast enough
+ // (say, if decoding time is longer than 16ms for 60fps 4k image)
+ {
+ base::AutoLock lock(lock_);
+ if (IsDecoding_Locked()) {
+ DVLOG(1) << "Drop captured frame. Previous jpeg frame is still decoding";
+ return;
+ }
+ }
+
+ // Enlarge input buffer if necessary.
+ if (!in_shared_memory_.get() ||
+ in_buffer_size > in_shared_memory_->mapped_size()) {
+ // Reserve 2x space to avoid frequent reallocations for initial frames.
+ const size_t reserved_size = 2 * in_buffer_size;
+ in_shared_memory_.reset(new base::SharedMemory);
+ if (!in_shared_memory_->CreateAndMapAnonymous(reserved_size)) {
+ base::AutoLock lock(lock_);
+ decoder_status_ = FAILED;
+ LOG(WARNING) << "CreateAndMapAnonymous failed, size=" << reserved_size;
+ return;
+ }
+ }
+ memcpy(in_shared_memory_->memory(), data, in_buffer_size);
+
+ // No need to lock for |in_buffer_id_| since IsDecoding_Locked() is false.
+ in_buffer_id_ = next_bitstream_buffer_id_;
+ media::BitstreamBuffer in_buffer(in_buffer_id_, in_shared_memory_->handle(),
+ in_buffer_size);
+ // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
+ next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
+
+ // The API of |decoder_| requires us to wrap the |out_buffer| in a VideoFrame.
+ const gfx::Size dimensions = frame_format.frame_size;
+ std::unique_ptr<media::VideoCaptureBufferHandle> out_buffer_access =
+ out_buffer.handle_provider->GetHandleForInProcessAccess();
+ base::SharedMemoryHandle out_handle =
+ out_buffer.handle_provider->GetNonOwnedSharedMemoryHandleForLegacyIPC();
+ scoped_refptr<media::VideoFrame> out_frame =
+ media::VideoFrame::WrapExternalSharedMemory(
+ media::PIXEL_FORMAT_I420, // format
+ dimensions, // coded_size
+ gfx::Rect(dimensions), // visible_rect
+ dimensions, // natural_size
+ out_buffer_access->data(), // data
+ out_buffer_access->mapped_size(), // data_size
+ out_handle, // handle
+ 0, // shared_memory_offset
+ timestamp); // timestamp
+ if (!out_frame) {
+ base::AutoLock lock(lock_);
+ decoder_status_ = FAILED;
+ LOG(ERROR) << "DecodeCapturedData: WrapExternalSharedMemory failed";
+ return;
+ }
+ // Hold onto the buffer access handle for the lifetime of the VideoFrame, to
+ // ensure the data pointers remain valid.
+ out_frame->AddDestructionObserver(base::BindOnce(
+ [](std::unique_ptr<media::VideoCaptureBufferHandle> handle) {},
+ std::move(out_buffer_access)));
+ out_frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE,
+ frame_format.frame_rate);
+
+ out_frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
+ reference_time);
+
+ media::mojom::VideoFrameInfoPtr out_frame_info =
+ media::mojom::VideoFrameInfo::New();
+ out_frame_info->timestamp = timestamp;
+ out_frame_info->pixel_format = media::PIXEL_FORMAT_I420;
+ out_frame_info->coded_size = dimensions;
+ out_frame_info->visible_rect = gfx::Rect(dimensions);
+ out_frame_info->metadata = out_frame->metadata()->GetInternalValues().Clone();
+
+ {
+ base::AutoLock lock(lock_);
+ decode_done_closure_ = base::BindOnce(
+ decode_done_cb_, out_buffer.id, out_buffer.frame_feedback_id,
+ base::Passed(&out_buffer.access_permission),
+ base::Passed(&out_frame_info));
+ }
+
+ // base::Unretained is safe because |decoder_| is deleted on
+ // |decoder_task_runner_|.
+ decoder_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&media::JpegDecodeAccelerator::Decode,
+ base::Unretained(decoder_.get()), in_buffer,
+ std::move(out_frame)));
+}
+
+void VideoCaptureJpegDecoderImpl::VideoFrameReady(int32_t bitstream_buffer_id) {
+ DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence());
+ TRACE_EVENT0("jpeg", "VideoCaptureJpegDecoderImpl::VideoFrameReady");
+ if (!has_received_decoded_frame_) {
+ send_log_message_cb_.Run("Received decoded frame from Gpu Jpeg decoder");
+ has_received_decoded_frame_ = true;
+ }
+ base::AutoLock lock(lock_);
+
+ if (!IsDecoding_Locked()) {
+ LOG(ERROR) << "Got decode response while not decoding";
+ return;
+ }
+
+ if (bitstream_buffer_id != in_buffer_id_) {
+ LOG(ERROR) << "Unexpected bitstream_buffer_id " << bitstream_buffer_id
+ << ", expected " << in_buffer_id_;
+ return;
+ }
+ in_buffer_id_ = media::JpegDecodeAccelerator::kInvalidBitstreamBufferId;
+
+ std::move(decode_done_closure_).Run();
+
+ TRACE_EVENT_ASYNC_END0("jpeg", "VideoCaptureJpegDecoderImpl decoding",
+ bitstream_buffer_id);
+}
+
+void VideoCaptureJpegDecoderImpl::NotifyError(
+ int32_t bitstream_buffer_id,
+ media::JpegDecodeAccelerator::Error error) {
+ DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence());
+ LOG(ERROR) << "Decode error, bitstream_buffer_id=" << bitstream_buffer_id
+ << ", error=" << error;
+ send_log_message_cb_.Run("Gpu Jpeg decoder failed");
+ base::AutoLock lock(lock_);
+ decode_done_closure_.Reset();
+ decoder_status_ = FAILED;
+}
+
+void VideoCaptureJpegDecoderImpl::FinishInitialization() {
+ TRACE_EVENT0("gpu", "VideoCaptureJpegDecoderImpl::FinishInitialization");
+ DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence());
+
+ media::mojom::JpegDecodeAcceleratorPtr remote_decoder;
+ jpeg_decoder_factory_.Run(mojo::MakeRequest(&remote_decoder));
+
+ base::AutoLock lock(lock_);
+ decoder_ = std::make_unique<media::MojoJpegDecodeAccelerator>(
+ decoder_task_runner_, remote_decoder.PassInterface());
+
+ decoder_->InitializeAsync(
+ this,
+ base::BindRepeating(&VideoCaptureJpegDecoderImpl::OnInitializationDone,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void VideoCaptureJpegDecoderImpl::OnInitializationDone(bool success) {
+ TRACE_EVENT0("gpu", "VideoCaptureJpegDecoderImpl::OnInitializationDone");
+ DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence());
+
+ base::AutoLock lock(lock_);
+ if (!success) {
+ decoder_.reset();
+ DLOG(ERROR) << "Failed to initialize JPEG decoder";
+ }
+
+ decoder_status_ = success ? INIT_PASSED : FAILED;
+ RecordInitDecodeUMA_Locked();
+}
+
+bool VideoCaptureJpegDecoderImpl::IsDecoding_Locked() const {
+ lock_.AssertAcquired();
+ return !decode_done_closure_.is_null();
+}
+
+void VideoCaptureJpegDecoderImpl::RecordInitDecodeUMA_Locked() {
+ UMA_HISTOGRAM_BOOLEAN("Media.VideoCaptureGpuJpegDecoder.InitDecodeSuccess",
+ decoder_status_ == INIT_PASSED);
+}
+
+void VideoCaptureJpegDecoderImpl::DestroyDecoderOnIOThread(
+ base::WaitableEvent* event) {
+ DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence());
+ decoder_.reset();
+ event->Signal();
+}
+
+} // namespace media
diff --git a/chromium/media/capture/video/video_capture_jpeg_decoder_impl.h b/chromium/media/capture/video/video_capture_jpeg_decoder_impl.h
new file mode 100644
index 00000000000..a1bfcee8b75
--- /dev/null
+++ b/chromium/media/capture/video/video_capture_jpeg_decoder_impl.h
@@ -0,0 +1,119 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAPTURE_VIDEO_VIDEO_CAPTURE_JPEG_DECODER_IMPL_H_
+#define MEDIA_CAPTURE_VIDEO_VIDEO_CAPTURE_JPEG_DECODER_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "gpu/config/gpu_info.h"
+#include "media/capture/capture_export.h"
+#include "media/capture/video/video_capture_device_factory.h"
+#include "media/capture/video/video_capture_jpeg_decoder.h"
+#include "media/mojo/clients/mojo_jpeg_decode_accelerator.h"
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace media {
+
+// Implementation of media::VideoCaptureJpegDecoder that delegates to a
+// media::mojom::JpegDecodeAccelerator. When a frame is received in
+// DecodeCapturedData(), it is copied to |in_shared_memory| for IPC transport
+// to |decoder_|. When the decoder is finished with the frame, |decode_done_cb_|
+// is invoked. Until |decode_done_cb_| is invoked, subsequent calls to
+// DecodeCapturedData() are ignored.
+// The given |decoder_task_runner| must allow blocking on |lock_|.
+class CAPTURE_EXPORT VideoCaptureJpegDecoderImpl
+ : public media::VideoCaptureJpegDecoder,
+ public media::JpegDecodeAccelerator::Client {
+ public:
+ // |decode_done_cb| is called on the IO thread when decode succeeds. This can
+ // be on any thread. |decode_done_cb| is never called after
+ // VideoCaptureGpuJpegDecoder is destroyed.
+ VideoCaptureJpegDecoderImpl(
+ MojoJpegDecodeAcceleratorFactoryCB jpeg_decoder_factory,
+ scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
+ DecodeDoneCB decode_done_cb,
+ base::RepeatingCallback<void(const std::string&)> send_log_message_cb);
+ ~VideoCaptureJpegDecoderImpl() override;
+
+ // Implementation of VideoCaptureJpegDecoder:
+ void Initialize() override;
+ STATUS GetStatus() const override;
+ void DecodeCapturedData(
+ const uint8_t* data,
+ size_t in_buffer_size,
+ const media::VideoCaptureFormat& frame_format,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp,
+ media::VideoCaptureDevice::Client::Buffer out_buffer) override;
+
+ // JpegDecodeAccelerator::Client implementation.
+ // These will be called on IO thread.
+ void VideoFrameReady(int32_t buffer_id) override;
+ void NotifyError(int32_t buffer_id,
+ media::JpegDecodeAccelerator::Error error) override;
+
+ private:
+ void FinishInitialization();
+ void OnInitializationDone(bool success);
+
+ // Returns true if the decoding of last frame is not finished yet.
+ bool IsDecoding_Locked() const;
+
+ // Records |decoder_status_| to histogram.
+ void RecordInitDecodeUMA_Locked();
+
+ void DestroyDecoderOnIOThread(base::WaitableEvent* event);
+
+ MojoJpegDecodeAcceleratorFactoryCB jpeg_decoder_factory_;
+ scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_;
+
+ // The underlying JPEG decode accelerator.
+ std::unique_ptr<media::JpegDecodeAccelerator> decoder_;
+
+ // The callback to run when decode succeeds.
+ const DecodeDoneCB decode_done_cb_;
+
+ const base::RepeatingCallback<void(const std::string&)> send_log_message_cb_;
+ bool has_received_decoded_frame_;
+
+ // Guards |decode_done_closure_| and |decoder_status_|.
+ mutable base::Lock lock_;
+
+ // The closure of |decode_done_cb_| with bound parameters.
+ base::OnceClosure decode_done_closure_;
+
+ // Next id for input BitstreamBuffer.
+ int32_t next_bitstream_buffer_id_;
+
+ // The id for current input BitstreamBuffer being decoded.
+ int32_t in_buffer_id_;
+
+ // Shared memory to store JPEG stream buffer. The input BitstreamBuffer is
+ // backed by this.
+ std::unique_ptr<base::SharedMemory> in_shared_memory_;
+
+ STATUS decoder_status_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ base::WeakPtrFactory<VideoCaptureJpegDecoderImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoCaptureJpegDecoderImpl);
+};
+
+} // namespace media
+
+#endif // MEDIA_CAPTURE_VIDEO_VIDEO_CAPTURE_JPEG_DECODER_IMPL_H_
diff --git a/chromium/media/capture/video/win/video_capture_device_factory_win.cc b/chromium/media/capture/video/win/video_capture_device_factory_win.cc
index ef04526c06f..bad25d00bf4 100644
--- a/chromium/media/capture/video/win/video_capture_device_factory_win.cc
+++ b/chromium/media/capture/video/win/video_capture_device_factory_win.cc
@@ -18,6 +18,7 @@
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/win/core_winrt_util.h"
@@ -83,6 +84,11 @@ static_assert(arraysize(kBlacklistedCameraNames) == BLACKLISTED_CAMERA_MAX + 1,
"kBlacklistedCameraNames should be same size as "
"BlacklistedCameraNames enum");
+const char* const kModelIdsBlacklistedForMediaFoundation[] = {
+ // Devices using Empia 2860 or 2820 chips, see https://crbug.com/849636.
+ "eb1a:2860", "eb1a:2820",
+};
+
const std::pair<VideoCaptureApi, std::vector<std::pair<GUID, GUID>>>
kMfAttributes[] = {{VideoCaptureApi::WIN_MEDIA_FOUNDATION,
{
@@ -100,6 +106,11 @@ bool IsDeviceBlacklistedForQueryingDetailedFrameRates(
return display_name.find("WebcamMax") != std::string::npos;
}
+bool IsDeviceBlacklistedForMediaFoundationByModelId(
+ const std::string& model_id) {
+ return base::ContainsValue(kModelIdsBlacklistedForMediaFoundation, model_id);
+}
+
bool LoadMediaFoundationDlls() {
static const wchar_t* const kMfDLLs[] = {
L"%WINDIR%\\system32\\mf.dll", L"%WINDIR%\\system32\\mfplat.dll",
@@ -354,7 +365,7 @@ VideoCaptureDeviceFactoryWin::VideoCaptureDeviceFactoryWin()
direct_show_get_supported_formats_func_ =
base::BindRepeating(&GetDeviceSupportedFormatsDirectShow);
- if (!PlatformSupportsMediaFoundation()) {
+ if (use_media_foundation_ && !PlatformSupportsMediaFoundation()) {
use_media_foundation_ = false;
LogVideoCaptureWinBackendUsed(
VideoCaptureWinBackendUsed::kUsingDirectShowAsFallback);
@@ -612,6 +623,8 @@ void VideoCaptureDeviceFactoryWin::GetDeviceDescriptorsMediaFoundation(
const std::string device_id =
base::SysWideToUTF8(std::wstring(id, id_size));
const std::string model_id = GetDeviceModelId(device_id);
+ if (IsDeviceBlacklistedForMediaFoundationByModelId(model_id))
+ continue;
if (list_was_empty ||
!DescriptorsContainDeviceId(*device_descriptors, device_id)) {
device_descriptors->emplace_back(
@@ -753,14 +766,4 @@ void VideoCaptureDeviceFactoryWin::GetSupportedFormats(
GetApiSpecificSupportedFormats(device, formats);
}
-// static
-VideoCaptureDeviceFactory*
-VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory(
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- MojoJpegDecodeAcceleratorFactoryCB jda_factory,
- MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
- return new VideoCaptureDeviceFactoryWin();
-}
-
} // namespace media
diff --git a/chromium/media/capture/video/win/video_capture_device_factory_win_unittest.cc b/chromium/media/capture/video/win/video_capture_device_factory_win_unittest.cc
index 80b5532a6a0..27dd51e4f55 100644
--- a/chromium/media/capture/video/win/video_capture_device_factory_win_unittest.cc
+++ b/chromium/media/capture/video/win/video_capture_device_factory_win_unittest.cc
@@ -33,8 +33,16 @@ const wchar_t* kMFDeviceName2 = L"Device 2";
const wchar_t* kMFDeviceId5 = L"\\\\?\\usb#vid_0005&pid_0005&mi_00";
const wchar_t* kMFDeviceName5 = L"Dazzle";
+const wchar_t* kMFDeviceId6 = L"\\\\?\\usb#vid_eb1a&pid_2860&mi_00";
+const wchar_t* kMFDeviceName6 = L"Empia Device";
+
void GetMFSupportedFormats(const VideoCaptureDeviceDescriptor& device,
- VideoCaptureFormats* formats) {}
+ VideoCaptureFormats* formats) {
+ if (device.device_id == base::SysWideToUTF8(kMFDeviceId6)) {
+ VideoCaptureFormat arbitrary_format;
+ formats->emplace_back(arbitrary_format);
+ }
+}
// DirectShow devices
const wchar_t* kDirectShowDeviceId0 = L"\\\\?\\usb#vid_0000&pid_0000&mi_00";
@@ -52,6 +60,9 @@ const wchar_t* kDirectShowDeviceName4 = L"Virtual Camera";
const wchar_t* kDirectShowDeviceId5 = L"\\\\?\\usb#vid_0005&pid_0005&mi_00#5";
const wchar_t* kDirectShowDeviceName5 = L"Dazzle";
+const wchar_t* kDirectShowDeviceId6 = L"\\\\?\\usb#vid_eb1a&pid_2860&mi_00";
+const wchar_t* kDirectShowDeviceName6 = L"Empia Device";
+
void GetDirectShowSupportedFormats(const VideoCaptureDeviceDescriptor& device,
VideoCaptureFormats* formats) {
if (device.device_id == base::SysWideToUTF8(kDirectShowDeviceId5)) {
@@ -426,7 +437,8 @@ HRESULT __stdcall MockMFEnumDeviceSources(IMFAttributes* attributes,
new MockMFActivate(kMFDeviceId0, kMFDeviceName0, true, false),
new MockMFActivate(kMFDeviceId1, kMFDeviceName1, true, true),
new MockMFActivate(kMFDeviceId2, kMFDeviceName2, false, true),
- new MockMFActivate(kMFDeviceId5, kMFDeviceName5, true, false)};
+ new MockMFActivate(kMFDeviceId5, kMFDeviceName5, true, false),
+ new MockMFActivate(kMFDeviceId6, kMFDeviceName6, true, false)};
// Iterate once to get the match count and check for errors.
*count = 0U;
HRESULT hr;
@@ -456,7 +468,8 @@ HRESULT EnumerateStubDirectShowDevices(IEnumMoniker** enum_moniker) {
new StubMoniker(kDirectShowDeviceId1, kDirectShowDeviceName1),
new StubMoniker(kDirectShowDeviceId3, kDirectShowDeviceName3),
new StubMoniker(kDirectShowDeviceId4, kDirectShowDeviceName4),
- new StubMoniker(kDirectShowDeviceId5, kDirectShowDeviceName5)};
+ new StubMoniker(kDirectShowDeviceId5, kDirectShowDeviceName5),
+ new StubMoniker(kDirectShowDeviceId6, kDirectShowDeviceName6)};
StubEnumMoniker* stub_enum_moniker = new StubEnumMoniker();
for (StubMoniker* moniker : monikers)
@@ -511,7 +524,7 @@ TEST_F(VideoCaptureDeviceFactoryMFWinTest, GetDeviceDescriptors) {
base::BindRepeating(&EnumerateStubDirectShowDevices));
VideoCaptureDeviceDescriptors descriptors;
factory_.GetDeviceDescriptors(&descriptors);
- EXPECT_EQ(descriptors.size(), 6U);
+ EXPECT_EQ(descriptors.size(), 7U);
for (auto it = descriptors.begin(); it != descriptors.end(); it++) {
// Verify that there are no duplicates.
EXPECT_EQ(FindDescriptorInRange(descriptors.begin(), it, it->device_id),
@@ -555,6 +568,15 @@ TEST_F(VideoCaptureDeviceFactoryMFWinTest, GetDeviceDescriptors) {
EXPECT_NE(it, descriptors.end());
EXPECT_EQ(it->capture_api, VideoCaptureApi::WIN_DIRECT_SHOW);
EXPECT_EQ(it->display_name(), base::SysWideToUTF8(kDirectShowDeviceName5));
+
+ // Devices that are listed in both MediaFoundation and DirectShow but are
+ // blacklisted for use with MediaFoundation are expected to get enumerated
+ // with VideoCaptureApi::WIN_DIRECT_SHOW.
+ it = FindDescriptorInRange(descriptors.begin(), descriptors.end(),
+ base::SysWideToUTF8(kDirectShowDeviceId6));
+ EXPECT_NE(it, descriptors.end());
+ EXPECT_EQ(it->capture_api, VideoCaptureApi::WIN_DIRECT_SHOW);
+ EXPECT_EQ(it->display_name(), base::SysWideToUTF8(kDirectShowDeviceName6));
}
} // namespace media
diff --git a/chromium/media/capture/video/win/video_capture_device_win.cc b/chromium/media/capture/video/win/video_capture_device_win.cc
index 78355961260..ae1bf4d602b 100644
--- a/chromium/media/capture/video/win/video_capture_device_win.cc
+++ b/chromium/media/capture/video/win/video_capture_device_win.cc
@@ -83,9 +83,9 @@ mojom::RangePtr RetrieveControlRangeAndCurrent(
control_range->max = max;
control_range->step = step;
if (supported_modes != nullptr) {
- if (flags && CameraControl_Flags_Auto)
+ if (flags & CameraControl_Flags_Auto)
supported_modes->push_back(mojom::MeteringMode::CONTINUOUS);
- if (flags && CameraControl_Flags_Manual)
+ if (flags & CameraControl_Flags_Manual)
supported_modes->push_back(mojom::MeteringMode::MANUAL);
}
}
@@ -95,9 +95,9 @@ mojom::RangePtr RetrieveControlRangeAndCurrent(
if (SUCCEEDED(hr)) {
control_range->current = current;
if (current_mode != nullptr) {
- if (flags && CameraControl_Flags_Auto)
+ if (flags & CameraControl_Flags_Auto)
*current_mode = mojom::MeteringMode::CONTINUOUS;
- else if (flags && CameraControl_Flags_Manual)
+ else if (flags & CameraControl_Flags_Manual)
*current_mode = mojom::MeteringMode::MANUAL;
}
}
diff --git a/chromium/media/capture/video_capture_types.cc b/chromium/media/capture/video_capture_types.cc
index b6fc66e20c3..6cd3063bfee 100644
--- a/chromium/media/capture/video_capture_types.cc
+++ b/chromium/media/capture/video_capture_types.cc
@@ -70,7 +70,8 @@ bool VideoCaptureFormat::ComparePixelFormatPreference(
}
VideoCaptureParams::VideoCaptureParams()
- : resolution_change_policy(ResolutionChangePolicy::FIXED_RESOLUTION),
+ : buffer_type(VideoCaptureBufferType::kSharedMemory),
+ resolution_change_policy(ResolutionChangePolicy::FIXED_RESOLUTION),
power_line_frequency(PowerLineFrequency::FREQUENCY_DEFAULT) {}
bool VideoCaptureParams::IsValid() const {
diff --git a/chromium/media/capture/video_capture_types.h b/chromium/media/capture/video_capture_types.h
index bb43a319454..cc7a5c42f6a 100644
--- a/chromium/media/capture/video_capture_types.h
+++ b/chromium/media/capture/video_capture_types.h
@@ -54,6 +54,12 @@ enum class PowerLineFrequency {
FREQUENCY_MAX = FREQUENCY_60HZ
};
+enum class VideoCaptureBufferType {
+ kSharedMemory,
+ kSharedMemoryViaRawFileDescriptor,
+ kMailboxHolder
+};
+
// Assert that the int:frequency mapping is correct.
static_assert(static_cast<int>(PowerLineFrequency::FREQUENCY_DEFAULT) == 0,
"static_cast<int>(FREQUENCY_DEFAULT) must equal 0.");
@@ -135,6 +141,8 @@ struct CAPTURE_EXPORT VideoCaptureParams {
// Requests a resolution and format at which the capture will occur.
VideoCaptureFormat requested_format;
+ VideoCaptureBufferType buffer_type;
+
// Policy for resolution change.
ResolutionChangePolicy resolution_change_policy;