diff options
author | mcasas <mcasas@chromium.org> | 2015-07-16 19:00:32 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-17 02:01:19 +0000 |
commit | 26973ef3748fda32787ce05a021ed4c68565fe6a (patch) | |
tree | 78de02cfe3e5bd0639c0ee688f142768f8390e2d /media/video/capture | |
parent | c36773843cb0d729166bb19074e960129e609dd5 (diff) | |
download | chromium_src-26973ef3748fda32787ce05a021ed4c68565fe6a.zip chromium_src-26973ef3748fda32787ce05a021ed4c68565fe6a.tar.gz chromium_src-26973ef3748fda32787ce05a021ed4c68565fe6a.tar.bz2 |
Folder shuffle media/capture -> media/capture/content and media/video/capture -> media/capture/video
Folder reorg, no code changes whatsoever (except #include path
renaming).
Rationale: media/capture includes ATM screen/tab capture;
media/video has a bunch of unrelated files and a
large capture/ folder. All that can be consolidated under
media/capture/bla where bla={content, video}.
Suggestion: move audio capture code in capture/audio.
TBR=
avi@chromium.org for content/browser/DEPS since is a
mechanical folder name change.
Review URL: https://codereview.chromium.org/1231863011
Cr-Commit-Position: refs/heads/master@{#339199}
Diffstat (limited to 'media/video/capture')
63 files changed, 0 insertions, 9499 deletions
diff --git a/media/video/capture/OWNERS b/media/video/capture/OWNERS deleted file mode 100644 index 92972c6..0000000 --- a/media/video/capture/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -mcasas@chromium.org -perkj@chromium.org -posciak@chromium.org -tommi@chromium.org diff --git a/media/video/capture/android/video_capture_device_android.cc b/media/video/capture/android/video_capture_device_android.cc deleted file mode 100644 index 81470a7..0000000 --- a/media/video/capture/android/video_capture_device_android.cc +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (c) 2013 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/android/video_capture_device_android.h" - - -#include "base/android/jni_android.h" -#include "base/strings/string_number_conversions.h" -#include "jni/VideoCapture_jni.h" -#include "media/video/capture/android/video_capture_device_factory_android.h" - -using base::android::AttachCurrentThread; -using base::android::CheckException; -using base::android::GetClass; -using base::android::MethodID; -using base::android::JavaRef; -using base::android::ScopedJavaLocalRef; - -namespace media { - -// static -bool VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -const std::string VideoCaptureDevice::Name::GetModel() const { - // Android cameras are not typically USB devices, and this method is currently - // only used for USB model identifiers, so this implementation just indicates - // an unknown device model. - return ""; -} - -VideoCaptureDeviceAndroid::VideoCaptureDeviceAndroid(const Name& device_name) - : state_(kIdle), got_first_frame_(false), device_name_(device_name) {} - -VideoCaptureDeviceAndroid::~VideoCaptureDeviceAndroid() { - StopAndDeAllocate(); -} - -bool VideoCaptureDeviceAndroid::Init() { - int id; - if (!base::StringToInt(device_name_.id(), &id)) - return false; - - j_capture_.Reset(VideoCaptureDeviceFactoryAndroid::createVideoCaptureAndroid( - id, reinterpret_cast<intptr_t>(this))); - return true; -} - -void VideoCaptureDeviceAndroid::AllocateAndStart( - const VideoCaptureParams& params, - scoped_ptr<Client> client) { - DVLOG(1) << "VideoCaptureDeviceAndroid::AllocateAndStart"; - { - base::AutoLock lock(lock_); - if (state_ != kIdle) - return; - client_ = client.Pass(); - got_first_frame_ = false; - } - - JNIEnv* env = AttachCurrentThread(); - - jboolean ret = Java_VideoCapture_allocate( - env, - j_capture_.obj(), - params.requested_format.frame_size.width(), - params.requested_format.frame_size.height(), - params.requested_format.frame_rate); - if (!ret) { - SetErrorState("failed to allocate"); - return; - } - - // Store current width and height. - capture_format_.frame_size.SetSize( - Java_VideoCapture_queryWidth(env, j_capture_.obj()), - Java_VideoCapture_queryHeight(env, j_capture_.obj())); - capture_format_.frame_rate = - Java_VideoCapture_queryFrameRate(env, j_capture_.obj()); - capture_format_.pixel_format = GetColorspace(); - DCHECK_NE(capture_format_.pixel_format, - media::VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN); - CHECK(capture_format_.frame_size.GetArea() > 0); - CHECK(!(capture_format_.frame_size.width() % 2)); - CHECK(!(capture_format_.frame_size.height() % 2)); - - if (capture_format_.frame_rate > 0) { - frame_interval_ = base::TimeDelta::FromMicroseconds( - (base::Time::kMicrosecondsPerSecond + capture_format_.frame_rate - 1) / - capture_format_.frame_rate); - } - - DVLOG(1) << "VideoCaptureDeviceAndroid::Allocate: queried frame_size=" - << capture_format_.frame_size.ToString() - << ", frame_rate=" << capture_format_.frame_rate; - - ret = Java_VideoCapture_startCapture(env, j_capture_.obj()); - if (!ret) { - SetErrorState("failed to start capture"); - return; - } - - { - base::AutoLock lock(lock_); - state_ = kCapturing; - } -} - -void VideoCaptureDeviceAndroid::StopAndDeAllocate() { - DVLOG(1) << "VideoCaptureDeviceAndroid::StopAndDeAllocate"; - { - base::AutoLock lock(lock_); - if (state_ != kCapturing && state_ != kError) - return; - } - - JNIEnv* env = AttachCurrentThread(); - - jboolean ret = Java_VideoCapture_stopCapture(env, j_capture_.obj()); - if (!ret) { - SetErrorState("failed to stop capture"); - return; - } - - { - base::AutoLock lock(lock_); - state_ = kIdle; - client_.reset(); - } - - Java_VideoCapture_deallocate(env, j_capture_.obj()); -} - -void VideoCaptureDeviceAndroid::OnFrameAvailable(JNIEnv* env, - jobject obj, - jbyteArray data, - jint length, - jint rotation) { - DVLOG(3) << "VideoCaptureDeviceAndroid::OnFrameAvailable: length =" << length; - - base::AutoLock lock(lock_); - if (state_ != kCapturing || !client_.get()) - return; - - jbyte* buffer = env->GetByteArrayElements(data, NULL); - if (!buffer) { - LOG(ERROR) << "VideoCaptureDeviceAndroid::OnFrameAvailable: " - "failed to GetByteArrayElements"; - return; - } - - base::TimeTicks current_time = base::TimeTicks::Now(); - if (!got_first_frame_) { - // Set aside one frame allowance for fluctuation. - expected_next_frame_time_ = current_time - frame_interval_; - got_first_frame_ = true; - } - - // Deliver the frame when it doesn't arrive too early. - if (expected_next_frame_time_ <= current_time) { - expected_next_frame_time_ += frame_interval_; - - client_->OnIncomingCapturedData(reinterpret_cast<uint8*>(buffer), - length, - capture_format_, - rotation, - base::TimeTicks::Now()); - } - - env->ReleaseByteArrayElements(data, buffer, JNI_ABORT); -} - -void VideoCaptureDeviceAndroid::OnError(JNIEnv* env, - jobject obj, - jstring message) { - const char *native_string = env->GetStringUTFChars(message, JNI_FALSE); - SetErrorState(native_string); - env->ReleaseStringUTFChars(message, native_string); -} - -VideoCapturePixelFormat VideoCaptureDeviceAndroid::GetColorspace() { - JNIEnv* env = AttachCurrentThread(); - int current_capture_colorspace = - Java_VideoCapture_getColorspace(env, j_capture_.obj()); - switch (current_capture_colorspace) { - case ANDROID_IMAGE_FORMAT_YV12: - return media::VIDEO_CAPTURE_PIXEL_FORMAT_YV12; - case ANDROID_IMAGE_FORMAT_YUV_420_888: - return media::VIDEO_CAPTURE_PIXEL_FORMAT_I420; - case ANDROID_IMAGE_FORMAT_NV21: - return media::VIDEO_CAPTURE_PIXEL_FORMAT_NV21; - case ANDROID_IMAGE_FORMAT_UNKNOWN: - default: - return media::VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN; - } -} - -void VideoCaptureDeviceAndroid::SetErrorState(const std::string& reason) { - { - base::AutoLock lock(lock_); - state_ = kError; - } - client_->OnError(reason); -} - -} // namespace media diff --git a/media/video/capture/android/video_capture_device_android.h b/media/video/capture/android/video_capture_device_android.h deleted file mode 100644 index f9e414a..0000000 --- a/media/video/capture/android/video_capture_device_android.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2013 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_VIDEO_CAPTURE_ANDROID_VIDEO_CAPTURE_DEVICE_ANDROID_H_ -#define MEDIA_VIDEO_CAPTURE_ANDROID_VIDEO_CAPTURE_DEVICE_ANDROID_H_ - -#include <jni.h> -#include <string> - -#include "base/android/scoped_java_ref.h" -#include "base/synchronization/lock.h" -#include "base/threading/thread.h" -#include "base/time/time.h" -#include "media/base/media_export.h" -#include "media/video/capture/video_capture_device.h" - -namespace media { - -// VideoCaptureDevice on Android. The VideoCaptureDevice API's are called -// by VideoCaptureManager on its own thread, while OnFrameAvailable is called -// on JAVA thread (i.e., UI thread). Both will access |state_| and |client_|, -// but only VideoCaptureManager would change their value. -class MEDIA_EXPORT VideoCaptureDeviceAndroid : public VideoCaptureDevice { - public: - // Automatically generated enum to interface with Java world. - // - // A Java counterpart will be generated for this enum. - // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.media - enum AndroidImageFormat { - // Android graphics ImageFormat mapping, see reference in: - // http://developer.android.com/reference/android/graphics/ImageFormat.html - ANDROID_IMAGE_FORMAT_NV21 = 17, - ANDROID_IMAGE_FORMAT_YUV_420_888 = 35, - ANDROID_IMAGE_FORMAT_YV12 = 842094169, - ANDROID_IMAGE_FORMAT_UNKNOWN = 0, - }; - - explicit VideoCaptureDeviceAndroid(const Name& device_name); - ~VideoCaptureDeviceAndroid() override; - - static VideoCaptureDevice* Create(const Name& device_name); - static bool RegisterVideoCaptureDevice(JNIEnv* env); - - // Registers the Java VideoCaptureDevice pointer, used by the rest of the - // methods of the class to operate the Java capture code. This method must be - // called after the class constructor and before AllocateAndStart(). - bool Init(); - - // VideoCaptureDevice implementation. - void AllocateAndStart(const VideoCaptureParams& params, - scoped_ptr<Client> client) override; - void StopAndDeAllocate() override; - - // Implement org.chromium.media.VideoCapture.nativeOnFrameAvailable. - void OnFrameAvailable( - JNIEnv* env, - jobject obj, - jbyteArray data, - jint length, - jint rotation); - - // Implement org.chromium.media.VideoCapture.nativeOnError. - void OnError(JNIEnv* env, jobject obj, jstring message); - - private: - enum InternalState { - kIdle, // The device is opened but not in use. - kCapturing, // Video is being captured. - kError // Hit error. User needs to recover by destroying the object. - }; - - VideoCapturePixelFormat GetColorspace(); - void SetErrorState(const std::string& reason); - - // Prevent racing on accessing |state_| and |client_| since both could be - // accessed from different threads. - base::Lock lock_; - InternalState state_; - bool got_first_frame_; - base::TimeTicks expected_next_frame_time_; - base::TimeDelta frame_interval_; - scoped_ptr<VideoCaptureDevice::Client> client_; - - Name device_name_; - VideoCaptureFormat capture_format_; - - // Java VideoCaptureAndroid instance. - base::android::ScopedJavaLocalRef<jobject> j_capture_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceAndroid); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_ANDROID_VIDEO_CAPTURE_DEVICE_ANDROID_H_ diff --git a/media/video/capture/android/video_capture_device_factory_android.cc b/media/video/capture/android/video_capture_device_factory_android.cc deleted file mode 100644 index 5f5532d..0000000 --- a/media/video/capture/android/video_capture_device_factory_android.cc +++ /dev/null @@ -1,141 +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/android/video_capture_device_factory_android.h" - -#include "base/android/jni_string.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "jni/VideoCaptureFactory_jni.h" -#include "media/video/capture/android/video_capture_device_android.h" - -using base::android::AttachCurrentThread; -using base::android::ScopedJavaLocalRef; - -namespace media { - -// static -bool VideoCaptureDeviceFactoryAndroid::RegisterVideoCaptureDeviceFactory( - JNIEnv* env) { - return RegisterNativesImpl(env); -} - -// static -ScopedJavaLocalRef<jobject> -VideoCaptureDeviceFactoryAndroid::createVideoCaptureAndroid( - int id, - jlong nativeVideoCaptureDeviceAndroid) { - return (Java_VideoCaptureFactory_createVideoCapture( - AttachCurrentThread(), - base::android::GetApplicationContext(), - id, - nativeVideoCaptureDeviceAndroid)); -} - -scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryAndroid::Create( - const VideoCaptureDevice::Name& device_name) { - DCHECK(thread_checker_.CalledOnValidThread()); - int id; - if (!base::StringToInt(device_name.id(), &id)) - return scoped_ptr<VideoCaptureDevice>(); - - scoped_ptr<VideoCaptureDeviceAndroid> video_capture_device( - new VideoCaptureDeviceAndroid(device_name)); - - if (video_capture_device->Init()) - return video_capture_device.Pass(); - - DLOG(ERROR) << "Error creating Video Capture Device."; - return scoped_ptr<VideoCaptureDevice>(); -} - -void VideoCaptureDeviceFactoryAndroid::GetDeviceNames( - VideoCaptureDevice::Names* device_names) { - DCHECK(thread_checker_.CalledOnValidThread()); - device_names->clear(); - - JNIEnv* env = AttachCurrentThread(); - - const jobject context = base::android::GetApplicationContext(); - const int num_cameras = Java_VideoCaptureFactory_getNumberOfCameras(env, - context); - DVLOG(1) << "VideoCaptureDevice::GetDeviceNames: num_cameras=" << num_cameras; - if (num_cameras <= 0) - return; - - for (int camera_id = num_cameras - 1; camera_id >= 0; --camera_id) { - base::android::ScopedJavaLocalRef<jstring> device_name = - Java_VideoCaptureFactory_getDeviceName(env, camera_id, context); - if (device_name.obj() == NULL) - continue; - - const int capture_api_type = - Java_VideoCaptureFactory_getCaptureApiType(env, camera_id, context); - - VideoCaptureDevice::Name name( - base::android::ConvertJavaStringToUTF8(device_name), - base::IntToString(camera_id), - static_cast<VideoCaptureDevice::Name::CaptureApiType>( - capture_api_type)); - device_names->push_back(name); - - DVLOG(1) << "VideoCaptureDeviceFactoryAndroid::GetDeviceNames: camera " - << "device_name=" << name.name() << ", unique_id=" << name.id(); - } -} - -void VideoCaptureDeviceFactoryAndroid::GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* capture_formats) { - DCHECK(thread_checker_.CalledOnValidThread()); - int id; - if (!base::StringToInt(device.id(), &id)) - return; - JNIEnv* env = AttachCurrentThread(); - base::android::ScopedJavaLocalRef<jobjectArray> collected_formats = - Java_VideoCaptureFactory_getDeviceSupportedFormats(env, - base::android::GetApplicationContext(), id); - if (collected_formats.is_null()) - return; - - jsize num_formats = env->GetArrayLength(collected_formats.obj()); - for (int i = 0; i < num_formats; ++i) { - base::android::ScopedJavaLocalRef<jobject> format( - env, env->GetObjectArrayElement(collected_formats.obj(), i)); - - VideoCapturePixelFormat pixel_format = - media::VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN; - switch (media::Java_VideoCaptureFactory_getCaptureFormatPixelFormat( - env, format.obj())) { - case VideoCaptureDeviceAndroid::ANDROID_IMAGE_FORMAT_YV12: - pixel_format = media::VIDEO_CAPTURE_PIXEL_FORMAT_YV12; - break; - case VideoCaptureDeviceAndroid::ANDROID_IMAGE_FORMAT_NV21: - pixel_format = media::VIDEO_CAPTURE_PIXEL_FORMAT_NV21; - break; - default: - continue; - } - VideoCaptureFormat capture_format( - gfx::Size(media::Java_VideoCaptureFactory_getCaptureFormatWidth(env, - format.obj()), - media::Java_VideoCaptureFactory_getCaptureFormatHeight(env, - format.obj())), - media::Java_VideoCaptureFactory_getCaptureFormatFramerate(env, - format.obj()), - pixel_format); - capture_formats->push_back(capture_format); - DVLOG(1) << device.name() << " " - << VideoCaptureFormat::ToString(capture_format); - } -} - -// static -VideoCaptureDeviceFactory* -VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { - return new VideoCaptureDeviceFactoryAndroid(); -} - -} // namespace media diff --git a/media/video/capture/android/video_capture_device_factory_android.h b/media/video/capture/android/video_capture_device_factory_android.h deleted file mode 100644 index 9941393..0000000 --- a/media/video/capture/android/video_capture_device_factory_android.h +++ /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. - -#ifndef MEDIA_VIDEO_CAPTURE_ANDROID_VIDEO_CAPTURE_DEVICE_FACTORY_ANDROID_H_ -#define MEDIA_VIDEO_CAPTURE_ANDROID_VIDEO_CAPTURE_DEVICE_FACTORY_ANDROID_H_ - -#include "media/video/capture/video_capture_device_factory.h" - -#include <jni.h> - -#include "base/android/scoped_java_ref.h" -#include "media/video/capture/video_capture_device.h" - -namespace media { - -// VideoCaptureDeviceFactory on Android. This class implements the static -// VideoCapture methods and the factory of VideoCaptureAndroid. -class MEDIA_EXPORT VideoCaptureDeviceFactoryAndroid : - public VideoCaptureDeviceFactory { - public: - static bool RegisterVideoCaptureDeviceFactory(JNIEnv* env); - static base::android::ScopedJavaLocalRef<jobject> createVideoCaptureAndroid( - int id, - jlong nativeVideoCaptureDeviceAndroid); - - VideoCaptureDeviceFactoryAndroid() {} - ~VideoCaptureDeviceFactoryAndroid() override {} - - scoped_ptr<VideoCaptureDevice> Create( - const VideoCaptureDevice::Name& device_name) override; - void GetDeviceNames(VideoCaptureDevice::Names* device_names) override; - void GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) override; - - private: - - DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactoryAndroid);}; -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_ANDROID_VIDEO_CAPTURE_DEVICE_FACTORY_ANDROID_H_ diff --git a/media/video/capture/fake_video_capture_device.cc b/media/video/capture/fake_video_capture_device.cc deleted file mode 100644 index 4232feb..0000000 --- a/media/video/capture/fake_video_capture_device.cc +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2012 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/fake_video_capture_device.h" - -#include <algorithm> - -#include "base/bind.h" -#include "base/strings/stringprintf.h" -#include "media/audio/fake_audio_input_stream.h" -#include "media/base/video_frame.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkPaint.h" - -namespace media { - -static const int kFakeCaptureBeepCycle = 10; // Visual beep every 0.5s. - -void DrawPacman(bool use_argb, - uint8_t* const data, - int frame_count, - int frame_interval, - const gfx::Size& frame_size) { - // |kN32_SkColorType| stands for the appropriiate RGBA/BGRA format. - const SkColorType colorspace = - use_argb ? kN32_SkColorType : kAlpha_8_SkColorType; - const SkImageInfo info = SkImageInfo::Make(frame_size.width(), - frame_size.height(), - colorspace, - kOpaque_SkAlphaType); - SkBitmap bitmap; - bitmap.setInfo(info); - bitmap.setPixels(data); - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - SkCanvas canvas(bitmap); - - // Equalize Alpha_8 that has light green background while RGBA has white. - if (use_argb) { - const SkRect full_frame = SkRect::MakeWH(frame_size.width(), - frame_size.height()); - paint.setARGB(255, 0, 127, 0); - canvas.drawRect(full_frame, paint); - } - paint.setColor(SK_ColorGREEN); - - // Draw a sweeping circle to show an animation. - const int end_angle = (3 * kFakeCaptureBeepCycle * frame_count % 361); - const int radius = std::min(frame_size.width(), frame_size.height()) / 4; - const SkRect rect = SkRect::MakeXYWH(frame_size.width() / 2 - radius, - frame_size.height() / 2 - radius, - 2 * radius, - 2 * radius); - canvas.drawArc(rect, 0, end_angle, true, paint); - - // Draw current time. - const int elapsed_ms = frame_interval * frame_count; - const int milliseconds = elapsed_ms % 1000; - const int seconds = (elapsed_ms / 1000) % 60; - const int minutes = (elapsed_ms / 1000 / 60) % 60; - const int hours = (elapsed_ms / 1000 / 60 / 60) % 60; - - const std::string time_string = base::StringPrintf("%d:%02d:%02d:%03d %d", - hours, minutes, seconds, milliseconds, frame_count); - canvas.scale(3, 3); - canvas.drawText(time_string.data(), time_string.length(), 30, 20, paint); -} - -FakeVideoCaptureDevice::FakeVideoCaptureDevice( - FakeVideoCaptureDeviceType device_type) - : device_type_(device_type), - frame_count_(0), - weak_factory_(this) {} - -FakeVideoCaptureDevice::~FakeVideoCaptureDevice() { - DCHECK(thread_checker_.CalledOnValidThread()); -} - -void FakeVideoCaptureDevice::AllocateAndStart( - const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) { - DCHECK(thread_checker_.CalledOnValidThread()); - - client_ = client.Pass(); - - // Incoming |params| can be none of the supported formats, so we get the - // closest thing rounded up. TODO(mcasas): Use the |params|, if they belong to - // the supported ones, when http://crbug.com/309554 is verified. - DCHECK_EQ(params.requested_format.pixel_format, - VIDEO_CAPTURE_PIXEL_FORMAT_I420); - capture_format_.pixel_format = params.requested_format.pixel_format; - capture_format_.frame_rate = 30.0; - if (params.requested_format.frame_size.width() > 1280) - capture_format_.frame_size.SetSize(1920, 1080); - else if (params.requested_format.frame_size.width() > 640) - capture_format_.frame_size.SetSize(1280, 720); - else if (params.requested_format.frame_size.width() > 320) - capture_format_.frame_size.SetSize(640, 480); - else - capture_format_.frame_size.SetSize(320, 240); - - if (device_type_ == USING_OWN_BUFFERS || - device_type_ == USING_OWN_BUFFERS_TRIPLANAR) { - capture_format_.pixel_storage = PIXEL_STORAGE_CPU; - fake_frame_.reset(new uint8[VideoFrame::AllocationSize( - PIXEL_FORMAT_I420, capture_format_.frame_size)]); - BeepAndScheduleNextCapture( - base::TimeTicks::Now(), - base::Bind(&FakeVideoCaptureDevice::CaptureUsingOwnBuffers, - weak_factory_.GetWeakPtr())); - } else if (device_type_ == USING_CLIENT_BUFFERS) { - DVLOG(1) << "starting with " - << (params.use_gpu_memory_buffers ? "GMB" : "ShMem"); - BeepAndScheduleNextCapture( - base::TimeTicks::Now(), - base::Bind(&FakeVideoCaptureDevice::CaptureUsingClientBuffers, - weak_factory_.GetWeakPtr(), - params.use_gpu_memory_buffers - ? VIDEO_CAPTURE_PIXEL_FORMAT_ARGB - : VIDEO_CAPTURE_PIXEL_FORMAT_I420, - params.use_gpu_memory_buffers ? PIXEL_STORAGE_GPUMEMORYBUFFER - : PIXEL_STORAGE_CPU)); - } else { - client_->OnError("Unknown Fake Video Capture Device type."); - } -} - -void FakeVideoCaptureDevice::StopAndDeAllocate() { - DCHECK(thread_checker_.CalledOnValidThread()); - client_.reset(); -} - -void FakeVideoCaptureDevice::CaptureUsingOwnBuffers( - base::TimeTicks expected_execution_time) { - DCHECK(thread_checker_.CalledOnValidThread()); - const size_t frame_size = capture_format_.ImageAllocationSize(); - memset(fake_frame_.get(), 0, frame_size); - - DrawPacman(false /* use_argb */, - fake_frame_.get(), - frame_count_, - kFakeCapturePeriodMs, - capture_format_.frame_size); - - // Give the captured frame to the client. - if (device_type_ == USING_OWN_BUFFERS) { - client_->OnIncomingCapturedData(fake_frame_.get(), - frame_size, - capture_format_, - 0 /* rotation */, - base::TimeTicks::Now()); - } else if (device_type_ == USING_OWN_BUFFERS_TRIPLANAR) { - client_->OnIncomingCapturedYuvData( - fake_frame_.get(), - fake_frame_.get() + capture_format_.frame_size.GetArea(), - fake_frame_.get() + capture_format_.frame_size.GetArea() * 5 / 4, - capture_format_.frame_size.width(), - capture_format_.frame_size.width() / 2, - capture_format_.frame_size.width() / 2, - capture_format_, - 0 /* rotation */, - base::TimeTicks::Now()); - } - BeepAndScheduleNextCapture( - expected_execution_time, - base::Bind(&FakeVideoCaptureDevice::CaptureUsingOwnBuffers, - weak_factory_.GetWeakPtr())); -} - -void FakeVideoCaptureDevice::CaptureUsingClientBuffers( - VideoCapturePixelFormat pixel_format, - VideoPixelStorage pixel_storage, - base::TimeTicks expected_execution_time) { - DCHECK(thread_checker_.CalledOnValidThread()); - - scoped_ptr<VideoCaptureDevice::Client::Buffer> capture_buffer( - client_->ReserveOutputBuffer(capture_format_.frame_size, pixel_format, - pixel_storage)); - DLOG_IF(ERROR, !capture_buffer) << "Couldn't allocate Capture Buffer"; - - if (capture_buffer.get()) { - uint8_t* const data_ptr = static_cast<uint8_t*>(capture_buffer->data()); - DCHECK(data_ptr) << "Buffer has NO backing memory"; - memset(data_ptr, 0, capture_buffer->size()); - - DrawPacman( - (pixel_format == media::VIDEO_CAPTURE_PIXEL_FORMAT_ARGB), /* use_argb */ - data_ptr, frame_count_, kFakeCapturePeriodMs, - capture_format_.frame_size); - - // Give the captured frame to the client. - const VideoCaptureFormat format(capture_format_.frame_size, - capture_format_.frame_rate, pixel_format, - pixel_storage); - client_->OnIncomingCapturedBuffer(capture_buffer.Pass(), format, - base::TimeTicks::Now()); - } - - BeepAndScheduleNextCapture( - expected_execution_time, - base::Bind(&FakeVideoCaptureDevice::CaptureUsingClientBuffers, - weak_factory_.GetWeakPtr(), pixel_format, pixel_storage)); -} - -void FakeVideoCaptureDevice::BeepAndScheduleNextCapture( - base::TimeTicks expected_execution_time, - const base::Callback<void(base::TimeTicks)>& next_capture) { - // Generate a synchronized beep sound every so many frames. - if (frame_count_++ % kFakeCaptureBeepCycle == 0) - FakeAudioInputStream::BeepOnce(); - - // Reschedule next CaptureTask. - const base::TimeTicks current_time = base::TimeTicks::Now(); - const base::TimeDelta frame_interval = - base::TimeDelta::FromMilliseconds(kFakeCapturePeriodMs); - // Don't accumulate any debt if we are lagging behind - just post the next - // frame immediately and continue as normal. - const base::TimeTicks next_execution_time = - std::max(current_time, expected_execution_time + frame_interval); - const base::TimeDelta delay = next_execution_time - current_time; - base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, base::Bind(next_capture, next_execution_time), delay); -} - -} // namespace media diff --git a/media/video/capture/fake_video_capture_device.h b/media/video/capture/fake_video_capture_device.h deleted file mode 100644 index 10b53db..0000000 --- a/media/video/capture/fake_video_capture_device.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2012 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 fake VideoCaptureDevice class. Used for testing other -// video capture classes when no real hardware is available. - -#ifndef MEDIA_VIDEO_CAPTURE_FAKE_VIDEO_CAPTURE_DEVICE_H_ -#define MEDIA_VIDEO_CAPTURE_FAKE_VIDEO_CAPTURE_DEVICE_H_ - -#include <string> - -#include "base/atomicops.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/thread.h" -#include "base/threading/thread_checker.h" -#include "base/time/time.h" -#include "media/video/capture/video_capture_device.h" - -namespace media { - -class MEDIA_EXPORT FakeVideoCaptureDevice : public VideoCaptureDevice { - public: - enum FakeVideoCaptureDeviceType { - USING_OWN_BUFFERS, - USING_OWN_BUFFERS_TRIPLANAR, - USING_CLIENT_BUFFERS, - }; - - static int FakeCapturePeriodMs() { return kFakeCapturePeriodMs; } - - explicit FakeVideoCaptureDevice(FakeVideoCaptureDeviceType device_type); - ~FakeVideoCaptureDevice() override; - - // VideoCaptureDevice implementation. - void AllocateAndStart(const VideoCaptureParams& params, - scoped_ptr<Client> client) override; - void StopAndDeAllocate() override; - - private: - static const int kFakeCapturePeriodMs = 50; - - void CaptureUsingOwnBuffers(base::TimeTicks expected_execution_time); - void CaptureUsingClientBuffers(VideoCapturePixelFormat pixel_format, - VideoPixelStorage pixel_storage, - base::TimeTicks expected_execution_time); - void BeepAndScheduleNextCapture( - base::TimeTicks expected_execution_time, - const base::Callback<void(base::TimeTicks)>& next_capture); - - // |thread_checker_| is used to check that all methods are called in the - // correct thread that owns the object. - base::ThreadChecker thread_checker_; - - const FakeVideoCaptureDeviceType device_type_; - - scoped_ptr<VideoCaptureDevice::Client> client_; - // |fake_frame_| is used for capturing on Own Buffers. - scoped_ptr<uint8[]> fake_frame_; - int frame_count_; - VideoCaptureFormat capture_format_; - - // FakeVideoCaptureDevice post tasks to itself for frame construction and - // needs to deal with asynchronous StopAndDeallocate(). - base::WeakPtrFactory<FakeVideoCaptureDevice> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(FakeVideoCaptureDevice); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_FAKE_VIDEO_CAPTURE_DEVICE_H_ diff --git a/media/video/capture/fake_video_capture_device_factory.cc b/media/video/capture/fake_video_capture_device_factory.cc deleted file mode 100644 index 31e6b2d..0000000 --- a/media/video/capture/fake_video_capture_device_factory.cc +++ /dev/null @@ -1,81 +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/fake_video_capture_device_factory.h" - -#include "base/command_line.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "media/base/media_switches.h" -#include "media/video/capture/fake_video_capture_device.h" - -namespace media { - -FakeVideoCaptureDeviceFactory::FakeVideoCaptureDeviceFactory() - : number_of_devices_(1) { -} - -scoped_ptr<VideoCaptureDevice> FakeVideoCaptureDeviceFactory::Create( - const VideoCaptureDevice::Name& device_name) { - DCHECK(thread_checker_.CalledOnValidThread()); - - const std::string option = base::CommandLine::ForCurrentProcess()-> - GetSwitchValueASCII(switches::kUseFakeDeviceForMediaStream); - - FakeVideoCaptureDevice::FakeVideoCaptureDeviceType fake_vcd_type; - if (option.empty()) - fake_vcd_type = FakeVideoCaptureDevice::USING_OWN_BUFFERS; - else if (base::EqualsCaseInsensitiveASCII(option, "triplanar")) - fake_vcd_type = FakeVideoCaptureDevice::USING_OWN_BUFFERS_TRIPLANAR; - else - fake_vcd_type = FakeVideoCaptureDevice::USING_CLIENT_BUFFERS; - - for (int n = 0; n < number_of_devices_; ++n) { - std::string possible_id = base::StringPrintf("/dev/video%d", n); - if (device_name.id().compare(possible_id) == 0) { - return scoped_ptr<VideoCaptureDevice>( - new FakeVideoCaptureDevice(fake_vcd_type)); - } - } - return scoped_ptr<VideoCaptureDevice>(); -} - -void FakeVideoCaptureDeviceFactory::GetDeviceNames( - VideoCaptureDevice::Names* const device_names) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(device_names->empty()); - for (int n = 0; n < number_of_devices_; ++n) { - VideoCaptureDevice::Name name(base::StringPrintf("fake_device_%d", n), - base::StringPrintf("/dev/video%d", n) -#if defined(OS_LINUX) - , VideoCaptureDevice::Name::V4L2_SINGLE_PLANE -#elif defined(OS_MACOSX) - , VideoCaptureDevice::Name::AVFOUNDATION -#elif defined(OS_WIN) - , VideoCaptureDevice::Name::DIRECT_SHOW -#elif defined(OS_ANDROID) - , VideoCaptureDevice::Name::API2_LEGACY -#endif - ); - device_names->push_back(name); - } -} - -void FakeVideoCaptureDeviceFactory::GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) { - DCHECK(thread_checker_.CalledOnValidThread()); - const int frame_rate = 1000 / FakeVideoCaptureDevice::FakeCapturePeriodMs(); - const gfx::Size supported_sizes[] = {gfx::Size(320, 240), - gfx::Size(640, 480), - gfx::Size(1280, 720), - gfx::Size(1920, 1080)}; - supported_formats->clear(); - for (const auto& size : supported_sizes) { - supported_formats->push_back(VideoCaptureFormat( - size, frame_rate, media::VIDEO_CAPTURE_PIXEL_FORMAT_I420)); - } -} - -} // namespace media diff --git a/media/video/capture/fake_video_capture_device_factory.h b/media/video/capture/fake_video_capture_device_factory.h deleted file mode 100644 index 00cea5d..0000000 --- a/media/video/capture/fake_video_capture_device_factory.h +++ /dev/null @@ -1,44 +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 fake VideoCaptureDeviceFactory class. - -#ifndef MEDIA_VIDEO_CAPTURE_FAKE_VIDEO_CAPTURE_DEVICE_FACTORY_H_ -#define MEDIA_VIDEO_CAPTURE_FAKE_VIDEO_CAPTURE_DEVICE_FACTORY_H_ - -#include "media/video/capture/video_capture_device_factory.h" - -namespace media { - -// Extension of VideoCaptureDeviceFactory to create and manipulate fake devices, -// not including file-based ones. -class MEDIA_EXPORT FakeVideoCaptureDeviceFactory : - public VideoCaptureDeviceFactory { - public: - FakeVideoCaptureDeviceFactory(); - ~FakeVideoCaptureDeviceFactory() override {} - - scoped_ptr<VideoCaptureDevice> Create( - const VideoCaptureDevice::Name& device_name) override; - void GetDeviceNames(VideoCaptureDevice::Names* device_names) override; - void GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) override; - - void set_number_of_devices(int number_of_devices) { - DCHECK(thread_checker_.CalledOnValidThread()); - number_of_devices_ = number_of_devices; - } - int number_of_devices() { - DCHECK(thread_checker_.CalledOnValidThread()); - return number_of_devices_; - } - - private: - int number_of_devices_; -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_FAKE_VIDEO_CAPTURE_DEVICE_FACTORY_H_ 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 e222bd02..0000000 --- a/media/video/capture/fake_video_capture_device_unittest.cc +++ /dev/null @@ -1,242 +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/base/video_capture_types.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 "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::_; -using ::testing::Bool; -using ::testing::Combine; -using ::testing::SaveArg; -using ::testing::Values; - -namespace media { - -namespace { - -// This class is a Client::Buffer that allocates and frees the requested |size|. -class MockBuffer : public VideoCaptureDevice::Client::Buffer { - public: - MockBuffer(int buffer_id, size_t size) - : id_(buffer_id), size_(size), data_(new uint8[size_]) {} - ~MockBuffer() override { delete[] data_; } - - int id() const override { return id_; } - size_t size() const override { return size_; } - void* data() override { return data_; } - ClientBuffer AsClientBuffer() override { return nullptr; } -#if defined(OS_POSIX) - base::FileDescriptor AsPlatformFile() override { - return base::FileDescriptor(); - } -#endif - - private: - const int id_; - const size_t size_; - uint8* const data_; -}; - -class MockClient : public VideoCaptureDevice::Client { - public: - MOCK_METHOD1(OnError, void(const std::string& reason)); - - explicit MockClient(base::Callback<void(const VideoCaptureFormat&)> frame_cb) - : frame_cb_(frame_cb) {} - - // Client virtual methods for capturing using Device Buffers. - void OnIncomingCapturedData(const uint8* data, - int length, - const VideoCaptureFormat& format, - int rotation, - const base::TimeTicks& timestamp) { - frame_cb_.Run(format); - } - void OnIncomingCapturedYuvData(const uint8* y_data, - const uint8* u_data, - const uint8* v_data, - size_t y_stride, - size_t u_stride, - size_t v_stride, - const VideoCaptureFormat& frame_format, - int clockwise_rotation, - const base::TimeTicks& timestamp) { - frame_cb_.Run(frame_format); - } - - // Virtual methods for capturing using Client's Buffers. - scoped_ptr<Buffer> ReserveOutputBuffer(const gfx::Size& dimensions, - media::VideoCapturePixelFormat format, - media::VideoPixelStorage storage) { - EXPECT_TRUE((format == media::VIDEO_CAPTURE_PIXEL_FORMAT_I420 && - storage == media::PIXEL_STORAGE_CPU) || - (format == media::VIDEO_CAPTURE_PIXEL_FORMAT_ARGB && - storage == media::PIXEL_STORAGE_GPUMEMORYBUFFER)); - EXPECT_GT(dimensions.GetArea(), 0); - const VideoCaptureFormat frame_format(dimensions, 0.0, format); - return make_scoped_ptr( - new MockBuffer(0, frame_format.ImageAllocationSize())); - } - void OnIncomingCapturedBuffer(scoped_ptr<Buffer> buffer, - const VideoCaptureFormat& frame_format, - const base::TimeTicks& timestamp) { - frame_cb_.Run(frame_format); - } - void OnIncomingCapturedVideoFrame( - scoped_ptr<Buffer> buffer, - const scoped_refptr<media::VideoFrame>& frame, - const base::TimeTicks& timestamp) { - VideoCaptureFormat format(frame->natural_size(), 30.0, - VIDEO_CAPTURE_PIXEL_FORMAT_I420); - frame_cb_.Run(format); - } - - double GetBufferPoolUtilization() const override { return 0.0; } - - private: - base::Callback<void(const VideoCaptureFormat&)> frame_cb_; -}; - -class DeviceEnumerationListener : - public base::RefCounted<DeviceEnumerationListener> { - public: - MOCK_METHOD1(OnEnumeratedDevicesCallbackPtr, - void(VideoCaptureDevice::Names* names)); - // GMock doesn't support move-only arguments, so we use this forward method. - void OnEnumeratedDevicesCallback( - scoped_ptr<VideoCaptureDevice::Names> names) { - OnEnumeratedDevicesCallbackPtr(names.release()); - } - - private: - friend class base::RefCounted<DeviceEnumerationListener>; - virtual ~DeviceEnumerationListener() {} -}; - -} // namespace - -class FakeVideoCaptureDeviceTest - : public testing::TestWithParam< - ::testing::tuple<FakeVideoCaptureDevice::FakeVideoCaptureDeviceType, - bool>> { - protected: - FakeVideoCaptureDeviceTest() - : loop_(new base::MessageLoop()), - client_(new MockClient( - base::Bind(&FakeVideoCaptureDeviceTest::OnFrameCaptured, - base::Unretained(this)))), - video_capture_device_factory_(new FakeVideoCaptureDeviceFactory()) { - device_enumeration_listener_ = new DeviceEnumerationListener(); - } - - void SetUp() override { - EXPECT_CALL(*client_, OnError(_)).Times(0); - } - - void OnFrameCaptured(const VideoCaptureFormat& format) { - last_format_ = format; - run_loop_->QuitClosure().Run(); - } - - void WaitForCapturedFrame() { - run_loop_.reset(new base::RunLoop()); - run_loop_->Run(); - } - - scoped_ptr<VideoCaptureDevice::Names> EnumerateDevices() { - VideoCaptureDevice::Names* names; - EXPECT_CALL(*device_enumeration_listener_.get(), - OnEnumeratedDevicesCallbackPtr(_)).WillOnce(SaveArg<0>(&names)); - - video_capture_device_factory_->EnumerateDeviceNames( - base::Bind(&DeviceEnumerationListener::OnEnumeratedDevicesCallback, - device_enumeration_listener_)); - base::MessageLoop::current()->RunUntilIdle(); - return scoped_ptr<VideoCaptureDevice::Names>(names); - } - - const VideoCaptureFormat& last_format() const { return last_format_; } - - VideoCaptureDevice::Names names_; - const scoped_ptr<base::MessageLoop> loop_; - scoped_ptr<base::RunLoop> run_loop_; - scoped_ptr<MockClient> client_; - scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_; - VideoCaptureFormat last_format_; - const scoped_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_; -}; - -TEST_P(FakeVideoCaptureDeviceTest, CaptureUsing) { - const scoped_ptr<VideoCaptureDevice::Names> names(EnumerateDevices()); - ASSERT_FALSE(names->empty()); - - scoped_ptr<VideoCaptureDevice> device( - new FakeVideoCaptureDevice(testing::get<0>(GetParam()))); - ASSERT_TRUE(device); - - 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 = - VIDEO_CAPTURE_PIXEL_FORMAT_I420; - capture_params.use_gpu_memory_buffers = ::testing::get<1>(GetParam()); - device->AllocateAndStart(capture_params, client_.Pass()); - - WaitForCapturedFrame(); - EXPECT_EQ(last_format().frame_size.width(), 640); - EXPECT_EQ(last_format().frame_size.height(), 480); - EXPECT_EQ(last_format().frame_rate, 30.0); - device->StopAndDeAllocate(); -} - -INSTANTIATE_TEST_CASE_P( - , - FakeVideoCaptureDeviceTest, - Combine(Values(FakeVideoCaptureDevice::USING_OWN_BUFFERS, - FakeVideoCaptureDevice::USING_OWN_BUFFERS_TRIPLANAR, - FakeVideoCaptureDevice::USING_CLIENT_BUFFERS), - Bool())); - -TEST_F(FakeVideoCaptureDeviceTest, GetDeviceSupportedFormats) { - scoped_ptr<VideoCaptureDevice::Names> names(EnumerateDevices()); - - VideoCaptureFormats supported_formats; - - for (const auto& names_iterator : *names) { - video_capture_device_factory_->GetDeviceSupportedFormats( - names_iterator, &supported_formats); - ASSERT_EQ(supported_formats.size(), 4u); - 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, - VIDEO_CAPTURE_PIXEL_FORMAT_I420); - EXPECT_GE(supported_formats[0].frame_rate, 20.0); - 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, - VIDEO_CAPTURE_PIXEL_FORMAT_I420); - EXPECT_GE(supported_formats[1].frame_rate, 20.0); - 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, - VIDEO_CAPTURE_PIXEL_FORMAT_I420); - EXPECT_GE(supported_formats[2].frame_rate, 20.0); - EXPECT_EQ(supported_formats[3].frame_size.width(), 1920); - EXPECT_EQ(supported_formats[3].frame_size.height(), 1080); - EXPECT_EQ(supported_formats[3].pixel_format, - VIDEO_CAPTURE_PIXEL_FORMAT_I420); - EXPECT_GE(supported_formats[3].frame_rate, 20.0); - } -} - -}; // namespace media diff --git a/media/video/capture/file_video_capture_device.cc b/media/video/capture/file_video_capture_device.cc deleted file mode 100644 index 00b99d7..0000000 --- a/media/video/capture/file_video_capture_device.cc +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2013 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/file_video_capture_device.h" - - -#include "base/bind.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "media/base/video_capture_types.h" - -namespace media { -static const int kY4MHeaderMaxSize = 200; -static const char kY4MSimpleFrameDelimiter[] = "FRAME"; -static const int kY4MSimpleFrameDelimiterSize = 6; - -int ParseY4MInt(const base::StringPiece& token) { - int temp_int; - CHECK(base::StringToInt(token, &temp_int)) << token; - return temp_int; -} - -// Extract numerator and denominator out of a token that must have the aspect -// numerator:denominator, both integer numbers. -void ParseY4MRational(const base::StringPiece& token, - int* numerator, - int* denominator) { - size_t index_divider = token.find(':'); - CHECK_NE(index_divider, token.npos); - *numerator = ParseY4MInt(token.substr(0, index_divider)); - *denominator = ParseY4MInt(token.substr(index_divider + 1, token.length())); - CHECK(*denominator); -} - -// This function parses the ASCII string in |header| as belonging to a Y4M file, -// returning the collected format in |video_format|. For a non authoritative -// explanation of the header format, check -// http://wiki.multimedia.cx/index.php?title=YUV4MPEG2 -// Restrictions: Only interlaced I420 pixel format is supported, and pixel -// aspect ratio is ignored. -// Implementation notes: Y4M header should end with an ASCII 0x20 (whitespace) -// character, however all examples mentioned in the Y4M header description end -// with a newline character instead. Also, some headers do _not_ specify pixel -// format, in this case it means I420. -// This code was inspired by third_party/libvpx/.../y4minput.* . -void ParseY4MTags(const std::string& file_header, - media::VideoCaptureFormat* video_format) { - video_format->pixel_format = media::VIDEO_CAPTURE_PIXEL_FORMAT_I420; - video_format->frame_size.set_width(0); - video_format->frame_size.set_height(0); - size_t index = 0; - size_t blank_position = 0; - base::StringPiece token; - while ((blank_position = file_header.find_first_of("\n ", index)) != - std::string::npos) { - // Every token is supposed to have an identifier letter and a bunch of - // information immediately after, which we extract into a |token| here. - token = - base::StringPiece(&file_header[index + 1], blank_position - index - 1); - CHECK(!token.empty()); - switch (file_header[index]) { - case 'W': - video_format->frame_size.set_width(ParseY4MInt(token)); - break; - case 'H': - video_format->frame_size.set_height(ParseY4MInt(token)); - break; - case 'F': { - // If the token is "FRAME", it means we have finished with the header. - if (token[0] == 'R') - break; - int fps_numerator, fps_denominator; - ParseY4MRational(token, &fps_numerator, &fps_denominator); - video_format->frame_rate = fps_numerator / fps_denominator; - break; - } - case 'I': - // Interlacing is ignored, but we don't like mixed modes. - CHECK_NE(token[0], 'm'); - break; - case 'A': - // Pixel aspect ratio ignored. - break; - case 'C': - CHECK(token == "420" || token == "420jpeg" || token == "420paldv") - << token; // Only I420 is supported, and we fudge the variants. - break; - default: - break; - } - // We're done if we have found a newline character right after the token. - if (file_header[blank_position] == '\n') - break; - index = blank_position + 1; - } - // Last video format semantic correctness check before sending it back. - CHECK(video_format->IsValid()); -} - -// Reads and parses the header of a Y4M |file|, returning the collected pixel -// format in |video_format|. Returns the index of the first byte of the first -// video frame. -// Restrictions: Only trivial per-frame headers are supported. -// static -int64 FileVideoCaptureDevice::ParseFileAndExtractVideoFormat( - base::File* file, - media::VideoCaptureFormat* video_format) { - std::string header(kY4MHeaderMaxSize, 0); - file->Read(0, &header[0], kY4MHeaderMaxSize - 1); - - size_t header_end = header.find(kY4MSimpleFrameDelimiter); - CHECK_NE(header_end, header.npos); - - ParseY4MTags(header, video_format); - return header_end + kY4MSimpleFrameDelimiterSize; -} - -// Opens a given file for reading, and returns the file to the caller, who is -// responsible for closing it. -// static -base::File FileVideoCaptureDevice::OpenFileForRead( - const base::FilePath& file_path) { - base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); - DLOG_IF(ERROR, file.IsValid()) - << file_path.value() - << ", error: " << base::File::ErrorToString(file.error_details()); - return file.Pass(); -} - -FileVideoCaptureDevice::FileVideoCaptureDevice(const base::FilePath& file_path) - : capture_thread_("CaptureThread"), - file_path_(file_path), - frame_size_(0), - current_byte_index_(0), - first_frame_byte_index_(0) {} - -FileVideoCaptureDevice::~FileVideoCaptureDevice() { - DCHECK(thread_checker_.CalledOnValidThread()); - // Check if the thread is running. - // This means that the device have not been DeAllocated properly. - CHECK(!capture_thread_.IsRunning()); -} - -void FileVideoCaptureDevice::AllocateAndStart( - const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) { - DCHECK(thread_checker_.CalledOnValidThread()); - CHECK(!capture_thread_.IsRunning()); - - capture_thread_.Start(); - capture_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&FileVideoCaptureDevice::OnAllocateAndStart, - base::Unretained(this), - params, - base::Passed(&client))); -} - -void FileVideoCaptureDevice::StopAndDeAllocate() { - DCHECK(thread_checker_.CalledOnValidThread()); - CHECK(capture_thread_.IsRunning()); - - capture_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&FileVideoCaptureDevice::OnStopAndDeAllocate, - base::Unretained(this))); - capture_thread_.Stop(); -} - -int FileVideoCaptureDevice::CalculateFrameSize() const { - DCHECK_EQ(capture_format_.pixel_format, VIDEO_CAPTURE_PIXEL_FORMAT_I420); - DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current()); - return capture_format_.ImageAllocationSize(); -} - -void FileVideoCaptureDevice::OnAllocateAndStart( - const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) { - DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current()); - - client_ = client.Pass(); - - // Open the file and parse the header. Get frame size and format. - DCHECK(!file_.IsValid()); - file_ = OpenFileForRead(file_path_); - if (!file_.IsValid()) { - client_->OnError("Could not open Video file"); - return; - } - first_frame_byte_index_ = - ParseFileAndExtractVideoFormat(&file_, &capture_format_); - current_byte_index_ = first_frame_byte_index_; - DVLOG(1) << "Opened video file " << capture_format_.frame_size.ToString() - << ", fps: " << capture_format_.frame_rate; - - frame_size_ = CalculateFrameSize(); - video_frame_.reset(new uint8[frame_size_]); - - capture_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&FileVideoCaptureDevice::OnCaptureTask, - base::Unretained(this))); -} - -void FileVideoCaptureDevice::OnStopAndDeAllocate() { - DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current()); - file_.Close(); - client_.reset(); - current_byte_index_ = 0; - first_frame_byte_index_ = 0; - frame_size_ = 0; - next_frame_time_ = base::TimeTicks(); - video_frame_.reset(); -} - -void FileVideoCaptureDevice::OnCaptureTask() { - DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current()); - if (!client_) - return; - int result = file_.Read(current_byte_index_, - reinterpret_cast<char*>(video_frame_.get()), - frame_size_); - - // If we passed EOF to base::File, it will return 0 read characters. In that - // case, reset the pointer and read again. - if (result != frame_size_) { - CHECK_EQ(result, 0); - current_byte_index_ = first_frame_byte_index_; - CHECK_EQ(file_.Read(current_byte_index_, - reinterpret_cast<char*>(video_frame_.get()), - frame_size_), - frame_size_); - } else { - current_byte_index_ += frame_size_ + kY4MSimpleFrameDelimiterSize; - } - - // Give the captured frame to the client. - const base::TimeTicks current_time = base::TimeTicks::Now(); - client_->OnIncomingCapturedData(video_frame_.get(), - frame_size_, - capture_format_, - 0, - current_time); - // Reschedule next CaptureTask. - const base::TimeDelta frame_interval = - base::TimeDelta::FromMicroseconds(1E6 / capture_format_.frame_rate); - if (next_frame_time_.is_null()) { - next_frame_time_ = current_time + frame_interval; - } else { - next_frame_time_ += frame_interval; - // Don't accumulate any debt if we are lagging behind - just post next frame - // immediately and continue as normal. - if (next_frame_time_ < current_time) - next_frame_time_ = current_time; - } - base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, - base::Bind(&FileVideoCaptureDevice::OnCaptureTask, - base::Unretained(this)), - next_frame_time_ - current_time); -} - -} // namespace media diff --git a/media/video/capture/file_video_capture_device.h b/media/video/capture/file_video_capture_device.h deleted file mode 100644 index 2ea6f35..0000000 --- a/media/video/capture/file_video_capture_device.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2013 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_VIDEO_CAPTURE_FILE_VIDEO_CAPTURE_DEVICE_H_ -#define MEDIA_VIDEO_CAPTURE_FILE_VIDEO_CAPTURE_DEVICE_H_ - -#include <string> - -#include "base/files/file.h" -#include "base/memory/scoped_ptr.h" -#include "base/threading/thread.h" -#include "base/threading/thread_checker.h" -#include "media/video/capture/video_capture_device.h" - -namespace media { - -// Implementation of a VideoCaptureDevice class that reads from a file. Used for -// testing the video capture pipeline when no real hardware is available. The -// only supported file format is YUV4MPEG2 (a.k.a. Y4M), a minimal container -// with a series of uncompressed video only frames, see the link -// http://wiki.multimedia.cx/index.php?title=YUV4MPEG2 for more information -// on the file format. Several restrictions and notes apply, see the -// implementation file. -// Example videos can be found in http://media.xiph.org/video/derf. -class MEDIA_EXPORT FileVideoCaptureDevice : public VideoCaptureDevice { - public: - static int64 ParseFileAndExtractVideoFormat( - base::File* file, - media::VideoCaptureFormat* video_format); - static base::File OpenFileForRead(const base::FilePath& file_path); - - // Constructor of the class, with a fully qualified file path as input, which - // represents the Y4M video file to stream repeatedly. - explicit FileVideoCaptureDevice(const base::FilePath& file_path); - - // VideoCaptureDevice implementation, class methods. - ~FileVideoCaptureDevice() override; - void AllocateAndStart(const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) override; - void StopAndDeAllocate() override; - - private: - // Returns size in bytes of an I420 frame, not including possible paddings, - // defined by |capture_format_|. - int CalculateFrameSize() const; - - // Called on the |capture_thread_|. - void OnAllocateAndStart(const VideoCaptureParams& params, - scoped_ptr<Client> client); - void OnStopAndDeAllocate(); - void OnCaptureTask(); - - // |thread_checker_| is used to check that destructor, AllocateAndStart() and - // StopAndDeAllocate() are called in the correct thread that owns the object. - base::ThreadChecker thread_checker_; - - // |capture_thread_| is used for internal operations via posting tasks to it. - // It is active between OnAllocateAndStart() and OnStopAndDeAllocate(). - base::Thread capture_thread_; - // The following members belong to |capture_thread_|. - scoped_ptr<VideoCaptureDevice::Client> client_; - const base::FilePath file_path_; - base::File file_; - scoped_ptr<uint8[]> video_frame_; - VideoCaptureFormat capture_format_; - int frame_size_; - int64 current_byte_index_; - int64 first_frame_byte_index_; - // Target time for the next frame. - base::TimeTicks next_frame_time_; - - DISALLOW_COPY_AND_ASSIGN(FileVideoCaptureDevice); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_FILE_VIDEO_CAPTURE_DEVICE_H_ diff --git a/media/video/capture/file_video_capture_device_factory.cc b/media/video/capture/file_video_capture_device_factory.cc deleted file mode 100644 index d5dd112..0000000 --- a/media/video/capture/file_video_capture_device_factory.cc +++ /dev/null @@ -1,80 +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/file_video_capture_device_factory.h" - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/strings/sys_string_conversions.h" -#include "media/base/media_switches.h" -#include "media/video/capture/file_video_capture_device.h" - -namespace media { - -const char kFileVideoCaptureDeviceName[] = - "/dev/placeholder-for-file-backed-fake-capture-device"; - -// Inspects the command line and retrieves the file path parameter. -base::FilePath GetFilePathFromCommandLine() { - base::FilePath command_line_file_path = - base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( - switches::kUseFileForFakeVideoCapture); - CHECK(!command_line_file_path.empty()); - return command_line_file_path; -} - -scoped_ptr<VideoCaptureDevice> FileVideoCaptureDeviceFactory::Create( - const VideoCaptureDevice::Name& device_name) { - DCHECK(thread_checker_.CalledOnValidThread()); -#if defined(OS_WIN) - return scoped_ptr<VideoCaptureDevice>(new FileVideoCaptureDevice( - base::FilePath(base::SysUTF8ToWide(device_name.name())))); -#else - return scoped_ptr<VideoCaptureDevice>(new FileVideoCaptureDevice( - base::FilePath(device_name.name()))); -#endif -} - -void FileVideoCaptureDeviceFactory::GetDeviceNames( - VideoCaptureDevice::Names* const device_names) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(device_names->empty()); - const base::FilePath command_line_file_path = GetFilePathFromCommandLine(); -#if defined(OS_WIN) - device_names->push_back(VideoCaptureDevice::Name( - base::SysWideToUTF8(command_line_file_path.value()), - kFileVideoCaptureDeviceName, - VideoCaptureDevice::Name::DIRECT_SHOW)); -#elif defined(OS_MACOSX) - device_names->push_back(VideoCaptureDevice::Name( - command_line_file_path.value(), - kFileVideoCaptureDeviceName, - VideoCaptureDevice::Name::AVFOUNDATION)); -#elif defined(OS_LINUX) - device_names->push_back(VideoCaptureDevice::Name( - command_line_file_path.value(), - kFileVideoCaptureDeviceName, - VideoCaptureDevice::Name::V4L2_SINGLE_PLANE)); -#else - device_names->push_back(VideoCaptureDevice::Name( - command_line_file_path.value(), - kFileVideoCaptureDeviceName)); -#endif -} - -void FileVideoCaptureDeviceFactory::GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) { - DCHECK(thread_checker_.CalledOnValidThread()); - base::File file = - FileVideoCaptureDevice::OpenFileForRead(GetFilePathFromCommandLine()); - if (!file.IsValid()) - return; - VideoCaptureFormat capture_format; - FileVideoCaptureDevice::ParseFileAndExtractVideoFormat(&file, - &capture_format); - supported_formats->push_back(capture_format); -} - -} // namespace media diff --git a/media/video/capture/file_video_capture_device_factory.h b/media/video/capture/file_video_capture_device_factory.h deleted file mode 100644 index 523cd71..0000000 --- a/media/video/capture/file_video_capture_device_factory.h +++ /dev/null @@ -1,31 +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_VIDEO_CAPTURE_FILE_VIDEO_CAPTURE_DEVICE_FACTORY_H_ -#define MEDIA_VIDEO_CAPTURE_FILE_VIDEO_CAPTURE_DEVICE_FACTORY_H_ - -#include "media/video/capture/video_capture_device_factory.h" - -namespace media { - -// Extension of VideoCaptureDeviceFactory to create and manipulate file-backed -// fake devices. These devices play back video-only files as video capture -// input. -class MEDIA_EXPORT FileVideoCaptureDeviceFactory : - public VideoCaptureDeviceFactory { - public: - FileVideoCaptureDeviceFactory() {} - ~FileVideoCaptureDeviceFactory() override {} - - scoped_ptr<VideoCaptureDevice> Create( - const VideoCaptureDevice::Name& device_name) override; - void GetDeviceNames(VideoCaptureDevice::Names* device_names) override; - void GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) override; -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_FILE_VIDEO_CAPTURE_DEVICE_FACTORY_H_ diff --git a/media/video/capture/linux/v4l2_capture_delegate.cc b/media/video/capture/linux/v4l2_capture_delegate.cc deleted file mode 100644 index 28fb2a6..0000000 --- a/media/video/capture/linux/v4l2_capture_delegate.cc +++ /dev/null @@ -1,426 +0,0 @@ -// Copyright 2015 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/linux/v4l2_capture_delegate.h" - -#include <poll.h> -#include <sys/fcntl.h> -#include <sys/ioctl.h> -#include <sys/mman.h> - -#include "base/bind.h" -#include "base/files/file_enumerator.h" -#include "base/posix/eintr_wrapper.h" -#include "base/strings/stringprintf.h" -#include "media/base/bind_to_current_loop.h" -#include "media/video/capture/linux/v4l2_capture_delegate_multi_plane.h" -#include "media/video/capture/linux/v4l2_capture_delegate_single_plane.h" -#include "media/video/capture/linux/video_capture_device_linux.h" - -namespace media { - -// Desired number of video buffers to allocate. The actual number of allocated -// buffers by v4l2 driver can be higher or lower than this number. -// kNumVideoBuffers should not be too small, or Chrome may not return enough -// buffers back to driver in time. -const uint32 kNumVideoBuffers = 4; -// Timeout in milliseconds v4l2_thread_ blocks waiting for a frame from the hw. -const int kCaptureTimeoutMs = 200; -// The number of continuous timeouts tolerated before treated as error. -const int kContinuousTimeoutLimit = 10; -// MJPEG is preferred if the requested width or height is larger than this. -const int kMjpegWidth = 640; -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. -static struct{ - uint32_t fourcc; - VideoCapturePixelFormat pixel_format; - size_t num_planes; -} const kSupportedFormatsAndPlanarity[] = { - {V4L2_PIX_FMT_YUV420, VIDEO_CAPTURE_PIXEL_FORMAT_I420, 1}, - {V4L2_PIX_FMT_YUYV, VIDEO_CAPTURE_PIXEL_FORMAT_YUY2, 1}, - {V4L2_PIX_FMT_UYVY, VIDEO_CAPTURE_PIXEL_FORMAT_UYVY, 1}, - {V4L2_PIX_FMT_RGB24, VIDEO_CAPTURE_PIXEL_FORMAT_RGB24, 1}, -#if !defined(OS_OPENBSD) - // TODO(mcasas): add V4L2_PIX_FMT_YVU420M when available in bots. - {V4L2_PIX_FMT_YUV420M, VIDEO_CAPTURE_PIXEL_FORMAT_I420, 3}, -#endif - // MJPEG is usually sitting fairly low since we don't want to have to - // decode. - // However, is needed for large resolutions due to USB bandwidth - // limitations, - // so GetListOfUsableFourCcs() can duplicate it on top, see that method. - {V4L2_PIX_FMT_MJPEG, VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG, 1}, - // JPEG works as MJPEG on some gspca webcams from field reports, see - // https://code.google.com/p/webrtc/issues/detail?id=529, put it as the - // least - // preferred format. - {V4L2_PIX_FMT_JPEG, VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG, 1}, -}; - -// static -scoped_refptr<V4L2CaptureDelegate> -V4L2CaptureDelegate::CreateV4L2CaptureDelegate( - const VideoCaptureDevice::Name& device_name, - const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner, - int power_line_frequency) { - switch (device_name.capture_api_type()) { - case VideoCaptureDevice::Name::V4L2_SINGLE_PLANE: - return make_scoped_refptr(new V4L2CaptureDelegateSinglePlane( - device_name, v4l2_task_runner, power_line_frequency)); - case VideoCaptureDevice::Name::V4L2_MULTI_PLANE: -#if !defined(OS_OPENBSD) - return make_scoped_refptr(new V4L2CaptureDelegateMultiPlane( - device_name, v4l2_task_runner, power_line_frequency)); - default: -#endif - NOTIMPLEMENTED() << "Unknown V4L2 capture API type"; - return scoped_refptr<V4L2CaptureDelegate>(); - } -} - -// static -size_t V4L2CaptureDelegate::GetNumPlanesForFourCc(uint32_t fourcc) { - for (const auto& fourcc_and_pixel_format : kSupportedFormatsAndPlanarity) { - if (fourcc_and_pixel_format.fourcc == fourcc) - return fourcc_and_pixel_format.num_planes; - } - DVLOG(1) << "Unknown fourcc " << FourccToString(fourcc); - return 0; -} - -// static -VideoCapturePixelFormat V4L2CaptureDelegate::V4l2FourCcToChromiumPixelFormat( - uint32_t v4l2_fourcc) { - for (const auto& fourcc_and_pixel_format : kSupportedFormatsAndPlanarity) { - if (fourcc_and_pixel_format.fourcc == v4l2_fourcc) - return fourcc_and_pixel_format.pixel_format; - } - // Not finding a pixel format is OK during device capabilities enumeration. - // Let the caller decide if VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN is an error or - // not. - DVLOG(1) << "Unsupported pixel format: " << FourccToString(v4l2_fourcc); - return VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN; -} - -// static -std::list<uint32_t> V4L2CaptureDelegate::GetListOfUsableFourCcs( - bool prefer_mjpeg) { - std::list<uint32_t> supported_formats; - for (const auto& format : kSupportedFormatsAndPlanarity) - supported_formats.push_back(format.fourcc); - - // Duplicate MJPEG on top of the list depending on |prefer_mjpeg|. - if (prefer_mjpeg) - supported_formats.push_front(V4L2_PIX_FMT_MJPEG); - - return supported_formats; -} - -// static -std::string V4L2CaptureDelegate::FourccToString(uint32_t fourcc) { - return base::StringPrintf("%c%c%c%c", fourcc & 0xFF, (fourcc >> 8) & 0xFF, - (fourcc >> 16) & 0xFF, (fourcc >> 24) & 0xFF); -} - -V4L2CaptureDelegate::BufferTracker::BufferTracker() { -} - -V4L2CaptureDelegate::BufferTracker::~BufferTracker() { - for (const auto& plane : planes_) { - if (plane.start == nullptr) - continue; - const int result = munmap(plane.start, plane.length); - PLOG_IF(ERROR, result < 0) << "Error munmap()ing V4L2 buffer"; - } -} - -void V4L2CaptureDelegate::BufferTracker::AddMmapedPlane(uint8_t* const start, - size_t length) { - Plane plane; - plane.start = start; - plane.length = length; - plane.payload_size = 0; - planes_.push_back(plane); -} - -V4L2CaptureDelegate::V4L2CaptureDelegate( - const VideoCaptureDevice::Name& device_name, - const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner, - int power_line_frequency) - : capture_type_((device_name.capture_api_type() == - VideoCaptureDevice::Name::V4L2_SINGLE_PLANE) - ? V4L2_BUF_TYPE_VIDEO_CAPTURE - : V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE), - v4l2_task_runner_(v4l2_task_runner), - device_name_(device_name), - power_line_frequency_(power_line_frequency), - is_capturing_(false), - timeout_count_(0), - rotation_(0) { -} - -V4L2CaptureDelegate::~V4L2CaptureDelegate() { -} - -void V4L2CaptureDelegate::AllocateAndStart( - int width, - int height, - float frame_rate, - scoped_ptr<VideoCaptureDevice::Client> client) { - DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); - DCHECK(client); - client_ = client.Pass(); - - // Need to open camera with O_RDWR after Linux kernel 3.3. - device_fd_.reset(HANDLE_EINTR(open(device_name_.id().c_str(), O_RDWR))); - if (!device_fd_.is_valid()) { - SetErrorState("Failed to open V4L2 device driver file."); - return; - } - - v4l2_capability cap = {}; - if (!((HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYCAP, &cap)) == 0) && - ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE || - cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) && - !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) && - !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)))) { - device_fd_.reset(); - SetErrorState("This is not a V4L2 video capture device"); - return; - } - - // Get supported video formats in preferred order. - // For large resolutions, favour mjpeg over raw formats. - const std::list<uint32_t>& desired_v4l2_formats = - GetListOfUsableFourCcs(width > kMjpegWidth || height > kMjpegHeight); - std::list<uint32_t>::const_iterator best = desired_v4l2_formats.end(); - - v4l2_fmtdesc fmtdesc = {}; - fmtdesc.type = capture_type_; - for (; HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_ENUM_FMT, &fmtdesc)) == 0; - ++fmtdesc.index) { - best = std::find(desired_v4l2_formats.begin(), best, fmtdesc.pixelformat); - } - if (best == desired_v4l2_formats.end()) { - SetErrorState("Failed to find a supported camera format."); - return; - } - - DVLOG(1) << "Chosen pixel format is " << FourccToString(*best); - - video_fmt_.type = capture_type_; - if (!FillV4L2Format(&video_fmt_, width, height, *best)) { - SetErrorState("Failed filling in V4L2 Format"); - return; - } - - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_FMT, &video_fmt_)) < 0) { - SetErrorState("Failed to set video capture format"); - return; - } - const VideoCapturePixelFormat pixel_format = - V4l2FourCcToChromiumPixelFormat(video_fmt_.fmt.pix.pixelformat); - if (pixel_format == VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN) { - SetErrorState("Unsupported pixel format"); - return; - } - - // Set capture framerate in the form of capture interval. - v4l2_streamparm streamparm = {}; - streamparm.type = capture_type_; - // The following line checks that the driver knows about framerate get/set. - if (HANDLE_EINTR(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. - streamparm.parm.capture.timeperframe.numerator = - media::kFrameRatePrecision; - streamparm.parm.capture.timeperframe.denominator = - (frame_rate) ? (frame_rate * media::kFrameRatePrecision) - : (kTypicalFramerate * media::kFrameRatePrecision); - - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_PARM, &streamparm)) < - 0) { - SetErrorState("Failed to set camera framerate"); - return; - } - DVLOG(2) << "Actual camera driverframerate: " - << streamparm.parm.capture.timeperframe.denominator << "/" - << streamparm.parm.capture.timeperframe.numerator; - } - } - // TODO(mcasas): what should be done if the camera driver does not allow - // framerate configuration, or the actual one is different from the desired? - - // Set anti-banding/anti-flicker to 50/60Hz. May fail due to not supported - // operation (|errno| == EINVAL in this case) or plain failure. - if ((power_line_frequency_ == V4L2_CID_POWER_LINE_FREQUENCY_50HZ) || - (power_line_frequency_ == V4L2_CID_POWER_LINE_FREQUENCY_60HZ) || - (power_line_frequency_ == V4L2_CID_POWER_LINE_FREQUENCY_AUTO)) { - struct v4l2_control control = {}; - 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)); - if (retval != 0) - DVLOG(1) << "Error setting power line frequency removal"; - } - - capture_format_.frame_size.SetSize(video_fmt_.fmt.pix.width, - video_fmt_.fmt.pix.height); - capture_format_.frame_rate = frame_rate; - capture_format_.pixel_format = pixel_format; - - v4l2_requestbuffers r_buffer = {}; - r_buffer.type = capture_type_; - r_buffer.memory = V4L2_MEMORY_MMAP; - r_buffer.count = kNumVideoBuffers; - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) { - SetErrorState("Error requesting MMAP buffers from V4L2"); - return; - } - for (unsigned int i = 0; i < r_buffer.count; ++i) { - if (!MapAndQueueBuffer(i)) { - SetErrorState("Allocate buffer failed"); - return; - } - } - - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMON, &capture_type_)) - < 0) { - SetErrorState("VIDIOC_STREAMON failed"); - return; - } - - is_capturing_ = true; - // Post task to start fetching frames from v4l2. - v4l2_task_runner_->PostTask( - FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, this)); -} - -void V4L2CaptureDelegate::StopAndDeAllocate() { - DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); - // The order is important: stop streaming, clear |buffer_pool_|, - // thus munmap()ing the v4l2_buffers, and then return them to the OS. - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &capture_type_)) - < 0) { - SetErrorState("VIDIOC_STREAMOFF failed"); - return; - } - - buffer_tracker_pool_.clear(); - - v4l2_requestbuffers r_buffer = {}; - r_buffer.type = capture_type_; - r_buffer.memory = V4L2_MEMORY_MMAP; - r_buffer.count = 0; - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) - SetErrorState("Failed to VIDIOC_REQBUFS with count = 0"); - - // At this point we can close the device. - // This is also needed for correctly changing settings later via VIDIOC_S_FMT. - device_fd_.reset(); - is_capturing_ = false; - client_.reset(); -} - -void V4L2CaptureDelegate::SetRotation(int rotation) { - DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); - DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0); - rotation_ = rotation; -} - -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"; - return false; - } - - const scoped_refptr<BufferTracker>& buffer_tracker = CreateBufferTracker(); - if (!buffer_tracker->Init(device_fd_.get(), buffer)) { - DLOG(ERROR) << "Error creating BufferTracker"; - return false; - } - 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"; - return false; - } - return true; -} - -void V4L2CaptureDelegate::FillV4L2Buffer(v4l2_buffer* buffer, - int i) const { - memset(buffer, 0, sizeof(*buffer)); - buffer->memory = V4L2_MEMORY_MMAP; - buffer->index = i; - FinishFillingV4L2Buffer(buffer); -} - -void V4L2CaptureDelegate::DoCapture() { - DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); - if (!is_capturing_) - return; - - pollfd device_pfd = {}; - device_pfd.fd = device_fd_.get(); - device_pfd.events = POLLIN; - const int result = HANDLE_EINTR(poll(&device_pfd, 1, kCaptureTimeoutMs)); - if (result < 0) { - SetErrorState("Poll failed"); - return; - } - // Check if poll() timed out; track the amount of times it did in a row and - // throw an error if it times out too many times. - if (result == 0) { - timeout_count_++; - if (timeout_count_ >= kContinuousTimeoutLimit) { - SetErrorState("Multiple continuous timeouts while read-polling."); - timeout_count_ = 0; - return; - } - } else { - timeout_count_ = 0; - } - - // Deenqueue, send and reenqueue a buffer if the driver has filled one in. - if (device_pfd.revents & POLLIN) { - v4l2_buffer buffer; - FillV4L2Buffer(&buffer, 0); - - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) < 0) { - SetErrorState("Failed to dequeue capture buffer"); - return; - } - - SetPayloadSize(buffer_tracker_pool_[buffer.index], buffer); - SendBuffer(buffer_tracker_pool_[buffer.index], video_fmt_); - - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) { - SetErrorState("Failed to enqueue capture buffer"); - return; - } - } - - v4l2_task_runner_->PostTask( - FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, this)); -} - -void V4L2CaptureDelegate::SetErrorState(const std::string& reason) { - DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); - is_capturing_ = false; - client_->OnError(reason); -} - -} // namespace media diff --git a/media/video/capture/linux/v4l2_capture_delegate.h b/media/video/capture/linux/v4l2_capture_delegate.h deleted file mode 100644 index 3bc4846..0000000 --- a/media/video/capture/linux/v4l2_capture_delegate.h +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2015 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_VIDEO_CAPTURE_LINUX_V4L2_VIDEO_CAPTURE_DELEGATE_H_ -#define MEDIA_VIDEO_CAPTURE_LINUX_V4L2_VIDEO_CAPTURE_DELEGATE_H_ - -#if defined(OS_OPENBSD) -#include <sys/videoio.h> -#else -#include <linux/videodev2.h> -#endif - -#include "base/files/scoped_file.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" -#include "media/video/capture/video_capture_device.h" - -namespace media { - -// Class doing the actual Linux capture using V4L2 API. V4L2 SPLANE/MPLANE -// capture specifics are implemented in derived classes. Created and destroyed -// on the owner's thread, otherwise living and operating on |v4l2_task_runner_|. -class V4L2CaptureDelegate - : public base::RefCountedThreadSafe<V4L2CaptureDelegate> { - public: - // Creates the appropiate VideoCaptureDelegate according to parameters. - static scoped_refptr<V4L2CaptureDelegate> CreateV4L2CaptureDelegate( - const VideoCaptureDevice::Name& device_name, - const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner, - int power_line_frequency); - - // Retrieves the #planes for a given |fourcc|, or 0 if unknown. - static size_t GetNumPlanesForFourCc(uint32_t fourcc); - // Returns the Chrome pixel format for |v4l2_fourcc| or - // VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN. - static VideoCapturePixelFormat V4l2FourCcToChromiumPixelFormat( - uint32_t v4l2_fourcc); - - // Composes a list of usable and supported pixel formats, in order of - // preference, with MJPEG prioritised depending on |prefer_mjpeg|. - static std::list<uint32_t> GetListOfUsableFourCcs(bool prefer_mjpeg); - - // Forward-to versions of VideoCaptureDevice virtual methods. - void AllocateAndStart(int width, - int height, - float frame_rate, - scoped_ptr<VideoCaptureDevice::Client> client); - void StopAndDeAllocate(); - - void SetRotation(int rotation); - - protected: - // Class keeping track of SPLANE/MPLANE V4L2 buffers, mmap()ed on construction - // and munmap()ed on destruction. Destruction is syntactically equal for - // S/MPLANE but not construction, so this is implemented in derived classes. - // Internally it has a vector of planes, which for SPLANE will contain only - // one element. - class BufferTracker : public base::RefCounted<BufferTracker> { - public: - BufferTracker(); - // Abstract method to mmap() given |fd| according to |buffer|, planarity - // specific. - virtual bool Init(int fd, const v4l2_buffer& buffer) = 0; - - uint8_t* const GetPlaneStart(size_t plane) const { - DCHECK_LT(plane, planes_.size()); - return planes_[plane].start; - } - - size_t GetPlanePayloadSize(size_t plane) const { - DCHECK_LT(plane, planes_.size()); - return planes_[plane].payload_size; - } - - void SetPlanePayloadSize(size_t plane, size_t payload_size) { - DCHECK_LT(plane, planes_.size()); - DCHECK_LE(payload_size, planes_[plane].length); - planes_[plane].payload_size = payload_size; - } - - protected: - friend class base::RefCounted<BufferTracker>; - virtual ~BufferTracker(); - // Adds a given mmap()ed plane to |planes_|. - void AddMmapedPlane(uint8_t* const start, size_t length); - - private: - struct Plane { - uint8_t* start; - size_t length; - size_t payload_size; - }; - std::vector<Plane> planes_; - }; - - V4L2CaptureDelegate( - const VideoCaptureDevice::Name& device_name, - const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner, - int power_line_frequency); - virtual ~V4L2CaptureDelegate(); - - // Creates the necessary, planarity-specific, internal tracking schemes, - virtual scoped_refptr<BufferTracker> CreateBufferTracker() const = 0; - - // Fill in |format| with the given parameters, in a planarity dependent way. - virtual bool FillV4L2Format(v4l2_format* format, - uint32_t width, - uint32_t height, - uint32_t pixelformat_fourcc) const = 0; - - // Finish filling |buffer| struct with planarity-dependent data. - virtual void FinishFillingV4L2Buffer(v4l2_buffer* buffer) const = 0; - - // Fetch the number of bytes occupied by data in |buffer| and set to - // |buffer_tracker|. - virtual void SetPayloadSize( - const scoped_refptr<BufferTracker>& buffer_tracker, - const v4l2_buffer& buffer) const = 0; - - // Sends the captured |buffer| to the |client_|, synchronously. - virtual void SendBuffer( - const scoped_refptr<BufferTracker>& buffer_tracker, - const v4l2_format& format) const = 0; - - // A few accessors for SendBuffer()'s to access private member variables. - VideoCaptureFormat capture_format() const { return capture_format_; } - VideoCaptureDevice::Client* client() const { return client_.get(); } - int rotation() const { return rotation_; } - - private: - friend class base::RefCountedThreadSafe<V4L2CaptureDelegate>; - - // Returns the input |fourcc| as a std::string four char representation. - static std::string FourccToString(uint32_t fourcc); - // VIDIOC_QUERYBUFs a buffer from V4L2, creates a BufferTracker for it and - // enqueues it (VIDIOC_QBUF) back into V4L2. - bool MapAndQueueBuffer(int index); - // Fills all common parts of |buffer|. Delegates to FinishFillingV4L2Buffer() - // for filling in the planar-dependent parts. - void FillV4L2Buffer(v4l2_buffer* buffer, int i) const; - void DoCapture(); - void SetErrorState(const std::string& reason); - - const v4l2_buf_type capture_type_; - const scoped_refptr<base::SingleThreadTaskRunner> v4l2_task_runner_; - const VideoCaptureDevice::Name device_name_; - const int power_line_frequency_; - - // The following members are only known on AllocateAndStart(). - VideoCaptureFormat capture_format_; - v4l2_format video_fmt_; - scoped_ptr<VideoCaptureDevice::Client> client_; - base::ScopedFD device_fd_; - - // Vector of BufferTracker to keep track of mmap()ed pointers and their use. - std::vector<scoped_refptr<BufferTracker>> buffer_tracker_pool_; - - bool is_capturing_; - int timeout_count_; - - // Clockwise rotation in degrees. This value should be 0, 90, 180, or 270. - int rotation_; - - DISALLOW_COPY_AND_ASSIGN(V4L2CaptureDelegate); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_LINUX_V4L2_VIDEO_CAPTURE_DELEGATE_H_ diff --git a/media/video/capture/linux/v4l2_capture_delegate_multi_plane.cc b/media/video/capture/linux/v4l2_capture_delegate_multi_plane.cc deleted file mode 100644 index 06a15e5..0000000 --- a/media/video/capture/linux/v4l2_capture_delegate_multi_plane.cc +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2015 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/linux/v4l2_capture_delegate_multi_plane.h" - -#include <sys/mman.h> - -namespace media { - -V4L2CaptureDelegateMultiPlane::V4L2CaptureDelegateMultiPlane( - const VideoCaptureDevice::Name& device_name, - const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner, - int power_line_frequency) - : V4L2CaptureDelegate(device_name, - v4l2_task_runner, - power_line_frequency) { -} - -V4L2CaptureDelegateMultiPlane::~V4L2CaptureDelegateMultiPlane() { -} - -scoped_refptr<V4L2CaptureDelegate::BufferTracker> -V4L2CaptureDelegateMultiPlane::CreateBufferTracker() const { - return make_scoped_refptr(new BufferTrackerMPlane()); -} - -bool V4L2CaptureDelegateMultiPlane::FillV4L2Format( - v4l2_format* format, - uint32_t width, - uint32_t height, - uint32_t pixelformat_fourcc) const { - format->fmt.pix_mp.width = width; - format->fmt.pix_mp.height = height; - format->fmt.pix_mp.pixelformat = pixelformat_fourcc; - - const size_t num_v4l2_planes = - V4L2CaptureDelegate::GetNumPlanesForFourCc(pixelformat_fourcc); - if (num_v4l2_planes == 0u) - return false; - DCHECK_LE(num_v4l2_planes, static_cast<size_t>(VIDEO_MAX_PLANES)); - format->fmt.pix_mp.num_planes = num_v4l2_planes; - - v4l2_planes_.resize(num_v4l2_planes); - return true; -} - -void V4L2CaptureDelegateMultiPlane::FinishFillingV4L2Buffer( - v4l2_buffer* buffer) const { - buffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - buffer->length = v4l2_planes_.size(); - - static const struct v4l2_plane empty_plane = {}; - std::fill(v4l2_planes_.begin(), v4l2_planes_.end(), empty_plane); - buffer->m.planes = v4l2_planes_.data(); -} - -void V4L2CaptureDelegateMultiPlane::SetPayloadSize( - const scoped_refptr<BufferTracker>& buffer_tracker, - const v4l2_buffer& buffer) const { - for (size_t i = 0; i < v4l2_planes_.size() && i < buffer.length; i++) - buffer_tracker->SetPlanePayloadSize(i, buffer.m.planes[i].bytesused); -} - -void V4L2CaptureDelegateMultiPlane::SendBuffer( - const scoped_refptr<BufferTracker>& buffer_tracker, - const v4l2_format& format) const { - DCHECK_EQ(capture_format().pixel_format, VIDEO_CAPTURE_PIXEL_FORMAT_I420); - const size_t y_stride = format.fmt.pix_mp.plane_fmt[0].bytesperline; - const size_t u_stride = format.fmt.pix_mp.plane_fmt[1].bytesperline; - const size_t v_stride = format.fmt.pix_mp.plane_fmt[2].bytesperline; - DCHECK_GE(y_stride, 1u * capture_format().frame_size.width()); - DCHECK_GE(u_stride, 1u * capture_format().frame_size.width() / 2); - DCHECK_GE(v_stride, 1u * capture_format().frame_size.width() / 2); - client()->OnIncomingCapturedYuvData(buffer_tracker->GetPlaneStart(0), - buffer_tracker->GetPlaneStart(1), - buffer_tracker->GetPlaneStart(2), - y_stride, - u_stride, - v_stride, - capture_format(), - rotation(), - base::TimeTicks::Now()); -} - -bool V4L2CaptureDelegateMultiPlane::BufferTrackerMPlane::Init( - int fd, - const v4l2_buffer& buffer) { - for (size_t p = 0; p < buffer.length; ++p) { - // Some devices require mmap() to be called with both READ and WRITE. - // See http://crbug.com/178582. - void* const start = - mmap(NULL, buffer.m.planes[p].length, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, buffer.m.planes[p].m.mem_offset); - if (start == MAP_FAILED) { - DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; - return false; - } - AddMmapedPlane(static_cast<uint8_t*>(start), buffer.m.planes[p].length); - DVLOG(3) << "Mmap()ed plane #" << p << " of " << buffer.m.planes[p].length - << "B"; - } - return true; -} - -} // namespace media diff --git a/media/video/capture/linux/v4l2_capture_delegate_multi_plane.h b/media/video/capture/linux/v4l2_capture_delegate_multi_plane.h deleted file mode 100644 index 64511ad..0000000 --- a/media/video/capture/linux/v4l2_capture_delegate_multi_plane.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2015 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_VIDEO_CAPTURE_LINUX_V4L2_CAPTURE_DELEGATE_MULTI_PLANE_H_ -#define MEDIA_VIDEO_CAPTURE_LINUX_V4L2_CAPTURE_DELEGATE_MULTI_PLANE_H_ - -#include "base/memory/ref_counted.h" -#include "media/video/capture/linux/v4l2_capture_delegate.h" - -#if defined(OS_OPENBSD) -#error "OpenBSD does not support MPlane capture API." -#endif - -namespace base { -class SingleThreadTaskRunner; -} // namespace base - -namespace media { - -// V4L2 specifics for MPLANE API. -class V4L2CaptureDelegateMultiPlane final : public V4L2CaptureDelegate { - public: - V4L2CaptureDelegateMultiPlane( - const VideoCaptureDevice::Name& device_name, - const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner, - int power_line_frequency); - - private: - // BufferTracker derivation to implement construction semantics for MPLANE. - class BufferTrackerMPlane final : public BufferTracker { - public: - bool Init(int fd, const v4l2_buffer& buffer) override; - - private: - ~BufferTrackerMPlane() override {} - }; - - ~V4L2CaptureDelegateMultiPlane() override; - - // V4L2CaptureDelegate virtual methods implementation. - scoped_refptr<BufferTracker> CreateBufferTracker() const override; - bool FillV4L2Format(v4l2_format* format, - uint32_t width, - uint32_t height, - uint32_t pixelformat_fourcc) const override; - void FinishFillingV4L2Buffer(v4l2_buffer* buffer) const override; - void SetPayloadSize(const scoped_refptr<BufferTracker>& buffer_tracker, - const v4l2_buffer& buffer) const override; - void SendBuffer(const scoped_refptr<BufferTracker>& buffer_tracker, - const v4l2_format& format) const override; - - // Vector to allocate and track as many v4l2_plane structs as planes, needed - // for v4l2_buffer.m.planes. This is a scratchpad marked mutable to enable - // using it in otherwise const methods. - mutable std::vector<struct v4l2_plane> v4l2_planes_; -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_LINUX_V4L2_CAPTURE_DELEGATE_SINGLE_PLANE_H_ diff --git a/media/video/capture/linux/v4l2_capture_delegate_single_plane.cc b/media/video/capture/linux/v4l2_capture_delegate_single_plane.cc deleted file mode 100644 index e2e7e5b..0000000 --- a/media/video/capture/linux/v4l2_capture_delegate_single_plane.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2015 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/linux/v4l2_capture_delegate_single_plane.h" - -#include <sys/mman.h> - -namespace media { - -scoped_refptr<V4L2CaptureDelegate::BufferTracker> -V4L2CaptureDelegateSinglePlane::CreateBufferTracker() const { - return make_scoped_refptr(new BufferTrackerSPlane()); -} - -bool V4L2CaptureDelegateSinglePlane::FillV4L2Format( - v4l2_format* format, - uint32_t width, - uint32_t height, - uint32_t pixelformat_fourcc) const { - format->fmt.pix.width = width; - format->fmt.pix.height = height; - format->fmt.pix.pixelformat = pixelformat_fourcc; - return true; -} - -void V4L2CaptureDelegateSinglePlane::FinishFillingV4L2Buffer( - v4l2_buffer* buffer) const { - buffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -} - -void V4L2CaptureDelegateSinglePlane::SetPayloadSize( - const scoped_refptr<BufferTracker>& buffer_tracker, - const v4l2_buffer& buffer) const { - buffer_tracker->SetPlanePayloadSize(0, buffer.bytesused); -} - -void V4L2CaptureDelegateSinglePlane::SendBuffer( - const scoped_refptr<BufferTracker>& buffer_tracker, - const v4l2_format& format) const { - client()->OnIncomingCapturedData( - buffer_tracker->GetPlaneStart(0), - buffer_tracker->GetPlanePayloadSize(0), - capture_format(), - rotation(), - base::TimeTicks::Now()); -} - -bool V4L2CaptureDelegateSinglePlane::BufferTrackerSPlane::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); - if (start == MAP_FAILED) { - DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; - return false; - } - AddMmapedPlane(static_cast<uint8_t*>(start), buffer.length); - return true; -} - -} // namespace media diff --git a/media/video/capture/linux/v4l2_capture_delegate_single_plane.h b/media/video/capture/linux/v4l2_capture_delegate_single_plane.h deleted file mode 100644 index 8d4dc91..0000000 --- a/media/video/capture/linux/v4l2_capture_delegate_single_plane.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2015 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_VIDEO_CAPTURE_LINUX_V4L2_CAPTURE_DELEGATE_SINGLE_PLANE_H_ -#define MEDIA_VIDEO_CAPTURE_LINUX_V4L2_CAPTURE_DELEGATE_SINGLE_PLANE_H_ - -#include "base/memory/ref_counted.h" -#include "media/video/capture/linux/v4l2_capture_delegate.h" -#include "media/video/capture/video_capture_device.h" - -namespace base { -class SingleThreadTaskRunner; -} // namespace base - -namespace media { - -// V4L2 specifics for SPLANE API. -class V4L2CaptureDelegateSinglePlane final : public V4L2CaptureDelegate { - public: - V4L2CaptureDelegateSinglePlane( - const VideoCaptureDevice::Name& device_name, - const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner, - int power_line_frequency) - : V4L2CaptureDelegate(device_name, - v4l2_task_runner, - power_line_frequency) {} - - private: - // BufferTracker derivation to implement construction semantics for SPLANE. - class BufferTrackerSPlane final : public BufferTracker { - public: - bool Init(int fd, const v4l2_buffer& buffer) override; - - private: - ~BufferTrackerSPlane() override {} - }; - - ~V4L2CaptureDelegateSinglePlane() override {} - - // V4L2CaptureDelegate virtual methods implementation. - scoped_refptr<BufferTracker> CreateBufferTracker() const override; - bool FillV4L2Format(v4l2_format* format, - uint32_t width, - uint32_t height, - uint32_t pixelformat_fourcc) const override; - void FinishFillingV4L2Buffer(v4l2_buffer* buffer) const override; - void SetPayloadSize(const scoped_refptr<BufferTracker>& buffer_tracker, - const v4l2_buffer& buffer) const override; - void SendBuffer(const scoped_refptr<BufferTracker>& buffer_tracker, - const v4l2_format& format) const override; -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_LINUX_V4L2_CAPTURE_DELEGATE_MULTI_PLANE_H_ diff --git a/media/video/capture/linux/video_capture_device_chromeos.cc b/media/video/capture/linux/video_capture_device_chromeos.cc deleted file mode 100644 index 5abfbff..0000000 --- a/media/video/capture/linux/video_capture_device_chromeos.cc +++ /dev/null @@ -1,115 +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/linux/video_capture_device_chromeos.h" - -#include "base/bind.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/thread_task_runner_handle.h" -#include "ui/gfx/display.h" -#include "ui/gfx/display_observer.h" -#include "ui/gfx/screen.h" - -namespace media { - -// This is a delegate class used to transfer Display change events from the UI -// thread to the media thread. -class VideoCaptureDeviceChromeOS::ScreenObserverDelegate - : public gfx::DisplayObserver, - public base::RefCountedThreadSafe<ScreenObserverDelegate> { - public: - ScreenObserverDelegate( - VideoCaptureDeviceChromeOS* capture_device, - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) - : capture_device_(capture_device), - ui_task_runner_(ui_task_runner), - capture_task_runner_(base::ThreadTaskRunnerHandle::Get()) { - ui_task_runner_->PostTask( - FROM_HERE, - base::Bind(&ScreenObserverDelegate::AddObserverOnUIThread, this)); - } - - void RemoveObserver() { - DCHECK(capture_task_runner_->BelongsToCurrentThread()); - capture_device_ = NULL; - ui_task_runner_->PostTask( - FROM_HERE, - base::Bind(&ScreenObserverDelegate::RemoveObserverOnUIThread, this)); - } - - private: - friend class base::RefCountedThreadSafe<ScreenObserverDelegate>; - - ~ScreenObserverDelegate() override { DCHECK(!capture_device_); } - - void OnDisplayAdded(const gfx::Display& /*new_display*/) override {} - void OnDisplayRemoved(const gfx::Display& /*old_display*/) override {} - void OnDisplayMetricsChanged(const gfx::Display& display, - uint32_t metrics) override { - DCHECK(ui_task_runner_->BelongsToCurrentThread()); - if (!(metrics & DISPLAY_METRIC_ROTATION)) - return; - SendDisplayRotation(display); - } - - void AddObserverOnUIThread() { - DCHECK(ui_task_runner_->BelongsToCurrentThread()); - gfx::Screen* screen = - gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE); - if (screen) { - screen->AddObserver(this); - SendDisplayRotation(screen->GetPrimaryDisplay()); - } - } - - void RemoveObserverOnUIThread() { - DCHECK(ui_task_runner_->BelongsToCurrentThread()); - gfx::Screen* screen = - gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE); - if (screen) - screen->RemoveObserver(this); - } - - // Post the screen rotation change from the UI thread to capture thread - void SendDisplayRotation(const gfx::Display& display) { - DCHECK(ui_task_runner_->BelongsToCurrentThread()); - capture_task_runner_->PostTask( - FROM_HERE, - base::Bind(&ScreenObserverDelegate::SendDisplayRotationOnCaptureThread, - this, display)); - } - - void SendDisplayRotationOnCaptureThread(const gfx::Display& display) { - DCHECK(capture_task_runner_->BelongsToCurrentThread()); - if (capture_device_) - capture_device_->SetDisplayRotation(display); - } - - VideoCaptureDeviceChromeOS* capture_device_; - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; - scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_; - DISALLOW_IMPLICIT_CONSTRUCTORS(ScreenObserverDelegate); -}; - - -VideoCaptureDeviceChromeOS::VideoCaptureDeviceChromeOS( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, - const Name& device_name) - : VideoCaptureDeviceLinux(device_name), - screen_observer_delegate_(new ScreenObserverDelegate(this, - ui_task_runner)) { -} - -VideoCaptureDeviceChromeOS::~VideoCaptureDeviceChromeOS() { - screen_observer_delegate_->RemoveObserver(); -} - -void VideoCaptureDeviceChromeOS::SetDisplayRotation( - const gfx::Display& display) { - if (display.IsInternal()) - SetRotation(display.rotation() * 90); -} - -} // namespace media diff --git a/media/video/capture/linux/video_capture_device_chromeos.h b/media/video/capture/linux/video_capture_device_chromeos.h deleted file mode 100644 index 50b77a9..0000000 --- a/media/video/capture/linux/video_capture_device_chromeos.h +++ /dev/null @@ -1,36 +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_VIDEO_CAPTURE_LINUX_VIDEO_CAPTURE_DEVICE_CHROMEOS_H_ -#define MEDIA_VIDEO_CAPTURE_LINUX_VIDEO_CAPTURE_DEVICE_CHROMEOS_H_ - -#include "media/video/capture/linux/video_capture_device_linux.h" - -namespace gfx { -class Display; -} // namespace gfx - -namespace media { - -// 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: - explicit VideoCaptureDeviceChromeOS( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, - const Name& device_name); - ~VideoCaptureDeviceChromeOS() override; - - private: - class ScreenObserverDelegate; - - void SetDisplayRotation(const gfx::Display& display); - scoped_refptr<ScreenObserverDelegate> screen_observer_delegate_; - DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceChromeOS); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_LINUX_VIDEO_CAPTURE_DEVICE_CHROMEOS_H_ diff --git a/media/video/capture/linux/video_capture_device_factory_linux.cc b/media/video/capture/linux/video_capture_device_factory_linux.cc deleted file mode 100644 index f0af921..0000000 --- a/media/video/capture/linux/video_capture_device_factory_linux.cc +++ /dev/null @@ -1,224 +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/linux/video_capture_device_factory_linux.h" - -#include <errno.h> -#include <fcntl.h> -#if defined(OS_OPENBSD) -#include <sys/videoio.h> -#else -#include <linux/videodev2.h> -#endif -#include <sys/ioctl.h> - -#include "base/files/file_enumerator.h" -#include "base/files/scoped_file.h" -#include "base/posix/eintr_wrapper.h" -#include "base/strings/stringprintf.h" -#if defined(OS_CHROMEOS) -#include "media/video/capture/linux/video_capture_device_chromeos.h" -#endif -#include "media/video/capture/linux/video_capture_device_linux.h" - -namespace media { - -static bool HasUsableFormats(int fd, uint32 capabilities) { - const std::list<uint32_t>& usable_fourccs = - VideoCaptureDeviceLinux::GetListOfUsableFourCCs(false); - - static const struct { - int capability; - v4l2_buf_type buf_type; - } kCapabilityAndBufferTypes[] = { - {V4L2_CAP_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_CAPTURE}, - {V4L2_CAP_VIDEO_CAPTURE_MPLANE, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE} - }; - - for (const auto& capability_and_buffer_type : kCapabilityAndBufferTypes) { - v4l2_fmtdesc fmtdesc = {}; - if (capabilities & capability_and_buffer_type.capability) { - fmtdesc.type = capability_and_buffer_type.buf_type; - 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; -} - -static std::list<float> GetFrameRateList(int fd, - uint32 fourcc, - uint32 width, - uint32 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(); - 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; -} - -static void GetSupportedFormatsForV4L2BufferType( - int fd, - v4l2_buf_type buf_type, - media::VideoCaptureFormats* supported_formats) { - v4l2_fmtdesc v4l2_format = {}; - v4l2_format.type = buf_type; - 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); - - if (supported_format.pixel_format == VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN) - continue; - - 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(); - } - - 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); - } - } - } -} - -VideoCaptureDeviceFactoryLinux::VideoCaptureDeviceFactoryLinux( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) - : ui_task_runner_(ui_task_runner) { -} - -VideoCaptureDeviceFactoryLinux::~VideoCaptureDeviceFactoryLinux() { -} - -scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryLinux::Create( - const VideoCaptureDevice::Name& device_name) { - DCHECK(thread_checker_.CalledOnValidThread()); -#if defined(OS_CHROMEOS) - VideoCaptureDeviceChromeOS* self = - new VideoCaptureDeviceChromeOS(ui_task_runner_, device_name); -#else - VideoCaptureDeviceLinux* self = new VideoCaptureDeviceLinux(device_name); -#endif - if (!self) - return scoped_ptr<VideoCaptureDevice>(); - // Test opening the device driver. This is to make sure it is available. - // We will reopen it again in our worker thread when someone - // allocates the camera. - base::ScopedFD fd(HANDLE_EINTR(open(device_name.id().c_str(), O_RDONLY))); - if (!fd.is_valid()) { - DLOG(ERROR) << "Cannot open device"; - delete self; - return scoped_ptr<VideoCaptureDevice>(); - } - - return scoped_ptr<VideoCaptureDevice>(self); -} - -void VideoCaptureDeviceFactoryLinux::GetDeviceNames( - VideoCaptureDevice::Names* const device_names) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(device_names->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))); - if (!fd.is_valid()) { - DLOG(ERROR) << "Couldn't open " << info.GetName().value(); - 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 - // 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) && - ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE || - cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) && - !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) && - !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)) && - HasUsableFormats(fd.get(), cap.capabilities)) { - device_names->push_back(VideoCaptureDevice::Name( - base::StringPrintf("%s", cap.card), unique_id, - (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) - ? VideoCaptureDevice::Name::V4L2_MULTI_PLANE - : VideoCaptureDevice::Name::V4L2_SINGLE_PLANE)); - } - } -} - -void VideoCaptureDeviceFactoryLinux::GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (device.id().empty()) - return; - base::ScopedFD fd(HANDLE_EINTR(open(device.id().c_str(), O_RDONLY))); - if (!fd.is_valid()) // Failed to open this device. - return; - supported_formats->clear(); - - DCHECK_NE(device.capture_api_type(), - VideoCaptureDevice::Name::API_TYPE_UNKNOWN); - const v4l2_buf_type buf_type = - (device.capture_api_type() == VideoCaptureDevice::Name::V4L2_MULTI_PLANE) - ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE - : V4L2_BUF_TYPE_VIDEO_CAPTURE; - GetSupportedFormatsForV4L2BufferType(fd.get(), buf_type, supported_formats); - - return; -} - -// static -VideoCaptureDeviceFactory* -VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { - return new VideoCaptureDeviceFactoryLinux(ui_task_runner); -} - -} // namespace media diff --git a/media/video/capture/linux/video_capture_device_factory_linux.h b/media/video/capture/linux/video_capture_device_factory_linux.h deleted file mode 100644 index 8e52abb..0000000 --- a/media/video/capture/linux/video_capture_device_factory_linux.h +++ /dev/null @@ -1,38 +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 VideoCaptureDeviceFactoryLinux class. - -#ifndef MEDIA_VIDEO_CAPTURE_LINUX_VIDEO_CAPTURE_DEVICE_FACTORY_LINUX_H_ -#define MEDIA_VIDEO_CAPTURE_LINUX_VIDEO_CAPTURE_DEVICE_FACTORY_LINUX_H_ - -#include "media/video/capture/video_capture_device_factory.h" - -#include "media/base/video_capture_types.h" - -namespace media { - -// Extension of VideoCaptureDeviceFactory to create and manipulate Linux -// devices. -class MEDIA_EXPORT VideoCaptureDeviceFactoryLinux - : public VideoCaptureDeviceFactory { - public: - explicit VideoCaptureDeviceFactoryLinux( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); - ~VideoCaptureDeviceFactoryLinux() override; - - scoped_ptr<VideoCaptureDevice> Create( - const VideoCaptureDevice::Name& device_name) override; - void GetDeviceNames(VideoCaptureDevice::Names* device_names) override; - void GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) override; - - private: - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; - DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactoryLinux); -}; - -} // namespace media -#endif // MEDIA_VIDEO_CAPTURE_LINUX_VIDEO_CAPTURE_DEVICE_FACTORY_LINUX_H_ diff --git a/media/video/capture/linux/video_capture_device_linux.cc b/media/video/capture/linux/video_capture_device_linux.cc deleted file mode 100644 index bd0d91f..0000000 --- a/media/video/capture/linux/video_capture_device_linux.cc +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2012 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/linux/video_capture_device_linux.h" - -#if defined(OS_OPENBSD) -#include <sys/videoio.h> -#else -#include <linux/videodev2.h> -#endif - -#include <list> - -#include "base/bind.h" -#include "base/strings/stringprintf.h" -#include "media/video/capture/linux/v4l2_capture_delegate.h" - -namespace media { - -// USB VID and PID are both 4 bytes long. -static const size_t kVidPidSize = 4; - -// /sys/class/video4linux/video{N}/device is a symlink to the corresponding -// USB device info directory. -static const char kVidPathTemplate[] = - "/sys/class/video4linux/%s/device/../idVendor"; -static const char kPidPathTemplate[] = - "/sys/class/video4linux/%s/device/../idProduct"; - -static bool ReadIdFile(const std::string path, std::string* id) { - char id_buf[kVidPidSize]; - FILE* file = fopen(path.c_str(), "rb"); - if (!file) - return false; - const bool success = fread(id_buf, kVidPidSize, 1, file) == 1; - fclose(file); - if (!success) - return false; - id->append(id_buf, kVidPidSize); - return true; -} - -// Translates Video4Linux pixel formats to Chromium pixel formats. -// static -VideoCapturePixelFormat -VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat(uint32 v4l2_fourcc) { - return V4L2CaptureDelegate::V4l2FourCcToChromiumPixelFormat(v4l2_fourcc); -} - -// Gets a list of usable Four CC formats prioritised. -// static -std::list<uint32_t> VideoCaptureDeviceLinux::GetListOfUsableFourCCs( - bool favour_mjpeg) { - return V4L2CaptureDelegate::GetListOfUsableFourCcs(favour_mjpeg); -} - -const std::string VideoCaptureDevice::Name::GetModel() const { - // |unique_id| is of the form "/dev/video2". |file_name| is "video2". - const std::string dev_dir = "/dev/"; - DCHECK_EQ(0, unique_id_.compare(0, dev_dir.length(), dev_dir)); - const std::string file_name = - unique_id_.substr(dev_dir.length(), unique_id_.length()); - - const std::string vidPath = - base::StringPrintf(kVidPathTemplate, file_name.c_str()); - const std::string pidPath = - base::StringPrintf(kPidPathTemplate, file_name.c_str()); - - std::string usb_id; - if (!ReadIdFile(vidPath, &usb_id)) - return ""; - usb_id.append(":"); - if (!ReadIdFile(pidPath, &usb_id)) - return ""; - - return usb_id; -} - -VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name) - : v4l2_thread_("V4L2CaptureThread"), - device_name_(device_name) { -} - -VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { - // Check if the thread is running. - // This means that the device has not been StopAndDeAllocate()d properly. - DCHECK(!v4l2_thread_.IsRunning()); - v4l2_thread_.Stop(); -} - -void VideoCaptureDeviceLinux::AllocateAndStart( - const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) { - DCHECK(!capture_impl_); - if (v4l2_thread_.IsRunning()) - return; // Wrong state. - v4l2_thread_.Start(); - - const int line_frequency = - TranslatePowerLineFrequencyToV4L2(GetPowerLineFrequencyForLocation()); - capture_impl_ = V4L2CaptureDelegate::CreateV4L2CaptureDelegate( - device_name_, v4l2_thread_.task_runner(), line_frequency); - if (!capture_impl_) { - client->OnError("Failed to create VideoCaptureDelegate"); - return; - } - v4l2_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&V4L2CaptureDelegate::AllocateAndStart, capture_impl_, - params.requested_format.frame_size.width(), - params.requested_format.frame_size.height(), - params.requested_format.frame_rate, base::Passed(&client))); -} - -void VideoCaptureDeviceLinux::StopAndDeAllocate() { - if (!v4l2_thread_.IsRunning()) - return; // Wrong state. - v4l2_thread_.message_loop()->PostTask( - FROM_HERE, - base::Bind(&V4L2CaptureDelegate::StopAndDeAllocate, capture_impl_)); - v4l2_thread_.Stop(); - - capture_impl_ = NULL; -} - -void VideoCaptureDeviceLinux::SetRotation(int rotation) { - if (v4l2_thread_.IsRunning()) { - v4l2_thread_.message_loop()->PostTask( - FROM_HERE, base::Bind(&V4L2CaptureDelegate::SetRotation, - capture_impl_, rotation)); - } -} - -// static -int VideoCaptureDeviceLinux::TranslatePowerLineFrequencyToV4L2(int frequency) { - switch (frequency) { - case kPowerLine50Hz: - return V4L2_CID_POWER_LINE_FREQUENCY_50HZ; - case kPowerLine60Hz: - return V4L2_CID_POWER_LINE_FREQUENCY_60HZ; - default: - // If we have no idea of the frequency, at least try and set it to AUTO. - return V4L2_CID_POWER_LINE_FREQUENCY_AUTO; - } -} - -} // namespace media diff --git a/media/video/capture/linux/video_capture_device_linux.h b/media/video/capture/linux/video_capture_device_linux.h deleted file mode 100644 index 3a3356c..0000000 --- a/media/video/capture/linux/video_capture_device_linux.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2012 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. - -// Linux specific implementation of VideoCaptureDevice. -// V4L2 is used for capturing. V4L2 does not provide its own thread for -// capturing so this implementation uses a Chromium thread for fetching frames -// from V4L2. - -#ifndef MEDIA_VIDEO_CAPTURE_LINUX_VIDEO_CAPTURE_DEVICE_LINUX_H_ -#define MEDIA_VIDEO_CAPTURE_LINUX_VIDEO_CAPTURE_DEVICE_LINUX_H_ - -#include <string> - -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/threading/thread.h" -#include "media/base/video_capture_types.h" -#include "media/video/capture/video_capture_device.h" - -namespace media { - -class V4L2CaptureDelegate; - -// Linux V4L2 implementation of VideoCaptureDevice. -class VideoCaptureDeviceLinux : public VideoCaptureDevice { - public: - static VideoCapturePixelFormat V4l2FourCcToChromiumPixelFormat( - uint32 v4l2_fourcc); - static std::list<uint32_t> GetListOfUsableFourCCs(bool favour_mjpeg); - - explicit VideoCaptureDeviceLinux(const Name& device_name); - ~VideoCaptureDeviceLinux() override; - - // VideoCaptureDevice implementation. - void AllocateAndStart(const VideoCaptureParams& params, - scoped_ptr<Client> client) override; - void StopAndDeAllocate() override; - - protected: - void SetRotation(int rotation); - - private: - static int TranslatePowerLineFrequencyToV4L2(int frequency); - - // Internal delegate doing the actual capture setting, buffer allocation and - // circulacion with the V4L2 API. Created and deleted in the thread where - // VideoCaptureDeviceLinux lives but otherwise operating on |v4l2_thread_|. - scoped_refptr<V4L2CaptureDelegate> capture_impl_; - - base::Thread v4l2_thread_; // Thread used for reading data from the device. - - const Name device_name_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceLinux); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_LINUX_VIDEO_CAPTURE_DEVICE_LINUX_H_ diff --git a/media/video/capture/mac/DEPS b/media/video/capture/mac/DEPS deleted file mode 100644 index 58a1003..0000000 --- a/media/video/capture/mac/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+third_party/decklink", -] diff --git a/media/video/capture/mac/platform_video_capturing_mac.h b/media/video/capture/mac/platform_video_capturing_mac.h deleted file mode 100644 index 33ad7b6..0000000 --- a/media/video/capture/mac/platform_video_capturing_mac.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2013 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_VIDEO_CAPTURE_MAC_PLATFORM_VIDEO_CAPTURING_MAC_H_ -#define MEDIA_VIDEO_CAPTURE_MAC_PLATFORM_VIDEO_CAPTURING_MAC_H_ - -#import <Foundation/Foundation.h> - -namespace media { -class VideoCaptureDeviceMac; -} - -// Protocol representing platform-dependent video capture on Mac, implemented -// by both QTKit and AVFoundation APIs. -@protocol PlatformVideoCapturingMac <NSObject> - -// This method initializes the instance by calling NSObject |init| and registers -// internally a frame receiver at the same time. The frame receiver is supposed -// to be initialised before and outlive the VideoCapturingDeviceMac -// implementation. -- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver; - -// Sets the frame receiver. This method executes the registration in mutual -// exclusion. -// TODO(mcasas): This method and stopCapture() are always called in sequence and -// this one is only used to clear the frameReceiver, investigate if both can be -// merged. -- (void)setFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver; - -// Sets which capture device to use by name passed as deviceId argument. The -// device names are usually obtained via VideoCaptureDevice::GetDeviceNames() -// method. This method will also configure all device properties except those in -// setCaptureHeight:width:frameRate. If |deviceId| is nil, capture is stopped -// and all potential configuration is torn down. Returns YES on sucess, NO -// otherwise. -- (BOOL)setCaptureDevice:(NSString*)deviceId; - -// Configures the capture properties. -- (BOOL)setCaptureHeight:(int)height - width:(int)width - frameRate:(float)frameRate; - -// Starts video capturing, registers observers. Returns YES on sucess, NO -// otherwise. -- (BOOL)startCapture; - -// Stops video capturing, unregisters observers. -- (void)stopCapture; - -@end - -#endif // MEDIA_VIDEO_CAPTURE_MAC_PLATFORM_VIDEO_CAPTURING_MAC_H_ diff --git a/media/video/capture/mac/video_capture_device_avfoundation_mac.h b/media/video/capture/mac/video_capture_device_avfoundation_mac.h deleted file mode 100644 index e30c2f8..0000000 --- a/media/video/capture/mac/video_capture_device_avfoundation_mac.h +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2013 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_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_ -#define MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_ - -#import <Foundation/Foundation.h> - -#import "base/mac/scoped_nsobject.h" -#include "base/synchronization/lock.h" -#include "base/threading/thread_checker.h" -#import "media/base/mac/avfoundation_glue.h" -#include "media/base/video_capture_types.h" -#import "media/video/capture/mac/platform_video_capturing_mac.h" -#include "media/video/capture/video_capture_device.h" - -namespace media { -class VideoCaptureDeviceMac; -} - -@class CrAVCaptureDevice; -@class CrAVCaptureSession; -@class CrAVCaptureVideoDataOutput; - -// Class used by VideoCaptureDeviceMac (VCDM) for video capture using -// AVFoundation API. This class lives inside the thread created by its owner -// VCDM. -// -// * Clients (VCDM) should call +deviceNames to fetch the list of devices -// available in the system; this method returns the list of device names that -// have to be used with -setCaptureDevice:. -// * Previous to any use, clients (VCDM) must call -initWithFrameReceiver: to -// initialise an object of this class and register a |frameReceiver_|. -// * Frame receiver registration or removal can also happen via explicit call -// to -setFrameReceiver:. Re-registrations are safe and allowed, even during -// capture using this method. -// * Method -setCaptureDevice: must be called at least once with a device -// identifier from +deviceNames. Creates all the necessary AVFoundation -// objects on first call; it connects them ready for capture every time. -// This method should not be called during capture (i.e. between -// -startCapture and -stopCapture). -// * -setCaptureWidth:height:frameRate: is called if a resolution or frame rate -// different than the by default one set by -setCaptureDevice: is needed. -// This method should not be called during capture. This method must be -// called after -setCaptureDevice:. -// * -startCapture registers the notification listeners and starts the -// capture. The capture can be stop using -stopCapture. The capture can be -// restarted and restoped multiple times, reconfiguring or not the device in -// between. -// * -setCaptureDevice can be called with a |nil| value, case in which it stops -// the capture and disconnects the library objects. This step is not -// necessary. -// * Deallocation of the library objects happens gracefully on destruction of -// the VideoCaptureDeviceAVFoundation object. -// -// -@interface VideoCaptureDeviceAVFoundation - : NSObject<CrAVCaptureVideoDataOutputSampleBufferDelegate, - PlatformVideoCapturingMac> { - @private - // The following attributes are set via -setCaptureHeight:width:frameRate:. - int frameWidth_; - int frameHeight_; - float frameRate_; - - base::Lock lock_; // Protects concurrent setting and using of frameReceiver_. - media::VideoCaptureDeviceMac* frameReceiver_; // weak. - - base::scoped_nsobject<CrAVCaptureSession> captureSession_; - - // |captureDevice_| is an object coming from AVFoundation, used only to be - // plugged in |captureDeviceInput_| and to query for session preset support. - CrAVCaptureDevice* captureDevice_; - // |captureDeviceInput_| is owned by |captureSession_|. - CrAVCaptureDeviceInput* captureDeviceInput_; - base::scoped_nsobject<CrAVCaptureVideoDataOutput> captureVideoDataOutput_; - - base::ThreadChecker main_thread_checker_; - base::ThreadChecker callback_thread_checker_; -} - -// Returns a dictionary of capture devices with friendly name and unique id. -+ (NSDictionary*)deviceNames; - -// Retrieve the capture supported formats for a given device |name|. -+ (void)getDevice:(const media::VideoCaptureDevice::Name&)name - supportedFormats:(media::VideoCaptureFormats*)formats; - -// Initializes the instance and the underlying capture session and registers the -// frame receiver. -- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver; - -// Sets the frame receiver. -- (void)setFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver; - -// Sets which capture device to use by name, retrieved via |deviceNames|. Once -// the deviceId is known, the library objects are created if needed and -// connected for the capture, and a by default resolution is set. If deviceId is -// nil, then the eventual capture is stopped and library objects are -// disconnected. Returns YES on sucess, NO otherwise. This method should not be -// called during capture. -- (BOOL)setCaptureDevice:(NSString*)deviceId; - -// Configures the capture properties for the capture session and the video data -// output; this means it MUST be called after setCaptureDevice:. Return YES on -// success, else NO. -- (BOOL)setCaptureHeight:(int)height - width:(int)width - frameRate:(float)frameRate; - -// Starts video capturing and register the notification listeners. Must be -// called after setCaptureDevice:, and, eventually, also after -// setCaptureHeight:width:frameRate:. Returns YES on sucess, NO otherwise. -- (BOOL)startCapture; - -// Stops video capturing and stops listening to notifications. -- (void)stopCapture; - -@end - -#endif // MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_ diff --git a/media/video/capture/mac/video_capture_device_avfoundation_mac.mm b/media/video/capture/mac/video_capture_device_avfoundation_mac.mm deleted file mode 100644 index fdf0f5e..0000000 --- a/media/video/capture/mac/video_capture_device_avfoundation_mac.mm +++ /dev/null @@ -1,353 +0,0 @@ -// Copyright 2013 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. - -#import "media/video/capture/mac/video_capture_device_avfoundation_mac.h" - -#import <CoreVideo/CoreVideo.h> - -#include "base/logging.h" -#include "base/mac/foundation_util.h" -#include "media/video/capture/mac/video_capture_device_mac.h" -#include "ui/gfx/geometry/size.h" - -// Prefer MJPEG if frame width or height is larger than this. -static const int kMjpegWidthThreshold = 640; -static const int kMjpegHeightThreshold = 480; - -// This function translates Mac Core Video pixel formats to Chromium pixel -// formats. Chromium pixel formats are sorted in order of preference. -media::VideoCapturePixelFormat FourCCToChromiumPixelFormat(FourCharCode code) { - switch (code) { - case kCVPixelFormatType_422YpCbCr8: - return media::VIDEO_CAPTURE_PIXEL_FORMAT_UYVY; - case CoreMediaGlue::kCMPixelFormat_422YpCbCr8_yuvs: - return media::VIDEO_CAPTURE_PIXEL_FORMAT_YUY2; - case CoreMediaGlue::kCMVideoCodecType_JPEG_OpenDML: - return media::VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG; - default: - return media::VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN; - } -} - -@implementation VideoCaptureDeviceAVFoundation - -#pragma mark Class methods - -+ (void)getDeviceNames:(NSMutableDictionary*)deviceNames { - // At this stage we already know that AVFoundation is supported and the whole - // library is loaded and initialised, by the device monitoring. - NSArray* devices = [AVCaptureDeviceGlue devices]; - for (CrAVCaptureDevice* device in devices) { - if (([device hasMediaType:AVFoundationGlue::AVMediaTypeVideo()] || - [device hasMediaType:AVFoundationGlue::AVMediaTypeMuxed()]) && - ![device isSuspended]) { - DeviceNameAndTransportType* nameAndTransportType = - [[[DeviceNameAndTransportType alloc] - initWithName:[device localizedName] - transportType:[device transportType]] autorelease]; - [deviceNames setObject:nameAndTransportType - forKey:[device uniqueID]]; - } - } -} - -+ (NSDictionary*)deviceNames { - NSMutableDictionary* deviceNames = - [[[NSMutableDictionary alloc] init] autorelease]; - // The device name retrieval is not going to happen in the main thread, and - // this might cause instabilities (it did in QTKit), so keep an eye here. - [self getDeviceNames:deviceNames]; - return deviceNames; -} - -+ (void)getDevice:(const media::VideoCaptureDevice::Name&)name - supportedFormats:(media::VideoCaptureFormats*)formats{ - NSArray* devices = [AVCaptureDeviceGlue devices]; - CrAVCaptureDevice* device = nil; - for (device in devices) { - if ([[device uniqueID] UTF8String] == name.id()) - break; - } - if (device == nil) - return; - for (CrAVCaptureDeviceFormat* format in device.formats) { - // MediaSubType is a CMPixelFormatType but can be used as CVPixelFormatType - // as well according to CMFormatDescription.h - const media::VideoCapturePixelFormat pixelFormat = - FourCCToChromiumPixelFormat( - CoreMediaGlue::CMFormatDescriptionGetMediaSubType( - [format formatDescription])); - - CoreMediaGlue::CMVideoDimensions dimensions = - CoreMediaGlue::CMVideoFormatDescriptionGetDimensions( - [format formatDescription]); - - for (CrAVFrameRateRange* frameRate in - [format videoSupportedFrameRateRanges]) { - media::VideoCaptureFormat format( - gfx::Size(dimensions.width, dimensions.height), - frameRate.maxFrameRate, - pixelFormat); - formats->push_back(format); - DVLOG(2) << name.name() << " " - << media::VideoCaptureFormat::ToString(format); - } - } - -} - -#pragma mark Public methods - -- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver { - if ((self = [super init])) { - DCHECK(main_thread_checker_.CalledOnValidThread()); - DCHECK(frameReceiver); - [self setFrameReceiver:frameReceiver]; - captureSession_.reset( - [[AVFoundationGlue::AVCaptureSessionClass() alloc] init]); - } - return self; -} - -- (void)dealloc { - [self stopCapture]; - [super dealloc]; -} - -- (void)setFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver { - base::AutoLock lock(lock_); - frameReceiver_ = frameReceiver; -} - -- (BOOL)setCaptureDevice:(NSString*)deviceId { - DCHECK(captureSession_); - DCHECK(main_thread_checker_.CalledOnValidThread()); - - if (!deviceId) { - // First stop the capture session, if it's running. - [self stopCapture]; - // Now remove the input and output from the capture session. - [captureSession_ removeOutput:captureVideoDataOutput_]; - if (captureDeviceInput_) { - [captureSession_ removeInput:captureDeviceInput_]; - // No need to release |captureDeviceInput_|, is owned by the session. - captureDeviceInput_ = nil; - } - return YES; - } - - // Look for input device with requested name. - captureDevice_ = [AVCaptureDeviceGlue deviceWithUniqueID:deviceId]; - if (!captureDevice_) { - [self sendErrorString:[NSString - stringWithUTF8String:"Could not open video capture device."]]; - return NO; - } - - // Create the capture input associated with the device. Easy peasy. - NSError* error = nil; - captureDeviceInput_ = [AVCaptureDeviceInputGlue - deviceInputWithDevice:captureDevice_ - error:&error]; - if (!captureDeviceInput_) { - captureDevice_ = nil; - [self sendErrorString:[NSString - stringWithFormat:@"Could not create video capture input (%@): %@", - [error localizedDescription], - [error localizedFailureReason]]]; - return NO; - } - [captureSession_ addInput:captureDeviceInput_]; - - // Create a new data output for video. The data output is configured to - // discard late frames by default. - captureVideoDataOutput_.reset( - [[AVFoundationGlue::AVCaptureVideoDataOutputClass() alloc] init]); - if (!captureVideoDataOutput_) { - [captureSession_ removeInput:captureDeviceInput_]; - [self sendErrorString:[NSString - stringWithUTF8String:"Could not create video data output."]]; - return NO; - } - [captureVideoDataOutput_ setAlwaysDiscardsLateVideoFrames:true]; - [captureVideoDataOutput_ - setSampleBufferDelegate:self - queue:dispatch_get_global_queue( - DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; - [captureSession_ addOutput:captureVideoDataOutput_]; - return YES; -} - -- (BOOL)setCaptureHeight:(int)height - width:(int)width - frameRate:(float)frameRate { - // Check if either of VideoCaptureDeviceMac::AllocateAndStart() or - // VideoCaptureDeviceMac::ReceiveFrame() is calling here, depending on the - // running state. VCDM::ReceiveFrame() calls here to change aspect ratio. - DCHECK((![captureSession_ isRunning] && - main_thread_checker_.CalledOnValidThread()) || - callback_thread_checker_.CalledOnValidThread()); - - frameWidth_ = width; - frameHeight_ = height; - frameRate_ = frameRate; - - FourCharCode best_fourcc = kCVPixelFormatType_422YpCbCr8; - const bool prefer_mjpeg = - width > kMjpegWidthThreshold || height > kMjpegHeightThreshold; - for (CrAVCaptureDeviceFormat* format in captureDevice_.formats) { - const FourCharCode fourcc = - CoreMediaGlue::CMFormatDescriptionGetMediaSubType( - [format formatDescription]); - if (prefer_mjpeg && - fourcc == CoreMediaGlue::kCMVideoCodecType_JPEG_OpenDML) { - best_fourcc = fourcc; - break; - } - // Compare according to Chromium preference. - if (FourCCToChromiumPixelFormat(fourcc) < - FourCCToChromiumPixelFormat(best_fourcc)) { - best_fourcc = fourcc; - } - } - - // The capture output has to be configured, despite Mac documentation - // detailing that setting the sessionPreset would be enough. The reason for - // this mismatch is probably because most of the AVFoundation docs are written - // for iOS and not for MacOsX. AVVideoScalingModeKey() refers to letterboxing - // yes/no and preserve aspect ratio yes/no when scaling. Currently we set - // cropping and preservation. - NSDictionary* videoSettingsDictionary = @{ - (id)kCVPixelBufferWidthKey : @(width), - (id)kCVPixelBufferHeightKey : @(height), - (id)kCVPixelBufferPixelFormatTypeKey : @(best_fourcc), - AVFoundationGlue::AVVideoScalingModeKey() : - AVFoundationGlue::AVVideoScalingModeResizeAspectFill() - }; - [captureVideoDataOutput_ setVideoSettings:videoSettingsDictionary]; - - CrAVCaptureConnection* captureConnection = [captureVideoDataOutput_ - connectionWithMediaType:AVFoundationGlue::AVMediaTypeVideo()]; - // Check selector existence, related to bugs http://crbug.com/327532 and - // http://crbug.com/328096. - // CMTimeMake accepts integer argumenst but |frameRate| is float, round it. - if ([captureConnection - respondsToSelector:@selector(isVideoMinFrameDurationSupported)] && - [captureConnection isVideoMinFrameDurationSupported]) { - [captureConnection setVideoMinFrameDuration: - CoreMediaGlue::CMTimeMake(media::kFrameRatePrecision, - (int)(frameRate * media::kFrameRatePrecision))]; - } - if ([captureConnection - respondsToSelector:@selector(isVideoMaxFrameDurationSupported)] && - [captureConnection isVideoMaxFrameDurationSupported]) { - [captureConnection setVideoMaxFrameDuration: - CoreMediaGlue::CMTimeMake(media::kFrameRatePrecision, - (int)(frameRate * media::kFrameRatePrecision))]; - } - return YES; -} - -- (BOOL)startCapture { - DCHECK(main_thread_checker_.CalledOnValidThread()); - if (!captureSession_) { - DLOG(ERROR) << "Video capture session not initialized."; - return NO; - } - // Connect the notifications. - NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:self - selector:@selector(onVideoError:) - name:AVFoundationGlue::AVCaptureSessionRuntimeErrorNotification() - object:captureSession_]; - [captureSession_ startRunning]; - return YES; -} - -- (void)stopCapture { - DCHECK(main_thread_checker_.CalledOnValidThread()); - if ([captureSession_ isRunning]) - [captureSession_ stopRunning]; // Synchronous. - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -#pragma mark Private methods - -// |captureOutput| is called by the capture device to deliver a new frame. -- (void)captureOutput:(CrAVCaptureOutput*)captureOutput - didOutputSampleBuffer:(CoreMediaGlue::CMSampleBufferRef)sampleBuffer - fromConnection:(CrAVCaptureConnection*)connection { - // AVFoundation calls from a number of threads, depending on, at least, if - // Chrome is on foreground or background. Sample the actual thread here. - callback_thread_checker_.DetachFromThread(); - CHECK(callback_thread_checker_.CalledOnValidThread()); - - const CoreMediaGlue::CMFormatDescriptionRef formatDescription = - CoreMediaGlue::CMSampleBufferGetFormatDescription(sampleBuffer); - const FourCharCode fourcc = - CoreMediaGlue::CMFormatDescriptionGetMediaSubType(formatDescription); - const CoreMediaGlue::CMVideoDimensions dimensions = - CoreMediaGlue::CMVideoFormatDescriptionGetDimensions(formatDescription); - const media::VideoCaptureFormat captureFormat( - gfx::Size(dimensions.width, dimensions.height), - frameRate_, - FourCCToChromiumPixelFormat(fourcc)); - - char* baseAddress = 0; - size_t frameSize = 0; - CVImageBufferRef videoFrame = nil; - if (fourcc == CoreMediaGlue::kCMVideoCodecType_JPEG_OpenDML) { - // If MJPEG, use block buffer instead of pixel buffer. - CoreMediaGlue::CMBlockBufferRef blockBuffer = - CoreMediaGlue::CMSampleBufferGetDataBuffer(sampleBuffer); - if (blockBuffer) { - size_t lengthAtOffset; - CoreMediaGlue::CMBlockBufferGetDataPointer( - blockBuffer, 0, &lengthAtOffset, &frameSize, &baseAddress); - // Expect the MJPEG data to be available as a contiguous reference, i.e. - // not covered by multiple memory blocks. - CHECK_EQ(lengthAtOffset, frameSize); - } - } else { - videoFrame = CoreMediaGlue::CMSampleBufferGetImageBuffer(sampleBuffer); - // Lock the frame and calculate frame size. - if (CVPixelBufferLockBaseAddress(videoFrame, kCVPixelBufferLock_ReadOnly) == - kCVReturnSuccess) { - baseAddress = static_cast<char*>(CVPixelBufferGetBaseAddress(videoFrame)); - frameSize = CVPixelBufferGetHeight(videoFrame) * - CVPixelBufferGetBytesPerRow(videoFrame); - } else { - videoFrame = nil; - } - } - - { - base::AutoLock lock(lock_); - if (frameReceiver_ && baseAddress) { - frameReceiver_->ReceiveFrame(reinterpret_cast<uint8_t*>(baseAddress), - frameSize, captureFormat, 0, 0); - } - } - - if (videoFrame) - CVPixelBufferUnlockBaseAddress(videoFrame, kCVPixelBufferLock_ReadOnly); -} - -- (void)onVideoError:(NSNotification*)errorNotification { - NSError* error = base::mac::ObjCCast<NSError>([[errorNotification userInfo] - objectForKey:AVFoundationGlue::AVCaptureSessionErrorKey()]); - [self sendErrorString:[NSString - stringWithFormat:@"%@: %@", - [error localizedDescription], - [error localizedFailureReason]]]; -} - -- (void)sendErrorString:(NSString*)error { - DLOG(ERROR) << [error UTF8String]; - base::AutoLock lock(lock_); - if (frameReceiver_) - frameReceiver_->ReceiveError([error UTF8String]); -} - -@end diff --git a/media/video/capture/mac/video_capture_device_decklink_mac.h b/media/video/capture/mac/video_capture_device_decklink_mac.h deleted file mode 100644 index 45e697d..0000000 --- a/media/video/capture/mac/video_capture_device_decklink_mac.h +++ /dev/null @@ -1,82 +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 VideoCaptureDevice class for Blackmagic video capture -// devices by using the DeckLink SDK. - -#ifndef MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_DECKLINK_MAC_H_ -#define MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_DECKLINK_MAC_H_ - -#include "media/video/capture/video_capture_device.h" - -#import <Foundation/Foundation.h> - -#include "base/synchronization/lock.h" -#include "base/threading/thread_checker.h" - -namespace { -class DeckLinkCaptureDelegate; -} // namespace - -namespace media { - -// Extension of VideoCaptureDevice to create and manipulate Blackmagic devices. -// Creates a reference counted |decklink_capture_delegate_| that does all the -// DeckLink SDK configuration and capture work while holding a weak reference to -// us for sending back frames, logs and error messages. -class MEDIA_EXPORT VideoCaptureDeviceDeckLinkMac : public VideoCaptureDevice { - public: - // Gets the names of all DeckLink video capture devices connected to this - // computer, as enumerated by the DeckLink SDK. To allow the user to choose - // exactly which capture format she wants, we enumerate as many cameras as - // capture formats. - static void EnumerateDevices(VideoCaptureDevice::Names* device_names); - - // Gets the supported formats of a particular device attached to the system, - // identified by |device|. Formats are retrieved from the DeckLink SDK. - // Following the enumeration, each camera will have only one capability. - static void EnumerateDeviceCapabilities( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats); - - explicit VideoCaptureDeviceDeckLinkMac(const Name& device_name); - ~VideoCaptureDeviceDeckLinkMac() override; - - // Copy of VideoCaptureDevice::Client::OnIncomingCapturedData(). Used by - // |decklink_capture_delegate_| to forward captured frames. - void OnIncomingCapturedData(const uint8* data, - size_t length, - const VideoCaptureFormat& frame_format, - int rotation, // Clockwise. - base::TimeTicks timestamp); - - // Forwarder to VideoCaptureDevice::Client::OnError(). - void SendErrorString(const std::string& reason); - - // Forwarder to VideoCaptureDevice::Client::OnLog(). - void SendLogString(const std::string& message); - - private: - // VideoCaptureDevice implementation. - void AllocateAndStart(const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) override; - void StopAndDeAllocate() override; - - // Protects concurrent setting and using of |client_|. - base::Lock lock_; - scoped_ptr<VideoCaptureDevice::Client> client_; - - // Reference counted handle to the DeckLink capture delegate, ref counted by - // the DeckLink SDK as well. - scoped_refptr<DeckLinkCaptureDelegate> decklink_capture_delegate_; - - // Checks for Device (a.k.a. Audio) thread. - base::ThreadChecker thread_checker_; - - DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceDeckLinkMac); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_DECKLINK_MAC_H_ diff --git a/media/video/capture/mac/video_capture_device_decklink_mac.mm b/media/video/capture/mac/video_capture_device_decklink_mac.mm deleted file mode 100644 index ce334e0..0000000 --- a/media/video/capture/mac/video_capture_device_decklink_mac.mm +++ /dev/null @@ -1,485 +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_decklink_mac.h" - -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/strings/sys_string_conversions.h" -#include "base/synchronization/lock.h" -#include "third_party/decklink/mac/include/DeckLinkAPI.h" - -namespace { - -// DeckLink SDK uses ScopedComPtr-style APIs. Chrome ScopedComPtr is only -// available for Windows builds. This is a verbatim knock-off of the needed -// parts of base::win::ScopedComPtr<> for ref counting. -template <class T> -class ScopedDeckLinkPtr : public scoped_refptr<T> { - private: - using scoped_refptr<T>::ptr_; - - public: - T** Receive() { - DCHECK(!ptr_) << "Object leak. Pointer must be NULL"; - return &ptr_; - } - - void** ReceiveVoid() { - return reinterpret_cast<void**>(Receive()); - } - - void Release() { - if (ptr_ != NULL) { - ptr_->Release(); - ptr_ = NULL; - } - } -}; - -// This class is used to interact directly with DeckLink SDK for video capture. -// Implements the reference counted interface IUnknown. Has a weak reference to -// VideoCaptureDeviceDeckLinkMac for sending captured frames, error messages and -// logs. -class DeckLinkCaptureDelegate : - public IDeckLinkInputCallback, - public base::RefCountedThreadSafe<DeckLinkCaptureDelegate> { - public: - DeckLinkCaptureDelegate(const media::VideoCaptureDevice::Name& device_name, - media::VideoCaptureDeviceDeckLinkMac* frame_receiver); - - void AllocateAndStart(const media::VideoCaptureParams& params); - void StopAndDeAllocate(); - - // Remove the VideoCaptureDeviceDeckLinkMac's weak reference. - void ResetVideoCaptureDeviceReference(); - - private: - // IDeckLinkInputCallback interface implementation. - HRESULT VideoInputFormatChanged( - BMDVideoInputFormatChangedEvents notification_events, - IDeckLinkDisplayMode* new_display_mode, - BMDDetectedVideoInputFormatFlags detected_signal_flags) override; - HRESULT VideoInputFrameArrived( - IDeckLinkVideoInputFrame* video_frame, - IDeckLinkAudioInputPacket* audio_packet) override; - - // IUnknown interface implementation. - HRESULT QueryInterface(REFIID iid, void** ppv) override; - ULONG AddRef() override; - ULONG Release() override; - - // Forwarder to VideoCaptureDeviceDeckLinkMac::SendErrorString(). - void SendErrorString(const std::string& reason); - - // Forwarder to VideoCaptureDeviceDeckLinkMac::SendLogString(). - void SendLogString(const std::string& message); - - const media::VideoCaptureDevice::Name device_name_; - - // Protects concurrent setting and using of |frame_receiver_|. - base::Lock lock_; - // Weak reference to the captured frames client, used also for error messages - // and logging. Initialized on construction and used until cleared by calling - // ResetVideoCaptureDeviceReference(). - media::VideoCaptureDeviceDeckLinkMac* frame_receiver_; - - // This is used to control the video capturing device input interface. - ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_; - // |decklink_| represents a physical device attached to the host. - ScopedDeckLinkPtr<IDeckLink> decklink_; - - // Checks for Device (a.k.a. Audio) thread. - base::ThreadChecker thread_checker_; - - friend class scoped_refptr<DeckLinkCaptureDelegate>; - friend class base::RefCountedThreadSafe<DeckLinkCaptureDelegate>; - - ~DeckLinkCaptureDelegate() override; - - DISALLOW_COPY_AND_ASSIGN(DeckLinkCaptureDelegate); -}; - -static float GetDisplayModeFrameRate( - const ScopedDeckLinkPtr<IDeckLinkDisplayMode>& display_mode) { - BMDTimeValue time_value, time_scale; - float display_mode_frame_rate = 0.0f; - if (display_mode->GetFrameRate(&time_value, &time_scale) == S_OK && - time_value > 0) { - display_mode_frame_rate = static_cast<float>(time_scale) / time_value; - } - // Interlaced formats are going to be marked as double the frame rate, - // which follows the general naming convention. - if (display_mode->GetFieldDominance() == bmdLowerFieldFirst || - display_mode->GetFieldDominance() == bmdUpperFieldFirst) { - display_mode_frame_rate *= 2.0f; - } - return display_mode_frame_rate; -} - -DeckLinkCaptureDelegate::DeckLinkCaptureDelegate( - const media::VideoCaptureDevice::Name& device_name, - media::VideoCaptureDeviceDeckLinkMac* frame_receiver) - : device_name_(device_name), - frame_receiver_(frame_receiver) { -} - -DeckLinkCaptureDelegate::~DeckLinkCaptureDelegate() {} - -void DeckLinkCaptureDelegate::AllocateAndStart( - const media::VideoCaptureParams& params) { - DCHECK(thread_checker_.CalledOnValidThread()); - scoped_refptr<IDeckLinkIterator> decklink_iter( - CreateDeckLinkIteratorInstance()); - DLOG_IF(ERROR, !decklink_iter.get()) << "Error creating DeckLink iterator"; - if (!decklink_iter.get()) - return; - - ScopedDeckLinkPtr<IDeckLink> decklink_local; - while (decklink_iter->Next(decklink_local.Receive()) == S_OK) { - CFStringRef device_model_name = NULL; - if ((decklink_local->GetModelName(&device_model_name) == S_OK) || - (device_name_.id() == base::SysCFStringRefToUTF8(device_model_name))) { - break; - } - } - if (!decklink_local.get()) { - SendErrorString("Device id not found in the system"); - return; - } - - ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_local; - if (decklink_local->QueryInterface(IID_IDeckLinkInput, - decklink_input_local.ReceiveVoid()) != S_OK) { - SendErrorString("Error querying input interface."); - return; - } - - ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; - if (decklink_input_local->GetDisplayModeIterator( - display_mode_iter.Receive()) != S_OK) { - SendErrorString("Error creating Display Mode Iterator"); - return; - } - - ScopedDeckLinkPtr<IDeckLinkDisplayMode> chosen_display_mode; - ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; - float min_diff = FLT_MAX; - while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { - const float diff = labs(display_mode->GetWidth() - - params.requested_format.frame_size.width()) + - labs(params.requested_format.frame_size.height() - - display_mode->GetHeight()) + fabs(params.requested_format.frame_rate - - GetDisplayModeFrameRate(display_mode)); - if (diff < min_diff) { - chosen_display_mode = display_mode; - min_diff = diff; - } - display_mode.Release(); - } - if (!chosen_display_mode.get()) { - SendErrorString("Could not find a display mode"); - return; - } -#if !defined(NDEBUG) - DVLOG(1) << "Requested format: " - << media::VideoCaptureFormat::ToString(params.requested_format); - CFStringRef format_name = NULL; - if (chosen_display_mode->GetName(&format_name) == S_OK) - DVLOG(1) << "Chosen format: " << base::SysCFStringRefToUTF8(format_name); -#endif - - // Enable video input. Configure for no input video format change detection, - // this in turn will disable calls to VideoInputFormatChanged(). - if (decklink_input_local->EnableVideoInput( - chosen_display_mode->GetDisplayMode(), bmdFormat8BitYUV, - bmdVideoInputFlagDefault) != S_OK) { - SendErrorString("Could not select the video format we like."); - return; - } - - decklink_input_local->SetCallback(this); - if (decklink_input_local->StartStreams() != S_OK) - SendErrorString("Could not start capturing"); - - decklink_.swap(decklink_local); - decklink_input_.swap(decklink_input_local); -} - -void DeckLinkCaptureDelegate::StopAndDeAllocate() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (!decklink_input_.get()) - return; - if (decklink_input_->StopStreams() != S_OK) - SendLogString("Problem stopping capture."); - decklink_input_->SetCallback(NULL); - decklink_input_->DisableVideoInput(); - decklink_input_.Release(); - decklink_.Release(); - ResetVideoCaptureDeviceReference(); -} - -HRESULT DeckLinkCaptureDelegate::VideoInputFormatChanged( - BMDVideoInputFormatChangedEvents notification_events, - IDeckLinkDisplayMode *new_display_mode, - BMDDetectedVideoInputFormatFlags detected_signal_flags) { - DCHECK(thread_checker_.CalledOnValidThread()); - return S_OK; -} - -HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived( - IDeckLinkVideoInputFrame* video_frame, - IDeckLinkAudioInputPacket* /* audio_packet */) { - // Capture frames are manipulated as an IDeckLinkVideoFrame. - uint8* video_data = NULL; - video_frame->GetBytes(reinterpret_cast<void**>(&video_data)); - - media::VideoCapturePixelFormat pixel_format = - media::VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN; - switch (video_frame->GetPixelFormat()) { - case bmdFormat8BitYUV: // A.k.a. '2vuy'; - pixel_format = media::VIDEO_CAPTURE_PIXEL_FORMAT_UYVY; - break; - case bmdFormat8BitARGB: - pixel_format = media::VIDEO_CAPTURE_PIXEL_FORMAT_ARGB; - break; - default: - SendErrorString("Unsupported pixel format"); - break; - } - - const media::VideoCaptureFormat capture_format( - gfx::Size(video_frame->GetWidth(), video_frame->GetHeight()), - 0.0f, // Frame rate is not needed for captured data callback. - pixel_format); - base::AutoLock lock(lock_); - if (frame_receiver_) { - frame_receiver_->OnIncomingCapturedData( - video_data, - video_frame->GetRowBytes() * video_frame->GetHeight(), - capture_format, - 0, // Rotation. - base::TimeTicks::Now()); - } - return S_OK; -} - -HRESULT DeckLinkCaptureDelegate::QueryInterface(REFIID iid, void** ppv) { - DCHECK(thread_checker_.CalledOnValidThread()); - CFUUIDBytes iunknown = CFUUIDGetUUIDBytes(IUnknownUUID); - if (memcmp(&iid, &iunknown, sizeof(REFIID)) == 0 || - memcmp(&iid, &IID_IDeckLinkInputCallback, sizeof(REFIID)) == 0) { - *ppv = static_cast<IDeckLinkInputCallback*>(this); - AddRef(); - return S_OK; - } - return E_NOINTERFACE; -} - -ULONG DeckLinkCaptureDelegate::AddRef() { - DCHECK(thread_checker_.CalledOnValidThread()); - base::RefCountedThreadSafe<DeckLinkCaptureDelegate>::AddRef(); - return 1; -} - -ULONG DeckLinkCaptureDelegate::Release() { - DCHECK(thread_checker_.CalledOnValidThread()); - bool ret_value = !HasOneRef(); - base::RefCountedThreadSafe<DeckLinkCaptureDelegate>::Release(); - return ret_value; -} - -void DeckLinkCaptureDelegate::SendErrorString(const std::string& reason) { - base::AutoLock lock(lock_); - if (frame_receiver_) - frame_receiver_->SendErrorString(reason); -} - -void DeckLinkCaptureDelegate::SendLogString(const std::string& message) { - base::AutoLock lock(lock_); - if (frame_receiver_) - frame_receiver_->SendLogString(message); -} - -void DeckLinkCaptureDelegate::ResetVideoCaptureDeviceReference() { - DCHECK(thread_checker_.CalledOnValidThread()); - base::AutoLock lock(lock_); - frame_receiver_ = NULL; -} - -} // namespace - -namespace media { - -static std::string JoinDeviceNameAndFormat(CFStringRef name, - CFStringRef format) { - return base::SysCFStringRefToUTF8(name) + " - " + - base::SysCFStringRefToUTF8(format); -} - -// static -void VideoCaptureDeviceDeckLinkMac::EnumerateDevices( - VideoCaptureDevice::Names* device_names) { - scoped_refptr<IDeckLinkIterator> decklink_iter( - CreateDeckLinkIteratorInstance()); - // At this point, not being able to create a DeckLink iterator means that - // there are no Blackmagic DeckLink devices in the system, don't print error. - DVLOG_IF(1, !decklink_iter.get()) << "Could not create DeckLink iterator"; - if (!decklink_iter.get()) - return; - - ScopedDeckLinkPtr<IDeckLink> decklink; - while (decklink_iter->Next(decklink.Receive()) == S_OK) { - ScopedDeckLinkPtr<IDeckLink> decklink_local; - decklink_local.swap(decklink); - - CFStringRef device_model_name = NULL; - HRESULT hr = decklink_local->GetModelName(&device_model_name); - DVLOG_IF(1, hr != S_OK) << "Error reading Blackmagic device model name"; - CFStringRef device_display_name = NULL; - hr = decklink_local->GetDisplayName(&device_display_name); - DVLOG_IF(1, hr != S_OK) << "Error reading Blackmagic device display name"; - DVLOG_IF(1, hr == S_OK) << "Blackmagic device found with name: " << - base::SysCFStringRefToUTF8(device_display_name); - - if (!device_model_name && !device_display_name) - continue; - - ScopedDeckLinkPtr<IDeckLinkInput> decklink_input; - if (decklink_local->QueryInterface(IID_IDeckLinkInput, - decklink_input.ReceiveVoid()) != S_OK) { - DLOG(ERROR) << "Error Blackmagic querying input interface."; - return; - } - - ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; - if (decklink_input->GetDisplayModeIterator(display_mode_iter.Receive()) != - S_OK) { - continue; - } - - ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; - while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { - CFStringRef format_name = NULL; - if (display_mode->GetName(&format_name) == S_OK) { - VideoCaptureDevice::Name name( - JoinDeviceNameAndFormat(device_display_name, format_name), - JoinDeviceNameAndFormat(device_model_name, format_name), - VideoCaptureDevice::Name::DECKLINK, - VideoCaptureDevice::Name::OTHER_TRANSPORT); - device_names->push_back(name); - DVLOG(1) << "Blackmagic camera enumerated: " << name.name(); - } - display_mode.Release(); - } - } -} - -// static -void VideoCaptureDeviceDeckLinkMac::EnumerateDeviceCapabilities( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) { - scoped_refptr<IDeckLinkIterator> decklink_iter( - CreateDeckLinkIteratorInstance()); - DLOG_IF(ERROR, !decklink_iter.get()) << "Error creating DeckLink iterator"; - if (!decklink_iter.get()) - return; - - ScopedDeckLinkPtr<IDeckLink> decklink; - while (decklink_iter->Next(decklink.Receive()) == S_OK) { - ScopedDeckLinkPtr<IDeckLink> decklink_local; - decklink_local.swap(decklink); - - ScopedDeckLinkPtr<IDeckLinkInput> decklink_input; - if (decklink_local->QueryInterface(IID_IDeckLinkInput, - decklink_input.ReceiveVoid()) != S_OK) { - DLOG(ERROR) << "Error Blackmagic querying input interface."; - return; - } - - ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; - if (decklink_input->GetDisplayModeIterator(display_mode_iter.Receive()) != - S_OK) { - continue; - } - - CFStringRef device_model_name = NULL; - if (decklink_local->GetModelName(&device_model_name) != S_OK) - continue; - - ScopedDeckLinkPtr<IDeckLinkDisplayMode> display_mode; - while (display_mode_iter->Next(display_mode.Receive()) == S_OK) { - CFStringRef format_name = NULL; - if (display_mode->GetName(&format_name) == S_OK && device.id() != - JoinDeviceNameAndFormat(device_model_name, format_name)) { - display_mode.Release(); - continue; - } - - // IDeckLinkDisplayMode does not have information on pixel format, this - // is only available on capture. - const media::VideoCaptureFormat format( - gfx::Size(display_mode->GetWidth(), display_mode->GetHeight()), - GetDisplayModeFrameRate(display_mode), - VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN); - supported_formats->push_back(format); - DVLOG(2) << device.name() << " " << VideoCaptureFormat::ToString(format); - display_mode.Release(); - } - return; - } -} - -VideoCaptureDeviceDeckLinkMac::VideoCaptureDeviceDeckLinkMac( - const Name& device_name) - : decklink_capture_delegate_( - new DeckLinkCaptureDelegate(device_name, this)) { -} - -VideoCaptureDeviceDeckLinkMac::~VideoCaptureDeviceDeckLinkMac() { - decklink_capture_delegate_->ResetVideoCaptureDeviceReference(); -} - -void VideoCaptureDeviceDeckLinkMac::OnIncomingCapturedData( - const uint8* data, - size_t length, - const VideoCaptureFormat& frame_format, - int rotation, // Clockwise. - base::TimeTicks timestamp) { - base::AutoLock lock(lock_); - if (client_) { - client_->OnIncomingCapturedData(data, length, frame_format, rotation, - timestamp); - } -} - -void VideoCaptureDeviceDeckLinkMac::SendErrorString(const std::string& reason) { - DCHECK(thread_checker_.CalledOnValidThread()); - base::AutoLock lock(lock_); - if (client_) - client_->OnError(reason); -} - -void VideoCaptureDeviceDeckLinkMac::SendLogString(const std::string& message) { - DCHECK(thread_checker_.CalledOnValidThread()); - base::AutoLock lock(lock_); - if (client_) - client_->OnLog(message); -} - -void VideoCaptureDeviceDeckLinkMac::AllocateAndStart( - const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) { - DCHECK(thread_checker_.CalledOnValidThread()); - client_ = client.Pass(); - if (decklink_capture_delegate_.get()) - decklink_capture_delegate_->AllocateAndStart(params); -} - -void VideoCaptureDeviceDeckLinkMac::StopAndDeAllocate() { - if (decklink_capture_delegate_.get()) - decklink_capture_delegate_->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 f3a180c..0000000 --- a/media/video/capture/mac/video_capture_device_factory_mac.h +++ /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. - -// 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: - static bool PlatformSupportsAVFoundation(); - - explicit VideoCaptureDeviceFactoryMac( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); - ~VideoCaptureDeviceFactoryMac() override; - - scoped_ptr<VideoCaptureDevice> Create( - const VideoCaptureDevice::Name& device_name) override; - void GetDeviceNames(VideoCaptureDevice::Names* device_names) override; - void EnumerateDeviceNames(const base::Callback< - void(scoped_ptr<media::VideoCaptureDevice::Names>)>& callback) override; - void GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) override; - - private: - // Cache of |ui_task_runner| for enumerating devices there for QTKit. - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; - - 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 443b7f3..0000000 --- a/media/video/capture/mac/video_capture_device_factory_mac.mm +++ /dev/null @@ -1,217 +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 <IOKit/audio/IOAudioTypes.h> - -#include "base/bind.h" -#include "base/location.h" -#include "base/profiler/scoped_tracker.h" -#include "base/strings/string_util.h" -#include "base/task_runner_util.h" -#import "media/base/mac/avfoundation_glue.h" -#import "media/video/capture/mac/video_capture_device_avfoundation_mac.h" -#import "media/video/capture/mac/video_capture_device_decklink_mac.h" -#include "media/video/capture/mac/video_capture_device_mac.h" -#import "media/video/capture/mac/video_capture_device_qtkit_mac.h" - -namespace media { - -// In QTKit API, some devices are known to crash if VGA is requested, for them -// HD is the only supported resolution (see http://crbug.com/396812). In the -// AVfoundation case, we skip enumerating them altogether. These devices are -// identified by a characteristic trailing substring of uniqueId. At the moment -// these are just Blackmagic devices. -const struct NameAndVid { - const char* unique_id_signature; - const int capture_width; - const int capture_height; - const float capture_frame_rate; -} kBlacklistedCameras[] = { {"-01FDA82C8A9C", 1280, 720, 60.0f } }; - -static bool IsDeviceBlacklisted(const VideoCaptureDevice::Name& name) { - bool is_device_blacklisted = false; - for(size_t i = 0; - !is_device_blacklisted && i < arraysize(kBlacklistedCameras); ++i) { - is_device_blacklisted = - base::EndsWith(name.id(), - kBlacklistedCameras[i].unique_id_signature, - base::CompareCase::INSENSITIVE_ASCII); - } - DVLOG_IF(2, is_device_blacklisted) << "Blacklisted camera: " << - name.name() << ", id: " << name.id(); - return is_device_blacklisted; -} - -static scoped_ptr<media::VideoCaptureDevice::Names> -EnumerateDevicesUsingQTKit() { - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/458397 is - // fixed. - tracked_objects::ScopedTracker tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "458397 media::EnumerateDevicesUsingQTKit")); - - scoped_ptr<VideoCaptureDevice::Names> device_names( - new VideoCaptureDevice::Names()); - NSMutableDictionary* capture_devices = - [[[NSMutableDictionary alloc] init] autorelease]; - [VideoCaptureDeviceQTKit getDeviceNames:capture_devices]; - for (NSString* key in capture_devices) { - VideoCaptureDevice::Name name( - [[[capture_devices valueForKey:key] deviceName] UTF8String], - [key UTF8String], VideoCaptureDevice::Name::QTKIT); - if (IsDeviceBlacklisted(name)) - name.set_is_blacklisted(true); - device_names->push_back(name); - } - return device_names.Pass(); -} - -static void RunDevicesEnumeratedCallback( - const base::Callback<void(scoped_ptr<media::VideoCaptureDevice::Names>)>& - callback, - scoped_ptr<media::VideoCaptureDevice::Names> device_names) { - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/458397 is - // fixed. - tracked_objects::ScopedTracker tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "458397 media::RunDevicesEnumeratedCallback")); - callback.Run(device_names.Pass()); -} - -// static -bool VideoCaptureDeviceFactoryMac::PlatformSupportsAVFoundation() { - return AVFoundationGlue::IsAVFoundationSupported(); -} - -VideoCaptureDeviceFactoryMac::VideoCaptureDeviceFactoryMac( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) - : ui_task_runner_(ui_task_runner) { - thread_checker_.DetachFromThread(); -} - -VideoCaptureDeviceFactoryMac::~VideoCaptureDeviceFactoryMac() {} - -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); - - scoped_ptr<VideoCaptureDevice> capture_device; - if (device_name.capture_api_type() == VideoCaptureDevice::Name::DECKLINK) { - capture_device.reset(new VideoCaptureDeviceDeckLinkMac(device_name)); - } else { - VideoCaptureDeviceMac* device = new VideoCaptureDeviceMac(device_name); - capture_device.reset(device); - if (!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* device_names) { - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/458397 is - // fixed. - tracked_objects::ScopedTracker tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "458397 VideoCaptureDeviceFactoryMac::GetDeviceNames")); - DCHECK(thread_checker_.CalledOnValidThread()); - // Loop through all available devices and add to |device_names|. - NSDictionary* capture_devices; - if (AVFoundationGlue::IsAVFoundationSupported()) { - DVLOG(1) << "Enumerating video capture devices using AVFoundation"; - capture_devices = [VideoCaptureDeviceAVFoundation deviceNames]; - // 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) { - int transport_type = [[capture_devices valueForKey:key] transportType]; - // Transport types are defined for Audio devices and reused for video. - VideoCaptureDevice::Name::TransportType device_transport_type = - (transport_type == kIOAudioDeviceTransportTypeBuiltIn || - transport_type == kIOAudioDeviceTransportTypeUSB) - ? VideoCaptureDevice::Name::USB_OR_BUILT_IN - : VideoCaptureDevice::Name::OTHER_TRANSPORT; - VideoCaptureDevice::Name name( - [[[capture_devices valueForKey:key] deviceName] UTF8String], - [key UTF8String], VideoCaptureDevice::Name::AVFOUNDATION, - device_transport_type); - if (IsDeviceBlacklisted(name)) - continue; - device_names->push_back(name); - } - // Also retrieve Blackmagic devices, if present, via DeckLink SDK API. - VideoCaptureDeviceDeckLinkMac::EnumerateDevices(device_names); - } else { - // We should not enumerate QTKit devices in Device Thread; - NOTREACHED(); - } -} - -void VideoCaptureDeviceFactoryMac::EnumerateDeviceNames(const base::Callback< - void(scoped_ptr<media::VideoCaptureDevice::Names>)>& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (AVFoundationGlue::IsAVFoundationSupported()) { - scoped_ptr<VideoCaptureDevice::Names> device_names( - new VideoCaptureDevice::Names()); - GetDeviceNames(device_names.get()); - callback.Run(device_names.Pass()); - } else { - DVLOG(1) << "Enumerating video capture devices using QTKit"; - base::PostTaskAndReplyWithResult(ui_task_runner_.get(), FROM_HERE, - base::Bind(&EnumerateDevicesUsingQTKit), - base::Bind(&RunDevicesEnumeratedCallback, callback)); - } -} - -void VideoCaptureDeviceFactoryMac::GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) { - DCHECK(thread_checker_.CalledOnValidThread()); - switch (device.capture_api_type()) { - case VideoCaptureDevice::Name::AVFOUNDATION: - DVLOG(1) << "Enumerating video capture capabilities, AVFoundation"; - [VideoCaptureDeviceAVFoundation getDevice:device - supportedFormats:supported_formats]; - break; - case VideoCaptureDevice::Name::QTKIT: - // Blacklisted cameras provide their own supported format(s), otherwise no - // such information is provided for QTKit devices. - if (device.is_blacklisted()) { - for (size_t i = 0; i < arraysize(kBlacklistedCameras); ++i) { - if (base::EndsWith(device.id(), - kBlacklistedCameras[i].unique_id_signature, - base::CompareCase::INSENSITIVE_ASCII)) { - supported_formats->push_back(media::VideoCaptureFormat( - gfx::Size(kBlacklistedCameras[i].capture_width, - kBlacklistedCameras[i].capture_height), - kBlacklistedCameras[i].capture_frame_rate, - media::VIDEO_CAPTURE_PIXEL_FORMAT_UYVY)); - break; - } - } - } - break; - case VideoCaptureDevice::Name::DECKLINK: - DVLOG(1) << "Enumerating video capture capabilities " << device.name(); - VideoCaptureDeviceDeckLinkMac::EnumerateDeviceCapabilities( - device, supported_formats); - break; - default: - NOTREACHED(); - } -} - -// static -VideoCaptureDeviceFactory* -VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { - return new VideoCaptureDeviceFactoryMac(ui_task_runner); -} - -} // 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 45027ba..0000000 --- a/media/video/capture/mac/video_capture_device_factory_mac_unittest.mm +++ /dev/null @@ -1,49 +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 "base/message_loop/message_loop.h" -#include "base/thread_task_runner_handle.h" -#import "media/base/mac/avfoundation_glue.h" -#include "media/base/media_switches.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 { - void SetUp() override { - AVFoundationGlue::InitializeAVFoundation(); - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableAVFoundation); - } - - private: - base::MessageLoop message_loop_; -}; - -TEST_F(VideoCaptureDeviceFactoryMacTest, ListDevicesAVFoundation) { - if (!AVFoundationGlue::IsAVFoundationSupported()) { - DVLOG(1) << "AVFoundation not supported, skipping test."; - return; - } - VideoCaptureDeviceFactoryMac video_capture_device_factory( - base::ThreadTaskRunnerHandle::Get()); - - 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 deleted file mode 100644 index bbe8a23..0000000 --- a/media/video/capture/mac/video_capture_device_mac.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2012 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. - -// 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. - -#ifndef MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_MAC_H_ -#define MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_MAC_H_ - -#import <Foundation/Foundation.h> - -#include <string> - -#include "base/compiler_specific.h" -#include "base/mac/scoped_nsobject.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "media/base/video_capture_types.h" -#include "media/video/capture/video_capture_device.h" - -@protocol PlatformVideoCapturingMac; - -namespace base { -class SingleThreadTaskRunner; -} - -// Small class to bundle device name and connection type into a dictionary. -MEDIA_EXPORT -@interface DeviceNameAndTransportType : NSObject { - @private - base::scoped_nsobject<NSString> deviceName_; - // The transport type of the device (USB, PCI, etc), values are defined in - // <IOKit/audio/IOAudioTypes.h> as kIOAudioDeviceTransportType*. - int32_t transportType_; -} - -- (id)initWithName:(NSString*)name transportType:(int32_t)transportType; - -- (NSString*)deviceName; -- (int32_t)transportType; -@end - -namespace media { - -enum { - // Unknown transport type, addition to the kIOAudioDeviceTransportType* - // family for QTKit devices where this attribute isn't published. - kIOAudioDeviceTransportTypeUnknown = 'unkn' -}; - -// Called by VideoCaptureManager to open, close and start, stop Mac video -// capture devices. -class VideoCaptureDeviceMac : public VideoCaptureDevice { - public: - explicit VideoCaptureDeviceMac(const Name& device_name); - ~VideoCaptureDeviceMac() override; - - // VideoCaptureDevice implementation. - void AllocateAndStart(const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) override; - void StopAndDeAllocate() override; - - bool Init(VideoCaptureDevice::Name::CaptureApiType capture_api_type); - - // Called to deliver captured video frames. - void ReceiveFrame(const uint8* video_frame, - int video_frame_length, - const VideoCaptureFormat& frame_format, - int aspect_numerator, - int aspect_denominator); - - // Forwarder to VideoCaptureDevice::Client::OnError(). - void ReceiveError(const std::string& reason); - - // Forwarder to VideoCaptureDevice::Client::OnLog(). - void LogMessage(const std::string& message); - - private: - void SetErrorState(const std::string& reason); - bool UpdateCaptureResolution(); - - // Flag indicating the internal state. - enum InternalState { - kNotInitialized, - kIdle, - kCapturing, - kError - }; - - Name device_name_; - scoped_ptr<VideoCaptureDevice::Client> client_; - - VideoCaptureFormat capture_format_; - // These variables control the two-step configure-start process for QTKit HD: - // the device is first started with no configuration and the captured frames - // are inspected to check if the camera really supports HD. AVFoundation does - // not need this process so |final_resolution_selected_| is false then. - bool final_resolution_selected_; - bool tried_to_square_pixels_; - - // Only read and write state_ from inside this loop. - const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - InternalState state_; - - id<PlatformVideoCapturingMac> capture_device_; - - // Used with Bind and PostTask to ensure that methods aren't called after the - // VideoCaptureDeviceMac is destroyed. - // NOTE: Weak pointers must be invalidated before all other member variables. - base::WeakPtrFactory<VideoCaptureDeviceMac> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceMac); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_MAC_H_ diff --git a/media/video/capture/mac/video_capture_device_mac.mm b/media/video/capture/mac/video_capture_device_mac.mm deleted file mode 100644 index aa08e16..0000000 --- a/media/video/capture/mac/video_capture_device_mac.mm +++ /dev/null @@ -1,579 +0,0 @@ -// Copyright (c) 2012 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_mac.h" - -#include <IOKit/IOCFPlugIn.h> -#include <IOKit/usb/IOUSBLib.h> -#include <IOKit/usb/USBSpec.h> - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/mac/scoped_ioobject.h" -#include "base/mac/scoped_ioplugininterface.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_number_conversions.h" -#include "base/thread_task_runner_handle.h" -#include "base/time/time.h" -#import "media/base/mac/avfoundation_glue.h" -#import "media/video/capture/mac/platform_video_capturing_mac.h" -#import "media/video/capture/mac/video_capture_device_avfoundation_mac.h" -#import "media/video/capture/mac/video_capture_device_qtkit_mac.h" -#include "ui/gfx/geometry/size.h" - -@implementation DeviceNameAndTransportType - -- (id)initWithName:(NSString*)deviceName transportType:(int32_t)transportType { - if (self = [super init]) { - deviceName_.reset([deviceName copy]); - transportType_ = transportType; - } - return self; -} - -- (NSString*)deviceName { - return deviceName_; -} - -- (int32_t)transportType { - return transportType_; -} - -@end // @implementation DeviceNameAndTransportType - -namespace media { - -// Mac specific limits for minimum and maximum frame rate. -const float kMinFrameRate = 1.0f; -const float kMaxFrameRate = 30.0f; - -// In device identifiers, the USB VID and PID are stored in 4 bytes each. -const size_t kVidPidSize = 4; - -const struct Resolution { - const int width; - const int height; -} kQVGA = { 320, 240 }, - kVGA = { 640, 480 }, - kHD = { 1280, 720 }; - -const struct Resolution* const kWellSupportedResolutions[] = { - &kQVGA, - &kVGA, - &kHD, -}; - -// Rescaling the image to fix the pixel aspect ratio runs the risk of making -// the aspect ratio worse, if QTKit selects a new source mode with a different -// shape. This constant ensures that we don't take this risk if the current -// aspect ratio is tolerable. -const float kMaxPixelAspectRatio = 1.15; - -// The following constants are extracted from the specification "Universal -// Serial Bus Device Class Definition for Video Devices", Rev. 1.1 June 1, 2005. -// http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip -// CS_INTERFACE: Sec. A.4 "Video Class-Specific Descriptor Types". -const int kVcCsInterface = 0x24; -// VC_PROCESSING_UNIT: Sec. A.5 "Video Class-Specific VC Interface Descriptor -// Subtypes". -const int kVcProcessingUnit = 0x5; -// SET_CUR: Sec. A.8 "Video Class-Specific Request Codes". -const int kVcRequestCodeSetCur = 0x1; -// PU_POWER_LINE_FREQUENCY_CONTROL: Sec. A.9.5 "Processing Unit Control -// Selectors". -const int kPuPowerLineFrequencyControl = 0x5; -// Sec. 4.2.2.3.5 Power Line Frequency Control. -const int k50Hz = 1; -const int k60Hz = 2; -const int kPuPowerLineFrequencyControlCommandSize = 1; - -// Addition to the IOUSB family of structures, with subtype and unit ID. -typedef struct IOUSBInterfaceDescriptor { - IOUSBDescriptorHeader header; - UInt8 bDescriptorSubType; - UInt8 bUnitID; -} IOUSBInterfaceDescriptor; - -static void GetBestMatchSupportedResolution(gfx::Size* resolution) { - int min_diff = kint32max; - const int desired_area = resolution->GetArea(); - for (size_t i = 0; i < arraysize(kWellSupportedResolutions); ++i) { - const int area = kWellSupportedResolutions[i]->width * - kWellSupportedResolutions[i]->height; - const int diff = std::abs(desired_area - area); - if (diff < min_diff) { - min_diff = diff; - resolution->SetSize(kWellSupportedResolutions[i]->width, - kWellSupportedResolutions[i]->height); - } - } -} - -// Tries to create a user-side device interface for a given USB device. Returns -// true if interface was found and passes it back in |device_interface|. The -// caller should release |device_interface|. -static bool FindDeviceInterfaceInUsbDevice( - const int vendor_id, - const int product_id, - const io_service_t usb_device, - IOUSBDeviceInterface*** device_interface) { - // Create a plugin, i.e. a user-side controller to manipulate USB device. - IOCFPlugInInterface** plugin; - SInt32 score; // Unused, but required for IOCreatePlugInInterfaceForService. - kern_return_t kr = - IOCreatePlugInInterfaceForService(usb_device, - kIOUSBDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, - &plugin, - &score); - if (kr != kIOReturnSuccess || !plugin) { - DLOG(ERROR) << "IOCreatePlugInInterfaceForService"; - return false; - } - base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> plugin_ref(plugin); - - // Fetch the Device Interface from the plugin. - HRESULT res = - (*plugin)->QueryInterface(plugin, - CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), - reinterpret_cast<LPVOID*>(device_interface)); - if (!SUCCEEDED(res) || !*device_interface) { - DLOG(ERROR) << "QueryInterface, couldn't create interface to USB"; - return false; - } - return true; -} - -// Tries to find a Video Control type interface inside a general USB device -// interface |device_interface|, and returns it in |video_control_interface| if -// found. The returned interface must be released in the caller. -static bool FindVideoControlInterfaceInDeviceInterface( - IOUSBDeviceInterface** device_interface, - IOCFPlugInInterface*** video_control_interface) { - // Create an iterator to the list of Video-AVControl interfaces of the device, - // then get the first interface in the list. - io_iterator_t interface_iterator; - IOUSBFindInterfaceRequest interface_request = { - .bInterfaceClass = kUSBVideoInterfaceClass, - .bInterfaceSubClass = kUSBVideoControlSubClass, - .bInterfaceProtocol = kIOUSBFindInterfaceDontCare, - .bAlternateSetting = kIOUSBFindInterfaceDontCare - }; - kern_return_t kr = - (*device_interface)->CreateInterfaceIterator(device_interface, - &interface_request, - &interface_iterator); - if (kr != kIOReturnSuccess) { - DLOG(ERROR) << "Could not create an iterator to the device's interfaces."; - return false; - } - base::mac::ScopedIOObject<io_iterator_t> iterator_ref(interface_iterator); - - // There should be just one interface matching the class-subclass desired. - io_service_t found_interface; - found_interface = IOIteratorNext(interface_iterator); - if (!found_interface) { - DLOG(ERROR) << "Could not find a Video-AVControl interface in the device."; - return false; - } - base::mac::ScopedIOObject<io_service_t> found_interface_ref(found_interface); - - // Create a user side controller (i.e. a "plugin") for the found interface. - SInt32 score; - kr = IOCreatePlugInInterfaceForService(found_interface, - kIOUSBInterfaceUserClientTypeID, - kIOCFPlugInInterfaceID, - video_control_interface, - &score); - if (kr != kIOReturnSuccess || !*video_control_interface) { - DLOG(ERROR) << "IOCreatePlugInInterfaceForService"; - return false; - } - return true; -} - -// Creates a control interface for |plugin_interface| and produces a command to -// set the appropriate Power Line frequency for flicker removal. -static void SetAntiFlickerInVideoControlInterface( - IOCFPlugInInterface** plugin_interface, - const int frequency) { - // Create, the control interface for the found plugin, and release - // the intermediate plugin. - IOUSBInterfaceInterface** control_interface = NULL; - HRESULT res = (*plugin_interface)->QueryInterface( - plugin_interface, - CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), - reinterpret_cast<LPVOID*>(&control_interface)); - if (!SUCCEEDED(res) || !control_interface ) { - DLOG(ERROR) << "Couldn’t create control interface"; - return; - } - base::mac::ScopedIOPluginInterface<IOUSBInterfaceInterface> - control_interface_ref(control_interface); - - // Find the device's unit ID presenting type 0x24 (kVcCsInterface) and - // subtype 0x5 (kVcProcessingUnit). Inside this unit is where we find the - // power line frequency removal setting, and this id is device dependent. - int real_unit_id = -1; - IOUSBDescriptorHeader* descriptor = NULL; - IOUSBInterfaceDescriptor* cs_descriptor = NULL; - IOUSBInterfaceInterface220** interface = - reinterpret_cast<IOUSBInterfaceInterface220**>(control_interface); - while ((descriptor = (*interface)->FindNextAssociatedDescriptor( - interface, descriptor, kUSBAnyDesc))) { - cs_descriptor = - reinterpret_cast<IOUSBInterfaceDescriptor*>(descriptor); - if ((descriptor->bDescriptorType == kVcCsInterface) && - (cs_descriptor->bDescriptorSubType == kVcProcessingUnit)) { - real_unit_id = cs_descriptor->bUnitID; - break; - } - } - DVLOG_IF(1, real_unit_id == -1) << "This USB device doesn't seem to have a " - << " VC_PROCESSING_UNIT, anti-flicker not available"; - if (real_unit_id == -1) - return; - - if ((*control_interface)->USBInterfaceOpen(control_interface) != - kIOReturnSuccess) { - DLOG(ERROR) << "Unable to open control interface"; - return; - } - - // Create the control request and launch it to the device's control interface. - // Note how the wIndex needs the interface number OR'ed in the lowest bits. - IOUSBDevRequest command; - command.bmRequestType = USBmakebmRequestType(kUSBOut, - kUSBClass, - kUSBInterface); - command.bRequest = kVcRequestCodeSetCur; - UInt8 interface_number; - (*control_interface)->GetInterfaceNumber(control_interface, - &interface_number); - command.wIndex = (real_unit_id << 8) | interface_number; - const int selector = kPuPowerLineFrequencyControl; - command.wValue = (selector << 8); - command.wLength = kPuPowerLineFrequencyControlCommandSize; - command.wLenDone = 0; - int power_line_flag_value = (frequency == 50) ? k50Hz : k60Hz; - command.pData = &power_line_flag_value; - - IOReturn ret = (*control_interface)->ControlRequest(control_interface, - 0, &command); - DLOG_IF(ERROR, ret != kIOReturnSuccess) << "Anti-flicker control request" - << " failed (0x" << std::hex << ret << "), unit id: " << real_unit_id; - DVLOG_IF(1, ret == kIOReturnSuccess) << "Anti-flicker set to " << frequency - << "Hz"; - - (*control_interface)->USBInterfaceClose(control_interface); -} - -// Sets the flicker removal in a USB webcam identified by |vendor_id| and -// |product_id|, if available. The process includes first finding all USB -// devices matching the specified |vendor_id| and |product_id|; for each -// matching device, a device interface, and inside it a video control interface -// are created. The latter is used to a send a power frequency setting command. -static void SetAntiFlickerInUsbDevice(const int vendor_id, - const int product_id, - const int frequency) { - if (frequency == 0) - return; - DVLOG(1) << "Setting Power Line Frequency to " << frequency << " Hz, device " - << std::hex << vendor_id << "-" << product_id; - - // Compose a search dictionary with vendor and product ID. - CFMutableDictionaryRef query_dictionary = - IOServiceMatching(kIOUSBDeviceClassName); - CFDictionarySetValue(query_dictionary, CFSTR(kUSBVendorName), - CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor_id)); - CFDictionarySetValue(query_dictionary, CFSTR(kUSBProductName), - CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product_id)); - - io_iterator_t usb_iterator; - kern_return_t kr = IOServiceGetMatchingServices(kIOMasterPortDefault, - query_dictionary, - &usb_iterator); - if (kr != kIOReturnSuccess) { - DLOG(ERROR) << "No devices found with specified Vendor and Product ID."; - return; - } - base::mac::ScopedIOObject<io_iterator_t> usb_iterator_ref(usb_iterator); - - while (io_service_t usb_device = IOIteratorNext(usb_iterator)) { - base::mac::ScopedIOObject<io_service_t> usb_device_ref(usb_device); - - IOUSBDeviceInterface** device_interface = NULL; - if (!FindDeviceInterfaceInUsbDevice(vendor_id, product_id, - usb_device, &device_interface)) { - return; - } - base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface> - device_interface_ref(device_interface); - - IOCFPlugInInterface** video_control_interface = NULL; - if (!FindVideoControlInterfaceInDeviceInterface(device_interface, - &video_control_interface)) { - return; - } - base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> - plugin_interface_ref(video_control_interface); - - SetAntiFlickerInVideoControlInterface(video_control_interface, frequency); - } -} - -const std::string VideoCaptureDevice::Name::GetModel() const { - // Skip the AVFoundation's not USB nor built-in devices. - if (capture_api_type() == AVFOUNDATION && transport_type() != USB_OR_BUILT_IN) - return ""; - if (capture_api_type() == DECKLINK) - return ""; - // Both PID and VID are 4 characters. - if (unique_id_.size() < 2 * kVidPidSize) - return ""; - - // The last characters of device id is a concatenation of VID and then PID. - const size_t vid_location = unique_id_.size() - 2 * kVidPidSize; - std::string id_vendor = unique_id_.substr(vid_location, kVidPidSize); - const size_t pid_location = unique_id_.size() - kVidPidSize; - std::string id_product = unique_id_.substr(pid_location, kVidPidSize); - - return id_vendor + ":" + id_product; -} - -VideoCaptureDeviceMac::VideoCaptureDeviceMac(const Name& device_name) - : device_name_(device_name), - tried_to_square_pixels_(false), - task_runner_(base::ThreadTaskRunnerHandle::Get()), - state_(kNotInitialized), - capture_device_(nil), - weak_factory_(this) { - // Avoid reconfiguring AVFoundation or blacklisted devices. - final_resolution_selected_ = AVFoundationGlue::IsAVFoundationSupported() || - device_name.is_blacklisted(); -} - -VideoCaptureDeviceMac::~VideoCaptureDeviceMac() { - DCHECK(task_runner_->BelongsToCurrentThread()); - [capture_device_ release]; -} - -void VideoCaptureDeviceMac::AllocateAndStart( - const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) { - DCHECK(task_runner_->BelongsToCurrentThread()); - if (state_ != kIdle) { - return; - } - - // QTKit API can scale captured frame to any size requested, which would lead - // to undesired aspect ratio changes. Try to open the camera with a known - // supported format and let the client crop/pad the captured frames. - gfx::Size resolution = params.requested_format.frame_size; - if (!AVFoundationGlue::IsAVFoundationSupported()) - GetBestMatchSupportedResolution(&resolution); - - client_ = client.Pass(); - if (device_name_.capture_api_type() == Name::AVFOUNDATION) - LogMessage("Using AVFoundation for device: " + device_name_.name()); - else - LogMessage("Using QTKit for device: " + device_name_.name()); - NSString* deviceId = - [NSString stringWithUTF8String:device_name_.id().c_str()]; - - [capture_device_ setFrameReceiver:this]; - - if (![capture_device_ setCaptureDevice:deviceId]) { - SetErrorState("Could not open capture device."); - return; - } - - capture_format_.frame_size = resolution; - capture_format_.frame_rate = - std::max(kMinFrameRate, - std::min(params.requested_format.frame_rate, kMaxFrameRate)); - // Leave the pixel format selection to AVFoundation/QTKit. The pixel format - // will be passed to |ReceiveFrame|. - capture_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN; - - // QTKit: Set the capture resolution only if this is VGA or smaller, otherwise - // leave it unconfigured and start capturing: QTKit will produce frames at the - // native resolution, allowing us to identify cameras whose native resolution - // is too low for HD. This additional information comes at a cost in startup - // latency, because the webcam will need to be reopened if its default - // resolution is not HD or VGA. - // AVfoundation is configured for all resolutions. - if (AVFoundationGlue::IsAVFoundationSupported() || - resolution.width() <= kVGA.width || resolution.height() <= kVGA.height) { - if (!UpdateCaptureResolution()) - return; - } - - // Try setting the power line frequency removal (anti-flicker). The built-in - // cameras are normally suspended so the configuration must happen right - // before starting capture and during configuration. - const std::string& device_model = device_name_.GetModel(); - if (device_model.length() > 2 * kVidPidSize) { - std::string vendor_id = device_model.substr(0, kVidPidSize); - std::string model_id = device_model.substr(kVidPidSize + 1); - int vendor_id_as_int, model_id_as_int; - if (base::HexStringToInt(base::StringPiece(vendor_id), &vendor_id_as_int) && - base::HexStringToInt(base::StringPiece(model_id), &model_id_as_int)) { - SetAntiFlickerInUsbDevice(vendor_id_as_int, model_id_as_int, - GetPowerLineFrequencyForLocation()); - } - } - - if (![capture_device_ startCapture]) { - SetErrorState("Could not start capture device."); - return; - } - - state_ = kCapturing; -} - -void VideoCaptureDeviceMac::StopAndDeAllocate() { - DCHECK(task_runner_->BelongsToCurrentThread()); - DCHECK(state_ == kCapturing || state_ == kError) << state_; - - [capture_device_ setCaptureDevice:nil]; - [capture_device_ setFrameReceiver:nil]; - client_.reset(); - state_ = kIdle; - tried_to_square_pixels_ = false; -} - -bool VideoCaptureDeviceMac::Init( - VideoCaptureDevice::Name::CaptureApiType capture_api_type) { - DCHECK(task_runner_->BelongsToCurrentThread()); - DCHECK_EQ(state_, kNotInitialized); - - if (capture_api_type == Name::AVFOUNDATION) { - capture_device_ = - [[VideoCaptureDeviceAVFoundation alloc] initWithFrameReceiver:this]; - } else { - capture_device_ = - [[VideoCaptureDeviceQTKit alloc] initWithFrameReceiver:this]; - } - - if (!capture_device_) - return false; - - state_ = kIdle; - return true; -} - -void VideoCaptureDeviceMac::ReceiveFrame( - const uint8* video_frame, - int video_frame_length, - const VideoCaptureFormat& frame_format, - int aspect_numerator, - int aspect_denominator) { - // This method is safe to call from a device capture thread, i.e. any thread - // controlled by QTKit/AVFoundation. - if (!final_resolution_selected_) { - DCHECK(!AVFoundationGlue::IsAVFoundationSupported()); - if (capture_format_.frame_size.width() > kVGA.width || - capture_format_.frame_size.height() > kVGA.height) { - // We are requesting HD. Make sure that the picture is good, otherwise - // drop down to VGA. - bool change_to_vga = false; - if (frame_format.frame_size.width() < - capture_format_.frame_size.width() || - frame_format.frame_size.height() < - capture_format_.frame_size.height()) { - // These are the default capture settings, not yet configured to match - // |capture_format_|. - DCHECK(frame_format.frame_rate == 0); - DVLOG(1) << "Switching to VGA because the default resolution is " << - frame_format.frame_size.ToString(); - change_to_vga = true; - } - - if (capture_format_.frame_size == frame_format.frame_size && - aspect_numerator != aspect_denominator) { - DVLOG(1) << "Switching to VGA because HD has nonsquare pixel " << - "aspect ratio " << aspect_numerator << ":" << aspect_denominator; - change_to_vga = true; - } - - if (change_to_vga) - capture_format_.frame_size.SetSize(kVGA.width, kVGA.height); - } - - if (capture_format_.frame_size == frame_format.frame_size && - !tried_to_square_pixels_ && - (aspect_numerator > kMaxPixelAspectRatio * aspect_denominator || - aspect_denominator > kMaxPixelAspectRatio * aspect_numerator)) { - // The requested size results in non-square PAR. Shrink the frame to 1:1 - // PAR (assuming QTKit selects the same input mode, which is not - // guaranteed). - int new_width = capture_format_.frame_size.width(); - int new_height = capture_format_.frame_size.height(); - if (aspect_numerator < aspect_denominator) - new_width = (new_width * aspect_numerator) / aspect_denominator; - else - new_height = (new_height * aspect_denominator) / aspect_numerator; - capture_format_.frame_size.SetSize(new_width, new_height); - tried_to_square_pixels_ = true; - } - - if (capture_format_.frame_size == frame_format.frame_size) { - final_resolution_selected_ = true; - } else { - UpdateCaptureResolution(); - // Let the resolution update sink through QTKit and wait for next frame. - return; - } - } - - // QTKit capture source can change resolution if someone else reconfigures the - // camera, and that is fine: http://crbug.com/353620. In AVFoundation, this - // should not happen, it should resize internally. - if (!AVFoundationGlue::IsAVFoundationSupported()) { - capture_format_.frame_size = frame_format.frame_size; - } else if (capture_format_.frame_size != frame_format.frame_size) { - ReceiveError("Captured resolution " + frame_format.frame_size.ToString() + - ", and expected " + capture_format_.frame_size.ToString()); - return; - } - - client_->OnIncomingCapturedData(video_frame, - video_frame_length, - frame_format, - 0, - base::TimeTicks::Now()); -} - -void VideoCaptureDeviceMac::ReceiveError(const std::string& reason) { - task_runner_->PostTask(FROM_HERE, - base::Bind(&VideoCaptureDeviceMac::SetErrorState, - weak_factory_.GetWeakPtr(), - reason)); -} - -void VideoCaptureDeviceMac::SetErrorState(const std::string& reason) { - DCHECK(task_runner_->BelongsToCurrentThread()); - state_ = kError; - client_->OnError(reason); -} - -void VideoCaptureDeviceMac::LogMessage(const std::string& message) { - DCHECK(task_runner_->BelongsToCurrentThread()); - if (client_) - client_->OnLog(message); -} - -bool VideoCaptureDeviceMac::UpdateCaptureResolution() { - if (![capture_device_ setCaptureHeight:capture_format_.frame_size.height() - width:capture_format_.frame_size.width() - frameRate:capture_format_.frame_rate]) { - ReceiveError("Could not configure capture device."); - return false; - } - return true; -} - -} // namespace media diff --git a/media/video/capture/mac/video_capture_device_qtkit_mac.h b/media/video/capture/mac/video_capture_device_qtkit_mac.h deleted file mode 100644 index c1af697..0000000 --- a/media/video/capture/mac/video_capture_device_qtkit_mac.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2011 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. - -// VideoCaptureDeviceQTKit implements all QTKit related code for -// communicating with a QTKit capture device. - -#ifndef MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_ -#define MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_ - -#import <Foundation/Foundation.h> - -#include <vector> - -#import "media/video/capture/mac/platform_video_capturing_mac.h" - -namespace media { -class VideoCaptureDeviceMac; -} - -@class QTCaptureDeviceInput; -@class QTCaptureSession; - -@interface VideoCaptureDeviceQTKit : NSObject<PlatformVideoCapturingMac> { - @private - // Settings. - float frameRate_; - - NSLock *lock_; - media::VideoCaptureDeviceMac *frameReceiver_; - - // QTKit variables. - QTCaptureSession *captureSession_; - QTCaptureDeviceInput *captureDeviceInput_; - - // Buffer for adjusting frames which do not fit receiver - // assumptions. scoped_array<> might make more sense, if the size - // can be proven invariant. - std::vector<UInt8> adjustedFrame_; -} - -// Fills up the |deviceNames| dictionary of capture devices with friendly name -// and unique id. No thread assumptions, but this method should run in UI -// thread, see http://crbug.com/139164 -+ (void)getDeviceNames:(NSMutableDictionary*)deviceNames; - -// Returns a dictionary of capture devices with friendly name and unique id, via -// runing +getDeviceNames: on Main Thread. -+ (NSDictionary*)deviceNames; - -// Initializes the instance and registers the frame receiver. -- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver; - -// Set the frame receiver. -- (void)setFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver; - -// Sets which capture device to use. Returns YES on sucess, NO otherwise. -- (BOOL)setCaptureDevice:(NSString*)deviceId; - -// Configures the capture properties. -- (BOOL)setCaptureHeight:(int)height - width:(int)width - frameRate:(float)frameRate; - -// Start video capturing. Returns YES on sucess, NO otherwise. -- (BOOL)startCapture; - -// Stops video capturing. -- (void)stopCapture; - -// Handle any QTCaptureSessionRuntimeErrorNotifications. -- (void)handleNotification:(NSNotification*)errorNotification; - -@end - -#endif // MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_ diff --git a/media/video/capture/mac/video_capture_device_qtkit_mac.mm b/media/video/capture/mac/video_capture_device_qtkit_mac.mm deleted file mode 100644 index 4d21d0d..0000000 --- a/media/video/capture/mac/video_capture_device_qtkit_mac.mm +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright (c) 2012 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. - -#import "media/video/capture/mac/video_capture_device_qtkit_mac.h" - -#import <QTKit/QTKit.h> - -#include "base/debug/crash_logging.h" -#include "base/logging.h" -#include "base/mac/scoped_nsexception_enabler.h" -#include "media/base/video_capture_types.h" -#include "media/video/capture/mac/video_capture_device_mac.h" -#include "media/video/capture/video_capture_device.h" -#include "ui/gfx/geometry/size.h" - -@implementation VideoCaptureDeviceQTKit - -#pragma mark Class methods - -+ (void)getDeviceNames:(NSMutableDictionary*)deviceNames { - // Third-party drivers often throw exceptions, which are fatal in - // Chromium (see comments in scoped_nsexception_enabler.h). The - // following catches any exceptions and continues in an orderly - // fashion with no devices detected. - NSArray* captureDevices = - base::mac::RunBlockIgnoringExceptions(^{ - return [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo]; - }); - - for (QTCaptureDevice* device in captureDevices) { - if ([[device attributeForKey:QTCaptureDeviceSuspendedAttribute] boolValue]) - continue; - DeviceNameAndTransportType* nameAndTransportType = - [[[DeviceNameAndTransportType alloc] - initWithName:[device localizedDisplayName] - transportType:media::kIOAudioDeviceTransportTypeUnknown] - autorelease]; - [deviceNames setObject:nameAndTransportType - forKey:[device uniqueID]]; - } -} - -+ (NSDictionary*)deviceNames { - NSMutableDictionary* deviceNames = - [[[NSMutableDictionary alloc] init] autorelease]; - - // TODO(shess): Post to the main thread to see if that helps - // http://crbug.com/139164 - [self performSelectorOnMainThread:@selector(getDeviceNames:) - withObject:deviceNames - waitUntilDone:YES]; - return deviceNames; -} - -#pragma mark Public methods - -- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver { - self = [super init]; - if (self) { - frameReceiver_ = frameReceiver; - lock_ = [[NSLock alloc] init]; - } - return self; -} - -- (void)dealloc { - [captureSession_ release]; - [captureDeviceInput_ release]; - [super dealloc]; -} - -- (void)setFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver { - [lock_ lock]; - frameReceiver_ = frameReceiver; - [lock_ unlock]; -} - -- (BOOL)setCaptureDevice:(NSString*)deviceId { - if (deviceId) { - // Set the capture device. - if (captureDeviceInput_) { - DLOG(ERROR) << "Video capture device already set."; - return NO; - } - - // TODO(mcasas): Consider using [QTCaptureDevice deviceWithUniqueID] instead - // of explicitly forcing reenumeration of devices. - NSArray *captureDevices = - [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo]; - NSArray *captureDevicesNames = - [captureDevices valueForKey:@"uniqueID"]; - NSUInteger index = [captureDevicesNames indexOfObject:deviceId]; - if (index == NSNotFound) { - [self sendErrorString:[NSString - stringWithUTF8String:"Video capture device not found."]]; - return NO; - } - QTCaptureDevice *device = [captureDevices objectAtIndex:index]; - if ([[device attributeForKey:QTCaptureDeviceSuspendedAttribute] - boolValue]) { - [self sendErrorString:[NSString - stringWithUTF8String:"Cannot open suspended video capture device."]]; - return NO; - } - NSError *error; - if (![device open:&error]) { - [self sendErrorString:[NSString - stringWithFormat:@"Could not open video capture device (%@): %@", - [error localizedDescription], - [error localizedFailureReason]]]; - return NO; - } - captureDeviceInput_ = [[QTCaptureDeviceInput alloc] initWithDevice:device]; - captureSession_ = [[QTCaptureSession alloc] init]; - - QTCaptureDecompressedVideoOutput *captureDecompressedOutput = - [[[QTCaptureDecompressedVideoOutput alloc] init] autorelease]; - [captureDecompressedOutput setDelegate:self]; - [captureDecompressedOutput setAutomaticallyDropsLateVideoFrames:YES]; - if (![captureSession_ addOutput:captureDecompressedOutput error:&error]) { - [self sendErrorString:[NSString - stringWithFormat:@"Could not connect video capture output (%@): %@", - [error localizedDescription], - [error localizedFailureReason]]]; - return NO; - } - - // This key can be used to check if video capture code was related to a - // particular crash. - base::debug::SetCrashKeyValue("VideoCaptureDeviceQTKit", "OpenedDevice"); - - // Set the video pixel format to 2VUY (a.k.a UYVY, packed 4:2:2). - NSDictionary *captureDictionary = [NSDictionary - dictionaryWithObject: - [NSNumber numberWithUnsignedInt:kCVPixelFormatType_422YpCbCr8] - forKey:(id)kCVPixelBufferPixelFormatTypeKey]; - [captureDecompressedOutput setPixelBufferAttributes:captureDictionary]; - - return YES; - } else { - // Remove the previously set capture device. - if (!captureDeviceInput_) { - // Being here means stopping a device that never started OK in the first - // place, log it. - [self sendLogString:[NSString - stringWithUTF8String:"No video capture device set, on removal."]]; - return YES; - } - // Tear down input and output, stop the capture and deregister observers. - [self stopCapture]; - [captureSession_ release]; - captureSession_ = nil; - [captureDeviceInput_ release]; - captureDeviceInput_ = nil; - return YES; - } -} - -- (BOOL)setCaptureHeight:(int)height - width:(int)width - frameRate:(float)frameRate { - if (!captureDeviceInput_) { - [self sendErrorString:[NSString - stringWithUTF8String:"No video capture device set."]]; - return NO; - } - if ([[captureSession_ outputs] count] != 1) { - [self sendErrorString:[NSString - stringWithUTF8String:"Video capture capabilities already set."]]; - return NO; - } - if (frameRate <= 0.0f) { - [self sendErrorString:[NSString stringWithUTF8String: "Wrong frame rate."]]; - return NO; - } - - frameRate_ = frameRate; - - QTCaptureDecompressedVideoOutput *output = - [[captureSession_ outputs] objectAtIndex:0]; - - // Set up desired output properties. The old capture dictionary is used to - // retrieve the initial pixel format, which must be maintained. - NSDictionary* videoSettingsDictionary = @{ - (id)kCVPixelBufferWidthKey : @(width), - (id)kCVPixelBufferHeightKey : @(height), - (id)kCVPixelBufferPixelFormatTypeKey : [[output pixelBufferAttributes] - valueForKey:(id)kCVPixelBufferPixelFormatTypeKey] - }; - [output setPixelBufferAttributes:videoSettingsDictionary]; - - [output setMinimumVideoFrameInterval:(NSTimeInterval)1/frameRate]; - return YES; -} - -- (BOOL)startCapture { - if ([[captureSession_ outputs] count] == 0) { - // Capture properties not set. - [self sendErrorString:[NSString - stringWithUTF8String:"Video capture device not initialized."]]; - return NO; - } - if ([[captureSession_ inputs] count] == 0) { - NSError *error; - if (![captureSession_ addInput:captureDeviceInput_ error:&error]) { - [self sendErrorString:[NSString - stringWithFormat:@"Could not connect video capture device (%@): %@", - [error localizedDescription], - [error localizedFailureReason]]]; - - return NO; - } - NSNotificationCenter * notificationCenter = - [NSNotificationCenter defaultCenter]; - [notificationCenter addObserver:self - selector:@selector(handleNotification:) - name:QTCaptureSessionRuntimeErrorNotification - object:captureSession_]; - [captureSession_ startRunning]; - } - return YES; -} - -- (void)stopCapture { - // QTKit achieves thread safety and asynchronous execution by posting messages - // to the main thread, e.g. -addOutput:. Both -removeOutput: and -removeInput: - // post a message to the main thread while holding a lock that the - // notification handler might need. To avoid a deadlock, we perform those - // tasks in the main thread. See bugs http://crbug.com/152757 and - // http://crbug.com/399792. - [self performSelectorOnMainThread:@selector(stopCaptureOnUIThread:) - withObject:nil - waitUntilDone:YES]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (void)stopCaptureOnUIThread:(id)dummy { - if ([[captureSession_ inputs] count] > 0) { - DCHECK_EQ([[captureSession_ inputs] count], 1u); - [captureSession_ removeInput:captureDeviceInput_]; - [captureSession_ stopRunning]; - } - if ([[captureSession_ outputs] count] > 0) { - DCHECK_EQ([[captureSession_ outputs] count], 1u); - id output = [[captureSession_ outputs] objectAtIndex:0]; - [output setDelegate:nil]; - [captureSession_ removeOutput:output]; - } -} - -// |captureOutput| is called by the capture device to deliver a new frame. -- (void)captureOutput:(QTCaptureOutput*)captureOutput - didOutputVideoFrame:(CVImageBufferRef)videoFrame - withSampleBuffer:(QTSampleBuffer*)sampleBuffer - fromConnection:(QTCaptureConnection*)connection { - [lock_ lock]; - if(!frameReceiver_) { - [lock_ unlock]; - return; - } - - // Lock the frame and calculate frame size. - const int kLockFlags = 0; - if (CVPixelBufferLockBaseAddress(videoFrame, kLockFlags) - == kCVReturnSuccess) { - void *baseAddress = CVPixelBufferGetBaseAddress(videoFrame); - size_t bytesPerRow = CVPixelBufferGetBytesPerRow(videoFrame); - size_t frameWidth = CVPixelBufferGetWidth(videoFrame); - size_t frameHeight = CVPixelBufferGetHeight(videoFrame); - size_t frameSize = bytesPerRow * frameHeight; - - // TODO(shess): bytesPerRow may not correspond to frameWidth_*2, - // but VideoCaptureController::OnIncomingCapturedData() requires - // it to do so. Plumbing things through is intrusive, for now - // just deliver an adjusted buffer. - // TODO(nick): This workaround could probably be eliminated by using - // VideoCaptureController::OnIncomingCapturedVideoFrame, which supports - // pitches. - UInt8* addressToPass = static_cast<UInt8*>(baseAddress); - // UYVY is 2 bytes per pixel. - size_t expectedBytesPerRow = frameWidth * 2; - if (bytesPerRow > expectedBytesPerRow) { - // TODO(shess): frameHeight and frameHeight_ are not the same, - // try to do what the surrounding code seems to assume. - // Ironically, captureCapability and frameSize are ignored - // anyhow. - adjustedFrame_.resize(expectedBytesPerRow * frameHeight); - // std::vector is contiguous according to standard. - UInt8* adjustedAddress = &adjustedFrame_[0]; - - for (size_t y = 0; y < frameHeight; ++y) { - memcpy(adjustedAddress + y * expectedBytesPerRow, - addressToPass + y * bytesPerRow, - expectedBytesPerRow); - } - - addressToPass = adjustedAddress; - frameSize = frameHeight * expectedBytesPerRow; - } - - media::VideoCaptureFormat captureFormat( - gfx::Size(frameWidth, frameHeight), frameRate_, - media::VIDEO_CAPTURE_PIXEL_FORMAT_UYVY); - - // The aspect ratio dictionary is often missing, in which case we report - // a pixel aspect ratio of 0:0. - int aspectNumerator = 0, aspectDenominator = 0; - CFDictionaryRef aspectRatioDict = (CFDictionaryRef)CVBufferGetAttachment( - videoFrame, kCVImageBufferPixelAspectRatioKey, NULL); - if (aspectRatioDict) { - CFNumberRef aspectNumeratorRef = (CFNumberRef)CFDictionaryGetValue( - aspectRatioDict, kCVImageBufferPixelAspectRatioHorizontalSpacingKey); - CFNumberRef aspectDenominatorRef = (CFNumberRef)CFDictionaryGetValue( - aspectRatioDict, kCVImageBufferPixelAspectRatioVerticalSpacingKey); - DCHECK(aspectNumeratorRef && aspectDenominatorRef) << - "Aspect Ratio dictionary missing its entries."; - CFNumberGetValue(aspectNumeratorRef, kCFNumberIntType, &aspectNumerator); - CFNumberGetValue( - aspectDenominatorRef, kCFNumberIntType, &aspectDenominator); - } - - // Deliver the captured video frame. - frameReceiver_->ReceiveFrame(addressToPass, frameSize, captureFormat, - aspectNumerator, aspectDenominator); - - CVPixelBufferUnlockBaseAddress(videoFrame, kLockFlags); - } - [lock_ unlock]; -} - -- (void)handleNotification:(NSNotification*)errorNotification { - NSError * error = (NSError*)[[errorNotification userInfo] - objectForKey:QTCaptureSessionErrorKey]; - [self sendErrorString:[NSString - stringWithFormat:@"%@: %@", - [error localizedDescription], - [error localizedFailureReason]]]; -} - -- (void)sendErrorString:(NSString*)error { - DLOG(ERROR) << [error UTF8String]; - [lock_ lock]; - if (frameReceiver_) - frameReceiver_->ReceiveError([error UTF8String]); - [lock_ unlock]; -} - -- (void)sendLogString:(NSString*)message { - DVLOG(1) << [message UTF8String]; - [lock_ lock]; - if (frameReceiver_) - frameReceiver_->LogMessage([message UTF8String]); - [lock_ unlock]; -} - -@end diff --git a/media/video/capture/video_capture_device.cc b/media/video/capture/video_capture_device.cc deleted file mode 100644 index cb03dba..0000000 --- a/media/video/capture/video_capture_device.cc +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2013 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/video_capture_device.h" - -#include "base/i18n/timezone.h" -#include "base/strings/string_util.h" - -namespace media { - -const std::string VideoCaptureDevice::Name::GetNameAndModel() const { - const std::string model_id = GetModel(); - if (model_id.empty()) - return device_name_; - const std::string suffix = " (" + model_id + ")"; - if (base::EndsWith(device_name_, suffix, base::CompareCase::SENSITIVE)) - return device_name_; - return device_name_ + suffix; -} - -VideoCaptureDevice::Name::Name() {} - -VideoCaptureDevice::Name::Name(const std::string& name, const std::string& id) - : device_name_(name), unique_id_(id) {} - -#if defined(OS_LINUX) -VideoCaptureDevice::Name::Name(const std::string& name, - const std::string& id, - const CaptureApiType api_type) - : device_name_(name), - unique_id_(id), - capture_api_class_(api_type) {} -#elif defined(OS_WIN) -VideoCaptureDevice::Name::Name(const std::string& name, - const std::string& id, - const CaptureApiType api_type) - : device_name_(name), - unique_id_(id), - capture_api_class_(api_type), - capabilities_id_(id) {} -#elif defined(OS_MACOSX) -VideoCaptureDevice::Name::Name(const std::string& name, - const std::string& id, - const CaptureApiType api_type) - : device_name_(name), - unique_id_(id), - capture_api_class_(api_type), - transport_type_(OTHER_TRANSPORT), - is_blacklisted_(false) {} - -VideoCaptureDevice::Name::Name(const std::string& name, - const std::string& id, - const CaptureApiType api_type, - const TransportType transport_type) - : device_name_(name), - unique_id_(id), - capture_api_class_(api_type), - transport_type_(transport_type), - is_blacklisted_(false) {} -#elif defined(ANDROID) -VideoCaptureDevice::Name::Name(const std::string& name, - const std::string& id, - const CaptureApiType api_type) - : device_name_(name), - unique_id_(id), - capture_api_class_(api_type) {} -#endif - -VideoCaptureDevice::Name::~Name() {} - -#if defined(OS_LINUX) -const char* VideoCaptureDevice::Name::GetCaptureApiTypeString() const { - switch (capture_api_type()) { - case V4L2_SINGLE_PLANE: - return "V4L2 SPLANE"; - case V4L2_MULTI_PLANE: - return "V4L2 MPLANE"; - default: - NOTREACHED() << "Unknown Video Capture API type!"; - return "Unknown API"; - } -} -#elif defined(OS_WIN) -const char* VideoCaptureDevice::Name::GetCaptureApiTypeString() const { - switch(capture_api_type()) { - case MEDIA_FOUNDATION: - return "Media Foundation"; - case DIRECT_SHOW: - return "Direct Show"; - default: - NOTREACHED() << "Unknown Video Capture API type!"; - return "Unknown API"; - } -} -#elif defined(OS_MACOSX) -const char* VideoCaptureDevice::Name::GetCaptureApiTypeString() const { - switch(capture_api_type()) { - case AVFOUNDATION: - return "AV Foundation"; - case QTKIT: - return "QTKit"; - case DECKLINK: - return "DeckLink"; - default: - NOTREACHED() << "Unknown Video Capture API type!"; - return "Unknown API"; - } -} -#elif defined(OS_ANDROID) -const char* VideoCaptureDevice::Name::GetCaptureApiTypeString() const { - switch(capture_api_type()) { - case API1: - return "Camera API1"; - case API2_LEGACY: - return "Camera API2 Legacy"; - case API2_FULL: - return "Camera API2 Full"; - case API2_LIMITED: - return "Camera API2 Limited"; - case TANGO: - return "Tango API"; - case API_TYPE_UNKNOWN: - default: - NOTREACHED() << "Unknown Video Capture API type!"; - return "Unknown API"; - } -} -#endif - -VideoCaptureDevice::Client::Buffer::~Buffer() {} - -VideoCaptureDevice::~VideoCaptureDevice() {} - -int VideoCaptureDevice::GetPowerLineFrequencyForLocation() const { - std::string current_country = base::CountryCodeForCurrentTimezone(); - if (current_country.empty()) - return 0; - // Sorted out list of countries with 60Hz power line frequency, from - // http://en.wikipedia.org/wiki/Mains_electricity_by_country - const char* countries_using_60Hz[] = { - "AI", "AO", "AS", "AW", "AZ", "BM", "BR", "BS", "BZ", "CA", "CO", - "CR", "CU", "DO", "EC", "FM", "GT", "GU", "GY", "HN", "HT", "JP", - "KN", "KR", "KY", "MS", "MX", "NI", "PA", "PE", "PF", "PH", "PR", - "PW", "SA", "SR", "SV", "TT", "TW", "UM", "US", "VG", "VI", "VE"}; - const char** countries_using_60Hz_end = - countries_using_60Hz + arraysize(countries_using_60Hz); - if (std::find(countries_using_60Hz, countries_using_60Hz_end, - current_country) == countries_using_60Hz_end) { - return kPowerLine50Hz; - } - return kPowerLine60Hz; -} - -} // namespace media diff --git a/media/video/capture/video_capture_device.h b/media/video/capture/video_capture_device.h deleted file mode 100644 index 5bc60f8..0000000 --- a/media/video/capture/video_capture_device.h +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright (c) 2012 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. -// -// VideoCaptureDevice is the abstract base class for realizing video capture -// device support in Chromium. It provides the interface for OS dependent -// implementations. -// The class is created and functions are invoked on a thread owned by -// VideoCaptureManager. Capturing is done on other threads, depending on the OS -// specific implementation. - -#ifndef MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_H_ -#define MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_H_ - -#include <list> -#include <string> - -#include "base/files/file.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/single_thread_task_runner.h" -#include "base/time/time.h" -#include "media/base/media_export.h" -#include "media/base/video_capture_types.h" -#include "media/base/video_frame.h" -#include "ui/gfx/gpu_memory_buffer.h" - -namespace media { - -class MEDIA_EXPORT VideoCaptureDevice { - public: - // Represents a capture device name and ID. - // You should not create an instance of this class directly by e.g. setting - // various properties directly. Instead use - // VideoCaptureDevice::GetDeviceNames to do this for you and if you need to - // cache your own copy of a name, you can do so via the copy constructor. - // The reason for this is that a device name might contain platform specific - // settings that are relevant only to the platform specific implementation of - // VideoCaptureDevice::Create. - class MEDIA_EXPORT Name { - public: - Name(); - Name(const std::string& name, const std::string& id); - -#if defined(OS_LINUX) - // Linux/CrOS targets Capture Api type: it can only be set on construction. - enum CaptureApiType { - V4L2_SINGLE_PLANE, - V4L2_MULTI_PLANE, - API_TYPE_UNKNOWN - }; -#elif defined(OS_WIN) - // Windows targets Capture Api type: it can only be set on construction. - enum CaptureApiType { - MEDIA_FOUNDATION, - DIRECT_SHOW, - API_TYPE_UNKNOWN - }; -#elif defined(OS_MACOSX) - // Mac targets Capture Api type: it can only be set on construction. - enum CaptureApiType { - AVFOUNDATION, - QTKIT, - DECKLINK, - API_TYPE_UNKNOWN - }; - // For AVFoundation Api, identify devices that are built-in or USB. - enum TransportType { - USB_OR_BUILT_IN, - OTHER_TRANSPORT - }; -#elif defined (OS_ANDROID) - // Android targets Capture Api type: it can only be set on construction. - // Automatically generated enum to interface with Java world. - // - // A Java counterpart will be generated for this enum. - // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.media - enum CaptureApiType { - API1, - API2_LEGACY, - API2_FULL, - API2_LIMITED, - TANGO, - API_TYPE_UNKNOWN - }; -#endif - -#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \ - defined(OS_ANDROID) - Name(const std::string& name, const std::string& id, - const CaptureApiType api_type); -#endif -#if defined(OS_MACOSX) - Name(const std::string& name, - const std::string& id, - const CaptureApiType api_type, - const TransportType transport_type); -#endif - ~Name(); - - // Friendly name of a device - const std::string& name() const { return device_name_; } - - // Unique name of a device. Even if there are multiple devices with the same - // friendly name connected to the computer this will be unique. - const std::string& id() const { return unique_id_; } - - // The unique hardware model identifier of the capture device. Returns - // "[vid]:[pid]" when a USB device is detected, otherwise "". - // The implementation of this method is platform-dependent. - const std::string GetModel() const; - - // Friendly name of a device, plus the model identifier in parentheses. - const std::string GetNameAndModel() const; - - // These operators are needed due to storing the name in an STL container. - // In the shared build, all methods from the STL container will be exported - // so even though they're not used, they're still depended upon. - bool operator==(const Name& other) const { - return other.id() == unique_id_; - } - bool operator<(const Name& other) const { - return unique_id_ < other.id(); - } - -#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \ - defined(OS_ANDROID) - CaptureApiType capture_api_type() const { - return capture_api_class_.capture_api_type(); - } - const char* GetCaptureApiTypeString() const; -#endif -#if defined(OS_WIN) - // Certain devices need an ID different from the |unique_id_| for - // capabilities retrieval. - const std::string& capabilities_id() const { - return capabilities_id_; - } - void set_capabilities_id(const std::string& id) { - capabilities_id_ = id; - } -#endif // if defined(OS_WIN) -#if defined(OS_MACOSX) - TransportType transport_type() const { - return transport_type_; - } - bool is_blacklisted() const { - return is_blacklisted_; - } - void set_is_blacklisted(bool is_blacklisted) { - is_blacklisted_ = is_blacklisted; - } -#endif // if defined(OS_MACOSX) - - private: - std::string device_name_; - std::string unique_id_; -#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \ - defined(OS_ANDROID) - // This class wraps the CaptureApiType to give it a by default value if not - // initialized. - class CaptureApiClass { - public: - CaptureApiClass(): capture_api_type_(API_TYPE_UNKNOWN) {} - CaptureApiClass(const CaptureApiType api_type) - : capture_api_type_(api_type) {} - CaptureApiType capture_api_type() const { - DCHECK_NE(capture_api_type_, API_TYPE_UNKNOWN); - return capture_api_type_; - } - private: - CaptureApiType capture_api_type_; - }; - - CaptureApiClass capture_api_class_; -#endif -#if defined(OS_WIN) - // ID used for capabilities retrieval. By default is equal to |unique_id|. - std::string capabilities_id_; -#endif -#if defined(OS_MACOSX) - TransportType transport_type_; - // Flag used to mark blacklisted devices for QTKit Api. - bool is_blacklisted_; -#endif - // Allow generated copy constructor and assignment. - }; - - // Manages a list of Name entries. - typedef std::list<Name> Names; - - // Interface defining the methods that clients of VideoCapture must have. It - // is actually two-in-one: clients may implement OnIncomingCapturedData() or - // ReserveOutputBuffer() + OnIncomingCapturedVideoFrame(), or all of them. - // All clients must implement OnError(). - class MEDIA_EXPORT Client { - public: - // Memory buffer returned by Client::ReserveOutputBuffer(). - class MEDIA_EXPORT Buffer { - public: - virtual ~Buffer() = 0; - virtual int id() const = 0; - virtual size_t size() const = 0; - virtual void* data() = 0; - virtual ClientBuffer AsClientBuffer() = 0; -#if defined(OS_POSIX) - virtual base::FileDescriptor AsPlatformFile() = 0; -#endif - }; - - virtual ~Client() {} - - // Captured a new video frame, data for which is pointed to by |data|. - // - // The format of the frame is described by |frame_format|, and is assumed to - // be tightly packed. This method will try to reserve an output buffer and - // copy from |data| into the output buffer. If no output buffer is - // available, the frame will be silently dropped. - virtual void OnIncomingCapturedData(const uint8* data, - int length, - const VideoCaptureFormat& frame_format, - int clockwise_rotation, - const base::TimeTicks& timestamp) = 0; - - // Captured a 3 planar YUV frame. Planes are possibly disjoint. - // |frame_format| must indicate I420. - virtual void OnIncomingCapturedYuvData( - const uint8* y_data, - const uint8* u_data, - const uint8* v_data, - size_t y_stride, - size_t u_stride, - size_t v_stride, - const VideoCaptureFormat& frame_format, - int clockwise_rotation, - const base::TimeTicks& timestamp) = 0; - - // Reserve an output buffer into which contents can be captured directly. - // The returned Buffer will always be allocated with a memory size suitable - // for holding a packed video frame with pixels of |format| format, of - // |dimensions| frame dimensions. It is permissible for |dimensions| to be - // zero; in which case the returned Buffer does not guarantee memory - // backing, but functions as a reservation for external input for the - // purposes of buffer throttling. - // - // The output buffer stays reserved and mapped for use until the Buffer - // object is destroyed or returned. - virtual scoped_ptr<Buffer> ReserveOutputBuffer( - const gfx::Size& dimensions, - VideoCapturePixelFormat format, - VideoPixelStorage storage) = 0; - - // Captured new video data, held in |frame| or |buffer|, respectively for - // OnIncomingCapturedVideoFrame() and OnIncomingCapturedBuffer(). - // - // In both cases, as the frame is backed by a reservation returned by - // ReserveOutputBuffer(), delivery is guaranteed and will require no - // additional copies in the browser process. - virtual void OnIncomingCapturedBuffer( - scoped_ptr<Buffer> buffer, - const VideoCaptureFormat& frame_format, - const base::TimeTicks& timestamp) = 0; - virtual void OnIncomingCapturedVideoFrame( - scoped_ptr<Buffer> buffer, - const scoped_refptr<VideoFrame>& frame, - const base::TimeTicks& timestamp) = 0; - - // An error has occurred that cannot be handled and VideoCaptureDevice must - // be StopAndDeAllocate()-ed. |reason| is a text description of the error. - virtual void OnError(const std::string& reason) = 0; - - // VideoCaptureDevice requests the |message| to be logged. - virtual void OnLog(const std::string& message) {} - - // Returns the current buffer pool utilization, in the range 0.0 (no buffers - // are in use by producers or consumers) to 1.0 (all buffers are in use). - virtual double GetBufferPoolUtilization() const = 0; - }; - - virtual ~VideoCaptureDevice(); - - // Prepares the camera for use. After this function has been called no other - // applications can use the camera. StopAndDeAllocate() must be called before - // the object is deleted. - virtual void AllocateAndStart(const VideoCaptureParams& params, - scoped_ptr<Client> client) = 0; - - // Deallocates the camera, possibly asynchronously. - // - // This call requires the device to do the following things, eventually: put - // camera hardware into a state where other applications could use it, free - // the memory associated with capture, and delete the |client| pointer passed - // into AllocateAndStart. - // - // If deallocation is done asynchronously, then the device implementation must - // ensure that a subsequent AllocateAndStart() operation targeting the same ID - // would be sequenced through the same task runner, so that deallocation - // happens first. - virtual void StopAndDeAllocate() = 0; - - // Gets the power line frequency from the current system time zone if this is - // defined, otherwise returns 0. - int GetPowerLineFrequencyForLocation() const; - - protected: - static const int kPowerLine50Hz = 50; - static const int kPowerLine60Hz = 60; -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_H_ diff --git a/media/video/capture/video_capture_device_factory.cc b/media/video/capture/video_capture_device_factory.cc deleted file mode 100644 index c87c39a..0000000 --- a/media/video/capture/video_capture_device_factory.cc +++ /dev/null @@ -1,63 +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/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" - -namespace media { - -// static -scoped_ptr<VideoCaptureDeviceFactory> VideoCaptureDeviceFactory::CreateFactory( - 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 scoped_ptr<VideoCaptureDeviceFactory>(new - media::FileVideoCaptureDeviceFactory()); - } else { - return scoped_ptr<VideoCaptureDeviceFactory>(new - media::FakeVideoCaptureDeviceFactory()); - } - } else { - // |ui_task_runner| is needed for the Linux ChromeOS factory to retrieve - // screen rotations and for the Mac factory to run QTKit device enumeration. - return scoped_ptr<VideoCaptureDeviceFactory>( - CreateVideoCaptureDeviceFactory(ui_task_runner)); - } -} - -VideoCaptureDeviceFactory::VideoCaptureDeviceFactory() { - thread_checker_.DetachFromThread(); -} - -VideoCaptureDeviceFactory::~VideoCaptureDeviceFactory() {} - -void VideoCaptureDeviceFactory::EnumerateDeviceNames(const base::Callback< - void(scoped_ptr<media::VideoCaptureDevice::Names>)>& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!callback.is_null()); - scoped_ptr<VideoCaptureDevice::Names> device_names( - new VideoCaptureDevice::Names()); - GetDeviceNames(device_names.get()); - callback.Run(device_names.Pass()); -} - -#if !defined(OS_MACOSX) && !defined(OS_LINUX) && !defined(OS_ANDROID) && !defined(OS_WIN) -// static -VideoCaptureDeviceFactory* -VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { - NOTIMPLEMENTED(); - return NULL; -} -#endif - -} // namespace media diff --git a/media/video/capture/video_capture_device_factory.h b/media/video/capture/video_capture_device_factory.h deleted file mode 100644 index 224cdba..0000000 --- a/media/video/capture/video_capture_device_factory.h +++ /dev/null @@ -1,57 +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_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_FACTORY_H_ -#define MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_FACTORY_H_ - -#include "base/threading/thread_checker.h" -#include "media/video/capture/video_capture_device.h" - -namespace media { - -// VideoCaptureDeviceFactory is the base class for creation of video capture -// devices in the different platforms. VCDFs are created by MediaStreamManager -// on IO thread and plugged into VideoCaptureManager, who owns and operates them -// in Device Thread (a.k.a. Audio Thread). -class MEDIA_EXPORT VideoCaptureDeviceFactory { - public: - static scoped_ptr<VideoCaptureDeviceFactory> CreateFactory( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); - - VideoCaptureDeviceFactory(); - virtual ~VideoCaptureDeviceFactory(); - - // Creates a VideoCaptureDevice object. Returns NULL if something goes wrong. - virtual scoped_ptr<VideoCaptureDevice> Create( - const VideoCaptureDevice::Name& device_name) = 0; - - // Asynchronous version of GetDeviceNames calling back to |callback|. - virtual void EnumerateDeviceNames(const base::Callback< - void(scoped_ptr<media::VideoCaptureDevice::Names>)>& callback); - - // Gets the supported formats of a particular device attached to the system. - // This method should be called before allocating or starting a device. In - // case format enumeration is not supported, or there was a problem, the - // formats array will be empty. - virtual void GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) = 0; - - protected: - // Gets the names of all video capture devices connected to this computer. - // Used by the default implementation of EnumerateDeviceNames(). - virtual void GetDeviceNames(VideoCaptureDevice::Names* device_names) = 0; - - base::ThreadChecker thread_checker_; - - private: - static VideoCaptureDeviceFactory* CreateVideoCaptureDeviceFactory( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); - - DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactory); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_FACTORY_H_ diff --git a/media/video/capture/video_capture_device_info.cc b/media/video/capture/video_capture_device_info.cc deleted file mode 100644 index 79becf3..0000000 --- a/media/video/capture/video_capture_device_info.cc +++ /dev/null @@ -1,19 +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/video_capture_device_info.h" - -namespace media { - -VideoCaptureDeviceInfo::VideoCaptureDeviceInfo() {} - -VideoCaptureDeviceInfo::VideoCaptureDeviceInfo( - const VideoCaptureDevice::Name& name, - const VideoCaptureFormats& supported_formats) - : name(name), - supported_formats(supported_formats) {} - -VideoCaptureDeviceInfo::~VideoCaptureDeviceInfo() {} - -} // namespace media diff --git a/media/video/capture/video_capture_device_info.h b/media/video/capture/video_capture_device_info.h deleted file mode 100644 index d215cf5..0000000 --- a/media/video/capture/video_capture_device_info.h +++ /dev/null @@ -1,28 +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_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_INFO_H_ -#define MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_INFO_H_ - -#include "media/base/video_capture_types.h" -#include "media/video/capture/video_capture_device.h" - -namespace media { - -// A convenience wrap of a device's name and associated supported formats. -struct MEDIA_EXPORT VideoCaptureDeviceInfo { - VideoCaptureDeviceInfo(); - VideoCaptureDeviceInfo(const VideoCaptureDevice::Name& name, - const VideoCaptureFormats& supported_formats); - ~VideoCaptureDeviceInfo(); - - VideoCaptureDevice::Name name; - VideoCaptureFormats supported_formats; -}; - -typedef std::vector<VideoCaptureDeviceInfo> VideoCaptureDeviceInfos; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_INFO_H_ diff --git a/media/video/capture/video_capture_device_unittest.cc b/media/video/capture/video_capture_device_unittest.cc deleted file mode 100644 index a6b8e18..0000000 --- a/media/video/capture/video_capture_device_unittest.cc +++ /dev/null @@ -1,489 +0,0 @@ -// Copyright (c) 2012 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/bind_helpers.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/test/test_timeouts.h" -#include "base/thread_task_runner_handle.h" -#include "base/threading/thread.h" -#include "media/base/video_capture_types.h" -#include "media/video/capture/video_capture_device.h" -#include "media/video/capture/video_capture_device_factory.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_WIN) -#include "base/win/scoped_com_initializer.h" -#include "media/video/capture/win/video_capture_device_factory_win.h" -#endif - -#if defined(OS_MACOSX) -#include "media/base/mac/avfoundation_glue.h" -#include "media/video/capture/mac/video_capture_device_factory_mac.h" -#endif - -#if defined(OS_ANDROID) -#include "base/android/jni_android.h" -#include "media/video/capture/android/video_capture_device_android.h" -#endif - -#if defined(OS_MACOSX) -// Mac/QTKit will always give you the size you ask for and this case will fail. -#define MAYBE_AllocateBadSize DISABLED_AllocateBadSize -// We will always get YUYV from the Mac QTKit/AVFoundation implementations. -#define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg -#elif defined(OS_WIN) -#define MAYBE_AllocateBadSize AllocateBadSize -#define MAYBE_CaptureMjpeg CaptureMjpeg -#elif defined(OS_ANDROID) -// TODO(wjia): enable those tests on Android. -// On Android, native camera (JAVA) delivers frames on UI thread which is the -// main thread for tests. This results in no frame received by -// VideoCaptureAndroid. -#define MAYBE_AllocateBadSize DISABLED_AllocateBadSize -#define ReAllocateCamera DISABLED_ReAllocateCamera -#define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning -#define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning -#define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg -#else -#define MAYBE_AllocateBadSize AllocateBadSize -#define MAYBE_CaptureMjpeg CaptureMjpeg -#endif - -using ::testing::_; -using ::testing::SaveArg; - -namespace media { -namespace { - -static const gfx::Size kCaptureSizes[] = { - gfx::Size(640, 480), - gfx::Size(1280, 720) -}; - -class MockClient : public VideoCaptureDevice::Client { - public: - MOCK_METHOD9(OnIncomingCapturedYuvData, - void(const uint8* y_data, - const uint8* u_data, - const uint8* v_data, - size_t y_stride, - size_t u_stride, - size_t v_stride, - const VideoCaptureFormat& frame_format, - int clockwise_rotation, - const base::TimeTicks& timestamp)); - MOCK_METHOD0(DoReserveOutputBuffer, void(void)); - MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void)); - MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void)); - MOCK_METHOD1(OnError, void(const std::string& reason)); - MOCK_CONST_METHOD0(GetBufferPoolUtilization, double(void)); - - explicit MockClient(base::Callback<void(const VideoCaptureFormat&)> frame_cb) - : main_thread_(base::ThreadTaskRunnerHandle::Get()), - frame_cb_(frame_cb) {} - - void OnIncomingCapturedData(const uint8* data, - int length, - const VideoCaptureFormat& format, - int rotation, - const base::TimeTicks& timestamp) override { - ASSERT_GT(length, 0); - ASSERT_TRUE(data != NULL); - main_thread_->PostTask(FROM_HERE, base::Bind(frame_cb_, format)); - } - - // Trampoline methods to workaround GMOCK problems with scoped_ptr<>. - scoped_ptr<Buffer> ReserveOutputBuffer( - const gfx::Size& dimensions, - media::VideoCapturePixelFormat format, - media::VideoPixelStorage storage) override { - DoReserveOutputBuffer(); - NOTREACHED() << "This should never be called"; - return scoped_ptr<Buffer>(); - } - void OnIncomingCapturedBuffer(scoped_ptr<Buffer> buffer, - const VideoCaptureFormat& frame_format, - const base::TimeTicks& timestamp) override { - DoOnIncomingCapturedBuffer(); - } - void OnIncomingCapturedVideoFrame(scoped_ptr<Buffer> buffer, - const scoped_refptr<VideoFrame>& frame, - const base::TimeTicks& timestamp) override { - DoOnIncomingCapturedVideoFrame(); - } - - private: - scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - base::Callback<void(const VideoCaptureFormat&)> frame_cb_; -}; - -class DeviceEnumerationListener : - public base::RefCounted<DeviceEnumerationListener> { - public: - MOCK_METHOD1(OnEnumeratedDevicesCallbackPtr, - void(VideoCaptureDevice::Names* names)); - // GMock doesn't support move-only arguments, so we use this forward method. - void OnEnumeratedDevicesCallback( - scoped_ptr<VideoCaptureDevice::Names> names) { - OnEnumeratedDevicesCallbackPtr(names.release()); - } - private: - friend class base::RefCounted<DeviceEnumerationListener>; - virtual ~DeviceEnumerationListener() {} -}; - -} // namespace - -class VideoCaptureDeviceTest : - public testing::TestWithParam<gfx::Size> { - protected: - typedef VideoCaptureDevice::Client Client; - - VideoCaptureDeviceTest() - : loop_(new base::MessageLoop()), - client_( - new MockClient(base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured, - base::Unretained(this)))), - video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory( - base::ThreadTaskRunnerHandle::Get())) { - device_enumeration_listener_ = new DeviceEnumerationListener(); - } - - void SetUp() override { -#if defined(OS_ANDROID) - VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice( - base::android::AttachCurrentThread()); -#endif -#if defined(OS_MACOSX) - AVFoundationGlue::InitializeAVFoundation(); -#endif - EXPECT_CALL(*client_, OnIncomingCapturedYuvData(_,_,_,_,_,_,_,_,_)) - .Times(0); - EXPECT_CALL(*client_, DoReserveOutputBuffer()).Times(0); - EXPECT_CALL(*client_, DoOnIncomingCapturedBuffer()).Times(0); - EXPECT_CALL(*client_, DoOnIncomingCapturedVideoFrame()).Times(0); - } - - void ResetWithNewClient() { - client_.reset(new MockClient(base::Bind( - &VideoCaptureDeviceTest::OnFrameCaptured, base::Unretained(this)))); - } - - void OnFrameCaptured(const VideoCaptureFormat& format) { - last_format_ = format; - run_loop_->QuitClosure().Run(); - } - - void WaitForCapturedFrame() { - run_loop_.reset(new base::RunLoop()); - run_loop_->Run(); - } - - scoped_ptr<VideoCaptureDevice::Names> EnumerateDevices() { - VideoCaptureDevice::Names* names; - EXPECT_CALL(*device_enumeration_listener_.get(), - OnEnumeratedDevicesCallbackPtr(_)).WillOnce(SaveArg<0>(&names)); - - video_capture_device_factory_->EnumerateDeviceNames( - base::Bind(&DeviceEnumerationListener::OnEnumeratedDevicesCallback, - device_enumeration_listener_)); - base::MessageLoop::current()->RunUntilIdle(); - return scoped_ptr<VideoCaptureDevice::Names>(names); - } - - const VideoCaptureFormat& last_format() const { return last_format_; } - - scoped_ptr<VideoCaptureDevice::Name> GetFirstDeviceNameSupportingPixelFormat( - const VideoCapturePixelFormat& pixel_format) { - names_ = EnumerateDevices(); - if (names_->empty()) { - DVLOG(1) << "No camera available."; - return scoped_ptr<VideoCaptureDevice::Name>(); - } - for (const auto& names_iterator : *names_) { - VideoCaptureFormats supported_formats; - video_capture_device_factory_->GetDeviceSupportedFormats( - names_iterator, - &supported_formats); - for (const auto& formats_iterator : supported_formats) { - if (formats_iterator.pixel_format == pixel_format) { - return scoped_ptr<VideoCaptureDevice::Name>( - new VideoCaptureDevice::Name(names_iterator)); - } - } - } - DVLOG_IF(1, pixel_format != VIDEO_CAPTURE_PIXEL_FORMAT_MAX) - << "No camera can capture the" - << " format: " << VideoCaptureFormat::PixelFormatToString(pixel_format); - return scoped_ptr<VideoCaptureDevice::Name>(); - } - - bool IsCaptureSizeSupported(const VideoCaptureDevice::Name& device, - const gfx::Size& size) { - VideoCaptureFormats supported_formats; - video_capture_device_factory_->GetDeviceSupportedFormats( - device, &supported_formats); - const auto it = - std::find_if(supported_formats.begin(), supported_formats.end(), - [&size](VideoCaptureFormat const& f) { - return f.frame_size == size; - }); - if (it == supported_formats.end()) { - DVLOG(1) << "Size " << size.ToString() << " is not supported."; - return false; - } - return true; - } - -#if defined(OS_WIN) - base::win::ScopedCOMInitializer initialize_com_; -#endif - scoped_ptr<VideoCaptureDevice::Names> names_; - scoped_ptr<base::MessageLoop> loop_; - scoped_ptr<base::RunLoop> run_loop_; - scoped_ptr<MockClient> client_; - scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_; - VideoCaptureFormat last_format_; - scoped_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_; -}; - -// Cause hangs on Windows Debug. http://crbug.com/417824 -#if defined(OS_WIN) && !defined(NDEBUG) -#define MAYBE_OpenInvalidDevice DISABLED_OpenInvalidDevice -#else -#define MAYBE_OpenInvalidDevice OpenInvalidDevice -#endif - -TEST_F(VideoCaptureDeviceTest, MAYBE_OpenInvalidDevice) { -#if defined(OS_WIN) - VideoCaptureDevice::Name::CaptureApiType api_type = - VideoCaptureDeviceFactoryWin::PlatformSupportsMediaFoundation() - ? 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", - VideoCaptureDeviceFactoryMac::PlatformSupportsAVFoundation() - ? VideoCaptureDevice::Name::AVFOUNDATION - : VideoCaptureDevice::Name::QTKIT); -#else - VideoCaptureDevice::Name device_name("jibberish", "jibberish"); -#endif - scoped_ptr<VideoCaptureDevice> device = - video_capture_device_factory_->Create(device_name); -#if !defined(OS_MACOSX) - EXPECT_TRUE(device == NULL); -#else - if (VideoCaptureDeviceFactoryMac::PlatformSupportsAVFoundation()) { - EXPECT_TRUE(device == NULL); - } else { - // The presence of the actual device is only checked on AllocateAndStart() - // and not on creation for QTKit API in Mac OS X platform. - EXPECT_CALL(*client_, OnError(_)).Times(1); - - 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 = - VIDEO_CAPTURE_PIXEL_FORMAT_I420; - device->AllocateAndStart(capture_params, client_.Pass()); - device->StopAndDeAllocate(); - } -#endif -} - -TEST_P(VideoCaptureDeviceTest, CaptureWithSize) { - names_ = EnumerateDevices(); - if (names_->empty()) { - DVLOG(1) << "No camera available. Exiting test."; - return; - } - - const gfx::Size& size = GetParam(); - if (!IsCaptureSizeSupported(names_->front(), size)) - return; - const int width = size.width(); - const int height = size.height(); - - scoped_ptr<VideoCaptureDevice> device( - video_capture_device_factory_->Create(names_->front())); - ASSERT_TRUE(device); - DVLOG(1) << names_->front().id(); - - EXPECT_CALL(*client_, OnError(_)).Times(0); - - VideoCaptureParams capture_params; - capture_params.requested_format.frame_size.SetSize(width, height); - capture_params.requested_format.frame_rate = 30.0f; - capture_params.requested_format.pixel_format = - VIDEO_CAPTURE_PIXEL_FORMAT_I420; - device->AllocateAndStart(capture_params, client_.Pass()); - // Get captured video frames. - WaitForCapturedFrame(); - EXPECT_EQ(last_format().frame_size.width(), width); - EXPECT_EQ(last_format().frame_size.height(), height); - if (last_format().pixel_format != VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG) - EXPECT_EQ(size.GetArea(), last_format().frame_size.GetArea()); - device->StopAndDeAllocate(); -} - -#if !defined(OS_ANDROID) -INSTANTIATE_TEST_CASE_P(MAYBE_VideoCaptureDeviceTests, - VideoCaptureDeviceTest, - testing::ValuesIn(kCaptureSizes)); -#endif - -TEST_F(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) { - names_ = EnumerateDevices(); - if (names_->empty()) { - DVLOG(1) << "No camera available. Exiting test."; - return; - } - scoped_ptr<VideoCaptureDevice> device( - video_capture_device_factory_->Create(names_->front())); - ASSERT_TRUE(device); - - EXPECT_CALL(*client_, OnError(_)).Times(0); - - const gfx::Size input_size(640, 480); - VideoCaptureParams capture_params; - capture_params.requested_format.frame_size.SetSize(637, 472); - capture_params.requested_format.frame_rate = 35; - capture_params.requested_format.pixel_format = - VIDEO_CAPTURE_PIXEL_FORMAT_I420; - device->AllocateAndStart(capture_params, client_.Pass()); - WaitForCapturedFrame(); - device->StopAndDeAllocate(); - EXPECT_EQ(last_format().frame_size.width(), input_size.width()); - EXPECT_EQ(last_format().frame_size.height(), input_size.height()); - if (last_format().pixel_format != VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG) - EXPECT_EQ(input_size.GetArea(), last_format().frame_size.GetArea()); -} - -// Cause hangs on Windows Debug. http://crbug.com/417824 -#if defined(OS_WIN) && !defined(NDEBUG) -#define MAYBE_ReAllocateCamera DISABLED_ReAllocateCamera -#else -#define MAYBE_ReAllocateCamera ReAllocateCamera -#endif - -TEST_F(VideoCaptureDeviceTest, MAYBE_ReAllocateCamera) { - names_ = EnumerateDevices(); - if (names_->empty()) { - DVLOG(1) << "No camera available. Exiting test."; - return; - } - - // First, do a number of very fast device start/stops. - for (int i = 0; i <= 5; i++) { - ResetWithNewClient(); - scoped_ptr<VideoCaptureDevice> device( - video_capture_device_factory_->Create(names_->front())); - gfx::Size resolution; - if (i % 2) { - resolution = gfx::Size(640, 480); - } else { - resolution = gfx::Size(1280, 1024); - } - VideoCaptureParams capture_params; - capture_params.requested_format.frame_size = resolution; - capture_params.requested_format.frame_rate = 30; - capture_params.requested_format.pixel_format = - VIDEO_CAPTURE_PIXEL_FORMAT_I420; - device->AllocateAndStart(capture_params, client_.Pass()); - device->StopAndDeAllocate(); - } - - // Finally, do a device start and wait for it to finish. - VideoCaptureParams capture_params; - capture_params.requested_format.frame_size.SetSize(320, 240); - capture_params.requested_format.frame_rate = 30; - capture_params.requested_format.pixel_format = - VIDEO_CAPTURE_PIXEL_FORMAT_I420; - - ResetWithNewClient(); - scoped_ptr<VideoCaptureDevice> device( - video_capture_device_factory_->Create(names_->front())); - - device->AllocateAndStart(capture_params, client_.Pass()); - WaitForCapturedFrame(); - device->StopAndDeAllocate(); - device.reset(); - EXPECT_EQ(last_format().frame_size.width(), 320); - EXPECT_EQ(last_format().frame_size.height(), 240); -} - -TEST_F(VideoCaptureDeviceTest, DeAllocateCameraWhileRunning) { - names_ = EnumerateDevices(); - if (names_->empty()) { - DVLOG(1) << "No camera available. Exiting test."; - return; - } - scoped_ptr<VideoCaptureDevice> device( - video_capture_device_factory_->Create(names_->front())); - ASSERT_TRUE(device); - - EXPECT_CALL(*client_, OnError(_)).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 = - VIDEO_CAPTURE_PIXEL_FORMAT_I420; - device->AllocateAndStart(capture_params, client_.Pass()); - // Get captured video frames. - 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 = - GetFirstDeviceNameSupportingPixelFormat(VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG); - if (!name) { - DVLOG(1) << "No camera supports MJPEG format. Exiting test."; - return; - } - scoped_ptr<VideoCaptureDevice> device( - video_capture_device_factory_->Create(*name)); - ASSERT_TRUE(device); - - EXPECT_CALL(*client_, OnError(_)).Times(0); - - VideoCaptureParams capture_params; - capture_params.requested_format.frame_size.SetSize(1280, 720); - capture_params.requested_format.frame_rate = 30; - capture_params.requested_format.pixel_format = - VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG; - device->AllocateAndStart(capture_params, client_.Pass()); - // Get captured video frames. - WaitForCapturedFrame(); - // Verify we get MJPEG from the device. Not all devices can capture 1280x720 - // @ 30 fps, so we don't care about the exact resolution we get. - EXPECT_EQ(last_format().pixel_format, VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG); - EXPECT_GE(static_cast<size_t>(1280 * 720), - last_format().ImageAllocationSize()); - device->StopAndDeAllocate(); -} - -TEST_F(VideoCaptureDeviceTest, GetDeviceSupportedFormats) { - // Use VIDEO_CAPTURE_PIXEL_FORMAT_MAX to iterate all device names for testing - // GetDeviceSupportedFormats(). - scoped_ptr<VideoCaptureDevice::Name> name = - GetFirstDeviceNameSupportingPixelFormat(VIDEO_CAPTURE_PIXEL_FORMAT_MAX); - // Verify no camera returned for VIDEO_CAPTURE_PIXEL_FORMAT_MAX. Nothing else - // to test here - // since we cannot forecast the hardware capabilities. - ASSERT_FALSE(name); -} - -}; // namespace media diff --git a/media/video/capture/win/capability_list_win.cc b/media/video/capture/win/capability_list_win.cc deleted file mode 100644 index 2de2786..0000000 --- a/media/video/capture/win/capability_list_win.cc +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2012 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/win/capability_list_win.h" - -#include <algorithm> -#include <functional> - -#include "base/logging.h" - -namespace media { - -static bool CompareCapability(const VideoCaptureFormat& requested, - const CapabilityWin& capability_lhs, - const CapabilityWin& capability_rhs) { - const VideoCaptureFormat& lhs = capability_lhs.supported_format; - const VideoCaptureFormat& rhs = capability_rhs.supported_format; - - const int diff_height_lhs = - std::abs(lhs.frame_size.height() - requested.frame_size.height()); - const int diff_height_rhs = - std::abs(rhs.frame_size.height() - requested.frame_size.height()); - if (diff_height_lhs != diff_height_rhs) - return diff_height_lhs < diff_height_rhs; - - const int diff_width_lhs = - std::abs(lhs.frame_size.width() - requested.frame_size.width()); - const int diff_width_rhs = - std::abs(rhs.frame_size.width() - requested.frame_size.width()); - if (diff_width_lhs != diff_width_rhs) - return diff_width_lhs < diff_width_rhs; - - const float diff_fps_lhs = std::fabs(lhs.frame_rate - requested.frame_rate); - const float diff_fps_rhs = std::fabs(rhs.frame_rate - requested.frame_rate); - if (diff_fps_lhs != diff_fps_rhs) - return diff_fps_lhs < diff_fps_rhs; - - return lhs.pixel_format < rhs.pixel_format; -} - -const CapabilityWin& GetBestMatchedCapability( - const VideoCaptureFormat& requested, - const CapabilityList& capabilities) { - DCHECK(!capabilities.empty()); - const CapabilityWin* best_match = &(*capabilities.begin()); - for (const CapabilityWin& capability : capabilities) { - if (CompareCapability(requested, capability, *best_match)) - best_match = &capability; - } - return *best_match; -} - -} // namespace media diff --git a/media/video/capture/win/capability_list_win.h b/media/video/capture/win/capability_list_win.h deleted file mode 100644 index dc74947..0000000 --- a/media/video/capture/win/capability_list_win.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2012 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. - -// Windows specific implementation of VideoCaptureDevice. -// DirectShow is used for capturing. DirectShow provide its own threads -// for capturing. - -#ifndef MEDIA_VIDEO_CAPTURE_WIN_CAPABILITY_LIST_WIN_H_ -#define MEDIA_VIDEO_CAPTURE_WIN_CAPABILITY_LIST_WIN_H_ - -#include <list> -#include <windows.h> - -#include "media/base/video_capture_types.h" - -namespace media { - -struct CapabilityWin { - CapabilityWin(int index, const VideoCaptureFormat& format) - : stream_index(index), supported_format(format), info_header() {} - - // Used by VideoCaptureDeviceWin. - CapabilityWin(int index, const VideoCaptureFormat& format, - const BITMAPINFOHEADER& info_header) - : stream_index(index), - supported_format(format), - info_header(info_header) { - } - - const int stream_index; - const VideoCaptureFormat supported_format; - - // |info_header| is only valid if DirectShow is used. - const BITMAPINFOHEADER info_header; -}; - -typedef std::list<CapabilityWin> CapabilityList; - -const CapabilityWin& GetBestMatchedCapability( - const VideoCaptureFormat& requested, - const CapabilityList& capabilities); - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_WIN_CAPABILITY_LIST_WIN_H_ diff --git a/media/video/capture/win/filter_base_win.cc b/media/video/capture/win/filter_base_win.cc deleted file mode 100644 index d371f8b..0000000 --- a/media/video/capture/win/filter_base_win.cc +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2011 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/win/filter_base_win.h" - -#pragma comment(lib, "strmiids.lib") - -namespace media { - -// Implement IEnumPins. -class PinEnumerator final - : public IEnumPins, - public base::RefCounted<PinEnumerator> { - public: - explicit PinEnumerator(FilterBase* filter) - : filter_(filter), - index_(0) { - } - - // IUnknown implementation. - STDMETHOD(QueryInterface)(REFIID iid, void** object_ptr) override { - if (iid == IID_IEnumPins || iid == IID_IUnknown) { - AddRef(); - *object_ptr = static_cast<IEnumPins*>(this); - return S_OK; - } - return E_NOINTERFACE; - } - - STDMETHOD_(ULONG, AddRef)() override { - base::RefCounted<PinEnumerator>::AddRef(); - return 1; - } - - STDMETHOD_(ULONG, Release)() override { - base::RefCounted<PinEnumerator>::Release(); - return 1; - } - - // Implement IEnumPins. - STDMETHOD(Next)(ULONG count, IPin** pins, ULONG* fetched) override { - ULONG pins_fetched = 0; - while (pins_fetched < count && filter_->NoOfPins() > index_) { - IPin* pin = filter_->GetPin(index_++); - pin->AddRef(); - pins[pins_fetched++] = pin; - } - - if (fetched) - *fetched = pins_fetched; - - return pins_fetched == count ? S_OK : S_FALSE; - } - - STDMETHOD(Skip)(ULONG count) override { - if (filter_->NoOfPins()- index_ > count) { - index_ += count; - return S_OK; - } - index_ = 0; - return S_FALSE; - } - - STDMETHOD(Reset)() override { - index_ = 0; - return S_OK; - } - - STDMETHOD(Clone)(IEnumPins** clone) override { - PinEnumerator* pin_enum = new PinEnumerator(filter_.get()); - pin_enum->AddRef(); - pin_enum->index_ = index_; - *clone = pin_enum; - return S_OK; - } - - private: - friend class base::RefCounted<PinEnumerator>; - ~PinEnumerator() {} - - scoped_refptr<FilterBase> filter_; - size_t index_; -}; - -FilterBase::FilterBase() : state_(State_Stopped) { -} - -STDMETHODIMP FilterBase::EnumPins(IEnumPins** enum_pins) { - *enum_pins = new PinEnumerator(this); - (*enum_pins)->AddRef(); - return S_OK; -} - -STDMETHODIMP FilterBase::FindPin(LPCWSTR id, IPin** pin) { - return E_NOTIMPL; -} - -STDMETHODIMP FilterBase::QueryFilterInfo(FILTER_INFO* info) { - info->pGraph = owning_graph_.get(); - info->achName[0] = L'\0'; - if (info->pGraph) - info->pGraph->AddRef(); - return S_OK; -} - -STDMETHODIMP FilterBase::JoinFilterGraph(IFilterGraph* graph, LPCWSTR name) { - owning_graph_ = graph; - return S_OK; -} - -STDMETHODIMP FilterBase::QueryVendorInfo(LPWSTR *pVendorInfo) { - return S_OK; -} - -// Implement IMediaFilter. -STDMETHODIMP FilterBase::Stop() { - state_ = State_Stopped; - return S_OK; -} - -STDMETHODIMP FilterBase::Pause() { - state_ = State_Paused; - return S_OK; -} - -STDMETHODIMP FilterBase::Run(REFERENCE_TIME start) { - state_ = State_Running; - return S_OK; -} - -STDMETHODIMP FilterBase::GetState(DWORD msec_timeout, FILTER_STATE* state) { - *state = state_; - return S_OK; -} - -STDMETHODIMP FilterBase::SetSyncSource(IReferenceClock* clock) { - return S_OK; -} - -STDMETHODIMP FilterBase::GetSyncSource(IReferenceClock** clock) { - return E_NOTIMPL; -} - -// Implement from IPersistent. -STDMETHODIMP FilterBase::GetClassID(CLSID* class_id) { - NOTREACHED(); - return E_NOTIMPL; -} - -// Implement IUnknown. -STDMETHODIMP FilterBase::QueryInterface(REFIID id, void** object_ptr) { - if (id == IID_IMediaFilter || id == IID_IUnknown) { - *object_ptr = static_cast<IMediaFilter*>(this); - } else if (id == IID_IPersist) { - *object_ptr = static_cast<IPersist*>(this); - } else { - return E_NOINTERFACE; - } - AddRef(); - return S_OK; -} - -ULONG STDMETHODCALLTYPE FilterBase::AddRef() { - base::RefCounted<FilterBase>::AddRef(); - return 1; -} - -ULONG STDMETHODCALLTYPE FilterBase::Release() { - base::RefCounted<FilterBase>::Release(); - return 1; -} - -FilterBase::~FilterBase() { -} - -} // namespace media diff --git a/media/video/capture/win/filter_base_win.h b/media/video/capture/win/filter_base_win.h deleted file mode 100644 index 25876ed..0000000 --- a/media/video/capture/win/filter_base_win.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2012 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. - -// Implement a simple base class for DirectShow filters. It may only be used in -// a single threaded apartment. - -#ifndef MEDIA_VIDEO_CAPTURE_WIN_FILTER_BASE_WIN_H_ -#define MEDIA_VIDEO_CAPTURE_WIN_FILTER_BASE_WIN_H_ - -// Avoid including strsafe.h via dshow as it will cause build warnings. -#define NO_DSHOW_STRSAFE -#include <dshow.h> - -#include "base/memory/ref_counted.h" -#include "base/win/scoped_comptr.h" - -namespace media { - -class FilterBase - : public IBaseFilter, - public base::RefCounted<FilterBase> { - public: - FilterBase(); - - // Number of pins connected to this filter. - virtual size_t NoOfPins() = 0; - // Returns the IPin interface pin no index. - virtual IPin* GetPin(int index) = 0; - - // Inherited from IUnknown. - STDMETHOD(QueryInterface)(REFIID id, void** object_ptr) override; - STDMETHOD_(ULONG, AddRef)() override; - STDMETHOD_(ULONG, Release)() override; - - // Inherited from IBaseFilter. - STDMETHOD(EnumPins)(IEnumPins** enum_pins) override; - - STDMETHOD(FindPin)(LPCWSTR id, IPin** pin) override; - - STDMETHOD(QueryFilterInfo)(FILTER_INFO* info) override; - - STDMETHOD(JoinFilterGraph)(IFilterGraph* graph, LPCWSTR name) override; - - STDMETHOD(QueryVendorInfo)(LPWSTR* vendor_info) override; - - // Inherited from IMediaFilter. - STDMETHOD(Stop)() override; - - STDMETHOD(Pause)() override; - - STDMETHOD(Run)(REFERENCE_TIME start) override; - - STDMETHOD(GetState)(DWORD msec_timeout, FILTER_STATE* state) override; - - STDMETHOD(SetSyncSource)(IReferenceClock* clock) override; - - STDMETHOD(GetSyncSource)(IReferenceClock** clock) override; - - // Inherited from IPersistent. - STDMETHOD(GetClassID)(CLSID* class_id) override = 0; - - protected: - friend class base::RefCounted<FilterBase>; - virtual ~FilterBase(); - - private: - FILTER_STATE state_; - base::win::ScopedComPtr<IFilterGraph> owning_graph_; - - DISALLOW_COPY_AND_ASSIGN(FilterBase); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_WIN_FILTER_BASE_WIN_H_ diff --git a/media/video/capture/win/pin_base_win.cc b/media/video/capture/win/pin_base_win.cc deleted file mode 100644 index 7340725..0000000 --- a/media/video/capture/win/pin_base_win.cc +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright (c) 2012 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/win/pin_base_win.h" - -#include "base/logging.h" - -namespace media { - -// Implement IEnumPins. -class TypeEnumerator final - : public IEnumMediaTypes, - public base::RefCounted<TypeEnumerator> { - public: - explicit TypeEnumerator(PinBase* pin) - : pin_(pin), - index_(0) { - } - - // Implement from IUnknown. - STDMETHOD(QueryInterface)(REFIID iid, void** object_ptr) override { - if (iid == IID_IEnumMediaTypes || iid == IID_IUnknown) { - AddRef(); - *object_ptr = static_cast<IEnumMediaTypes*>(this); - return S_OK; - } - return E_NOINTERFACE; - } - - STDMETHOD_(ULONG, AddRef)() override { - base::RefCounted<TypeEnumerator>::AddRef(); - return 1; - } - - STDMETHOD_(ULONG, Release)() override { - base::RefCounted<TypeEnumerator>::Release(); - return 1; - } - - // Implement IEnumMediaTypes. - STDMETHOD(Next)(ULONG count, AM_MEDIA_TYPE** types, ULONG* fetched) override { - ULONG types_fetched = 0; - - while (types_fetched < count) { - // Allocate AM_MEDIA_TYPE that we will store the media type in. - AM_MEDIA_TYPE* type = reinterpret_cast<AM_MEDIA_TYPE*>(CoTaskMemAlloc( - sizeof(AM_MEDIA_TYPE))); - if (!type) { - FreeAllocatedMediaTypes(types_fetched, types); - return E_OUTOFMEMORY; - } - ZeroMemory(type, sizeof(AM_MEDIA_TYPE)); - - // Allocate a VIDEOINFOHEADER and connect it to the AM_MEDIA_TYPE. - type->cbFormat = sizeof(VIDEOINFOHEADER); - BYTE *format = reinterpret_cast<BYTE*>(CoTaskMemAlloc( - sizeof(VIDEOINFOHEADER))); - if (!format) { - CoTaskMemFree(type); - FreeAllocatedMediaTypes(types_fetched, types); - return E_OUTOFMEMORY; - } - type->pbFormat = format; - // Get the media type from the pin. - if (pin_->GetValidMediaType(index_++, type)) { - types[types_fetched++] = type; - } else { - CoTaskMemFree(format); - CoTaskMemFree(type); - break; - } - } - - if (fetched) - *fetched = types_fetched; - - return types_fetched == count ? S_OK : S_FALSE; - } - - STDMETHOD(Skip)(ULONG count) override { - index_ += count; - return S_OK; - } - - STDMETHOD(Reset)() override { - index_ = 0; - return S_OK; - } - - STDMETHOD(Clone)(IEnumMediaTypes** clone) override { - TypeEnumerator* type_enum = new TypeEnumerator(pin_.get()); - type_enum->AddRef(); - type_enum->index_ = index_; - *clone = type_enum; - return S_OK; - } - - private: - friend class base::RefCounted<TypeEnumerator>; - ~TypeEnumerator() {} - - void FreeAllocatedMediaTypes(ULONG allocated, AM_MEDIA_TYPE** types) { - for (ULONG i = 0; i < allocated; ++i) { - CoTaskMemFree(types[i]->pbFormat); - CoTaskMemFree(types[i]); - } - } - - scoped_refptr<PinBase> pin_; - int index_; -}; - -PinBase::PinBase(IBaseFilter* owner) - : owner_(owner) { - memset(¤t_media_type_, 0, sizeof(current_media_type_)); -} - -void PinBase::SetOwner(IBaseFilter* owner) { - owner_ = owner; -} - -// Called on an output pin to and establish a -// connection. -STDMETHODIMP PinBase::Connect(IPin* receive_pin, - const AM_MEDIA_TYPE* media_type) { - if (!receive_pin || !media_type) - return E_POINTER; - - current_media_type_ = *media_type; - receive_pin->AddRef(); - connected_pin_.Attach(receive_pin); - HRESULT hr = receive_pin->ReceiveConnection(this, media_type); - - return hr; -} - -// Called from an output pin on an input pin to and establish a -// connection. -STDMETHODIMP PinBase::ReceiveConnection(IPin* connector, - const AM_MEDIA_TYPE* media_type) { - if (!IsMediaTypeValid(media_type)) - return VFW_E_TYPE_NOT_ACCEPTED; - - current_media_type_ = *media_type; - connector->AddRef(); - connected_pin_.Attach(connector); - return S_OK; -} - -STDMETHODIMP PinBase::Disconnect() { - if (!connected_pin_.get()) - return S_FALSE; - - connected_pin_.Release(); - return S_OK; -} - -STDMETHODIMP PinBase::ConnectedTo(IPin** pin) { - *pin = connected_pin_.get(); - if (!connected_pin_.get()) - return VFW_E_NOT_CONNECTED; - - connected_pin_.get()->AddRef(); - return S_OK; -} - -STDMETHODIMP PinBase::ConnectionMediaType(AM_MEDIA_TYPE* media_type) { - if (!connected_pin_.get()) - return VFW_E_NOT_CONNECTED; - *media_type = current_media_type_; - return S_OK; -} - -STDMETHODIMP PinBase::QueryPinInfo(PIN_INFO* info) { - info->dir = PINDIR_INPUT; - info->pFilter = owner_; - if (owner_) - owner_->AddRef(); - info->achName[0] = L'\0'; - - return S_OK; -} - -STDMETHODIMP PinBase::QueryDirection(PIN_DIRECTION* pin_dir) { - *pin_dir = PINDIR_INPUT; - return S_OK; -} - -STDMETHODIMP PinBase::QueryId(LPWSTR* id) { - NOTREACHED(); - return E_OUTOFMEMORY; -} - -STDMETHODIMP PinBase::QueryAccept(const AM_MEDIA_TYPE* media_type) { - return S_FALSE; -} - -STDMETHODIMP PinBase::EnumMediaTypes(IEnumMediaTypes** types) { - *types = new TypeEnumerator(this); - (*types)->AddRef(); - return S_OK; -} - -STDMETHODIMP PinBase::QueryInternalConnections(IPin** pins, ULONG* no_pins) { - return E_NOTIMPL; -} - -STDMETHODIMP PinBase::EndOfStream() { - return S_OK; -} - -STDMETHODIMP PinBase::BeginFlush() { - return S_OK; -} - -STDMETHODIMP PinBase::EndFlush() { - return S_OK; -} - -STDMETHODIMP PinBase::NewSegment(REFERENCE_TIME start, - REFERENCE_TIME stop, - double rate) { - NOTREACHED(); - return E_NOTIMPL; -} - -// Inherited from IMemInputPin. -STDMETHODIMP PinBase::GetAllocator(IMemAllocator** allocator) { - return VFW_E_NO_ALLOCATOR; -} - -STDMETHODIMP PinBase::NotifyAllocator(IMemAllocator* allocator, - BOOL read_only) { - return S_OK; -} - -STDMETHODIMP PinBase::GetAllocatorRequirements( - ALLOCATOR_PROPERTIES* properties) { - return E_NOTIMPL; -} - -STDMETHODIMP PinBase::ReceiveMultiple(IMediaSample** samples, - long sample_count, - long* processed) { - DCHECK(samples); - - HRESULT hr = S_OK; - *processed = 0; - while (sample_count--) { - hr = Receive(samples[*processed]); - // S_FALSE means don't send any more. - if (hr != S_OK) - break; - ++(*processed); - } - return hr; -} - -STDMETHODIMP PinBase::ReceiveCanBlock() { - return S_FALSE; -} - -// Inherited from IUnknown. -STDMETHODIMP PinBase::QueryInterface(REFIID id, void** object_ptr) { - if (id == IID_IPin || id == IID_IUnknown) { - *object_ptr = static_cast<IPin*>(this); - } else if (id == IID_IMemInputPin) { - *object_ptr = static_cast<IMemInputPin*>(this); - } else { - return E_NOINTERFACE; - } - AddRef(); - return S_OK; -} - -STDMETHODIMP_(ULONG) PinBase::AddRef() { - base::RefCounted<PinBase>::AddRef(); - return 1; -} - -STDMETHODIMP_(ULONG) PinBase::Release() { - base::RefCounted<PinBase>::Release(); - return 1; -} - -PinBase::~PinBase() { -} - -} // namespace media diff --git a/media/video/capture/win/pin_base_win.h b/media/video/capture/win/pin_base_win.h deleted file mode 100644 index f531ec2..0000000 --- a/media/video/capture/win/pin_base_win.h +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2012 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. - -// Implement a simple base class for a DirectShow input pin. It may only be -// used in a single threaded apartment. - -#ifndef MEDIA_VIDEO_CAPTURE_WIN_PIN_BASE_WIN_H_ -#define MEDIA_VIDEO_CAPTURE_WIN_PIN_BASE_WIN_H_ - -// Avoid including strsafe.h via dshow as it will cause build warnings. -#define NO_DSHOW_STRSAFE -#include <dshow.h> - -#include "base/memory/ref_counted.h" -#include "base/win/scoped_comptr.h" - -namespace media { - -class PinBase - : public IPin, - public IMemInputPin, - public base::RefCounted<PinBase> { - public: - explicit PinBase(IBaseFilter* owner); - - // Function used for changing the owner. - // If the owner is deleted the owner should first call this function - // with owner = NULL. - void SetOwner(IBaseFilter* owner); - - // Checks if a media type is acceptable. This is called when this pin is - // connected to an output pin. Must return true if the media type is - // acceptable, false otherwise. - virtual bool IsMediaTypeValid(const AM_MEDIA_TYPE* media_type) = 0; - - // Enumerates valid media types. - virtual bool GetValidMediaType(int index, AM_MEDIA_TYPE* media_type) = 0; - - // Called when new media is received. Note that this is not on the same - // thread as where the pin is created. - STDMETHOD(Receive)(IMediaSample* sample) override = 0; - - STDMETHOD(Connect)(IPin* receive_pin, - const AM_MEDIA_TYPE* media_type) override; - - STDMETHOD(ReceiveConnection)(IPin* connector, - const AM_MEDIA_TYPE* media_type) override; - - STDMETHOD(Disconnect)() override; - - STDMETHOD(ConnectedTo)(IPin** pin) override; - - STDMETHOD(ConnectionMediaType)(AM_MEDIA_TYPE* media_type) override; - - STDMETHOD(QueryPinInfo)(PIN_INFO* info) override; - - STDMETHOD(QueryDirection)(PIN_DIRECTION* pin_dir) override; - - STDMETHOD(QueryId)(LPWSTR* id) override; - - STDMETHOD(QueryAccept)(const AM_MEDIA_TYPE* media_type) override; - - STDMETHOD(EnumMediaTypes)(IEnumMediaTypes** types) override; - - STDMETHOD(QueryInternalConnections)(IPin** pins, ULONG* no_pins) override; - - STDMETHOD(EndOfStream)() override; - - STDMETHOD(BeginFlush)() override; - - STDMETHOD(EndFlush)() override; - - STDMETHOD(NewSegment)(REFERENCE_TIME start, - REFERENCE_TIME stop, - double dRate) override; - - // Inherited from IMemInputPin. - STDMETHOD(GetAllocator)(IMemAllocator** allocator) override; - - STDMETHOD(NotifyAllocator)(IMemAllocator* allocator, BOOL read_only) override; - - STDMETHOD(GetAllocatorRequirements)( - ALLOCATOR_PROPERTIES* properties) override; - - STDMETHOD(ReceiveMultiple)(IMediaSample** samples, - long sample_count, - long* processed) override; - STDMETHOD(ReceiveCanBlock)() override; - - // Inherited from IUnknown. - STDMETHOD(QueryInterface)(REFIID id, void** object_ptr) override; - - STDMETHOD_(ULONG, AddRef)() override; - - STDMETHOD_(ULONG, Release)() override; - - protected: - friend class base::RefCounted<PinBase>; - virtual ~PinBase(); - - private: - AM_MEDIA_TYPE current_media_type_; - base::win::ScopedComPtr<IPin> connected_pin_; - // owner_ is the filter owning this pin. We don't reference count it since - // that would create a circular reference count. - IBaseFilter* owner_; -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_WIN_PIN_BASE_WIN_H_ diff --git a/media/video/capture/win/sink_filter_observer_win.h b/media/video/capture/win/sink_filter_observer_win.h deleted file mode 100644 index 13451b4..0000000 --- a/media/video/capture/win/sink_filter_observer_win.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2011 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. - -// Observer class of Sinkfilter. The implementor of this class receive video -// frames from the SinkFilter DirectShow filter. - -#ifndef MEDIA_VIDEO_CAPTURE_WIN_SINK_FILTER_OBSERVER_WIN_H_ -#define MEDIA_VIDEO_CAPTURE_WIN_SINK_FILTER_OBSERVER_WIN_H_ - -namespace media { - -class SinkFilterObserver { - public: - // SinkFilter will call this function with all frames delivered to it. - // buffer in only valid during this function call. - virtual void FrameReceived(const uint8* buffer, int length) = 0; - protected: - virtual ~SinkFilterObserver(); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_WIN_SINK_FILTER_OBSERVER_WIN_H_ diff --git a/media/video/capture/win/sink_filter_win.cc b/media/video/capture/win/sink_filter_win.cc deleted file mode 100644 index 09d5dd9..0000000 --- a/media/video/capture/win/sink_filter_win.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2012 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/win/sink_filter_win.h" - -#include "base/logging.h" -#include "media/video/capture/win/sink_input_pin_win.h" - -namespace media { - -// Define GUID for I420. This is the color format we would like to support but -// it is not defined in the DirectShow SDK. -// http://msdn.microsoft.com/en-us/library/dd757532.aspx -// 30323449-0000-0010-8000-00AA00389B71. -GUID kMediaSubTypeI420 = { - 0x30323449, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71} -}; - -// UYVY synonym with BT709 color components, used in HD video. This variation -// might appear in non-USB capture cards and it's implemented as a normal YUV -// pixel format with the characters HDYC encoded in the first array word. -GUID kMediaSubTypeHDYC = { - 0x43594448, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -}; - -SinkFilterObserver::~SinkFilterObserver() {} - -SinkFilter::SinkFilter(SinkFilterObserver* observer) - : input_pin_(NULL) { - input_pin_ = new SinkInputPin(this, observer); -} - -void SinkFilter::SetRequestedMediaFormat(VideoCapturePixelFormat pixel_format, - float frame_rate, - const BITMAPINFOHEADER& info_header) { - input_pin_->SetRequestedMediaFormat(pixel_format, frame_rate, info_header); -} - -const VideoCaptureFormat& SinkFilter::ResultingFormat() { - return input_pin_->ResultingFormat(); -} - -size_t SinkFilter::NoOfPins() { - return 1; -} - -IPin* SinkFilter::GetPin(int index) { - return index == 0 ? input_pin_.get() : NULL; -} - -STDMETHODIMP SinkFilter::GetClassID(CLSID* clsid) { - *clsid = __uuidof(SinkFilter); - return S_OK; -} - -SinkFilter::~SinkFilter() { - input_pin_->SetOwner(NULL); -} - -} // namespace media diff --git a/media/video/capture/win/sink_filter_win.h b/media/video/capture/win/sink_filter_win.h deleted file mode 100644 index 40dd544..0000000 --- a/media/video/capture/win/sink_filter_win.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2012 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. - -// Implement a DirectShow sink filter used for receiving captured frames from -// a DirectShow Capture filter. - -#ifndef MEDIA_VIDEO_CAPTURE_WIN_SINK_FILTER_WIN_H_ -#define MEDIA_VIDEO_CAPTURE_WIN_SINK_FILTER_WIN_H_ - -#include <windows.h> - -#include "base/memory/ref_counted.h" -#include "media/base/video_capture_types.h" -#include "media/video/capture/video_capture_device.h" -#include "media/video/capture/win/filter_base_win.h" -#include "media/video/capture/win/sink_filter_observer_win.h" - -namespace media { - -// Define GUID for I420. This is the color format we would like to support but -// it is not defined in the DirectShow SDK. -// http://msdn.microsoft.com/en-us/library/dd757532.aspx -// 30323449-0000-0010-8000-00AA00389B71. -extern GUID kMediaSubTypeI420; - -// UYVY synonym with BT709 color components, used in HD video. This variation -// might appear in non-USB capture cards and it's implemented as a normal YUV -// pixel format with the characters HDYC encoded in the first array word. -extern GUID kMediaSubTypeHDYC; - -class SinkInputPin; - -class __declspec(uuid("88cdbbdc-a73b-4afa-acbf-15d5e2ce12c3")) - SinkFilter : public FilterBase { - public: - explicit SinkFilter(SinkFilterObserver* observer); - - void SetRequestedMediaFormat(VideoCapturePixelFormat pixel_format, - float frame_rate, - const BITMAPINFOHEADER& info_header); - // Returns the format that is negotiated when this - // filter is connected to a media filter. - const VideoCaptureFormat& ResultingFormat(); - - // Implement FilterBase. - size_t NoOfPins() override; - IPin* GetPin(int index) override; - - STDMETHOD(GetClassID)(CLSID* clsid) override; - - private: - ~SinkFilter() override; - - scoped_refptr<SinkInputPin> input_pin_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(SinkFilter); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_WIN_SINK_FILTER_WIN_H_ diff --git a/media/video/capture/win/sink_input_pin_win.cc b/media/video/capture/win/sink_input_pin_win.cc deleted file mode 100644 index be5b3ab..0000000 --- a/media/video/capture/win/sink_input_pin_win.cc +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2012 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/win/sink_input_pin_win.h" - -#include <cstring> - -// Avoid including strsafe.h via dshow as it will cause build warnings. -#define NO_DSHOW_STRSAFE -#include <dshow.h> - -#include "base/logging.h" - -namespace media { - -const REFERENCE_TIME kSecondsToReferenceTime = 10000000; - - -static DWORD GetArea(const BITMAPINFOHEADER& info_header) { - return info_header.biWidth * info_header.biHeight; -} - -SinkInputPin::SinkInputPin(IBaseFilter* filter, SinkFilterObserver* observer) - : PinBase(filter), requested_frame_rate_(0), observer_(observer) { -} - -void SinkInputPin::SetRequestedMediaFormat( - VideoCapturePixelFormat pixel_format, - float frame_rate, - const BITMAPINFOHEADER& info_header) { - requested_pixel_format_ = pixel_format; - requested_frame_rate_ = frame_rate; - requested_info_header_ = info_header; - resulting_format_.frame_size.SetSize(0, 0); - resulting_format_.frame_rate = 0; - resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN; -} - -const VideoCaptureFormat& SinkInputPin::ResultingFormat() { - return resulting_format_; -} - -bool SinkInputPin::IsMediaTypeValid(const AM_MEDIA_TYPE* media_type) { - GUID type = media_type->majortype; - if (type != MEDIATYPE_Video) - return false; - - GUID format_type = media_type->formattype; - if (format_type != FORMAT_VideoInfo) - return false; - - // Check for the sub types we support. - GUID sub_type = media_type->subtype; - VIDEOINFOHEADER* pvi = - reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); - if (pvi == NULL) - return false; - - // Store the incoming width and height. - resulting_format_.frame_size.SetSize(pvi->bmiHeader.biWidth, - abs(pvi->bmiHeader.biHeight)); - if (pvi->AvgTimePerFrame > 0) { - resulting_format_.frame_rate = - static_cast<int>(kSecondsToReferenceTime / pvi->AvgTimePerFrame); - } else { - resulting_format_.frame_rate = requested_frame_rate_; - } - if (sub_type == kMediaSubTypeI420 && - pvi->bmiHeader.biCompression == MAKEFOURCC('I', '4', '2', '0')) { - resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_I420; - return true; - } - if (sub_type == MEDIASUBTYPE_YUY2 && - pvi->bmiHeader.biCompression == MAKEFOURCC('Y', 'U', 'Y', '2')) { - resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_YUY2; - return true; - } - if (sub_type == MEDIASUBTYPE_MJPG && - pvi->bmiHeader.biCompression == MAKEFOURCC('M', 'J', 'P', 'G')) { - resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG; - return true; - } - if (sub_type == MEDIASUBTYPE_RGB24 && - pvi->bmiHeader.biCompression == BI_RGB) { - resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_RGB24; - return true; - } - if (sub_type == MEDIASUBTYPE_RGB32 && - pvi->bmiHeader.biCompression == BI_RGB) { - resulting_format_.pixel_format = VIDEO_CAPTURE_PIXEL_FORMAT_RGB32; - return true; - } - return false; -} - -bool SinkInputPin::GetValidMediaType(int index, AM_MEDIA_TYPE* media_type) { - if (media_type->cbFormat < sizeof(VIDEOINFOHEADER)) - return false; - - VIDEOINFOHEADER* pvi = - reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); - - ZeroMemory(pvi, sizeof(VIDEOINFOHEADER)); - pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - pvi->bmiHeader.biPlanes = 1; - pvi->bmiHeader.biClrImportant = 0; - pvi->bmiHeader.biClrUsed = 0; - if (requested_frame_rate_ > 0) { - pvi->AvgTimePerFrame = - kSecondsToReferenceTime / requested_frame_rate_; - } - - media_type->majortype = MEDIATYPE_Video; - media_type->formattype = FORMAT_VideoInfo; - media_type->bTemporalCompression = FALSE; - - if (requested_pixel_format_ == VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG) { - // If the requested pixel format is MJPEG, accept only MJPEG. - // This is ok since the capabilities of the capturer have been - // enumerated and we know that it is supported. - if (index != 0) - return false; - - pvi->bmiHeader = requested_info_header_; - return true; - } - - switch (index) { - case 0: { - pvi->bmiHeader.biCompression = MAKEFOURCC('I', '4', '2', '0'); - pvi->bmiHeader.biBitCount = 12; // bit per pixel - pvi->bmiHeader.biWidth = requested_info_header_.biWidth; - pvi->bmiHeader.biHeight = requested_info_header_.biHeight; - pvi->bmiHeader.biSizeImage = GetArea(requested_info_header_) * 3 / 2; - media_type->subtype = kMediaSubTypeI420; - break; - } - case 1: { - pvi->bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y', '2'); - pvi->bmiHeader.biBitCount = 16; - pvi->bmiHeader.biWidth = requested_info_header_.biWidth; - pvi->bmiHeader.biHeight = requested_info_header_.biHeight; - pvi->bmiHeader.biSizeImage = GetArea(requested_info_header_) * 2; - media_type->subtype = MEDIASUBTYPE_YUY2; - break; - } - case 2: { - pvi->bmiHeader.biCompression = BI_RGB; - pvi->bmiHeader.biBitCount = 24; - pvi->bmiHeader.biWidth = requested_info_header_.biWidth; - pvi->bmiHeader.biHeight = requested_info_header_.biHeight; - pvi->bmiHeader.biSizeImage = GetArea(requested_info_header_) * 3; - media_type->subtype = MEDIASUBTYPE_RGB24; - break; - } - case 3: { - pvi->bmiHeader.biCompression = BI_RGB; - pvi->bmiHeader.biBitCount = 32; - pvi->bmiHeader.biWidth = requested_info_header_.biWidth; - pvi->bmiHeader.biHeight = requested_info_header_.biHeight; - pvi->bmiHeader.biSizeImage = GetArea(requested_info_header_) * 4; - media_type->subtype = MEDIASUBTYPE_RGB32; - break; - } - default: - return false; - } - - media_type->bFixedSizeSamples = TRUE; - media_type->lSampleSize = pvi->bmiHeader.biSizeImage; - return true; -} - -HRESULT SinkInputPin::Receive(IMediaSample* sample) { - const int length = sample->GetActualDataLength(); - uint8* buffer = NULL; - - if (length <= 0) { - DLOG(WARNING) << "Media sample length is 0 or less."; - return S_FALSE; - } - - if (FAILED(sample->GetPointer(&buffer))) - return S_FALSE; - - observer_->FrameReceived(buffer, length); - return S_OK; -} - -SinkInputPin::~SinkInputPin() {} - -} // namespace media diff --git a/media/video/capture/win/sink_input_pin_win.h b/media/video/capture/win/sink_input_pin_win.h deleted file mode 100644 index 3353e0f..0000000 --- a/media/video/capture/win/sink_input_pin_win.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2012 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. - -// Implement a DirectShow input pin used for receiving captured frames from -// a DirectShow Capture filter. - -#ifndef MEDIA_VIDEO_CAPTURE_WIN_SINK_INPUT_PIN_WIN_H_ -#define MEDIA_VIDEO_CAPTURE_WIN_SINK_INPUT_PIN_WIN_H_ - -#include "media/base/video_capture_types.h" -#include "media/video/capture/video_capture_device.h" -#include "media/video/capture/win/pin_base_win.h" -#include "media/video/capture/win/sink_filter_win.h" - -namespace media { - -// Const used for converting Seconds to REFERENCE_TIME. -extern const REFERENCE_TIME kSecondsToReferenceTime; - -// Input pin of the SinkFilter. -class SinkInputPin : public PinBase { - public: - SinkInputPin(IBaseFilter* filter, SinkFilterObserver* observer); - - void SetRequestedMediaFormat(VideoCapturePixelFormat pixel_format, - float frame_rate, - const BITMAPINFOHEADER& info_header); - // Returns the capability that is negotiated when this - // pin is connected to a media filter. - const VideoCaptureFormat& ResultingFormat(); - - // Implement PinBase. - bool IsMediaTypeValid(const AM_MEDIA_TYPE* media_type) override; - bool GetValidMediaType(int index, AM_MEDIA_TYPE* media_type) override; - - STDMETHOD(Receive)(IMediaSample* media_sample) override; - - private: - ~SinkInputPin() override; - - VideoCapturePixelFormat requested_pixel_format_; - float requested_frame_rate_; - BITMAPINFOHEADER requested_info_header_; - VideoCaptureFormat resulting_format_; - SinkFilterObserver* observer_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(SinkInputPin); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_WIN_SINK_INPUT_PIN_WIN_H_ diff --git a/media/video/capture/win/video_capture_device_factory_win.cc b/media/video/capture/win/video_capture_device_factory_win.cc deleted file mode 100644 index 96b11de..0000000 --- a/media/video/capture/win/video_capture_device_factory_win.cc +++ /dev/null @@ -1,435 +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/win/video_capture_device_factory_win.h" - -#include <mfapi.h> -#include <mferror.h> - -#include "base/command_line.h" -#include "base/macros.h" -#include "base/metrics/histogram.h" -#include "base/strings/string_util.h" -#include "base/strings/sys_string_conversions.h" -#include "base/win/metro.h" -#include "base/win/scoped_co_mem.h" -#include "base/win/scoped_variant.h" -#include "base/win/windows_version.h" -#include "media/base/media_switches.h" -#include "media/base/win/mf_initializer.h" -#include "media/video/capture/win/video_capture_device_mf_win.h" -#include "media/video/capture/win/video_capture_device_win.h" - -using base::win::ScopedCoMem; -using base::win::ScopedComPtr; -using base::win::ScopedVariant; -using Name = media::VideoCaptureDevice::Name; -using Names = media::VideoCaptureDevice::Names; - -namespace media { - -// Avoid enumerating and/or using certain devices due to they provoking crashes -// or any other reason (http://crbug.com/378494). This enum is defined for the -// purposes of UMA collection. Existing entries cannot be removed. -enum BlacklistedCameraNames { - BLACKLISTED_CAMERA_GOOGLE_CAMERA_ADAPTER = 0, - BLACKLISTED_CAMERA_IP_CAMERA = 1, - BLACKLISTED_CAMERA_CYBERLINK_WEBCAM_SPLITTER = 2, - BLACKLISTED_CAMERA_EPOCCAM = 3, - // This one must be last, and equal to the previous enumerated value. - BLACKLISTED_CAMERA_MAX = BLACKLISTED_CAMERA_EPOCCAM, -}; - -// Blacklisted devices are identified by a characteristic prefix of the name. -// This prefix is used case-insensitively. This list must be kept in sync with -// |BlacklistedCameraNames|. -static const char* const kBlacklistedCameraNames[] = { - // Name of a fake DirectShow filter on computers with GTalk installed. - "Google Camera Adapter", - // The following software WebCams cause crashes. - "IP Camera [JPEG/MJPEG]", - "CyberLink Webcam Splitter", - "EpocCam", -}; -static_assert(arraysize(kBlacklistedCameraNames) == BLACKLISTED_CAMERA_MAX + 1, - "kBlacklistedCameraNames should be same size as BlacklistedCameraNames enum"); - -static bool LoadMediaFoundationDlls() { - static const wchar_t* const kMfDLLs[] = { - L"%WINDIR%\\system32\\mf.dll", - L"%WINDIR%\\system32\\mfplat.dll", - L"%WINDIR%\\system32\\mfreadwrite.dll", - }; - - for (int i = 0; i < arraysize(kMfDLLs); ++i) { - wchar_t path[MAX_PATH] = {0}; - ExpandEnvironmentStringsW(kMfDLLs[i], path, arraysize(path)); - if (!LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) - return false; - } - return true; -} - -static bool PrepareVideoCaptureAttributesMediaFoundation( - IMFAttributes** attributes, - int count) { - InitializeMediaFoundation(); - - if (FAILED(MFCreateAttributes(attributes, count))) - return false; - - return SUCCEEDED((*attributes)->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, - MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID)); -} - -static bool CreateVideoCaptureDeviceMediaFoundation(const char* sym_link, - IMFMediaSource** source) { - ScopedComPtr<IMFAttributes> attributes; - if (!PrepareVideoCaptureAttributesMediaFoundation(attributes.Receive(), 2)) - return false; - - attributes->SetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, - base::SysUTF8ToWide(sym_link).c_str()); - - return SUCCEEDED(MFCreateDeviceSource(attributes.get(), source)); -} - -static bool EnumerateVideoDevicesMediaFoundation(IMFActivate*** devices, - UINT32* count) { - ScopedComPtr<IMFAttributes> attributes; - if (!PrepareVideoCaptureAttributesMediaFoundation(attributes.Receive(), 1)) - return false; - - return SUCCEEDED(MFEnumDeviceSources(attributes.get(), devices, count)); -} - -static bool IsDeviceBlackListed(const std::string& name) { - DCHECK_EQ(BLACKLISTED_CAMERA_MAX + 1, - static_cast<int>(arraysize(kBlacklistedCameraNames))); - for (size_t i = 0; i < arraysize(kBlacklistedCameraNames); ++i) { - if (base::StartsWith(name, kBlacklistedCameraNames[i], - base::CompareCase::INSENSITIVE_ASCII)) { - DVLOG(1) << "Enumerated blacklisted device: " << name; - UMA_HISTOGRAM_ENUMERATION("Media.VideoCapture.BlacklistedDevice", - i, BLACKLISTED_CAMERA_MAX + 1); - return true; - } - } - return false; -} - -static void GetDeviceNamesDirectShow(Names* device_names) { - DCHECK(device_names); - DVLOG(1) << " GetDeviceNamesDirectShow"; - - ScopedComPtr<ICreateDevEnum> dev_enum; - HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, - CLSCTX_INPROC); - if (FAILED(hr)) - return; - - ScopedComPtr<IEnumMoniker> enum_moniker; - hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, - enum_moniker.Receive(), 0); - // CreateClassEnumerator returns S_FALSE on some Windows OS - // when no camera exist. Therefore the FAILED macro can't be used. - if (hr != S_OK) - return; - - // Enumerate all video capture devices. - for (ScopedComPtr<IMoniker> moniker; - enum_moniker->Next(1, moniker.Receive(), NULL) == S_OK; - moniker.Release()) { - ScopedComPtr<IPropertyBag> prop_bag; - hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, prop_bag.ReceiveVoid()); - if (FAILED(hr)) - continue; - - // Find the description or friendly name. - ScopedVariant name; - hr = prop_bag->Read(L"Description", name.Receive(), 0); - if (FAILED(hr)) - hr = prop_bag->Read(L"FriendlyName", name.Receive(), 0); - - if (FAILED(hr) || name.type() != VT_BSTR) - continue; - - const std::string device_name(base::SysWideToUTF8(V_BSTR(name.ptr()))); - if (IsDeviceBlackListed(device_name)) - continue; - - name.Reset(); - hr = prop_bag->Read(L"DevicePath", name.Receive(), 0); - std::string id; - if (FAILED(hr) || name.type() != VT_BSTR) { - id = device_name; - } else { - DCHECK_EQ(name.type(), VT_BSTR); - id = base::SysWideToUTF8(V_BSTR(name.ptr())); - } - device_names->push_back(Name(device_name, id, Name::DIRECT_SHOW)); - } -} - -static void GetDeviceNamesMediaFoundation(Names* device_names) { - DVLOG(1) << " GetDeviceNamesMediaFoundation"; - ScopedCoMem<IMFActivate*> devices; - UINT32 count; - if (!EnumerateVideoDevicesMediaFoundation(&devices, &count)) - return; - - for (UINT32 i = 0; i < count; ++i) { - ScopedCoMem<wchar_t> name; - UINT32 name_size; - HRESULT hr = devices[i]->GetAllocatedString( - MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &name, &name_size); - if (SUCCEEDED(hr)) { - ScopedCoMem<wchar_t> id; - UINT32 id_size; - hr = devices[i]->GetAllocatedString( - MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &id, - &id_size); - if (SUCCEEDED(hr)) { - device_names->push_back(Name( - base::SysWideToUTF8(std::wstring(name, name_size)), - base::SysWideToUTF8(std::wstring(id, id_size)), - Name::MEDIA_FOUNDATION)); - } - } - DLOG_IF(ERROR, FAILED(hr)) << "GetAllocatedString failed: " - << logging::SystemErrorCodeToString(hr); - devices[i]->Release(); - } -} - -static void GetDeviceSupportedFormatsDirectShow(const Name& device, - VideoCaptureFormats* formats) { - DVLOG(1) << "GetDeviceSupportedFormatsDirectShow for " << device.name(); - ScopedComPtr<ICreateDevEnum> dev_enum; - HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, - CLSCTX_INPROC); - if (FAILED(hr)) - return; - - ScopedComPtr<IEnumMoniker> enum_moniker; - hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, - enum_moniker.Receive(), 0); - // CreateClassEnumerator returns S_FALSE on some Windows OS when no camera - // exists. Therefore the FAILED macro can't be used. - if (hr != S_OK) - return; - - // Walk the capture devices. No need to check for device presence again since - // that is anyway needed in GetDeviceFilter(). "google camera adapter" and old - // VFW devices are already skipped previously in GetDeviceNames() enumeration. - base::win::ScopedComPtr<IBaseFilter> capture_filter; - hr = VideoCaptureDeviceWin::GetDeviceFilter(device.capabilities_id(), - CLSID_VideoInputDeviceCategory, - capture_filter.Receive()); - if (!capture_filter.get()) { - DLOG(ERROR) << "Failed to create capture filter: " - << logging::SystemErrorCodeToString(hr); - return; - } - - base::win::ScopedComPtr<IPin> output_capture_pin( - VideoCaptureDeviceWin::GetPin(capture_filter.get(), PINDIR_OUTPUT, - PIN_CATEGORY_CAPTURE, GUID_NULL)); - if (!output_capture_pin.get()) { - DLOG(ERROR) << "Failed to get capture output pin"; - return; - } - - ScopedComPtr<IAMStreamConfig> stream_config; - hr = output_capture_pin.QueryInterface(stream_config.Receive()); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to get IAMStreamConfig interface from " - "capture device: " << logging::SystemErrorCodeToString(hr); - return; - } - - int count = 0, size = 0; - hr = stream_config->GetNumberOfCapabilities(&count, &size); - if (FAILED(hr)) { - DLOG(ERROR) << "GetNumberOfCapabilities failed: " - << logging::SystemErrorCodeToString(hr); - return; - } - - scoped_ptr<BYTE[]> caps(new BYTE[size]); - for (int i = 0; i < count; ++i) { - VideoCaptureDeviceWin::ScopedMediaType media_type; - hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get()); - // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() - // macros here since they'll trigger incorrectly. - if (hr != S_OK || !media_type.get()) { - DLOG(ERROR) << "GetStreamCaps failed: " - << logging::SystemErrorCodeToString(hr); - return; - } - - if (media_type->majortype == MEDIATYPE_Video && - media_type->formattype == FORMAT_VideoInfo) { - VideoCaptureFormat format; - format.pixel_format = - VideoCaptureDeviceWin::TranslateMediaSubtypeToPixelFormat( - media_type->subtype); - if (format.pixel_format == VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN) - continue; - VIDEOINFOHEADER* h = - reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); - format.frame_size.SetSize(h->bmiHeader.biWidth, - h->bmiHeader.biHeight); - // Trust the frame rate from the VIDEOINFOHEADER. - format.frame_rate = (h->AvgTimePerFrame > 0) ? - kSecondsToReferenceTime / static_cast<float>(h->AvgTimePerFrame) : - 0.0f; - formats->push_back(format); - DVLOG(1) << device.name() << " " << VideoCaptureFormat::ToString(format); - } - } -} - -static void GetDeviceSupportedFormatsMediaFoundation( - const Name& device, - VideoCaptureFormats* formats) { - DVLOG(1) << "GetDeviceSupportedFormatsMediaFoundation for " << device.name(); - ScopedComPtr<IMFMediaSource> source; - if (!CreateVideoCaptureDeviceMediaFoundation(device.id().c_str(), - source.Receive())) { - return; - } - - base::win::ScopedComPtr<IMFSourceReader> reader; - HRESULT hr = - MFCreateSourceReaderFromMediaSource(source.get(), NULL, reader.Receive()); - if (FAILED(hr)) { - DLOG(ERROR) << "MFCreateSourceReaderFromMediaSource failed: " - << logging::SystemErrorCodeToString(hr); - return; - } - - DWORD stream_index = 0; - ScopedComPtr<IMFMediaType> type; - while (SUCCEEDED(reader->GetNativeMediaType( - kFirstVideoStream, stream_index, type.Receive()))) { - UINT32 width, height; - hr = MFGetAttributeSize(type.get(), MF_MT_FRAME_SIZE, &width, &height); - if (FAILED(hr)) { - DLOG(ERROR) << "MFGetAttributeSize failed: " - << logging::SystemErrorCodeToString(hr); - return; - } - VideoCaptureFormat capture_format; - capture_format.frame_size.SetSize(width, height); - - UINT32 numerator, denominator; - hr = MFGetAttributeRatio(type.get(), MF_MT_FRAME_RATE, &numerator, - &denominator); - if (FAILED(hr)) { - DLOG(ERROR) << "MFGetAttributeSize failed: " - << logging::SystemErrorCodeToString(hr); - return; - } - capture_format.frame_rate = denominator - ? static_cast<float>(numerator) / denominator : 0.0f; - - GUID type_guid; - hr = type->GetGUID(MF_MT_SUBTYPE, &type_guid); - if (FAILED(hr)) { - DLOG(ERROR) << "GetGUID failed: " - << logging::SystemErrorCodeToString(hr); - return; - } - VideoCaptureDeviceMFWin::FormatFromGuid(type_guid, - &capture_format.pixel_format); - type.Release(); - formats->push_back(capture_format); - ++stream_index; - - DVLOG(1) << device.name() << " " - << VideoCaptureFormat::ToString(capture_format); - } -} - -// Returns true iff the current platform supports the Media Foundation API -// and that the DLLs are available. On Vista this API is an optional download -// but the API is advertised as a part of Windows 7 and onwards. However, -// we've seen that the required DLLs are not available in some Win7 -// distributions such as Windows 7 N and Windows 7 KN. -// static -bool VideoCaptureDeviceFactoryWin::PlatformSupportsMediaFoundation() { - // Even though the DLLs might be available on Vista, we get crashes - // when running our tests on the build bots. - if (base::win::GetVersion() < base::win::VERSION_WIN7) - return false; - - static bool g_dlls_available = LoadMediaFoundationDlls(); - return g_dlls_available; -} - -VideoCaptureDeviceFactoryWin::VideoCaptureDeviceFactoryWin() { - // Use Media Foundation for Metro processes (after and including Win8) and - // DirectShow for any other versions, unless forced via flag. Media Foundation - // can also be forced if appropriate flag is set and we are in Windows 7 or - // 8 in non-Metro mode. - const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); - use_media_foundation_ = (base::win::IsMetroProcess() && - !cmd_line->HasSwitch(switches::kForceDirectShowVideoCapture)) || - (base::win::GetVersion() >= base::win::VERSION_WIN7 && - cmd_line->HasSwitch(switches::kForceMediaFoundationVideoCapture)); -} - -scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryWin::Create( - const Name& device_name) { - DCHECK(thread_checker_.CalledOnValidThread()); - scoped_ptr<VideoCaptureDevice> device; - if (device_name.capture_api_type() == Name::MEDIA_FOUNDATION) { - DCHECK(PlatformSupportsMediaFoundation()); - device.reset(new VideoCaptureDeviceMFWin(device_name)); - DVLOG(1) << " MediaFoundation Device: " << device_name.name(); - ScopedComPtr<IMFMediaSource> source; - if (!CreateVideoCaptureDeviceMediaFoundation(device_name.id().c_str(), - source.Receive())) { - return scoped_ptr<VideoCaptureDevice>(); - } - if (!static_cast<VideoCaptureDeviceMFWin*>(device.get())->Init(source)) - device.reset(); - } else { - DCHECK(device_name.capture_api_type() == Name::DIRECT_SHOW); - device.reset(new VideoCaptureDeviceWin(device_name)); - DVLOG(1) << " DirectShow Device: " << device_name.name(); - if (!static_cast<VideoCaptureDeviceWin*>(device.get())->Init()) - device.reset(); - } - return device.Pass(); -} - -void VideoCaptureDeviceFactoryWin::GetDeviceNames(Names* device_names) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (use_media_foundation_) { - GetDeviceNamesMediaFoundation(device_names); - } else { - GetDeviceNamesDirectShow(device_names); - } -} - -void VideoCaptureDeviceFactoryWin::GetDeviceSupportedFormats( - const Name& device, - VideoCaptureFormats* formats) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (use_media_foundation_) - GetDeviceSupportedFormatsMediaFoundation(device, formats); - else - GetDeviceSupportedFormatsDirectShow(device, formats); -} - -// static -VideoCaptureDeviceFactory* -VideoCaptureDeviceFactory::CreateVideoCaptureDeviceFactory( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { - return new VideoCaptureDeviceFactoryWin(); -} - -} // namespace media diff --git a/media/video/capture/win/video_capture_device_factory_win.h b/media/video/capture/win/video_capture_device_factory_win.h deleted file mode 100644 index f76fe63..0000000 --- a/media/video/capture/win/video_capture_device_factory_win.h +++ /dev/null @@ -1,39 +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 Windows platforms. - -#ifndef MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_FACTORY_WIN_H_ -#define MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_FACTORY_WIN_H_ - -#include "media/video/capture/video_capture_device_factory.h" - -namespace media { - -// Extension of VideoCaptureDeviceFactory to create and manipulate Windows -// devices, via either DirectShow or MediaFoundation APIs. -class MEDIA_EXPORT VideoCaptureDeviceFactoryWin : - public VideoCaptureDeviceFactory { - public: - static bool PlatformSupportsMediaFoundation(); - - VideoCaptureDeviceFactoryWin(); - ~VideoCaptureDeviceFactoryWin() override {} - - scoped_ptr<VideoCaptureDevice> Create( - const VideoCaptureDevice::Name& device_name) override; - void GetDeviceNames(VideoCaptureDevice::Names* device_names) override; - void GetDeviceSupportedFormats( - const VideoCaptureDevice::Name& device, - VideoCaptureFormats* supported_formats) override; - - private: - bool use_media_foundation_; - - DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceFactoryWin); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_FACTORY_WIN_H_ diff --git a/media/video/capture/win/video_capture_device_mf_win.cc b/media/video/capture/win/video_capture_device_mf_win.cc deleted file mode 100644 index f9d3dca..0000000 --- a/media/video/capture/win/video_capture_device_mf_win.cc +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright (c) 2012 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/win/video_capture_device_mf_win.h" - -#include <mfapi.h> -#include <mferror.h> - -#include "base/memory/ref_counted.h" -#include "base/strings/stringprintf.h" -#include "base/strings/sys_string_conversions.h" -#include "base/synchronization/waitable_event.h" -#include "base/win/scoped_co_mem.h" -#include "base/win/windows_version.h" -#include "media/video/capture/win/capability_list_win.h" - -using base::win::ScopedCoMem; -using base::win::ScopedComPtr; - -namespace media { - -// In Windows device identifiers, the USB VID and PID are preceded by the string -// "vid_" or "pid_". The identifiers are each 4 bytes long. -const char kVidPrefix[] = "vid_"; // Also contains '\0'. -const char kPidPrefix[] = "pid_"; // Also contains '\0'. -const size_t kVidPidSize = 4; - -static bool GetFrameSize(IMFMediaType* type, gfx::Size* frame_size) { - UINT32 width32, height32; - if (FAILED(MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &width32, &height32))) - return false; - frame_size->SetSize(width32, height32); - return true; -} - -static bool GetFrameRate(IMFMediaType* type, float* frame_rate) { - UINT32 numerator, denominator; - if (FAILED(MFGetAttributeRatio(type, MF_MT_FRAME_RATE, &numerator, - &denominator))|| - !denominator) { - return false; - } - *frame_rate = static_cast<float>(numerator) / denominator; - return true; -} - -static bool FillFormat(IMFMediaType* type, VideoCaptureFormat* format) { - GUID type_guid; - if (FAILED(type->GetGUID(MF_MT_SUBTYPE, &type_guid)) || - !GetFrameSize(type, &format->frame_size) || - !GetFrameRate(type, &format->frame_rate) || - !VideoCaptureDeviceMFWin::FormatFromGuid(type_guid, - &format->pixel_format)) { - return false; - } - - return true; -} - -HRESULT FillCapabilities(IMFSourceReader* source, - CapabilityList* capabilities) { - DWORD stream_index = 0; - ScopedComPtr<IMFMediaType> type; - HRESULT hr; - while (SUCCEEDED(hr = source->GetNativeMediaType( - kFirstVideoStream, stream_index, type.Receive()))) { - VideoCaptureFormat format; - if (FillFormat(type.get(), &format)) - capabilities->emplace_back(stream_index, format); - type.Release(); - ++stream_index; - } - - if (capabilities->empty() && (SUCCEEDED(hr) || hr == MF_E_NO_MORE_TYPES)) - hr = HRESULT_FROM_WIN32(ERROR_EMPTY); - - return (hr == MF_E_NO_MORE_TYPES) ? S_OK : hr; -} - - -class MFReaderCallback final - : public base::RefCountedThreadSafe<MFReaderCallback>, - public IMFSourceReaderCallback { - public: - MFReaderCallback(VideoCaptureDeviceMFWin* observer) - : observer_(observer), wait_event_(NULL) { - } - - void SetSignalOnFlush(base::WaitableEvent* event) { - wait_event_ = event; - } - - STDMETHOD(QueryInterface)(REFIID riid, void** object) override { - if (riid != IID_IUnknown && riid != IID_IMFSourceReaderCallback) - return E_NOINTERFACE; - *object = static_cast<IMFSourceReaderCallback*>(this); - AddRef(); - return S_OK; - } - - STDMETHOD_(ULONG, AddRef)() override { - base::RefCountedThreadSafe<MFReaderCallback>::AddRef(); - return 1U; - } - - STDMETHOD_(ULONG, Release)() override { - base::RefCountedThreadSafe<MFReaderCallback>::Release(); - return 1U; - } - - STDMETHOD(OnReadSample)(HRESULT status, - DWORD stream_index, - DWORD stream_flags, - LONGLONG time_stamp, - IMFSample* sample) override { - base::TimeTicks stamp(base::TimeTicks::Now()); - if (!sample) { - observer_->OnIncomingCapturedData(NULL, 0, 0, stamp); - return S_OK; - } - - DWORD count = 0; - sample->GetBufferCount(&count); - - for (DWORD i = 0; i < count; ++i) { - ScopedComPtr<IMFMediaBuffer> buffer; - sample->GetBufferByIndex(i, buffer.Receive()); - if (buffer.get()) { - DWORD length = 0, max_length = 0; - BYTE* data = NULL; - buffer->Lock(&data, &max_length, &length); - observer_->OnIncomingCapturedData(data, length, 0, stamp); - buffer->Unlock(); - } - } - return S_OK; - } - - STDMETHOD(OnFlush)(DWORD stream_index) override { - if (wait_event_) { - wait_event_->Signal(); - wait_event_ = NULL; - } - return S_OK; - } - - STDMETHOD(OnEvent)(DWORD stream_index, IMFMediaEvent* event) override { - NOTIMPLEMENTED(); - return S_OK; - } - - private: - friend class base::RefCountedThreadSafe<MFReaderCallback>; - ~MFReaderCallback() {} - - VideoCaptureDeviceMFWin* observer_; - base::WaitableEvent* wait_event_; -}; - -// static -bool VideoCaptureDeviceMFWin::FormatFromGuid(const GUID& guid, - VideoCapturePixelFormat* format) { - struct { - const GUID& guid; - const VideoCapturePixelFormat format; - } static const kFormatMap[] = { - {MFVideoFormat_I420, VIDEO_CAPTURE_PIXEL_FORMAT_I420}, - {MFVideoFormat_YUY2, VIDEO_CAPTURE_PIXEL_FORMAT_YUY2}, - {MFVideoFormat_UYVY, VIDEO_CAPTURE_PIXEL_FORMAT_UYVY}, - {MFVideoFormat_RGB24, VIDEO_CAPTURE_PIXEL_FORMAT_RGB24}, - {MFVideoFormat_ARGB32, VIDEO_CAPTURE_PIXEL_FORMAT_ARGB}, - {MFVideoFormat_MJPG, VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG}, - {MFVideoFormat_YV12, VIDEO_CAPTURE_PIXEL_FORMAT_YV12}, - }; - - for (int i = 0; i < arraysize(kFormatMap); ++i) { - if (kFormatMap[i].guid == guid) { - *format = kFormatMap[i].format; - return true; - } - } - - return false; -} - -const std::string VideoCaptureDevice::Name::GetModel() const { - const size_t vid_prefix_size = sizeof(kVidPrefix) - 1; - const size_t pid_prefix_size = sizeof(kPidPrefix) - 1; - const size_t vid_location = unique_id_.find(kVidPrefix); - if (vid_location == std::string::npos || - vid_location + vid_prefix_size + kVidPidSize > unique_id_.size()) { - return std::string(); - } - const size_t pid_location = unique_id_.find(kPidPrefix); - if (pid_location == std::string::npos || - pid_location + pid_prefix_size + kVidPidSize > unique_id_.size()) { - return std::string(); - } - std::string id_vendor = - unique_id_.substr(vid_location + vid_prefix_size, kVidPidSize); - std::string id_product = - unique_id_.substr(pid_location + pid_prefix_size, kVidPidSize); - return id_vendor + ":" + id_product; -} - -VideoCaptureDeviceMFWin::VideoCaptureDeviceMFWin(const Name& device_name) - : name_(device_name), capture_(0) { - DetachFromThread(); -} - -VideoCaptureDeviceMFWin::~VideoCaptureDeviceMFWin() { - DCHECK(CalledOnValidThread()); -} - -bool VideoCaptureDeviceMFWin::Init( - const base::win::ScopedComPtr<IMFMediaSource>& source) { - DCHECK(CalledOnValidThread()); - DCHECK(!reader_.get()); - - ScopedComPtr<IMFAttributes> attributes; - MFCreateAttributes(attributes.Receive(), 1); - DCHECK(attributes.get()); - - callback_ = new MFReaderCallback(this); - attributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, callback_.get()); - - return SUCCEEDED(MFCreateSourceReaderFromMediaSource( - source.get(), attributes.get(), reader_.Receive())); -} - -void VideoCaptureDeviceMFWin::AllocateAndStart( - const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) { - DCHECK(CalledOnValidThread()); - - base::AutoLock lock(lock_); - - client_ = client.Pass(); - DCHECK_EQ(capture_, false); - - CapabilityList capabilities; - HRESULT hr = S_OK; - if (reader_.get()) { - hr = FillCapabilities(reader_.get(), &capabilities); - if (SUCCEEDED(hr)) { - const CapabilityWin found_capability = - GetBestMatchedCapability(params.requested_format, capabilities); - ScopedComPtr<IMFMediaType> type; - hr = reader_->GetNativeMediaType( - kFirstVideoStream, found_capability.stream_index, type.Receive()); - if (SUCCEEDED(hr)) { - hr = reader_->SetCurrentMediaType(kFirstVideoStream, NULL, type.get()); - if (SUCCEEDED(hr)) { - hr = reader_->ReadSample(kFirstVideoStream, 0, NULL, NULL, NULL, - NULL); - if (SUCCEEDED(hr)) { - capture_format_ = found_capability.supported_format; - capture_ = true; - return; - } - } - } - } - } - - OnError(hr); -} - -void VideoCaptureDeviceMFWin::StopAndDeAllocate() { - DCHECK(CalledOnValidThread()); - base::WaitableEvent flushed(false, false); - const int kFlushTimeOutInMs = 1000; - bool wait = false; - { - base::AutoLock lock(lock_); - if (capture_) { - capture_ = false; - callback_->SetSignalOnFlush(&flushed); - wait = SUCCEEDED(reader_->Flush( - static_cast<DWORD>(MF_SOURCE_READER_ALL_STREAMS))); - if (!wait) { - callback_->SetSignalOnFlush(NULL); - } - } - client_.reset(); - } - - // If the device has been unplugged, the Flush() won't trigger the event - // and a timeout will happen. - // TODO(tommi): Hook up the IMFMediaEventGenerator notifications API and - // do not wait at all after getting MEVideoCaptureDeviceRemoved event. - // See issue/226396. - if (wait) - flushed.TimedWait(base::TimeDelta::FromMilliseconds(kFlushTimeOutInMs)); -} - -void VideoCaptureDeviceMFWin::OnIncomingCapturedData( - const uint8* data, - int length, - int rotation, - const base::TimeTicks& time_stamp) { - base::AutoLock lock(lock_); - if (data && client_.get()) { - client_->OnIncomingCapturedData( - data, length, capture_format_, rotation, time_stamp); - } - - if (capture_) { - HRESULT hr = - reader_->ReadSample(kFirstVideoStream, 0, NULL, NULL, NULL, NULL); - if (FAILED(hr)) { - // If running the *VideoCap* unit tests on repeat, this can sometimes - // fail with HRESULT_FROM_WINHRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION). - // It's not clear to me why this is, but it is possible that it has - // something to do with this bug: - // http://support.microsoft.com/kb/979567 - OnError(hr); - } - } -} - -void VideoCaptureDeviceMFWin::OnError(HRESULT hr) { - if (client_.get()) { - client_->OnError( - base::StringPrintf("VideoCaptureDeviceMFWin: %s", - logging::SystemErrorCodeToString(hr).c_str())); - } -} - -} // namespace media diff --git a/media/video/capture/win/video_capture_device_mf_win.h b/media/video/capture/win/video_capture_device_mf_win.h deleted file mode 100644 index ada6636..0000000 --- a/media/video/capture/win/video_capture_device_mf_win.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2012 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. - -// Windows specific implementation of VideoCaptureDevice. -// DirectShow is used for capturing. DirectShow provide its own threads -// for capturing. - -#ifndef MEDIA_VIDEO_CAPTURE_WIN_VIDEO_CAPTURE_DEVICE_MF_WIN_H_ -#define MEDIA_VIDEO_CAPTURE_WIN_VIDEO_CAPTURE_DEVICE_MF_WIN_H_ - -#include <mfidl.h> -#include <mfreadwrite.h> - -#include <vector> - -#include "base/synchronization/lock.h" -#include "base/threading/non_thread_safe.h" -#include "base/win/scoped_comptr.h" -#include "media/base/media_export.h" -#include "media/video/capture/video_capture_device.h" - -interface IMFSourceReader; - -namespace media { - -class MFReaderCallback; - -const DWORD kFirstVideoStream = - static_cast<DWORD>(MF_SOURCE_READER_FIRST_VIDEO_STREAM); - -class MEDIA_EXPORT VideoCaptureDeviceMFWin - : public base::NonThreadSafe, - public VideoCaptureDevice { - public: - static bool FormatFromGuid(const GUID& guid, VideoCapturePixelFormat* format); - - explicit VideoCaptureDeviceMFWin(const Name& device_name); - ~VideoCaptureDeviceMFWin() override; - - // Opens the device driver for this device. - bool Init(const base::win::ScopedComPtr<IMFMediaSource>& source); - - // VideoCaptureDevice implementation. - void AllocateAndStart(const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) override; - void StopAndDeAllocate() override; - - // Captured new video data. - void OnIncomingCapturedData(const uint8* data, - int length, - int rotation, - const base::TimeTicks& time_stamp); - - private: - void OnError(HRESULT hr); - - Name name_; - base::win::ScopedComPtr<IMFActivate> device_; - scoped_refptr<MFReaderCallback> callback_; - - base::Lock lock_; // Used to guard the below variables. - scoped_ptr<VideoCaptureDevice::Client> client_; - base::win::ScopedComPtr<IMFSourceReader> reader_; - VideoCaptureFormat capture_format_; - bool capture_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceMFWin); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_WIN_VIDEO_CAPTURE_DEVICE_MF_WIN_H_ diff --git a/media/video/capture/win/video_capture_device_win.cc b/media/video/capture/win/video_capture_device_win.cc deleted file mode 100644 index 344ee9b..0000000 --- a/media/video/capture/win/video_capture_device_win.cc +++ /dev/null @@ -1,581 +0,0 @@ -// Copyright (c) 2012 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/win/video_capture_device_win.h" - -#include <ks.h> -#include <ksmedia.h> - -#include <algorithm> -#include <list> - -#include "base/strings/sys_string_conversions.h" -#include "base/win/scoped_co_mem.h" -#include "base/win/scoped_variant.h" -#include "media/video/capture/win/video_capture_device_mf_win.h" - -using base::win::ScopedCoMem; -using base::win::ScopedComPtr; -using base::win::ScopedVariant; - -namespace media { - -// Check if a Pin matches a category. -bool PinMatchesCategory(IPin* pin, REFGUID category) { - DCHECK(pin); - bool found = false; - ScopedComPtr<IKsPropertySet> ks_property; - HRESULT hr = ks_property.QueryFrom(pin); - if (SUCCEEDED(hr)) { - GUID pin_category; - DWORD return_value; - hr = ks_property->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0, - &pin_category, sizeof(pin_category), &return_value); - if (SUCCEEDED(hr) && (return_value == sizeof(pin_category))) { - found = (pin_category == category); - } - } - return found; -} - -// Check if a Pin's MediaType matches a given |major_type|. -bool PinMatchesMajorType(IPin* pin, REFGUID major_type) { - DCHECK(pin); - AM_MEDIA_TYPE connection_media_type; - HRESULT hr = pin->ConnectionMediaType(&connection_media_type); - return SUCCEEDED(hr) && connection_media_type.majortype == major_type; -} - -// Finds and creates a DirectShow Video Capture filter matching the |device_id|. -// |class_id| is usually CLSID_VideoInputDeviceCategory for standard DirectShow -// devices but might also be AM_KSCATEGORY_CAPTURE or AM_KSCATEGORY_CROSSBAR, to -// enumerate WDM capture devices or WDM crossbars, respectively. -// static -HRESULT VideoCaptureDeviceWin::GetDeviceFilter(const std::string& device_id, - const CLSID device_class_id, - IBaseFilter** filter) { - DCHECK(filter); - - ScopedComPtr<ICreateDevEnum> dev_enum; - HRESULT hr = - dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC); - if (FAILED(hr)) - return hr; - - ScopedComPtr<IEnumMoniker> enum_moniker; - hr = dev_enum->CreateClassEnumerator(device_class_id, enum_moniker.Receive(), - 0); - // CreateClassEnumerator returns S_FALSE on some Windows OS - // when no camera exist. Therefore the FAILED macro can't be used. - if (hr != S_OK) - return NULL; - - ScopedComPtr<IMoniker> moniker; - ScopedComPtr<IBaseFilter> capture_filter; - DWORD fetched = 0; - while (enum_moniker->Next(1, moniker.Receive(), &fetched) == S_OK) { - ScopedComPtr<IPropertyBag> prop_bag; - hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, prop_bag.ReceiveVoid()); - if (FAILED(hr)) { - moniker.Release(); - continue; - } - - // Find the device via DevicePath, Description or FriendlyName, whichever is - // available first. - static const wchar_t* kPropertyNames[] = { - L"DevicePath", L"Description", L"FriendlyName"}; - - ScopedVariant name; - for (const auto* property_name : kPropertyNames) { - if (name.type() != VT_BSTR) - prop_bag->Read(property_name, name.Receive(), 0); - } - - if (name.type() == VT_BSTR) { - std::string device_path(base::SysWideToUTF8(V_BSTR(name.ptr()))); - if (device_path.compare(device_id) == 0) { - // We have found the requested device - hr = moniker->BindToObject(0, 0, IID_IBaseFilter, - capture_filter.ReceiveVoid()); - DLOG_IF(ERROR, FAILED(hr)) << "Failed to bind camera filter: " - << logging::SystemErrorCodeToString(hr); - break; - } - } - moniker.Release(); - } - - *filter = capture_filter.Detach(); - if (!*filter && SUCCEEDED(hr)) - hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); - - return hr; -} - -// Finds an IPin on an IBaseFilter given the direction, Category and/or Major -// Type. If either |category| or |major_type| are GUID_NULL, they are ignored. -// static -ScopedComPtr<IPin> VideoCaptureDeviceWin::GetPin(IBaseFilter* filter, - PIN_DIRECTION pin_dir, - REFGUID category, - REFGUID major_type) { - ScopedComPtr<IPin> pin; - ScopedComPtr<IEnumPins> pin_enum; - HRESULT hr = filter->EnumPins(pin_enum.Receive()); - if (pin_enum.get() == NULL) - return pin; - - // Get first unconnected pin. - hr = pin_enum->Reset(); // set to first pin - while ((hr = pin_enum->Next(1, pin.Receive(), NULL)) == S_OK) { - PIN_DIRECTION this_pin_dir = static_cast<PIN_DIRECTION>(-1); - hr = pin->QueryDirection(&this_pin_dir); - if (pin_dir == this_pin_dir) { - if ((category == GUID_NULL || PinMatchesCategory(pin.get(), category)) && - (major_type == GUID_NULL || - PinMatchesMajorType(pin.get(), major_type))) { - return pin; - } - } - pin.Release(); - } - - DCHECK(!pin.get()); - return pin; -} - -// static -VideoCapturePixelFormat -VideoCaptureDeviceWin::TranslateMediaSubtypeToPixelFormat( - const GUID& sub_type) { - static struct { - const GUID& sub_type; - VideoCapturePixelFormat format; - } pixel_formats[] = { - {kMediaSubTypeI420, VIDEO_CAPTURE_PIXEL_FORMAT_I420}, - {MEDIASUBTYPE_IYUV, VIDEO_CAPTURE_PIXEL_FORMAT_I420}, - {MEDIASUBTYPE_RGB24, VIDEO_CAPTURE_PIXEL_FORMAT_RGB24}, - {MEDIASUBTYPE_YUY2, VIDEO_CAPTURE_PIXEL_FORMAT_YUY2}, - {MEDIASUBTYPE_MJPG, VIDEO_CAPTURE_PIXEL_FORMAT_MJPEG}, - {MEDIASUBTYPE_UYVY, VIDEO_CAPTURE_PIXEL_FORMAT_UYVY}, - {MEDIASUBTYPE_ARGB32, VIDEO_CAPTURE_PIXEL_FORMAT_ARGB}, - {kMediaSubTypeHDYC, VIDEO_CAPTURE_PIXEL_FORMAT_UYVY}, - }; - for (size_t i = 0; i < arraysize(pixel_formats); ++i) { - if (sub_type == pixel_formats[i].sub_type) - return pixel_formats[i].format; - } -#ifndef NDEBUG - WCHAR guid_str[128]; - StringFromGUID2(sub_type, guid_str, arraysize(guid_str)); - DVLOG(2) << "Device (also) supports an unknown media type " << guid_str; -#endif - return VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN; -} - -void VideoCaptureDeviceWin::ScopedMediaType::Free() { - if (!media_type_) - return; - - DeleteMediaType(media_type_); - media_type_ = NULL; -} - -AM_MEDIA_TYPE** VideoCaptureDeviceWin::ScopedMediaType::Receive() { - DCHECK(!media_type_); - return &media_type_; -} - -// Release the format block for a media type. -// http://msdn.microsoft.com/en-us/library/dd375432(VS.85).aspx -void VideoCaptureDeviceWin::ScopedMediaType::FreeMediaType(AM_MEDIA_TYPE* mt) { - if (mt->cbFormat != 0) { - CoTaskMemFree(mt->pbFormat); - mt->cbFormat = 0; - mt->pbFormat = NULL; - } - if (mt->pUnk != NULL) { - NOTREACHED(); - // pUnk should not be used. - mt->pUnk->Release(); - mt->pUnk = NULL; - } -} - -// Delete a media type structure that was allocated on the heap. -// http://msdn.microsoft.com/en-us/library/dd375432(VS.85).aspx -void VideoCaptureDeviceWin::ScopedMediaType::DeleteMediaType( - AM_MEDIA_TYPE* mt) { - if (mt != NULL) { - FreeMediaType(mt); - CoTaskMemFree(mt); - } -} - -VideoCaptureDeviceWin::VideoCaptureDeviceWin(const Name& device_name) - : device_name_(device_name), state_(kIdle) { - DetachFromThread(); -} - -VideoCaptureDeviceWin::~VideoCaptureDeviceWin() { - DCHECK(CalledOnValidThread()); - if (media_control_.get()) - media_control_->Stop(); - - if (graph_builder_.get()) { - if (sink_filter_.get()) { - graph_builder_->RemoveFilter(sink_filter_.get()); - sink_filter_ = NULL; - } - - if (capture_filter_.get()) - graph_builder_->RemoveFilter(capture_filter_.get()); - } - - if (capture_graph_builder_.get()) - capture_graph_builder_.Release(); -} - -bool VideoCaptureDeviceWin::Init() { - DCHECK(CalledOnValidThread()); - HRESULT hr; - - hr = GetDeviceFilter(device_name_.id(), CLSID_VideoInputDeviceCategory, - capture_filter_.Receive()); - - if (!capture_filter_.get()) { - DLOG(ERROR) << "Failed to create capture filter: " - << logging::SystemErrorCodeToString(hr); - return false; - } - - output_capture_pin_ = GetPin(capture_filter_.get(), PINDIR_OUTPUT, - PIN_CATEGORY_CAPTURE, GUID_NULL); - if (!output_capture_pin_.get()) { - DLOG(ERROR) << "Failed to get capture output pin"; - return false; - } - - // Create the sink filter used for receiving Captured frames. - sink_filter_ = new SinkFilter(this); - if (sink_filter_.get() == NULL) { - DLOG(ERROR) << "Failed to create send filter"; - return false; - } - - input_sink_pin_ = sink_filter_->GetPin(0); - - hr = graph_builder_.CreateInstance(CLSID_FilterGraph, NULL, - CLSCTX_INPROC_SERVER); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to create graph builder: " - << logging::SystemErrorCodeToString(hr); - return false; - } - - hr = capture_graph_builder_.CreateInstance(CLSID_CaptureGraphBuilder2, NULL, - CLSCTX_INPROC); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to create the Capture Graph Builder: " - << logging::SystemErrorCodeToString(hr); - return false; - } - - hr = capture_graph_builder_->SetFiltergraph(graph_builder_.get()); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to give graph to capture graph builder: " - << logging::SystemErrorCodeToString(hr); - return false; - } - - hr = graph_builder_.QueryInterface(media_control_.Receive()); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to create media control builder: " - << logging::SystemErrorCodeToString(hr); - return false; - } - - hr = graph_builder_->AddFilter(capture_filter_.get(), NULL); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to add the capture device to the graph: " - << logging::SystemErrorCodeToString(hr); - return false; - } - - hr = graph_builder_->AddFilter(sink_filter_.get(), NULL); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to add the send filter to the graph: " - << logging::SystemErrorCodeToString(hr); - return false; - } - - // The following code builds the upstream portions of the graph, - // for example if a capture device uses a Windows Driver Model (WDM) - // driver, the graph may require certain filters upstream from the - // WDM Video Capture filter, such as a TV Tuner filter or an Analog - // Video Crossbar filter. We try using the more prevalent - // MEDIATYPE_Interleaved first. - base::win::ScopedComPtr<IAMStreamConfig> stream_config; - - hr = capture_graph_builder_->FindInterface( - &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, capture_filter_.get(), - IID_IAMStreamConfig, (void**)stream_config.Receive()); - if (FAILED(hr)) { - hr = capture_graph_builder_->FindInterface( - &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, capture_filter_.get(), - IID_IAMStreamConfig, (void**)stream_config.Receive()); - DLOG_IF(ERROR, FAILED(hr)) << "Failed to find CapFilter:IAMStreamConfig: " - << logging::SystemErrorCodeToString(hr); - } - - return CreateCapabilityMap(); -} - -void VideoCaptureDeviceWin::AllocateAndStart( - const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) { - DCHECK(CalledOnValidThread()); - if (state_ != kIdle) - return; - - client_ = client.Pass(); - - // Get the camera capability that best match the requested format. - const CapabilityWin found_capability = - GetBestMatchedCapability(params.requested_format, capabilities_); - - // Reduce the frame rate if the requested frame rate is lower - // than the capability. - float frame_rate = std::min(found_capability.supported_format.frame_rate, - params.requested_format.frame_rate); - - ScopedComPtr<IAMStreamConfig> stream_config; - HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); - if (FAILED(hr)) { - SetErrorState("Can't get the Capture format settings"); - return; - } - - int count = 0, size = 0; - hr = stream_config->GetNumberOfCapabilities(&count, &size); - if (FAILED(hr)) { - SetErrorState("Failed to GetNumberOfCapabilities"); - return; - } - - scoped_ptr<BYTE[]> caps(new BYTE[size]); - ScopedMediaType media_type; - - // Get the windows capability from the capture device. - // GetStreamCaps can return S_FALSE which we consider an error. Therefore the - // FAILED macro can't be used. - hr = stream_config->GetStreamCaps(found_capability.stream_index, - media_type.Receive(), caps.get()); - if (hr != S_OK) { - SetErrorState("Failed to get capture device capabilities"); - return; - } - if (media_type->formattype == FORMAT_VideoInfo) { - VIDEOINFOHEADER* h = - reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); - if (frame_rate > 0) - h->AvgTimePerFrame = kSecondsToReferenceTime / frame_rate; - } - // Set the sink filter to request this format. - sink_filter_->SetRequestedMediaFormat( - found_capability.supported_format.pixel_format, frame_rate, - found_capability.info_header); - // Order the capture device to use this format. - hr = stream_config->SetFormat(media_type.get()); - if (FAILED(hr)) { - // TODO(grunell): Log the error. http://crbug.com/405016. - SetErrorState("Failed to set capture device output format"); - return; - } - - SetAntiFlickerInCaptureFilter(); - - if (media_type->subtype == kMediaSubTypeHDYC) { - // HDYC pixel format, used by the DeckLink capture card, needs an AVI - // decompressor filter after source, let |graph_builder_| add it. - hr = graph_builder_->Connect(output_capture_pin_.get(), - input_sink_pin_.get()); - } else { - hr = graph_builder_->ConnectDirect(output_capture_pin_.get(), - input_sink_pin_.get(), NULL); - } - - if (FAILED(hr)) { - SetErrorState("Failed to connect the Capture graph."); - return; - } - - hr = media_control_->Pause(); - if (FAILED(hr)) { - SetErrorState( - "Failed to Pause the Capture device. " - "Is it already occupied?"); - return; - } - - // Get the format back from the sink filter after the filter have been - // connected. - capture_format_ = sink_filter_->ResultingFormat(); - - // Start capturing. - hr = media_control_->Run(); - if (FAILED(hr)) { - SetErrorState("Failed to start the Capture device."); - return; - } - - state_ = kCapturing; -} - -void VideoCaptureDeviceWin::StopAndDeAllocate() { - DCHECK(CalledOnValidThread()); - if (state_ != kCapturing) - return; - - HRESULT hr = media_control_->Stop(); - if (FAILED(hr)) { - SetErrorState("Failed to stop the capture graph."); - return; - } - - graph_builder_->Disconnect(output_capture_pin_.get()); - graph_builder_->Disconnect(input_sink_pin_.get()); - - client_.reset(); - state_ = kIdle; -} - -// Implements SinkFilterObserver::SinkFilterObserver. -void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer, int length) { - client_->OnIncomingCapturedData(buffer, length, capture_format_, 0, - base::TimeTicks::Now()); -} - -bool VideoCaptureDeviceWin::CreateCapabilityMap() { - DCHECK(CalledOnValidThread()); - ScopedComPtr<IAMStreamConfig> stream_config; - HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); - if (FAILED(hr)) { - DPLOG(ERROR) << "Failed to get IAMStreamConfig interface from " - "capture device: " << logging::SystemErrorCodeToString(hr); - return false; - } - - // Get interface used for getting the frame rate. - ScopedComPtr<IAMVideoControl> video_control; - hr = capture_filter_.QueryInterface(video_control.Receive()); - DLOG_IF(WARNING, FAILED(hr)) << "IAMVideoControl Interface NOT SUPPORTED: " - << logging::SystemErrorCodeToString(hr); - - int count = 0, size = 0; - hr = stream_config->GetNumberOfCapabilities(&count, &size); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to GetNumberOfCapabilities: " - << logging::SystemErrorCodeToString(hr); - return false; - } - - scoped_ptr<BYTE[]> caps(new BYTE[size]); - for (int stream_index = 0; stream_index < count; ++stream_index) { - ScopedMediaType media_type; - hr = stream_config->GetStreamCaps(stream_index, media_type.Receive(), - caps.get()); - // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() - // macros here since they'll trigger incorrectly. - if (hr != S_OK) { - DLOG(ERROR) << "Failed to GetStreamCaps: " - << logging::SystemErrorCodeToString(hr); - return false; - } - - if (media_type->majortype == MEDIATYPE_Video && - media_type->formattype == FORMAT_VideoInfo) { - VideoCaptureFormat format; - format.pixel_format = - TranslateMediaSubtypeToPixelFormat(media_type->subtype); - if (format.pixel_format == VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN) - continue; - - VIDEOINFOHEADER* h = - reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); - format.frame_size.SetSize(h->bmiHeader.biWidth, h->bmiHeader.biHeight); - - // Try to get a better |time_per_frame| from IAMVideoControl. If not, use - // the value from VIDEOINFOHEADER. - REFERENCE_TIME time_per_frame = h->AvgTimePerFrame; - if (video_control.get()) { - ScopedCoMem<LONGLONG> max_fps; - LONG list_size = 0; - const SIZE size = {format.frame_size.width(), - format.frame_size.height()}; - hr = video_control->GetFrameRateList(output_capture_pin_.get(), - stream_index, size, &list_size, - &max_fps); - // Can't assume the first value will return the max fps. - // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some - // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates - // into success, so explicitly check S_OK. See http://crbug.com/306237. - if (hr == S_OK && list_size > 0 && max_fps) { - time_per_frame = - *std::min_element(max_fps.get(), max_fps.get() + list_size); - } - } - - format.frame_rate = - (time_per_frame > 0) - ? (kSecondsToReferenceTime / static_cast<float>(time_per_frame)) - : 0.0; - - capabilities_.emplace_back(stream_index, format, h->bmiHeader); - } - } - - return !capabilities_.empty(); -} - -// Set the power line frequency removal in |capture_filter_| if available. -void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter() { - const int power_line_frequency = GetPowerLineFrequencyForLocation(); - if (power_line_frequency != kPowerLine50Hz && - power_line_frequency != kPowerLine60Hz) { - return; - } - ScopedComPtr<IKsPropertySet> ks_propset; - DWORD type_support = 0; - HRESULT hr; - if (SUCCEEDED(hr = ks_propset.QueryFrom(capture_filter_.get())) && - SUCCEEDED(hr = ks_propset->QuerySupported( - PROPSETID_VIDCAP_VIDEOPROCAMP, - KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY, - &type_support)) && - (type_support & KSPROPERTY_SUPPORT_SET)) { - KSPROPERTY_VIDEOPROCAMP_S data = {}; - data.Property.Set = PROPSETID_VIDCAP_VIDEOPROCAMP; - data.Property.Id = KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY; - data.Property.Flags = KSPROPERTY_TYPE_SET; - data.Value = (power_line_frequency == kPowerLine50Hz) ? 1 : 2; - data.Flags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL; - hr = ks_propset->Set(PROPSETID_VIDCAP_VIDEOPROCAMP, - KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY, &data, - sizeof(data), &data, sizeof(data)); - DLOG_IF(ERROR, FAILED(hr)) << "Anti-flicker setting failed: " - << logging::SystemErrorCodeToString(hr); - DVLOG_IF(2, SUCCEEDED(hr)) << "Anti-flicker set correctly."; - } else { - DVLOG(2) << "Anti-flicker setting not supported."; - } -} - -void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) { - DCHECK(CalledOnValidThread()); - state_ = kError; - client_->OnError(reason); -} -} // namespace media diff --git a/media/video/capture/win/video_capture_device_win.h b/media/video/capture/win/video_capture_device_win.h deleted file mode 100644 index 53eb338..0000000 --- a/media/video/capture/win/video_capture_device_win.h +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) 2012 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. - -// Windows specific implementation of VideoCaptureDevice. -// DirectShow is used for capturing. DirectShow provide its own threads -// for capturing. - -#ifndef MEDIA_VIDEO_CAPTURE_WIN_VIDEO_CAPTURE_DEVICE_WIN_H_ -#define MEDIA_VIDEO_CAPTURE_WIN_VIDEO_CAPTURE_DEVICE_WIN_H_ - -// Avoid including strsafe.h via dshow as it will cause build warnings. -#define NO_DSHOW_STRSAFE -#include <dshow.h> - -#include <map> -#include <string> - -#include "base/threading/non_thread_safe.h" -#include "base/threading/thread.h" -#include "base/win/scoped_comptr.h" -#include "media/base/video_capture_types.h" -#include "media/video/capture/video_capture_device.h" -#include "media/video/capture/win/capability_list_win.h" -#include "media/video/capture/win/sink_filter_win.h" -#include "media/video/capture/win/sink_input_pin_win.h" - -namespace media { - -// All the methods in the class can only be run on a COM initialized thread. -class VideoCaptureDeviceWin - : public base::NonThreadSafe, - public VideoCaptureDevice, - public SinkFilterObserver { - public: - // A utility class that wraps the AM_MEDIA_TYPE type and guarantees that - // we free the structure when exiting the scope. DCHECKing is also done to - // avoid memory leaks. - class ScopedMediaType { - public: - ScopedMediaType() : media_type_(NULL) {} - ~ScopedMediaType() { Free(); } - - AM_MEDIA_TYPE* operator->() { return media_type_; } - AM_MEDIA_TYPE* get() { return media_type_; } - void Free(); - AM_MEDIA_TYPE** Receive(); - - private: - void FreeMediaType(AM_MEDIA_TYPE* mt); - void DeleteMediaType(AM_MEDIA_TYPE* mt); - - AM_MEDIA_TYPE* media_type_; - }; - - static HRESULT GetDeviceFilter(const std::string& device_id, - const CLSID device_class_id, - IBaseFilter** filter); - static base::win::ScopedComPtr<IPin> GetPin(IBaseFilter* filter, - PIN_DIRECTION pin_dir, - REFGUID category, - REFGUID major_type); - static VideoCapturePixelFormat TranslateMediaSubtypeToPixelFormat( - const GUID& sub_type); - - explicit VideoCaptureDeviceWin(const Name& device_name); - ~VideoCaptureDeviceWin() override; - // Opens the device driver for this device. - bool Init(); - - // VideoCaptureDevice implementation. - void AllocateAndStart(const VideoCaptureParams& params, - scoped_ptr<VideoCaptureDevice::Client> client) override; - void StopAndDeAllocate() override; - - private: - enum InternalState { - kIdle, // The device driver is opened but camera is not in use. - kCapturing, // Video is being captured. - kError // Error accessing HW functions. - // User needs to recover by destroying the object. - }; - - // Implements SinkFilterObserver. - void FrameReceived(const uint8* buffer, int length) override; - - bool CreateCapabilityMap(); - void SetAntiFlickerInCaptureFilter(); - void SetErrorState(const std::string& reason); - - Name device_name_; - InternalState state_; - scoped_ptr<VideoCaptureDevice::Client> client_; - - base::win::ScopedComPtr<IBaseFilter> capture_filter_; - - base::win::ScopedComPtr<IGraphBuilder> graph_builder_; - base::win::ScopedComPtr<ICaptureGraphBuilder2> capture_graph_builder_; - - base::win::ScopedComPtr<IMediaControl> media_control_; - base::win::ScopedComPtr<IPin> input_sink_pin_; - base::win::ScopedComPtr<IPin> output_capture_pin_; - - scoped_refptr<SinkFilter> sink_filter_; - - // Map of all capabilities this device support. - CapabilityList capabilities_; - VideoCaptureFormat capture_format_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceWin); -}; - -} // namespace media - -#endif // MEDIA_VIDEO_CAPTURE_WIN_VIDEO_CAPTURE_DEVICE_WIN_H_ |