summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authormcasas@chromium.org <mcasas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 15:27:34 +0000
committermcasas@chromium.org <mcasas@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 15:27:34 +0000
commit7629a77a64629178432fe9f6a0903a2dab3cc641 (patch)
treead1ea906f325604c9ff20a1d67c42b6d343723b8 /media
parent789822be0cb55567d4bfcc3c44d9eb33ca0ed660 (diff)
downloadchromium_src-7629a77a64629178432fe9f6a0903a2dab3cc641.zip
chromium_src-7629a77a64629178432fe9f6a0903a2dab3cc641.tar.gz
chromium_src-7629a77a64629178432fe9f6a0903a2dab3cc641.tar.bz2
Revert of Mac Video Capture Device: split VCD into VCD and Factory. (https://codereview.chromium.org/265263004/)
Reason for revert: Some backoffice bots broke due to |kUseFakeDeviceForMediaStream| not being correctly defined - reverting until M36 storm passes and then I'll figure those out. Original issue's description: > Mac Video Capture Device: split VCD into VCD and Factory. > > VideoCaptureDeviceMac includes factory and non-factory parts. > This CL splits them into VideoCaptureDeviceMac and > VideoCaptureDeviceFactoryMac. The latter inherits the previous > class' static methods: Create(), GetDeviceNames() and > GetDeviceSupportedFormats(). > > All video factory code previously in MediaStreamManager is > moved into VideoCaptureFactory. This includes the use > of the flag |kUseFakeDeviceForMediaStream|. > This flag is moved correspondingly into media_switches.cc -- > (but note that this flag is still used in MediaStreamManager for > the Fake Audio parts). File media_switches.cc is > included in several test files where the flag is used. > > > VideoCaptureDeviceTest is splitted as well into: > a) Tests that were exercising only the FakeVCD > (FakeVideoCaptureDeviceTest). > b) All other tests, that use the underlying OS webcam. > This VideoCaptureDeviceTest gets a Factory and uses it > instead of static methods. > > A unit test is added to VCDFMac, doing little for the moment > but I'm planning to add support for testing at least the > blacklisting -- req from rsesek@ in another CL. > > BUG=288562, 323913, 255552 > > Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=269271 TBR=perkj@chromium.org,jochen@chromium.org,dalecurtis@chromium.org NOTREECHECKS=true NOTRY=true BUG=288562, 323913, 255552 Review URL: https://codereview.chromium.org/273063002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269312 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/base/media_switches.cc4
-rw-r--r--media/base/media_switches.h1
-rw-r--r--media/media.gyp10
-rw-r--r--media/video/capture/fake_video_capture_device_unittest.cc180
-rw-r--r--media/video/capture/mac/video_capture_device_factory_mac.h34
-rw-r--r--media/video/capture/mac/video_capture_device_factory_mac.mm125
-rw-r--r--media/video/capture/mac/video_capture_device_factory_mac_unittest.mm42
-rw-r--r--media/video/capture/mac/video_capture_device_mac.h17
-rw-r--r--media/video/capture/mac/video_capture_device_mac.mm114
-rw-r--r--media/video/capture/video_capture_device_factory.cc38
-rw-r--r--media/video/capture/video_capture_device_factory.h4
-rw-r--r--media/video/capture/video_capture_device_unittest.cc142
12 files changed, 223 insertions, 488 deletions
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index e7982da..515c0bc 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -40,7 +40,6 @@ const char kAlsaOutputDevice[] = "alsa-output-device";
// for experimentation purposes, in particular library load time issue, the
// usage of this library can be enabled by using this flag.
const char kEnableAVFoundation[] = "enable-avfoundation";
-
// QTKit is the media capture API predecessor to AVFoundation, available up and
// until Mac OS X 10.9 (despite being deprecated in this last one). This flag
// is used for troubleshooting and testing, and forces QTKit in builds and
@@ -86,9 +85,6 @@ const char kWaveOutBuffers[] = "waveout-buffers";
const char kUseCras[] = "use-cras";
#endif
-// Use fake device for Media Stream to replace actual camera and microphone.
-const char kUseFakeDeviceForMediaStream[] = "use-fake-device-for-media-stream";
-
// Use a raw video file as fake video capture device.
const char kUseFileForFakeVideoCapture[] = "use-file-for-fake-video-capture";
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index a225a18..90a25f4 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -46,7 +46,6 @@ MEDIA_EXPORT extern const char kWaveOutBuffers[];
MEDIA_EXPORT extern const char kUseCras[];
#endif
-MEDIA_EXPORT extern const char kUseFakeDeviceForMediaStream[];
MEDIA_EXPORT extern const char kUseFileForFakeVideoCapture[];
} // namespace switches
diff --git a/media/media.gyp b/media/media.gyp
index ddc91fa..a799028 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -52,7 +52,7 @@
'type': '<(component)',
'dependencies': [
'../base/base.gyp:base',
- '../base/base.gyp:base_i18n',
+ '../base/base.gyp:base_i18n',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../crypto/crypto.gyp:crypto',
'../gpu/gpu.gyp:command_buffer_common',
@@ -475,8 +475,6 @@
'video/capture/mac/platform_video_capturing_mac.h',
'video/capture/mac/video_capture_device_avfoundation_mac.h',
'video/capture/mac/video_capture_device_avfoundation_mac.mm',
- 'video/capture/mac/video_capture_device_factory_mac.h',
- 'video/capture/mac/video_capture_device_factory_mac.mm',
'video/capture/mac/video_capture_device_mac.h',
'video/capture/mac/video_capture_device_mac.mm',
'video/capture/mac/video_capture_device_qtkit_mac.h',
@@ -1065,7 +1063,6 @@
'midi/usb_midi_descriptor_parser_unittest.cc',
'midi/usb_midi_input_stream_unittest.cc',
'midi/usb_midi_output_stream_unittest.cc',
- 'video/capture/fake_video_capture_device_unittest.cc',
'video/capture/video_capture_device_unittest.cc',
'formats/common/offset_byte_queue_unittest.cc',
'formats/webm/cluster_builder.cc',
@@ -1196,11 +1193,6 @@
['OS=="win" and target_arch=="x64"', {
'msvs_disabled_warnings': [ 4267, ],
}],
- ['OS=="mac"', {
- 'sources': [
- 'video/capture/mac/video_capture_device_factory_mac_unittest.mm',
- ]
- }],
],
},
{
diff --git a/media/video/capture/fake_video_capture_device_unittest.cc b/media/video/capture/fake_video_capture_device_unittest.cc
deleted file mode 100644
index 9bbbe67..0000000
--- a/media/video/capture/fake_video_capture_device_unittest.cc
+++ /dev/null
@@ -1,180 +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 "base/bind.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/run_loop.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/thread.h"
-#include "media/video/capture/fake_video_capture_device.h"
-#include "media/video/capture/fake_video_capture_device_factory.h"
-#include "media/video/capture/video_capture_device.h"
-#include "media/video/capture/video_capture_types.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-
-namespace media {
-
-class MockClient : public media::VideoCaptureDevice::Client {
- public:
- MOCK_METHOD2(ReserveOutputBuffer,
- scoped_refptr<Buffer>(media::VideoFrame::Format format,
- const gfx::Size& dimensions));
- MOCK_METHOD0(OnErr, void());
-
- explicit MockClient(base::Callback<void(const VideoCaptureFormat&)> frame_cb)
- : main_thread_(base::MessageLoopProxy::current()), frame_cb_(frame_cb) {}
-
- virtual void OnError(const std::string& error_message) OVERRIDE {
- OnErr();
- }
-
- virtual void OnIncomingCapturedData(const uint8* data,
- int length,
- const VideoCaptureFormat& format,
- int rotation,
- base::TimeTicks timestamp) OVERRIDE {
- main_thread_->PostTask(FROM_HERE, base::Bind(frame_cb_, format));
- }
-
- virtual void OnIncomingCapturedVideoFrame(
- const scoped_refptr<Buffer>& buffer,
- const media::VideoCaptureFormat& buffer_format,
- const scoped_refptr<media::VideoFrame>& frame,
- base::TimeTicks timestamp) OVERRIDE {
- NOTREACHED();
- }
-
- private:
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
- base::Callback<void(const VideoCaptureFormat&)> frame_cb_;
-};
-
-class FakeVideoCaptureDeviceTest : public testing::Test {
- protected:
- typedef media::VideoCaptureDevice::Client Client;
-
- FakeVideoCaptureDeviceTest()
- : loop_(new base::MessageLoop()),
- client_(new MockClient(
- base::Bind(&FakeVideoCaptureDeviceTest::OnFrameCaptured,
- base::Unretained(this)))),
- video_capture_device_factory_(new FakeVideoCaptureDeviceFactory()) {}
-
- virtual void SetUp() {
- }
-
- void OnFrameCaptured(const VideoCaptureFormat& format) {
- last_format_ = format;
- run_loop_->QuitClosure().Run();
- }
-
- void WaitForCapturedFrame() {
- run_loop_.reset(new base::RunLoop());
- run_loop_->Run();
- }
-
- const VideoCaptureFormat& last_format() const { return last_format_; }
-
- VideoCaptureDevice::Names names_;
- scoped_ptr<base::MessageLoop> loop_;
- scoped_ptr<base::RunLoop> run_loop_;
- scoped_ptr<MockClient> client_;
- VideoCaptureFormat last_format_;
- scoped_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_;
-};
-
-TEST_F(FakeVideoCaptureDeviceTest, Capture) {
- VideoCaptureDevice::Names names;
-
- video_capture_device_factory_->GetDeviceNames(&names);
-
- ASSERT_GT(static_cast<int>(names.size()), 0);
-
- scoped_ptr<VideoCaptureDevice> device(
- video_capture_device_factory_->Create(names.front()));
- ASSERT_TRUE(device);
-
- EXPECT_CALL(*client_, OnErr()).Times(0);
-
- VideoCaptureParams capture_params;
- capture_params.requested_format.frame_size.SetSize(640, 480);
- capture_params.requested_format.frame_rate = 30;
- capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
- device->AllocateAndStart(capture_params, client_.PassAs<Client>());
- WaitForCapturedFrame();
- EXPECT_EQ(last_format().frame_size.width(), 640);
- EXPECT_EQ(last_format().frame_size.height(), 480);
- EXPECT_EQ(last_format().frame_rate, 30);
- device->StopAndDeAllocate();
-}
-
-TEST_F(FakeVideoCaptureDeviceTest, GetDeviceSupportedFormats) {
- VideoCaptureDevice::Names names;
- video_capture_device_factory_->GetDeviceNames(&names);
-
- VideoCaptureFormats supported_formats;
- VideoCaptureDevice::Names::iterator names_iterator;
-
- for (names_iterator = names.begin(); names_iterator != names.end();
- ++names_iterator) {
- video_capture_device_factory_->GetDeviceSupportedFormats(
- *names_iterator, &supported_formats);
- EXPECT_EQ(supported_formats.size(), 3u);
- EXPECT_EQ(supported_formats[0].frame_size.width(), 320);
- EXPECT_EQ(supported_formats[0].frame_size.height(), 240);
- EXPECT_EQ(supported_formats[0].pixel_format, media::PIXEL_FORMAT_I420);
- EXPECT_GE(supported_formats[0].frame_rate, 20);
- EXPECT_EQ(supported_formats[1].frame_size.width(), 640);
- EXPECT_EQ(supported_formats[1].frame_size.height(), 480);
- EXPECT_EQ(supported_formats[1].pixel_format, media::PIXEL_FORMAT_I420);
- EXPECT_GE(supported_formats[1].frame_rate, 20);
- EXPECT_EQ(supported_formats[2].frame_size.width(), 1280);
- EXPECT_EQ(supported_formats[2].frame_size.height(), 720);
- EXPECT_EQ(supported_formats[2].pixel_format, media::PIXEL_FORMAT_I420);
- EXPECT_GE(supported_formats[2].frame_rate, 20);
- }
-}
-
-TEST_F(FakeVideoCaptureDeviceTest, CaptureVariableResolution) {
- VideoCaptureDevice::Names names;
-
- video_capture_device_factory_->GetDeviceNames(&names);
- VideoCaptureParams capture_params;
- capture_params.requested_format.frame_size.SetSize(640, 480);
- capture_params.requested_format.frame_rate = 30;
- capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = true;
-
- ASSERT_GT(static_cast<int>(names.size()), 0);
-
- scoped_ptr<VideoCaptureDevice> device(
- video_capture_device_factory_->Create(names.front()));
- ASSERT_TRUE(device);
-
- // Configure the FakeVideoCaptureDevice to use all its formats as roster.
- VideoCaptureFormats formats;
- video_capture_device_factory_->GetDeviceSupportedFormats(names.front(),
- &formats);
- static_cast<FakeVideoCaptureDevice*>(device.get())->
- PopulateVariableFormatsRoster(formats);
-
- EXPECT_CALL(*client_, OnErr())
- .Times(0);
- int action_count = 200;
-
- device->AllocateAndStart(capture_params, client_.PassAs<Client>());
-
- // We set TimeWait to 200 action timeouts and this should be enough for at
- // least action_count/kFakeCaptureCapabilityChangePeriod calls.
- for (int i = 0; i < action_count; ++i) {
- WaitForCapturedFrame();
- }
- device->StopAndDeAllocate();
-}
-
-}; // namespace media
diff --git a/media/video/capture/mac/video_capture_device_factory_mac.h b/media/video/capture/mac/video_capture_device_factory_mac.h
deleted file mode 100644
index a581925..0000000
--- a/media/video/capture/mac/video_capture_device_factory_mac.h
+++ /dev/null
@@ -1,34 +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.
-
-// Implementation of a VideoCaptureDeviceFactory class for Mac.
-
-#ifndef MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_FACTORY_MAC_H_
-#define MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_FACTORY_MAC_H_
-
-#include "media/video/capture/video_capture_device_factory.h"
-
-namespace media {
-
-// Extension of VideoCaptureDeviceFactory to create and manipulate Mac devices.
-class MEDIA_EXPORT VideoCaptureDeviceFactoryMac :
- public VideoCaptureDeviceFactory {
- public:
- VideoCaptureDeviceFactoryMac();
- virtual ~VideoCaptureDeviceFactoryMac() {}
-
- virtual scoped_ptr<VideoCaptureDevice> Create(
- const VideoCaptureDevice::Name& device_name) OVERRIDE;
- virtual void GetDeviceNames(VideoCaptureDevice::Names* device_names) OVERRIDE;
- virtual void GetDeviceSupportedFormats(
- const VideoCaptureDevice::Name& device,
- VideoCaptureFormats* supported_formats) OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactoryMac);
-};
-
-} // namespace media
-
-#endif // MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_FACTORY_MAC_H_
diff --git a/media/video/capture/mac/video_capture_device_factory_mac.mm b/media/video/capture/mac/video_capture_device_factory_mac.mm
deleted file mode 100644
index 0e24203..0000000
--- a/media/video/capture/mac/video_capture_device_factory_mac.mm
+++ /dev/null
@@ -1,125 +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/video/capture/mac/video_capture_device_factory_mac.h"
-
-#import "media/video/capture/mac/avfoundation_glue.h"
-#include "media/video/capture/mac/video_capture_device_mac.h"
-#import "media/video/capture/mac/video_capture_device_avfoundation_mac.h"
-#import "media/video/capture/mac/video_capture_device_qtkit_mac.h"
-
-namespace media {
-
-// Some devices are not correctly supported in AVFoundation, f.i. Blackmagic,
-// see http://crbug.com/347371. The devices are identified by USB Vendor ID and
-// by a characteristic substring of the name, usually the vendor's name.
-const struct NameAndVid {
- const char* vid;
- const char* name;
-} kBlacklistedCameras[] = { { "a82c", "Blackmagic" } };
-
-// In device identifiers, the USB VID and PID are stored in 4 bytes each.
-const size_t kVidPidSize = 4;
-
-VideoCaptureDeviceFactoryMac::VideoCaptureDeviceFactoryMac() {
- thread_checker_.DetachFromThread();
-}
-
-scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryMac::Create(
- const VideoCaptureDevice::Name& device_name) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK_NE(device_name.capture_api_type(),
- VideoCaptureDevice::Name::API_TYPE_UNKNOWN);
-
- VideoCaptureDevice::Names device_names;
- GetDeviceNames(&device_names);
- VideoCaptureDevice::Names::iterator it = device_names.begin();
- for (; it != device_names.end(); ++it) {
- if (it->id() == device_name.id())
- break;
- }
- if (it == device_names.end())
- return scoped_ptr<VideoCaptureDevice>();
-
- scoped_ptr<VideoCaptureDeviceMac> capture_device(
- new VideoCaptureDeviceMac(device_name));
- if (!capture_device->Init(device_name.capture_api_type())) {
- LOG(ERROR) << "Could not initialize VideoCaptureDevice.";
- capture_device.reset();
- }
- return scoped_ptr<VideoCaptureDevice>(capture_device.Pass());
-}
-
-void VideoCaptureDeviceFactoryMac::GetDeviceNames(
- VideoCaptureDevice::Names* const device_names) {
- DCHECK(thread_checker_.CalledOnValidThread());
- // Loop through all available devices and add to |device_names|.
- NSDictionary* capture_devices;
- if (AVFoundationGlue::IsAVFoundationSupported()) {
- bool is_any_device_blacklisted = false;
- DVLOG(1) << "Enumerating video capture devices using AVFoundation";
- capture_devices = [VideoCaptureDeviceAVFoundation deviceNames];
- std::string device_vid;
- // Enumerate all devices found by AVFoundation, translate the info for each
- // to class Name and add it to |device_names|.
- for (NSString* key in capture_devices) {
- VideoCaptureDevice::Name name(
- [[capture_devices valueForKey:key] UTF8String],
- [key UTF8String], VideoCaptureDevice::Name::AVFOUNDATION);
- device_names->push_back(name);
- // Extract the device's Vendor ID and compare to all blacklisted ones.
- device_vid = name.GetModel().substr(0, kVidPidSize);
- for (size_t i = 0; i < arraysize(kBlacklistedCameras); ++i) {
- is_any_device_blacklisted |=
- !strcasecmp(device_vid.c_str(), kBlacklistedCameras[i].vid);
- if (is_any_device_blacklisted)
- break;
- }
- }
- // If there is any device blacklisted in the system, walk the QTKit device
- // list and add those devices with a blacklisted name to the |device_names|.
- // AVFoundation and QTKit device lists partially overlap, so add a "QTKit"
- // prefix to the latter ones to distinguish them from the AVFoundation ones.
- if (is_any_device_blacklisted) {
- capture_devices = [VideoCaptureDeviceQTKit deviceNames];
- for (NSString* key in capture_devices) {
- NSString* device_name = [capture_devices valueForKey:key];
- for (size_t i = 0; i < arraysize(kBlacklistedCameras); ++i) {
- if ([device_name rangeOfString:@(kBlacklistedCameras[i].name)
- options:NSCaseInsensitiveSearch].length != 0) {
- DVLOG(1) << "Enumerated blacklisted " << [device_name UTF8String];
- VideoCaptureDevice::Name name(
- "QTKit " + std::string([device_name UTF8String]),
- [key UTF8String], VideoCaptureDevice::Name::QTKIT);
- device_names->push_back(name);
- }
- }
- }
- }
- } else {
- DVLOG(1) << "Enumerating video capture devices using QTKit";
- capture_devices = [VideoCaptureDeviceQTKit deviceNames];
- for (NSString* key in capture_devices) {
- VideoCaptureDevice::Name name(
- [[capture_devices valueForKey:key] UTF8String],
- [key UTF8String], VideoCaptureDevice::Name::QTKIT);
- device_names->push_back(name);
- }
- }
-}
-
-void VideoCaptureDeviceFactoryMac::GetDeviceSupportedFormats(
- const VideoCaptureDevice::Name& device,
- VideoCaptureFormats* supported_formats) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (device.capture_api_type() == VideoCaptureDevice::Name::AVFOUNDATION) {
- DVLOG(1) << "Enumerating video capture capabilities, AVFoundation";
- [VideoCaptureDeviceAVFoundation getDevice:device
- supportedFormats:supported_formats];
- } else {
- NOTIMPLEMENTED();
- }
-}
-
-} // namespace media
diff --git a/media/video/capture/mac/video_capture_device_factory_mac_unittest.mm b/media/video/capture/mac/video_capture_device_factory_mac_unittest.mm
deleted file mode 100644
index 6aa23a9..0000000
--- a/media/video/capture/mac/video_capture_device_factory_mac_unittest.mm
+++ /dev/null
@@ -1,42 +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 "base/command_line.h"
-#include "media/base/media_switches.h"
-#import "media/video/capture/mac/avfoundation_glue.h"
-#include "media/video/capture/mac/video_capture_device_factory_mac.h"
-#include "media/video/capture/mac/video_capture_device_mac.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace media {
-
-class VideoCaptureDeviceFactoryMacTest : public testing::Test {
- virtual void SetUp() {
- CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableAVFoundation);
- }
-};
-
-TEST_F(VideoCaptureDeviceFactoryMacTest, ListDevicesAVFoundation) {
- if (!AVFoundationGlue::IsAVFoundationSupported()) {
- DVLOG(1) << "AVFoundation not supported, skipping test.";
- return;
- }
- VideoCaptureDeviceFactoryMac video_capture_device_factory;
-
- VideoCaptureDevice::Names names;
- video_capture_device_factory.GetDeviceNames(&names);
- if (!names.size()) {
- DVLOG(1) << "No camera available. Exiting test.";
- return;
- }
- // There should be no blacklisted devices, i.e. QTKit.
- std::string device_vid;
- for (VideoCaptureDevice::Names::const_iterator it = names.begin();
- it != names.end(); ++it) {
- EXPECT_EQ(it->capture_api_type(), VideoCaptureDevice::Name::AVFOUNDATION);
- }
-}
-
-}; // namespace media
diff --git a/media/video/capture/mac/video_capture_device_mac.h b/media/video/capture/mac/video_capture_device_mac.h
index b28dacb..3b12d83 100644
--- a/media/video/capture/mac/video_capture_device_mac.h
+++ b/media/video/capture/mac/video_capture_device_mac.h
@@ -3,9 +3,8 @@
// found in the LICENSE file.
// MacOSX implementation of generic VideoCaptureDevice, using either QTKit or
-// AVFoundation as native capture API. QTKit is available in all OSX versions,
-// although namely deprecated in 10.9, and AVFoundation is available in versions
-// 10.7 (Lion) and later.
+// AVFoundation as native capture API. QTKit is used in OSX versions 10.6 and
+// previous, and AVFoundation is used in the rest.
#ifndef MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_MAC_H_
#define MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_MAC_H_
@@ -26,20 +25,20 @@ class SingleThreadTaskRunner;
namespace media {
-// Called by VideoCaptureManager to open, close and start, stop Mac video
-// capture devices.
+// Called by VideoCaptureManager to open, close and start, stop video capture
+// devices.
class VideoCaptureDeviceMac : public VideoCaptureDevice {
public:
explicit VideoCaptureDeviceMac(const Name& device_name);
virtual ~VideoCaptureDeviceMac();
// VideoCaptureDevice implementation.
- virtual void AllocateAndStart(
- const VideoCaptureParams& params,
- scoped_ptr<VideoCaptureDevice::Client> client) OVERRIDE;
+ virtual void AllocateAndStart(const VideoCaptureParams& params,
+ scoped_ptr<VideoCaptureDevice::Client> client)
+ OVERRIDE;
virtual void StopAndDeAllocate() OVERRIDE;
- bool Init(VideoCaptureDevice::Name::CaptureApiType capture_api_type);
+ bool Init();
// Called to deliver captured video frames.
void ReceiveFrame(const uint8* video_frame,
diff --git a/media/video/capture/mac/video_capture_device_mac.mm b/media/video/capture/mac/video_capture_device_mac.mm
index 5aacd26..bc3d541 100644
--- a/media/video/capture/mac/video_capture_device_mac.mm
+++ b/media/video/capture/mac/video_capture_device_mac.mm
@@ -22,6 +22,14 @@ const int kMaxFrameRate = 30;
// In device identifiers, the USB VID and PID are stored in 4 bytes each.
const size_t kVidPidSize = 4;
+// Some devices are not correctly supported in AVFoundation, f.i. Blackmagic,
+// see http://crbug.com/347371. The devices are identified by USB Vendor ID and
+// by a characteristic substring of the name, usually the vendor's name.
+const struct NameAndVid {
+ const char* vid;
+ const char* name;
+} kBlacklistedCameras[] = { { "a82c", "Blackmagic" } };
+
const struct Resolution {
const int width;
const int height;
@@ -61,26 +69,70 @@ void GetBestMatchSupportedResolution(int* width, int* height) {
*height = matched_height;
}
-// TODO(mcasas): Remove the following static methods when they are no longer
-// referenced from VideoCaptureDeviceFactory, i.e. when all OS platforms have
-// splitted the VideoCaptureDevice into VideoCaptureDevice and
-// VideoCaptureDeviceFactory.
-
-// static
-VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) {
- NOTREACHED();
- return NULL;
-}
-// static
+//static
void VideoCaptureDevice::GetDeviceNames(Names* device_names) {
- NOTREACHED();
+ // Loop through all available devices and add to |device_names|.
+ NSDictionary* capture_devices;
+ if (AVFoundationGlue::IsAVFoundationSupported()) {
+ bool is_any_device_blacklisted = false;
+ DVLOG(1) << "Enumerating video capture devices using AVFoundation";
+ capture_devices = [VideoCaptureDeviceAVFoundation deviceNames];
+ std::string device_vid;
+ // Enumerate all devices found by AVFoundation, translate the info for each
+ // to class Name and add it to |device_names|.
+ for (NSString* key in capture_devices) {
+ Name name([[capture_devices valueForKey:key] UTF8String],
+ [key UTF8String], Name::AVFOUNDATION);
+ device_names->push_back(name);
+ // Extract the device's Vendor ID and compare to all blacklisted ones.
+ device_vid = name.GetModel().substr(0, kVidPidSize);
+ for (size_t i = 0; i < arraysize(kBlacklistedCameras); ++i) {
+ is_any_device_blacklisted |=
+ !strcasecmp(device_vid.c_str(), kBlacklistedCameras[i].vid);
+ if (is_any_device_blacklisted)
+ break;
+ }
+ }
+ // If there is any device blacklisted in the system, walk the QTKit device
+ // list and add those devices with a blacklisted name to the |device_names|.
+ // AVFoundation and QTKit device lists partially overlap, so add a "QTKit"
+ // prefix to the latter ones to distinguish them from the AVFoundation ones.
+ if (is_any_device_blacklisted) {
+ capture_devices = [VideoCaptureDeviceQTKit deviceNames];
+ for (NSString* key in capture_devices) {
+ NSString* device_name = [capture_devices valueForKey:key];
+ for (size_t i = 0; i < arraysize(kBlacklistedCameras); ++i) {
+ if ([device_name rangeOfString:@(kBlacklistedCameras[i].name)
+ options:NSCaseInsensitiveSearch].length != 0) {
+ DVLOG(1) << "Enumerated blacklisted " << [device_name UTF8String];
+ Name name("QTKit " + std::string([device_name UTF8String]),
+ [key UTF8String], Name::QTKIT);
+ device_names->push_back(name);
+ }
+ }
+ }
+ }
+ } else {
+ DVLOG(1) << "Enumerating video capture devices using QTKit";
+ capture_devices = [VideoCaptureDeviceQTKit deviceNames];
+ for (NSString* key in capture_devices) {
+ Name name([[capture_devices valueForKey:key] UTF8String],
+ [key UTF8String], Name::QTKIT);
+ device_names->push_back(name);
+ }
+ }
}
// static
-void VideoCaptureDevice::GetDeviceSupportedFormats(
- const Name& device,
- VideoCaptureFormats* supported_formats) {
- NOTREACHED();
+void VideoCaptureDevice::GetDeviceSupportedFormats(const Name& device,
+ VideoCaptureFormats* formats) {
+ if (device.capture_api_type() == Name::AVFOUNDATION) {
+ DVLOG(1) << "Enumerating video capture capabilities, AVFoundation";
+ [VideoCaptureDeviceAVFoundation getDevice:device
+ supportedFormats:formats];
+ } else {
+ NOTIMPLEMENTED();
+ }
}
const std::string VideoCaptureDevice::Name::GetModel() const {
@@ -98,6 +150,17 @@ const std::string VideoCaptureDevice::Name::GetModel() const {
return id_vendor + ":" + id_product;
}
+VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) {
+ VideoCaptureDeviceMac* capture_device =
+ new VideoCaptureDeviceMac(device_name);
+ if (!capture_device->Init()) {
+ LOG(ERROR) << "Could not initialize VideoCaptureDevice.";
+ delete capture_device;
+ capture_device = NULL;
+ }
+ return capture_device;
+}
+
VideoCaptureDeviceMac::VideoCaptureDeviceMac(const Name& device_name)
: device_name_(device_name),
tried_to_square_pixels_(false),
@@ -181,12 +244,25 @@ void VideoCaptureDeviceMac::StopAndDeAllocate() {
tried_to_square_pixels_ = false;
}
-bool VideoCaptureDeviceMac::Init(
- VideoCaptureDevice::Name::CaptureApiType capture_api_type) {
+bool VideoCaptureDeviceMac::Init() {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kNotInitialized);
- if (capture_api_type == Name::AVFOUNDATION) {
+ // TODO(mcasas): The following check might not be necessary; if the device has
+ // disappeared after enumeration and before coming here, opening would just
+ // fail but not necessarily produce a crash.
+ Names device_names;
+ GetDeviceNames(&device_names);
+ Names::iterator it = device_names.begin();
+ for (; it != device_names.end(); ++it) {
+ if (it->id() == device_name_.id())
+ break;
+ }
+ if (it == device_names.end())
+ return false;
+
+ DCHECK_NE(it->capture_api_type(), Name::API_TYPE_UNKNOWN);
+ if (it->capture_api_type() == Name::AVFOUNDATION) {
capture_device_ =
[[VideoCaptureDeviceAVFoundation alloc] initWithFrameReceiver:this];
} else {
diff --git a/media/video/capture/video_capture_device_factory.cc b/media/video/capture/video_capture_device_factory.cc
index 661900c..e63225d 100644
--- a/media/video/capture/video_capture_device_factory.cc
+++ b/media/video/capture/video_capture_device_factory.cc
@@ -4,47 +4,11 @@
#include "media/video/capture/video_capture_device_factory.h"
-#include "base/command_line.h"
-#include "media/base/media_switches.h"
-#include "media/video/capture/fake_video_capture_device_factory.h"
-#include "media/video/capture/file_video_capture_device_factory.h"
-
-#if defined(OS_MACOSX)
-#include "media/video/capture/mac/video_capture_device_factory_mac.h"
-#endif
-
namespace media {
-// static
-scoped_ptr<VideoCaptureDeviceFactory>
- VideoCaptureDeviceFactory::CreateFactory() {
- const CommandLine* command_line = 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 scoped_ptr<VideoCaptureDeviceFactory>(new
- media::FileVideoCaptureDeviceFactory());
- } else {
- return scoped_ptr<VideoCaptureDeviceFactory>(new
- media::FakeVideoCaptureDeviceFactory());
- }
- } else {
-#if defined(OS_MACOSX)
- return scoped_ptr<VideoCaptureDeviceFactory>(new
- VideoCaptureDeviceFactoryMac());
-#else
- return scoped_ptr<VideoCaptureDeviceFactory>(new
- VideoCaptureDeviceFactory());
-#endif
- }
-}
-
VideoCaptureDeviceFactory::VideoCaptureDeviceFactory() {
thread_checker_.DetachFromThread();
-}
-
-VideoCaptureDeviceFactory::~VideoCaptureDeviceFactory() {}
+};
scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactory::Create(
const VideoCaptureDevice::Name& device_name) {
diff --git a/media/video/capture/video_capture_device_factory.h b/media/video/capture/video_capture_device_factory.h
index 4a19e83..ab58ad6 100644
--- a/media/video/capture/video_capture_device_factory.h
+++ b/media/video/capture/video_capture_device_factory.h
@@ -16,10 +16,8 @@ namespace media {
// in Device Thread (a.k.a. Audio Thread).
class MEDIA_EXPORT VideoCaptureDeviceFactory {
public:
- static scoped_ptr<VideoCaptureDeviceFactory> CreateFactory();
-
VideoCaptureDeviceFactory();
- virtual ~VideoCaptureDeviceFactory();
+ virtual ~VideoCaptureDeviceFactory() {}
// Creates a VideoCaptureDevice object. Returns NULL if something goes wrong.
virtual scoped_ptr<VideoCaptureDevice> Create(
diff --git a/media/video/capture/video_capture_device_unittest.cc b/media/video/capture/video_capture_device_unittest.cc
index e897d20..f079a1f 100644
--- a/media/video/capture/video_capture_device_unittest.cc
+++ b/media/video/capture/video_capture_device_unittest.cc
@@ -3,12 +3,15 @@
// found in the LICENSE file.
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "base/threading/thread.h"
+#include "media/video/capture/fake_video_capture_device.h"
+#include "media/video/capture/fake_video_capture_device_factory.h"
#include "media/video/capture/video_capture_device.h"
-#include "media/video/capture/video_capture_device_factory.h"
#include "media/video/capture/video_capture_types.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -50,6 +53,11 @@
#define MAYBE_CaptureMjpeg CaptureMjpeg
#endif
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::Return;
+using ::testing::AtLeast;
+
namespace media {
class MockClient : public media::VideoCaptureDevice::Client {
@@ -96,8 +104,7 @@ class VideoCaptureDeviceTest : public testing::Test {
client_(
new MockClient(base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured,
base::Unretained(this)))),
- video_capture_device_factory_(
- VideoCaptureDeviceFactory::CreateFactory()) {}
+ video_capture_device_factory_(new FakeVideoCaptureDeviceFactory()) {}
virtual void SetUp() {
#if defined(OS_ANDROID)
@@ -125,7 +132,7 @@ class VideoCaptureDeviceTest : public testing::Test {
scoped_ptr<VideoCaptureDevice::Name> GetFirstDeviceNameSupportingPixelFormat(
const VideoPixelFormat& pixel_format) {
- video_capture_device_factory_->GetDeviceNames(&names_);
+ VideoCaptureDevice::GetDeviceNames(&names_);
if (!names_.size()) {
DVLOG(1) << "No camera available.";
return scoped_ptr<VideoCaptureDevice::Name>();
@@ -134,9 +141,8 @@ class VideoCaptureDeviceTest : public testing::Test {
for (names_iterator = names_.begin(); names_iterator != names_.end();
++names_iterator) {
VideoCaptureFormats supported_formats;
- video_capture_device_factory_->GetDeviceSupportedFormats(
- *names_iterator,
- &supported_formats);
+ VideoCaptureDevice::GetDeviceSupportedFormats(*names_iterator,
+ &supported_formats);
VideoCaptureFormats::iterator formats_iterator;
for (formats_iterator = supported_formats.begin();
formats_iterator != supported_formats.end(); ++formats_iterator) {
@@ -168,26 +174,22 @@ TEST_F(VideoCaptureDeviceTest, OpenInvalidDevice) {
? VideoCaptureDevice::Name::MEDIA_FOUNDATION
: VideoCaptureDevice::Name::DIRECT_SHOW;
VideoCaptureDevice::Name device_name("jibberish", "jibberish", api_type);
-#elif defined(OS_MACOSX)
- VideoCaptureDevice::Name device_name("jibberish", "jibberish",
- VideoCaptureDevice::Name::AVFOUNDATION);
#else
VideoCaptureDevice::Name device_name("jibberish", "jibberish");
#endif
- scoped_ptr<VideoCaptureDevice> device =
- video_capture_device_factory_->Create(device_name);
+ VideoCaptureDevice* device = VideoCaptureDevice::Create(device_name);
EXPECT_TRUE(device == NULL);
}
TEST_F(VideoCaptureDeviceTest, CaptureVGA) {
- video_capture_device_factory_->GetDeviceNames(&names_);
+ VideoCaptureDevice::GetDeviceNames(&names_);
if (!names_.size()) {
DVLOG(1) << "No camera available. Exiting test.";
return;
}
scoped_ptr<VideoCaptureDevice> device(
- video_capture_device_factory_->Create(names_.front()));
+ VideoCaptureDevice::Create(names_.front()));
ASSERT_TRUE(device);
DVLOG(1) << names_.front().id();
@@ -208,14 +210,14 @@ TEST_F(VideoCaptureDeviceTest, CaptureVGA) {
}
TEST_F(VideoCaptureDeviceTest, Capture720p) {
- video_capture_device_factory_->GetDeviceNames(&names_);
+ VideoCaptureDevice::GetDeviceNames(&names_);
if (!names_.size()) {
DVLOG(1) << "No camera available. Exiting test.";
return;
}
scoped_ptr<VideoCaptureDevice> device(
- video_capture_device_factory_->Create(names_.front()));
+ VideoCaptureDevice::Create(names_.front()));
ASSERT_TRUE(device);
EXPECT_CALL(*client_, OnErr())
@@ -233,13 +235,13 @@ TEST_F(VideoCaptureDeviceTest, Capture720p) {
}
TEST_F(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) {
- video_capture_device_factory_->GetDeviceNames(&names_);
+ VideoCaptureDevice::GetDeviceNames(&names_);
if (!names_.size()) {
DVLOG(1) << "No camera available. Exiting test.";
return;
}
scoped_ptr<VideoCaptureDevice> device(
- video_capture_device_factory_->Create(names_.front()));
+ VideoCaptureDevice::Create(names_.front()));
ASSERT_TRUE(device);
EXPECT_CALL(*client_, OnErr())
@@ -258,7 +260,7 @@ TEST_F(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) {
}
TEST_F(VideoCaptureDeviceTest, ReAllocateCamera) {
- video_capture_device_factory_->GetDeviceNames(&names_);
+ VideoCaptureDevice::GetDeviceNames(&names_);
if (!names_.size()) {
DVLOG(1) << "No camera available. Exiting test.";
return;
@@ -268,7 +270,7 @@ TEST_F(VideoCaptureDeviceTest, ReAllocateCamera) {
for (int i = 0; i <= 5; i++) {
ResetWithNewClient();
scoped_ptr<VideoCaptureDevice> device(
- video_capture_device_factory_->Create(names_.front()));
+ VideoCaptureDevice::Create(names_.front()));
gfx::Size resolution;
if (i % 2) {
resolution = gfx::Size(640, 480);
@@ -293,7 +295,7 @@ TEST_F(VideoCaptureDeviceTest, ReAllocateCamera) {
ResetWithNewClient();
scoped_ptr<VideoCaptureDevice> device(
- video_capture_device_factory_->Create(names_.front()));
+ VideoCaptureDevice::Create(names_.front()));
device->AllocateAndStart(capture_params, client_.PassAs<Client>());
WaitForCapturedFrame();
@@ -304,13 +306,13 @@ TEST_F(VideoCaptureDeviceTest, ReAllocateCamera) {
}
TEST_F(VideoCaptureDeviceTest, DeAllocateCameraWhileRunning) {
- video_capture_device_factory_->GetDeviceNames(&names_);
+ VideoCaptureDevice::GetDeviceNames(&names_);
if (!names_.size()) {
DVLOG(1) << "No camera available. Exiting test.";
return;
}
scoped_ptr<VideoCaptureDevice> device(
- video_capture_device_factory_->Create(names_.front()));
+ VideoCaptureDevice::Create(names_.front()));
ASSERT_TRUE(device);
EXPECT_CALL(*client_, OnErr())
@@ -330,6 +332,33 @@ TEST_F(VideoCaptureDeviceTest, DeAllocateCameraWhileRunning) {
device->StopAndDeAllocate();
}
+TEST_F(VideoCaptureDeviceTest, FakeCapture) {
+ VideoCaptureDevice::Names names;
+
+ video_capture_device_factory_->GetDeviceNames(&names);
+
+ ASSERT_GT(static_cast<int>(names.size()), 0);
+
+ scoped_ptr<VideoCaptureDevice> device(
+ video_capture_device_factory_->Create(names.front()));
+ ASSERT_TRUE(device);
+
+ EXPECT_CALL(*client_, OnErr())
+ .Times(0);
+
+ VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(640, 480);
+ capture_params.requested_format.frame_rate = 30;
+ capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = false;
+ device->AllocateAndStart(capture_params, client_.PassAs<Client>());
+ WaitForCapturedFrame();
+ EXPECT_EQ(last_format().frame_size.width(), 640);
+ EXPECT_EQ(last_format().frame_size.height(), 480);
+ EXPECT_EQ(last_format().frame_rate, 30);
+ device->StopAndDeAllocate();
+}
+
// Start the camera in 720p to capture MJPEG instead of a raw format.
TEST_F(VideoCaptureDeviceTest, MAYBE_CaptureMjpeg) {
scoped_ptr<VideoCaptureDevice::Name> name =
@@ -338,8 +367,7 @@ TEST_F(VideoCaptureDeviceTest, MAYBE_CaptureMjpeg) {
DVLOG(1) << "No camera supports MJPEG format. Exiting test.";
return;
}
- scoped_ptr<VideoCaptureDevice> device(
- video_capture_device_factory_->Create(*name));
+ scoped_ptr<VideoCaptureDevice> device(VideoCaptureDevice::Create(*name));
ASSERT_TRUE(device);
EXPECT_CALL(*client_, OnErr())
@@ -369,4 +397,68 @@ TEST_F(VideoCaptureDeviceTest, GetDeviceSupportedFormats) {
ASSERT_FALSE(name);
}
+TEST_F(VideoCaptureDeviceTest, FakeCaptureVariableResolution) {
+ VideoCaptureDevice::Names names;
+
+ video_capture_device_factory_->GetDeviceNames(&names);
+ VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(640, 480);
+ capture_params.requested_format.frame_rate = 30;
+ capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
+ capture_params.allow_resolution_change = true;
+
+ ASSERT_GT(static_cast<int>(names.size()), 0);
+
+ scoped_ptr<VideoCaptureDevice> device(
+ video_capture_device_factory_->Create(names.front()));
+ ASSERT_TRUE(device);
+
+ // Configure the FakeVideoCaptureDevice to use all its formats as roster.
+ VideoCaptureFormats formats;
+ video_capture_device_factory_->GetDeviceSupportedFormats(names.front(),
+ &formats);
+ static_cast<FakeVideoCaptureDevice*>(device.get())->
+ PopulateVariableFormatsRoster(formats);
+
+ EXPECT_CALL(*client_, OnErr())
+ .Times(0);
+ int action_count = 200;
+
+ device->AllocateAndStart(capture_params, client_.PassAs<Client>());
+
+ // We set TimeWait to 200 action timeouts and this should be enough for at
+ // least action_count/kFakeCaptureCapabilityChangePeriod calls.
+ for (int i = 0; i < action_count; ++i) {
+ WaitForCapturedFrame();
+ }
+ device->StopAndDeAllocate();
+}
+
+TEST_F(VideoCaptureDeviceTest, FakeGetDeviceSupportedFormats) {
+ VideoCaptureDevice::Names names;
+ video_capture_device_factory_->GetDeviceNames(&names);
+
+ VideoCaptureFormats supported_formats;
+ VideoCaptureDevice::Names::iterator names_iterator;
+
+ for (names_iterator = names.begin(); names_iterator != names.end();
+ ++names_iterator) {
+ video_capture_device_factory_->GetDeviceSupportedFormats(
+ *names_iterator, &supported_formats);
+ EXPECT_EQ(supported_formats.size(), 3u);
+ EXPECT_EQ(supported_formats[0].frame_size.width(), 320);
+ EXPECT_EQ(supported_formats[0].frame_size.height(), 240);
+ EXPECT_EQ(supported_formats[0].pixel_format, media::PIXEL_FORMAT_I420);
+ EXPECT_GE(supported_formats[0].frame_rate, 20);
+ EXPECT_EQ(supported_formats[1].frame_size.width(), 640);
+ EXPECT_EQ(supported_formats[1].frame_size.height(), 480);
+ EXPECT_EQ(supported_formats[1].pixel_format, media::PIXEL_FORMAT_I420);
+ EXPECT_GE(supported_formats[1].frame_rate, 20);
+ EXPECT_EQ(supported_formats[2].frame_size.width(), 1280);
+ EXPECT_EQ(supported_formats[2].frame_size.height(), 720);
+ EXPECT_EQ(supported_formats[2].pixel_format, media::PIXEL_FORMAT_I420);
+ EXPECT_GE(supported_formats[2].frame_rate, 20);
+ }
+}
+
}; // namespace media