diff options
Diffstat (limited to 'content/browser/renderer_host')
-rw-r--r-- | content/browser/renderer_host/browser_render_process_host.cc | 6 | ||||
-rw-r--r-- | content/browser/renderer_host/media/OWNERS | 9 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_common.cc (renamed from content/browser/renderer_host/audio_common.cc) | 2 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_common.h (renamed from content/browser/renderer_host/audio_common.h) | 6 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_input_renderer_host.cc (renamed from content/browser/renderer_host/audio_input_renderer_host.cc) | 6 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_input_renderer_host.h (renamed from content/browser/renderer_host/audio_input_renderer_host.h) | 6 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_input_sync_writer.cc (renamed from content/browser/renderer_host/audio_input_sync_writer.cc) | 4 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_input_sync_writer.h (renamed from content/browser/renderer_host/audio_input_sync_writer.h) | 6 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_renderer_host.cc (renamed from content/browser/renderer_host/audio_renderer_host.cc) | 6 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_renderer_host.h (renamed from content/browser/renderer_host/audio_renderer_host.h) | 6 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_renderer_host_unittest.cc (renamed from content/browser/renderer_host/audio_renderer_host_unittest.cc) | 2 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_sync_reader.cc (renamed from content/browser/renderer_host/audio_sync_reader.cc) | 4 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_sync_reader.h (renamed from content/browser/renderer_host/audio_sync_reader.h) | 8 | ||||
-rw-r--r-- | content/browser/renderer_host/media/media_stream_provider.cc | 29 | ||||
-rw-r--r-- | content/browser/renderer_host/media/media_stream_provider.h | 108 | ||||
-rw-r--r-- | content/browser/renderer_host/media/video_capture_controller.cc (renamed from content/browser/renderer_host/video_capture_controller.cc) | 4 | ||||
-rw-r--r-- | content/browser/renderer_host/media/video_capture_controller.h (renamed from content/browser/renderer_host/video_capture_controller.h) | 8 | ||||
-rw-r--r-- | content/browser/renderer_host/media/video_capture_controller_event_handler.cc (renamed from content/browser/renderer_host/video_capture_controller_event_handler.cc) | 2 | ||||
-rw-r--r-- | content/browser/renderer_host/media/video_capture_controller_event_handler.h (renamed from content/browser/renderer_host/video_capture_controller_event_handler.h) | 6 | ||||
-rw-r--r-- | content/browser/renderer_host/media/video_capture_host.cc (renamed from content/browser/renderer_host/video_capture_host.cc) | 2 | ||||
-rw-r--r-- | content/browser/renderer_host/media/video_capture_host.h (renamed from content/browser/renderer_host/video_capture_host.h) | 8 | ||||
-rw-r--r-- | content/browser/renderer_host/media/video_capture_host_unittest.cc (renamed from content/browser/renderer_host/video_capture_host_unittest.cc) | 4 | ||||
-rw-r--r-- | content/browser/renderer_host/media/video_capture_manager.cc | 383 | ||||
-rw-r--r-- | content/browser/renderer_host/media/video_capture_manager.h | 125 | ||||
-rw-r--r-- | content/browser/renderer_host/media/video_capture_manager_unittest.cc | 296 |
25 files changed, 998 insertions, 48 deletions
diff --git a/content/browser/renderer_host/browser_render_process_host.cc b/content/browser/renderer_host/browser_render_process_host.cc index 3b5dad0..f30ae78 100644 --- a/content/browser/renderer_host/browser_render_process_host.cc +++ b/content/browser/renderer_host/browser_render_process_host.cc @@ -40,14 +40,13 @@ #include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h" #include "content/browser/mime_registry_message_filter.h" #include "content/browser/plugin_service.h" -#include "content/browser/renderer_host/audio_input_renderer_host.h" -#include "content/browser/renderer_host/audio_renderer_host.h" #include "content/browser/renderer_host/blob_message_filter.h" #include "content/browser/renderer_host/clipboard_message_filter.h" #include "content/browser/renderer_host/database_message_filter.h" -#include "content/browser/resolve_proxy_msg_helper.h" #include "content/browser/renderer_host/file_utilities_message_filter.h" #include "content/browser/renderer_host/gpu_message_filter.h" +#include "content/browser/renderer_host/media/audio_input_renderer_host.h" +#include "content/browser/renderer_host/media/audio_renderer_host.h" #include "content/browser/renderer_host/p2p/socket_dispatcher_host.h" #include "content/browser/renderer_host/pepper_file_message_filter.h" #include "content/browser/renderer_host/pepper_message_filter.h" @@ -59,6 +58,7 @@ #include "content/browser/renderer_host/render_widget_host.h" #include "content/browser/renderer_host/resource_message_filter.h" #include "content/browser/renderer_host/socket_stream_dispatcher_host.h" +#include "content/browser/resolve_proxy_msg_helper.h" #include "content/browser/speech/speech_input_dispatcher_host.h" #include "content/browser/trace_message_filter.h" #include "content/browser/user_metrics.h" diff --git a/content/browser/renderer_host/media/OWNERS b/content/browser/renderer_host/media/OWNERS new file mode 100644 index 0000000..d37c12f --- /dev/null +++ b/content/browser/renderer_host/media/OWNERS @@ -0,0 +1,9 @@ +acolwell@chromium.org +annacc@chromium.org +ddorwin@chormium.org +fischman@chromium.org +imasaki@chromium.org +scherkus@chromium.org +sjl@chromium.org +vrk@chromium.org +wjia@chromium.org diff --git a/content/browser/renderer_host/audio_common.cc b/content/browser/renderer_host/media/audio_common.cc index 50bc068..7126ddb 100644 --- a/content/browser/renderer_host/audio_common.cc +++ b/content/browser/renderer_host/media/audio_common.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/audio_common.h" +#include "content/browser/renderer_host/media/audio_common.h" #include "base/time.h" #include "media/audio/audio_parameters.h" diff --git a/content/browser/renderer_host/audio_common.h b/content/browser/renderer_host/media/audio_common.h index 8e60316..52b7337 100644 --- a/content/browser/renderer_host/audio_common.h +++ b/content/browser/renderer_host/media/audio_common.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_AUDIO_COMMON_H_ -#define CONTENT_BROWSER_RENDERER_HOST_AUDIO_COMMON_H_ +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_COMMON_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_COMMON_H_ #pragma once #include "base/basictypes.h" @@ -14,4 +14,4 @@ struct AudioParameters; // of audio parameters. uint32 SelectSamplesPerPacket(const AudioParameters& params); -#endif // CONTENT_BROWSER_RENDERER_HOST_AUDIO_COMMON_H_ +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_COMMON_H_ diff --git a/content/browser/renderer_host/audio_input_renderer_host.cc b/content/browser/renderer_host/media/audio_input_renderer_host.cc index 2aee865..4a5c57a 100644 --- a/content/browser/renderer_host/audio_input_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/audio_input_renderer_host.h" +#include "content/browser/renderer_host/media/audio_input_renderer_host.h" #include "base/metrics/histogram.h" #include "base/process.h" #include "base/shared_memory.h" -#include "content/browser/renderer_host/audio_common.h" -#include "content/browser/renderer_host/audio_input_sync_writer.h" +#include "content/browser/renderer_host/media/audio_common.h" +#include "content/browser/renderer_host/media/audio_input_sync_writer.h" #include "content/common/audio_messages.h" #include "ipc/ipc_logging.h" diff --git a/content/browser/renderer_host/audio_input_renderer_host.h b/content/browser/renderer_host/media/audio_input_renderer_host.h index 4452569..82b79a3 100644 --- a/content/browser/renderer_host/audio_input_renderer_host.h +++ b/content/browser/renderer_host/media/audio_input_renderer_host.h @@ -15,8 +15,8 @@ // For low latency audio, a SyncSocket pair is used to signal buffer readiness // without having to route messages using the IO thread. -#ifndef CONTENT_BROWSER_RENDERER_HOST_AUDIO_INPUT_RENDERER_HOST_H_ -#define CONTENT_BROWSER_RENDERER_HOST_AUDIO_INPUT_RENDERER_HOST_H_ +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_RENDERER_HOST_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_RENDERER_HOST_H_ #pragma once #include <map> @@ -161,4 +161,4 @@ class AudioInputRendererHost : public BrowserMessageFilter, DISALLOW_COPY_AND_ASSIGN(AudioInputRendererHost); }; -#endif // CONTENT_BROWSER_RENDERER_HOST_AUDIO_INPUT_RENDERER_HOST_H_ +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_RENDERER_HOST_H_ diff --git a/content/browser/renderer_host/audio_input_sync_writer.cc b/content/browser/renderer_host/media/audio_input_sync_writer.cc index cd4acca..b027479 100644 --- a/content/browser/renderer_host/audio_input_sync_writer.cc +++ b/content/browser/renderer_host/media/audio_input_sync_writer.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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 "content/browser/renderer_host/audio_input_sync_writer.h" +#include "content/browser/renderer_host/media/audio_input_sync_writer.h" #include "base/process_util.h" #include "base/shared_memory.h" diff --git a/content/browser/renderer_host/audio_input_sync_writer.h b/content/browser/renderer_host/media/audio_input_sync_writer.h index af95e069..5dc89df 100644 --- a/content/browser/renderer_host/audio_input_sync_writer.h +++ b/content/browser/renderer_host/media/audio_input_sync_writer.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_AUDIO_INPUT_SYNC_WRITER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_AUDIO_INPUT_SYNC_WRITER_H_ +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_SYNC_WRITER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_SYNC_WRITER_H_ #pragma once #include "base/file_descriptor_posix.h" @@ -51,4 +51,4 @@ class AudioInputSyncWriter : public media::AudioInputController::SyncWriter { DISALLOW_IMPLICIT_CONSTRUCTORS(AudioInputSyncWriter); }; -#endif // CONTENT_BROWSER_RENDERER_HOST_AUDIO_INPUT_SYNC_WRITER_H_ +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_SYNC_WRITER_H_ diff --git a/content/browser/renderer_host/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc index 2f4bce1..5ee647c 100644 --- a/content/browser/renderer_host/audio_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_renderer_host.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/audio_renderer_host.h" +#include "content/browser/renderer_host/media/audio_renderer_host.h" #include "base/metrics/histogram.h" #include "base/process.h" #include "base/shared_memory.h" -#include "content/browser/renderer_host/audio_common.h" -#include "content/browser/renderer_host/audio_sync_reader.h" +#include "content/browser/renderer_host/media/audio_common.h" +#include "content/browser/renderer_host/media/audio_sync_reader.h" #include "content/common/audio_messages.h" #include "ipc/ipc_logging.h" diff --git a/content/browser/renderer_host/audio_renderer_host.h b/content/browser/renderer_host/media/audio_renderer_host.h index 30dee10..944857f 100644 --- a/content/browser/renderer_host/audio_renderer_host.h +++ b/content/browser/renderer_host/media/audio_renderer_host.h @@ -49,8 +49,8 @@ // pair is used to signal buffer readiness without having to route messages // using the IO thread. -#ifndef CONTENT_BROWSER_RENDERER_HOST_AUDIO_RENDERER_HOST_H_ -#define CONTENT_BROWSER_RENDERER_HOST_AUDIO_RENDERER_HOST_H_ +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_ #pragma once #include <map> @@ -219,4 +219,4 @@ class AudioRendererHost : public BrowserMessageFilter, DISALLOW_COPY_AND_ASSIGN(AudioRendererHost); }; -#endif // CONTENT_BROWSER_RENDERER_HOST_AUDIO_RENDERER_HOST_H_ +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_ diff --git a/content/browser/renderer_host/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc index 6a13acd..df2d5b0 100644 --- a/content/browser/renderer_host/audio_renderer_host_unittest.cc +++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc @@ -8,7 +8,7 @@ #include "base/process_util.h" #include "base/sync_socket.h" #include "content/browser/browser_thread.h" -#include "content/browser/renderer_host/audio_renderer_host.h" +#include "content/browser/renderer_host/media/audio_renderer_host.h" #include "content/common/audio_messages.h" #include "ipc/ipc_message_utils.h" #include "media/audio/audio_manager.h" diff --git a/content/browser/renderer_host/audio_sync_reader.cc b/content/browser/renderer_host/media/audio_sync_reader.cc index 261bec0..b6f779e 100644 --- a/content/browser/renderer_host/audio_sync_reader.cc +++ b/content/browser/renderer_host/media/audio_sync_reader.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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 "content/browser/renderer_host/audio_sync_reader.h" +#include "content/browser/renderer_host/media/audio_sync_reader.h" #include "base/process_util.h" #include "base/shared_memory.h" diff --git a/content/browser/renderer_host/audio_sync_reader.h b/content/browser/renderer_host/media/audio_sync_reader.h index 054bb52..ddb5d61 100644 --- a/content/browser/renderer_host/audio_sync_reader.h +++ b/content/browser/renderer_host/media/audio_sync_reader.h @@ -1,9 +1,9 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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. -#ifndef CONTENT_BROWSER_RENDERER_HOST_AUDIO_SYNC_READER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_AUDIO_SYNC_READER_H_ +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_SYNC_READER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_SYNC_READER_H_ #pragma once #include "base/file_descriptor_posix.h" @@ -53,4 +53,4 @@ class AudioSyncReader : public media::AudioOutputController::SyncReader { DISALLOW_COPY_AND_ASSIGN(AudioSyncReader); }; -#endif // CONTENT_BROWSER_RENDERER_HOST_AUDIO_SYNC_READER_H_ +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_SYNC_READER_H_ diff --git a/content/browser/renderer_host/media/media_stream_provider.cc b/content/browser/renderer_host/media/media_stream_provider.cc new file mode 100644 index 0000000..d446929 --- /dev/null +++ b/content/browser/renderer_host/media/media_stream_provider.cc @@ -0,0 +1,29 @@ +// 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 "content/browser/renderer_host/media/media_stream_provider.h" + +namespace media_stream { + +MediaCaptureDeviceInfo::MediaCaptureDeviceInfo() + : stream_type(kNoService), + name(), + device_id(), + in_use(false) {} + +MediaCaptureDeviceInfo::MediaCaptureDeviceInfo(MediaStreamType service_param, + const std::string name_param, + const std::string device_param, + bool opened) + : stream_type(service_param), + name(name_param), + device_id(device_param), + in_use(opened) {} + +MediaStreamProviderListener::~MediaStreamProviderListener() {} + +MediaStreamProvider::~MediaStreamProvider() {} + +} // namespace + diff --git a/content/browser/renderer_host/media/media_stream_provider.h b/content/browser/renderer_host/media/media_stream_provider.h new file mode 100644 index 0000000..a864847 --- /dev/null +++ b/content/browser/renderer_host/media/media_stream_provider.h @@ -0,0 +1,108 @@ +// 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. + +// MediaStreamProvider is used to capture media of the types defined in +// MediaStreamType. There is only one MediaStreamProvider instance per media +// type and a MediaStreamProvider instance can have only one registered +// listener. +// The MediaStreamManager is expected to be called on Browser::IO thread and +// the listener will be called on the same thread. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_PROVIDER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_PROVIDER_H_ + +#include <list> +#include <string> + +namespace media_stream { + +// TODO(mflodman) Create a common type to use for all video capture and media +// stream classes. +typedef int MediaCaptureSessionId; + +enum MediaStreamType { + kNoService = 0, + kAudioCapture, + kVideoCapture +}; + +enum MediaStreamProviderError { + kMediaStreamOk = 0, + kInvalidMediaStreamType, + kInvalidSession, + kUnknownSession, + kDeviceNotAvailable, + kDeviceAlreadyInUse, + kUnknownError +}; + +enum { kInvalidMediaCaptureSessionId = 0xFFFFFFFF }; + +struct MediaCaptureDeviceInfo { + MediaCaptureDeviceInfo(); + MediaCaptureDeviceInfo(MediaStreamType service_param, + const std::string name_param, + const std::string device_param, + bool opened); + + MediaStreamType stream_type; + std::string name; + std::string device_id; + bool in_use; +}; + +typedef std::list<MediaCaptureDeviceInfo> MediaCaptureDevices; + +// Callback class used by MediaStreamProvider. +class MediaStreamProviderListener { + public: + // Called by a MediaStreamProvider when a stream has been opened. + virtual void Opened(MediaStreamType stream_type, + MediaCaptureSessionId capture_session_id) = 0; + + // Called by a MediaStreamProvider when a stream has been closed. + virtual void Closed(MediaStreamType stream_type, + MediaCaptureSessionId capture_session_id) = 0; + + // Called by a MediaStreamProvider when available devices has been enumerated. + virtual void DevicesEnumerated(MediaStreamType stream_type, + const MediaCaptureDevices& devices) = 0; + + // Called by a MediaStreamProvider when an error has occured. + virtual void Error(MediaStreamType stream_type, + MediaCaptureSessionId capture_session_id, + MediaStreamProviderError error) = 0; + + protected: + virtual ~MediaStreamProviderListener(); +}; + +// Implemented by a manager class providing captured media. +class MediaStreamProvider { + public: + // Registers a listener, only one listener is allowed. + virtual bool Register(MediaStreamProviderListener* listener) = 0; + + // Unregisters the previously registered listener. + virtual void Unregister() = 0; + + // Enumerates existing capture devices and calls |DevicesEnumerated|. + virtual void EnumerateDevices() = 0; + + // Opens the specified device. The device is not started and it is still + // possible for other applications to open the device before the device is + // started. |Opened| is called when the device is opened. + // kInvalidMediaCaptureSessionId is returned on error. + virtual MediaCaptureSessionId Open(const MediaCaptureDeviceInfo& device) = 0; + + // Closes the specified device and calls |Closed| when done. + virtual void Close(MediaCaptureSessionId capture_session_id) = 0; + + protected: + virtual ~MediaStreamProvider(); +}; + +} // namespace media_stream + +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_PROVIDER_H_ diff --git a/content/browser/renderer_host/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc index c36232b..228656d 100644 --- a/content/browser/renderer_host/video_capture_controller.cc +++ b/content/browser/renderer_host/media/video_capture_controller.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/video_capture_controller.h" +#include "content/browser/renderer_host/media/video_capture_controller.h" #include "base/stl_util-inl.h" #include "content/browser/browser_thread.h" -#include "content/browser/media_stream/video_capture_manager.h" +#include "content/browser/renderer_host/media/video_capture_manager.h" #include "media/base/yuv_convert.h" // The number of TransportDIBs VideoCaptureController allocate. diff --git a/content/browser/renderer_host/video_capture_controller.h b/content/browser/renderer_host/media/video_capture_controller.h index 4879492..432ac4a 100644 --- a/content/browser/renderer_host/video_capture_controller.h +++ b/content/browser/renderer_host/media/video_capture_controller.h @@ -12,8 +12,8 @@ // from a VideoCaptureDevice object and do color conversion straight into the // TransportDIBs to avoid a memory copy. -#ifndef CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_CONTROLLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_CONTROLLER_H_ +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_H_ #include <list> #include <map> @@ -22,7 +22,7 @@ #include "base/process.h" #include "base/synchronization/lock.h" #include "base/task.h" -#include "content/browser/renderer_host/video_capture_controller_event_handler.h" +#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h" #include "media/video/capture/video_capture_device.h" #include "media/video/capture/video_capture_types.h" #include "ui/gfx/surface/transport_dib.h" @@ -90,4 +90,4 @@ class VideoCaptureController DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureController); }; -#endif // CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_CONTROLLER_H_ +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_H_ diff --git a/content/browser/renderer_host/video_capture_controller_event_handler.cc b/content/browser/renderer_host/media/video_capture_controller_event_handler.cc index e9fcf3f..61ccc4a 100644 --- a/content/browser/renderer_host/video_capture_controller_event_handler.cc +++ b/content/browser/renderer_host/media/video_capture_controller_event_handler.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/video_capture_controller_event_handler.h" +#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h" VideoCaptureControllerID::VideoCaptureControllerID(int32 rid, int did) : routing_id(rid), diff --git a/content/browser/renderer_host/video_capture_controller_event_handler.h b/content/browser/renderer_host/media/video_capture_controller_event_handler.h index 397e5ae..73424bb 100644 --- a/content/browser/renderer_host/video_capture_controller_event_handler.h +++ b/content/browser/renderer_host/media/video_capture_controller_event_handler.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_CONTROLLER_EVENT_HANDLER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_CONTROLLER_EVENT_HANDLER_H_ +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_EVENT_HANDLER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_EVENT_HANDLER_H_ #include "base/shared_memory.h" #include "base/time.h" @@ -49,4 +49,4 @@ class VideoCaptureControllerEventHandler { virtual ~VideoCaptureControllerEventHandler() {} }; -#endif // CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_CONTROLLER_EVENT_HANDLER_H_ +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_EVENT_HANDLER_H_ diff --git a/content/browser/renderer_host/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc index f4e4011..01cd3e0 100644 --- a/content/browser/renderer_host/video_capture_host.cc +++ b/content/browser/renderer_host/media/video_capture_host.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/video_capture_host.h" +#include "content/browser/renderer_host/media/video_capture_host.h" #include "base/memory/scoped_ptr.h" #include "base/stl_util-inl.h" diff --git a/content/browser/renderer_host/video_capture_host.h b/content/browser/renderer_host/media/video_capture_host.h index d2f611f05..1a57a04 100644 --- a/content/browser/renderer_host/video_capture_host.h +++ b/content/browser/renderer_host/media/video_capture_host.h @@ -33,14 +33,14 @@ // | (kStopped) | // v v -#ifndef CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_HOST_H_ -#define CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_HOST_H_ +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_HOST_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_HOST_H_ #include <map> #include "base/memory/ref_counted.h" #include "content/browser/browser_message_filter.h" -#include "content/browser/renderer_host/video_capture_controller.h" +#include "content/browser/renderer_host/media/video_capture_controller.h" #include "ipc/ipc_message.h" class VideoCaptureHost : public BrowserMessageFilter, @@ -134,4 +134,4 @@ class VideoCaptureHost : public BrowserMessageFilter, DISALLOW_COPY_AND_ASSIGN(VideoCaptureHost); }; -#endif // CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_HOST_H_ +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_HOST_H_ diff --git a/content/browser/renderer_host/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc index e9986ca..a7a56ab 100644 --- a/content/browser/renderer_host/video_capture_host_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc @@ -12,8 +12,8 @@ #include "base/stl_util-inl.h" #include "base/stringprintf.h" #include "content/browser/browser_thread.h" -#include "content/browser/media_stream/video_capture_manager.h" -#include "content/browser/renderer_host/video_capture_host.h" +#include "content/browser/renderer_host/media/video_capture_host.h" +#include "content/browser/renderer_host/media/video_capture_manager.h" #include "content/common/video_capture_messages.h" #include "media/video/capture/video_capture_types.h" diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc new file mode 100644 index 0000000..787f577 --- /dev/null +++ b/content/browser/renderer_host/media/video_capture_manager.cc @@ -0,0 +1,383 @@ +// 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 "content/browser/renderer_host/media/video_capture_manager.h" + +#include "base/memory/scoped_ptr.h" +#include "content/browser/browser_thread.h" +#include "media/video/capture/fake_video_capture_device.h" +#include "media/video/capture/video_capture_device.h" + +namespace media_stream { + +// Starting id for the first capture session. +// VideoCaptureManager::kStartOpenSessionId is used as default id without +// explicitly calling open device. +enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 }; + +static ::base::LazyInstance<VideoCaptureManager> g_video_capture_manager( + base::LINKER_INITIALIZED); + +VideoCaptureManager* VideoCaptureManager::Get() { + return g_video_capture_manager.Pointer(); +} + +VideoCaptureManager::VideoCaptureManager() + : vc_device_thread_("VideoCaptureManagerThread"), + listener_(NULL), + new_capture_session_id_(kFirstSessionId), + devices_(), + use_fake_device_(false) { + vc_device_thread_.Start(); +} + +VideoCaptureManager::~VideoCaptureManager() { + vc_device_thread_.Stop(); +} + +bool VideoCaptureManager::Register(MediaStreamProviderListener* listener) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK(!listener_); + listener_ = listener; + return true; +} + +void VideoCaptureManager::Unregister() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + listener_ = NULL; +} + +void VideoCaptureManager::EnumerateDevices() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK(listener_); + + vc_device_thread_.message_loop()->PostTask( + FROM_HERE, + NewRunnableMethod(this, + &VideoCaptureManager::OnEnumerateDevices)); +} + +MediaCaptureSessionId VideoCaptureManager::Open( + const MediaCaptureDeviceInfo& device) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK(listener_); + + // Generate a new id for this device + MediaCaptureSessionId video_capture_session_id = new_capture_session_id_++; + + vc_device_thread_.message_loop()->PostTask( + FROM_HERE, + NewRunnableMethod(this, + &VideoCaptureManager::OnOpen, + video_capture_session_id, + device)); + + return video_capture_session_id; +} + +void VideoCaptureManager::Close(MediaCaptureSessionId capture_session_id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK(listener_); + + vc_device_thread_.message_loop()->PostTask( + FROM_HERE, + NewRunnableMethod(this, + &VideoCaptureManager::OnClose, + capture_session_id)); +} + +void VideoCaptureManager::Start( + const media::VideoCaptureParams& capture_params, + media::VideoCaptureDevice::EventHandler* video_capture_receiver) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + vc_device_thread_.message_loop()->PostTask( + FROM_HERE, + NewRunnableMethod(this, + &VideoCaptureManager::OnStart, + capture_params, + video_capture_receiver)); +} + +void VideoCaptureManager::Stop( + const media::VideoCaptureSessionId capture_session_id, Task* stopped_task) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + vc_device_thread_.message_loop()->PostTask( + FROM_HERE, + NewRunnableMethod(this, + &VideoCaptureManager::OnStop, + capture_session_id, + stopped_task)); +} + +void VideoCaptureManager::UseFakeDevice() { + use_fake_device_ = true; +} + +MessageLoop* VideoCaptureManager::GetMessageLoop() { + return vc_device_thread_.message_loop(); +} + +void VideoCaptureManager::OnEnumerateDevices() { + DCHECK(IsOnCaptureDeviceThread()); + + scoped_ptr<media::VideoCaptureDevice::Names> device_names( + new media::VideoCaptureDevice::Names()); + GetAvailableDevices(device_names.get()); + + MediaCaptureDevices devices; + for (media::VideoCaptureDevice::Names::iterator it = + device_names.get()->begin(); it != device_names.get()->end(); ++it) { + bool opened = DeviceOpened(*it); + devices.push_back(MediaCaptureDeviceInfo(kVideoCapture, it->device_name, + it->unique_id, opened)); + } + + PostOnDevicesEnumerated(devices); + + // Clean-up + devices.clear(); + device_names.get()->clear(); +} + +void VideoCaptureManager::OnOpen(MediaCaptureSessionId capture_session_id, + const MediaCaptureDeviceInfo device) { + DCHECK(IsOnCaptureDeviceThread()); + DCHECK(devices_.find(capture_session_id) == devices_.end()); + + // Check if another session has already opened this device, only one user per + // device is supported. + if (DeviceOpened(device)) { + PostOnError(capture_session_id, kDeviceAlreadyInUse); + return; + } + + // Open the device + media::VideoCaptureDevice::Name vc_device_name; + vc_device_name.device_name = device.name; + vc_device_name.unique_id = device.device_id; + + media::VideoCaptureDevice* video_capture_device = NULL; + if (!use_fake_device_) { + video_capture_device = media::VideoCaptureDevice::Create(vc_device_name); + } else { + video_capture_device = + media::FakeVideoCaptureDevice::Create(vc_device_name); + } + if (video_capture_device == NULL) { + PostOnError(capture_session_id, kDeviceNotAvailable); + return; + } + + devices_[capture_session_id] = video_capture_device; + PostOnOpened(capture_session_id); +} + +void VideoCaptureManager::OnClose( + MediaCaptureSessionId capture_session_id) { + DCHECK(IsOnCaptureDeviceThread()); + + VideoCaptureDevices::iterator it = devices_.find(capture_session_id); + if (it != devices_.end()) { + // Deallocate (if not done already) and delete the device + media::VideoCaptureDevice* video_capture_device = it->second; + video_capture_device->DeAllocate(); + delete video_capture_device; + devices_.erase(it); + } + + PostOnClosed(capture_session_id); +} + +void VideoCaptureManager::OnStart( + const media::VideoCaptureParams capture_params, + media::VideoCaptureDevice::EventHandler* video_capture_receiver) { + DCHECK(IsOnCaptureDeviceThread()); + + // Solution for not using MediaStreamManager + // This session id won't be returned by Open() + if (capture_params.session_id == kStartOpenSessionId) { + // Start() is called without using Open(), we need to open a device + scoped_ptr<media::VideoCaptureDevice::Names> device_names( + new media::VideoCaptureDevice::Names()); + GetAvailableDevices(device_names.get()); + + MediaCaptureDeviceInfo device(kVideoCapture, + device_names.get()->front().device_name, + device_names.get()->front().unique_id, false); + + // Call OnOpen to open using the first device in the list + OnOpen(capture_params.session_id, device); + } + + VideoCaptureDevices::iterator it = devices_.find(capture_params.session_id); + if (it == devices_.end()) { + // Invalid session id + video_capture_receiver->OnError(); + return; + } + media::VideoCaptureDevice* video_capture_device = it->second; + + // Possible errors are signaled to video_capture_receiver by + // video_capture_device. video_capture_receiver to perform actions. + video_capture_device->Allocate(capture_params.width, capture_params.height, + capture_params.frame_per_second, + video_capture_receiver); + video_capture_device->Start(); +} + +void VideoCaptureManager::OnStop( + const media::VideoCaptureSessionId capture_session_id, + Task* stopped_task) { + DCHECK(IsOnCaptureDeviceThread()); + + VideoCaptureDevices::iterator it = devices_.find(capture_session_id); + if (it != devices_.end()) { + media::VideoCaptureDevice* video_capture_device = it->second; + // Possible errors are signaled to video_capture_receiver by + // video_capture_device. video_capture_receiver to perform actions. + video_capture_device->Stop(); + video_capture_device->DeAllocate(); + } + + if (stopped_task) { + stopped_task->Run(); + delete stopped_task; + } + + if (capture_session_id == kStartOpenSessionId) { + // This device was opened from Start(), not Open(). Close it! + OnClose(capture_session_id); + } +} + +void VideoCaptureManager::OnOpened( + MediaCaptureSessionId capture_session_id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (listener_ == NULL) { + // Listener has been removed + return; + } + listener_->Opened(kVideoCapture, capture_session_id); +} + +void VideoCaptureManager::OnClosed( + MediaCaptureSessionId capture_session_id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (listener_ == NULL) { + // Listener has been removed + return; + } + listener_->Closed(kVideoCapture, capture_session_id); +} + +void VideoCaptureManager::OnDevicesEnumerated( + const MediaCaptureDevices& devices) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (listener_ == NULL) { + // Listener has been removed + return; + } + listener_->DevicesEnumerated(kVideoCapture, devices); +} + +void VideoCaptureManager::OnError(MediaCaptureSessionId capture_session_id, + MediaStreamProviderError error) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (listener_ == NULL) { + // Listener has been removed + return; + } + listener_->Error(kVideoCapture, capture_session_id, error); +} + +void VideoCaptureManager::PostOnOpened( + MediaCaptureSessionId capture_session_id) { + DCHECK(IsOnCaptureDeviceThread()); + BrowserThread::PostTask(BrowserThread::IO, + FROM_HERE, + NewRunnableMethod(this, + &VideoCaptureManager::OnOpened, + capture_session_id)); +} + +void VideoCaptureManager::PostOnClosed( + MediaCaptureSessionId capture_session_id) { + DCHECK(IsOnCaptureDeviceThread()); + BrowserThread::PostTask(BrowserThread::IO, + FROM_HERE, + NewRunnableMethod(this, + &VideoCaptureManager::OnClosed, + capture_session_id)); +} + +void VideoCaptureManager::PostOnDevicesEnumerated(MediaCaptureDevices devices) { + DCHECK(IsOnCaptureDeviceThread()); + + BrowserThread::PostTask(BrowserThread::IO, + FROM_HERE, + NewRunnableMethod( + this, + &VideoCaptureManager::OnDevicesEnumerated, + devices)); +} + +void VideoCaptureManager::PostOnError(MediaCaptureSessionId capture_session_id, + MediaStreamProviderError error) { + // Don't check thread here, can be called from both IO thread and device + // thread. + BrowserThread::PostTask(BrowserThread::IO, + FROM_HERE, + NewRunnableMethod(this, + &VideoCaptureManager::OnError, + capture_session_id, + error)); +} + +bool VideoCaptureManager::IsOnCaptureDeviceThread() const { + return MessageLoop::current() == vc_device_thread_.message_loop(); +} + +void VideoCaptureManager::GetAvailableDevices( + media::VideoCaptureDevice::Names* device_names) { + DCHECK(IsOnCaptureDeviceThread()); + + if (!use_fake_device_) { + media::VideoCaptureDevice::GetDeviceNames(device_names); + } else { + media::FakeVideoCaptureDevice::GetDeviceNames(device_names); + } +} + +bool VideoCaptureManager::DeviceOpened( + const media::VideoCaptureDevice::Name& device_name) { + DCHECK(IsOnCaptureDeviceThread()); + + for (VideoCaptureDevices::iterator it = devices_.begin(); + it != devices_.end(); + ++it) { + if (device_name.unique_id == it->second->device_name().unique_id) { + // We've found the device! + return true; + } + } + return false; +} + +bool VideoCaptureManager::DeviceOpened( + const MediaCaptureDeviceInfo& device_info) { + DCHECK(IsOnCaptureDeviceThread()); + + for (VideoCaptureDevices::iterator it = devices_.begin(); + it != devices_.end(); + it++) { + if (device_info.device_id == it->second->device_name().unique_id) { + return true; + } + } + return false; +} + +} // namespace media diff --git a/content/browser/renderer_host/media/video_capture_manager.h b/content/browser/renderer_host/media/video_capture_manager.h new file mode 100644 index 0000000..9823995 --- /dev/null +++ b/content/browser/renderer_host/media/video_capture_manager.h @@ -0,0 +1,125 @@ +// 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. + +// VideoCaptureManager is used to open/close, start/stop as well as enumerate +// available video capture devices. All functions are expected to be called from +// the Browser::IO thread. VideoCaptureManager will open OS dependent instances +// of VideoCaptureDevice. A device can only be opened once. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_MANAGER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_MANAGER_H_ + +#include <map> + +#include "base/lazy_instance.h" +#include "base/threading/thread.h" +#include "content/browser/renderer_host/media/media_stream_provider.h" +#include "media/video/capture/video_capture_device.h" +#include "media/video/capture/video_capture_types.h" + +namespace media_stream { + +// VideoCaptureManager opens/closes and start/stops video capture devices. +class VideoCaptureManager : public MediaStreamProvider { + public: + // Calling |Start| of this id will open the first device, even though open has + // not been called. This is used to be able to use video capture devices + // before MediaStream is implemented in Chrome and WebKit. + enum { kStartOpenSessionId = 1 }; + + // Called to get a pointer to the singleton + static VideoCaptureManager* Get(); + + // Implements MediaStreamProvider. + virtual bool Register(MediaStreamProviderListener* listener); + + virtual void Unregister(); + + virtual void EnumerateDevices(); + + virtual MediaCaptureSessionId Open(const MediaCaptureDeviceInfo& device); + + virtual void Close(MediaCaptureSessionId capture_session_id); + + // Functions used to start and stop media flow. + // Start allocates the device and no other application can use the device + // before Stop is called. Captured video frames will be delivered to + // video_capture_receiver. + void Start(const media::VideoCaptureParams& capture_params, + media::VideoCaptureDevice::EventHandler* video_capture_receiver); + + // Stops capture device referenced by |capture_session_id|. No more frames + // will be delivered to the frame receiver, and |stopped_task| will be called. + void Stop(const media::VideoCaptureSessionId capture_session_id, + Task* stopped_task); + + virtual ~VideoCaptureManager(); + + // Used by unit test to make sure a fake device is used instead of a real + // video capture device. Due to timing requirements, the function must be + // called before EnumerateDevices and Open. + void UseFakeDevice(); + MessageLoop* GetMessageLoop(); + + private: + friend struct base::DefaultLazyInstanceTraits<VideoCaptureManager>; + + VideoCaptureManager(); + + // Called by the public functions, executed on vc_device_thread_. + void OnEnumerateDevices(); + void OnOpen(MediaCaptureSessionId capture_session_id, + const MediaCaptureDeviceInfo device); + void OnClose(MediaCaptureSessionId capture_session_id); + void OnStart(const media::VideoCaptureParams capture_params, + media::VideoCaptureDevice::EventHandler* video_capture_receiver); + void OnStop(const media::VideoCaptureSessionId capture_session_id, + Task* stopped_task); + + + // Executed on Browser::IO thread to call Listener. + void OnOpened(MediaCaptureSessionId capture_session_id); + void OnClosed(MediaCaptureSessionId capture_session_id); + void OnDevicesEnumerated(const MediaCaptureDevices& devices); + void OnError(MediaCaptureSessionId capture_session_id, + MediaStreamProviderError error); + + // Executed on vc_device_thread_ to make sure Listener is called from + // Browser::IO thread. + void PostOnOpened(MediaCaptureSessionId capture_session_id); + void PostOnClosed(MediaCaptureSessionId capture_session_id); + void PostOnDevicesEnumerated(MediaCaptureDevices devices); + void PostOnError(MediaCaptureSessionId capture_session_id, + MediaStreamProviderError error); + + // Helpers + void GetAvailableDevices(media::VideoCaptureDevice::Names* device_names); + bool DeviceOpened(const media::VideoCaptureDevice::Name& device_name); + bool DeviceOpened(const MediaCaptureDeviceInfo& device_info); + bool IsOnCaptureDeviceThread() const; + + // Thread for all calls to VideoCaptureDevice + base::Thread vc_device_thread_; + + // Only accessed on Browser::IO thread + MediaStreamProviderListener* listener_; + MediaCaptureSessionId new_capture_session_id_; + + // Only accessed from vc_device_thread_ + // TODO(mflodman) Change map key type when changing typedef for + // MediaCaptureSessionId. + typedef std::map<int, media::VideoCaptureDevice*> VideoCaptureDevices; + VideoCaptureDevices devices_; + + // Set to true if using fake devices for testing, false by default. + bool use_fake_device_; + + DISALLOW_COPY_AND_ASSIGN(VideoCaptureManager); +}; + +} // namespace media_stream + +DISABLE_RUNNABLE_METHOD_REFCOUNT(media_stream::VideoCaptureManager); + +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_MANAGER_H_ diff --git a/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/content/browser/renderer_host/media/video_capture_manager_unittest.cc new file mode 100644 index 0000000..22a6066 --- /dev/null +++ b/content/browser/renderer_host/media/video_capture_manager_unittest.cc @@ -0,0 +1,296 @@ +// 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. + +// Unit test for VideoCaptureManager + +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "base/process_util.h" +#include "content/browser/browser_thread.h" +#include "content/browser/renderer_host/media/media_stream_provider.h" +#include "content/browser/renderer_host/media/video_capture_manager.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::AnyNumber; +using ::testing::InSequence; +using ::testing::Return; + +namespace media_stream { + +// Listener class used to track progress of VideoCaptureManager test +class MockMediaStreamProviderListener : public MediaStreamProviderListener { + public: + MockMediaStreamProviderListener() + : devices_() { + } + ~MockMediaStreamProviderListener() {} + + MOCK_METHOD2(Opened, void(MediaStreamType, MediaCaptureSessionId)); + MOCK_METHOD2(Closed, void(MediaStreamType, MediaCaptureSessionId)); + MOCK_METHOD1(DevicesEnumerated, void(const MediaCaptureDevices&)); + MOCK_METHOD3(Error, void(MediaStreamType, MediaCaptureSessionId, + MediaStreamProviderError)); + + virtual void DevicesEnumerated(MediaStreamType stream_type, + const MediaCaptureDevices& devices) { + devices_.clear(); + for (MediaCaptureDevices::const_iterator it = devices.begin(); + it != devices.end(); + ++it) { + devices_.push_back(*it); + } + DevicesEnumerated(devices); + } + + media_stream::MediaCaptureDevices devices_; +}; // class MockMediaStreamProviderListener + +} // namespace media_stream + +namespace { + +// Needed as an input argument to Start() +class MockFrameObserver: public media::VideoCaptureDevice::EventHandler { + public: + virtual void OnError() {} + void OnFrameInfo(const media::VideoCaptureDevice::Capability& info) {} + virtual void OnIncomingCapturedFrame(const uint8* data, int length, + base::Time timestamp) {} +}; + +// Test class +class VideoCaptureManagerTest : public testing::Test { + public: + VideoCaptureManagerTest() + : listener_(), + message_loop_(), + io_thread_(), + frame_observer_() { + } + virtual ~VideoCaptureManagerTest() {} + + protected: + virtual void SetUp() { + listener_.reset(new media_stream::MockMediaStreamProviderListener()); + message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO)); + io_thread_.reset(new BrowserThread(BrowserThread::IO, message_loop_.get())); + frame_observer_.reset(new MockFrameObserver()); + } + + virtual void TearDown() { + io_thread_.reset(); + } + + // Called on the VideoCaptureManager thread. + static void PostQuitMessageLoop(MessageLoop* message_loop) { + message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); + } + + // Called on the main thread. + static void PostQuitOnVideoCaptureManagerThread(MessageLoop* message_loop) { + media_stream::VideoCaptureManager::Get()->GetMessageLoop()->PostTask( + FROM_HERE, NewRunnableFunction(&PostQuitMessageLoop, message_loop)); + } + + // SyncWithVideoCaptureManagerThread() waits until all pending tasks on the + // video_capture_manager internal thread are executed while also processing + // pending task in message_loop_ on the current thread. It is used to + // synchronize with the video capture manager thread when we are stopping a + // video capture device. + void SyncWithVideoCaptureManagerThread() { + message_loop_->PostTask( + FROM_HERE, NewRunnableFunction(&PostQuitOnVideoCaptureManagerThread, + message_loop_.get())); + message_loop_->Run(); + } + scoped_ptr<media_stream::MockMediaStreamProviderListener> listener_; + scoped_ptr<MessageLoop> message_loop_; + scoped_ptr<BrowserThread> io_thread_; + scoped_ptr<MockFrameObserver> frame_observer_; + + private: + DISALLOW_COPY_AND_ASSIGN(VideoCaptureManagerTest); +}; + +// Test cases + +// Try to open, start, stop and close a device. +TEST_F(VideoCaptureManagerTest, CreateAndClose) { + InSequence s; + EXPECT_CALL(*listener_, DevicesEnumerated(_)) + .Times(1); + EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) + .Times(1); + EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) + .Times(1); + + media_stream::VideoCaptureManager* vcm = + media_stream::VideoCaptureManager::Get(); + // Make sure fake devices are used + vcm->UseFakeDevice(); + vcm->Register(listener_.get()); + vcm->EnumerateDevices(); + + // Wait to get device callback... + SyncWithVideoCaptureManagerThread(); + + int video_session_id = vcm->Open(listener_->devices_.front()); + + media::VideoCaptureParams capture_params; + capture_params.session_id = video_session_id; + capture_params.width = 320; + capture_params.height = 240; + capture_params.frame_per_second = 30; + vcm->Start(capture_params, frame_observer_.get()); + + vcm->Stop(video_session_id, NULL); + vcm->Close(video_session_id); + + // Wait to check callbacks before removing the listener + SyncWithVideoCaptureManagerThread(); + vcm->Unregister(); +} + +// Open the same device twice, should fail. +TEST_F(VideoCaptureManagerTest, OpenTwice) { + InSequence s; + EXPECT_CALL(*listener_, DevicesEnumerated(_)) + .Times(1); + EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) + .Times(1); + EXPECT_CALL(*listener_, Error(media_stream::kVideoCapture, _, + media_stream::kDeviceAlreadyInUse)) + .Times(1); + EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) + .Times(1); + + media_stream::VideoCaptureManager* vcm = + media_stream::VideoCaptureManager::Get(); + // Make sure fake devices are used + vcm->UseFakeDevice(); + vcm->Register(listener_.get()); + vcm->EnumerateDevices(); + + // Wait to get device callback... + SyncWithVideoCaptureManagerThread(); + + int video_session_id = vcm->Open(listener_->devices_.front()); + + // This should trigger an error callback with error code 'kDeviceAlreadyInUse' + vcm->Open(listener_->devices_.front()); + + vcm->Close(video_session_id); + + // Wait to check callbacks before removing the listener + SyncWithVideoCaptureManagerThread(); + vcm->Unregister(); +} + +// Open two different devices. +TEST_F(VideoCaptureManagerTest, OpenTwo) { + InSequence s; + EXPECT_CALL(*listener_, DevicesEnumerated(_)) + .Times(1); + EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) + .Times(2); + EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) + .Times(2); + + media_stream::VideoCaptureManager* vcm = + media_stream::VideoCaptureManager::Get(); + // Make sure fake devices are used + vcm->UseFakeDevice(); + vcm->Register(listener_.get()); + vcm->EnumerateDevices(); + + // Wait to get device callback... + SyncWithVideoCaptureManagerThread(); + + media_stream::MediaCaptureDevices::iterator it = + listener_->devices_.begin(); + + int video_session_id_first = vcm->Open(*it); + + // This should trigger an error callback with error code 'kDeviceAlreadyInUse' + ++it; + int video_session_id_second = vcm->Open(*it); + + vcm->Close(video_session_id_first); + vcm->Close(video_session_id_second); + + // Wait to check callbacks before removing the listener + SyncWithVideoCaptureManagerThread(); + vcm->Unregister(); +} + +// Try open a non-existing device. +TEST_F(VideoCaptureManagerTest, OpenNotExisting) { + InSequence s; + EXPECT_CALL(*listener_, DevicesEnumerated(_)) + .Times(1); + EXPECT_CALL(*listener_, Error(media_stream::kVideoCapture, _, + media_stream::kDeviceNotAvailable)) + .Times(1); + + media_stream::VideoCaptureManager* vcm = + media_stream::VideoCaptureManager::Get(); + // Make sure fake devices are used + vcm->UseFakeDevice(); + vcm->Register(listener_.get()); + vcm->EnumerateDevices(); + + // Wait to get device callback... + SyncWithVideoCaptureManagerThread(); + + media_stream::MediaStreamType stream_type = media_stream::kVideoCapture; + std::string device_name("device_doesnt_exist"); + std::string device_id("id_doesnt_exist"); + media_stream::MediaCaptureDeviceInfo dummy_device(stream_type, device_name, + device_id, false); + + // This should fail with error code 'kDeviceNotAvailable' + vcm->Open(dummy_device); + + // Wait to check callbacks before removing the listener + SyncWithVideoCaptureManagerThread(); + vcm->Unregister(); +} + +// Start a device using "magic" id, i.e. call Start without calling Open. +TEST_F(VideoCaptureManagerTest, StartUsingId) { + InSequence s; + EXPECT_CALL(*listener_, Opened(media_stream::kVideoCapture, _)) + .Times(1); + EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _)) + .Times(1); + + media_stream::VideoCaptureManager* vcm = + media_stream::VideoCaptureManager::Get(); + // Make sure fake devices are used + vcm->UseFakeDevice(); + vcm->Register(listener_.get()); + + media::VideoCaptureParams capture_params; + capture_params.session_id = + media_stream::VideoCaptureManager::kStartOpenSessionId; + capture_params.width = 320; + capture_params.height = 240; + capture_params.frame_per_second = 30; + // Start shall trigger the Open callback + vcm->Start(capture_params, frame_observer_.get()); + + // Stop shall trigger the Close callback + vcm->Stop(media_stream::VideoCaptureManager::kStartOpenSessionId, NULL); + + // Wait to check callbacks before removing the listener + SyncWithVideoCaptureManagerThread(); + vcm->Unregister(); +} + +} // namespace |