#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_VIDEO_SOURCE_H_
#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_VIDEO_SOURCE_H_
+#include <string>
+#include <vector>
+
#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/non_thread_safe.h"
#include "content/common/content_export.h"
-#include "content/renderer/media/media_stream_dependency_factory.h"
+#include "content/common/media/video_capture.h"
#include "content/renderer/media/media_stream_source.h"
+#include "content/renderer/media/video_frame_deliverer.h"
+#include "media/base/video_frame.h"
+#include "media/video/capture/video_capture_types.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
-namespace media {
-class VideoFrame;
-}
-
namespace content {
-class MediaStreamDependencyFactory;
+class MediaStreamVideoTrack;
// MediaStreamVideoSource is an interface used for sending video frames to a
// MediaStreamVideoTrack.
// http://dev.w3.org/2011/webrtc/editor/getusermedia.html
+// The purpose of this base class is to be able to implement different
+// MediaStreaVideoSources such as local video capture, video sources received
+// on a PeerConnection or a source created in NaCl.
// All methods calls will be done from the main render thread.
+//
+// When the first track is added to the source by calling AddTrack
+// the MediaStreamVideoSource implementation calls GetCurrentSupportedFormats.
+// the source implementation must call OnSupportedFormats.
+// MediaStreamVideoSource then match the constraints provided in AddTrack with
+// the formats and call StartSourceImpl. The source implementation must call
+// OnStartDone when the underlying source has been started or failed to
+// start.
class CONTENT_EXPORT MediaStreamVideoSource
: public MediaStreamSource,
- NON_EXPORTED_BASE(public webrtc::ObserverInterface),
NON_EXPORTED_BASE(public base::NonThreadSafe) {
public:
- explicit MediaStreamVideoSource(
- MediaStreamDependencyFactory* factory);
+ MediaStreamVideoSource();
+ virtual ~MediaStreamVideoSource();
+ // Returns the MediaStreamVideoSource object owned by |source|.
+ static MediaStreamVideoSource* GetVideoSource(
+ const blink::WebMediaStreamSource& source);
// Puts |track| in the registered tracks list.
- virtual void AddTrack(const blink::WebMediaStreamTrack& track,
- const blink::WebMediaConstraints& constraints,
- const ConstraintsCallback& callback) OVERRIDE;
- virtual void RemoveTrack(const blink::WebMediaStreamTrack& track) OVERRIDE;
-
- // TODO(ronghuawu): Remove webrtc::VideoSourceInterface from the public
- // interface of this class.
- webrtc::VideoSourceInterface* GetAdapter() {
- return adapter_;
- }
+ void AddTrack(MediaStreamVideoTrack* track,
+ const VideoCaptureDeliverFrameCB& frame_callback,
+ const blink::WebMediaConstraints& constraints,
+ const ConstraintsCallback& callback);
+ void RemoveTrack(MediaStreamVideoTrack* track);
+
+ // Return true if |name| is a constraint supported by MediaStreamVideoSource.
+ static bool IsConstraintSupported(const std::string& name);
+
+ // Returns the MessageLoopProxy where video frames will be delivered on.
+ const scoped_refptr<base::MessageLoopProxy>& io_message_loop() const;
+
+ // Constraint keys used by a video source.
+ // Specified by draft-alvestrand-constraints-resolution-00b
+ static const char kMinAspectRatio[]; // minAspectRatio
+ static const char kMaxAspectRatio[]; // maxAspectRatio
+ static const char kMaxWidth[]; // maxWidth
+ static const char kMinWidth[]; // minWidthOnCaptureFormats
+ static const char kMaxHeight[]; // maxHeight
+ static const char kMinHeight[]; // minHeight
+ static const char kMaxFrameRate[]; // maxFrameRate
+ static const char kMinFrameRate[]; // minFrameRate
+
+ // Default resolution. If no constraints are specified and the delegate
+ // support it, this is the resolution that will be used.
+ static const int kDefaultWidth;
+ static const int kDefaultHeight;
+ static const int kDefaultFrameRate;
protected:
- virtual void DoStopSource() OVERRIDE {}
-
- // Called when the first track is added to this source.
- // It currently creates a webrtc::VideoSourceInterface.
- // If a derived class overrides this method, it must call SetAdapter.
- virtual void InitAdapter(const blink::WebMediaConstraints& constraints);
-
- // Set the webrtc::VideoSourceInterface adapter used by this class.
- // It must be called by a derived class that overrides the InitAdapter method.
- void SetAdapter(webrtc::VideoSourceInterface* adapter) {
- DCHECK(!adapter_);
- adapter_ = adapter;
- }
-
- MediaStreamDependencyFactory* factory() { return factory_; }
+ virtual void DoStopSource() OVERRIDE;
// Sets ready state and notifies the ready state to all registered tracks.
virtual void SetReadyState(blink::WebMediaStreamSource::ReadyState state);
- // Delivers |frame| to registered tracks according to their constraints.
- // Note: current implementation assumes |frame| be contiguous layout of image
- // planes and I420.
- virtual void DeliverVideoFrame(const scoped_refptr<media::VideoFrame>& frame);
-
- // Implements webrtc::Observer.
- virtual void OnChanged() OVERRIDE;
-
- virtual ~MediaStreamVideoSource();
+ // An implementation must fetch the formats that can currently be used by
+ // the source and call OnSupportedFormats when done.
+ // |max_requested_height| and |max_requested_width| is the max height and
+ // width set as a mandatory constraint if set when calling
+ // MediaStreamVideoSource::AddTrack. If max height and max width is not set
+ // |max_requested_height| and |max_requested_width| are 0.
+ virtual void GetCurrentSupportedFormats(
+ int max_requested_width,
+ int max_requested_height,
+ const VideoCaptureDeviceFormatsCB& callback) = 0;
+
+ // An implementation must start capture frames using the resolution in
+ // |params|. When the source has started or the source failed to start
+ // OnStartDone must be called. An implementation must call
+ // invoke |frame_callback| on the IO thread with the captured frames.
+ // TODO(perkj): pass a VideoCaptureFormats instead of VideoCaptureParams for
+ // subclasses to customize.
+ virtual void StartSourceImpl(
+ const media::VideoCaptureParams& params,
+ const VideoCaptureDeliverFrameCB& frame_callback) = 0;
+ void OnStartDone(bool success);
+
+ // An implementation must immediately stop capture video frames and must not
+ // call OnSupportedFormats after this method has been called. After this
+ // method has been called, MediaStreamVideoSource may be deleted.
+ virtual void StopSourceImpl() = 0;
+
+ enum State {
+ NEW,
+ RETRIEVING_CAPABILITIES,
+ STARTING,
+ STARTED,
+ ENDED
+ };
+ State state() const { return state_; }
private:
- // Checks if the underlying source state has changed from an initializing
- // state to a final state and in that case trigger all callbacks in
- // |constraints_callbacks_|.
- void TriggerConstraintsCallbackOnStateChange();
-
- bool initializing_;
- MediaStreamDependencyFactory* factory_;
- scoped_refptr<webrtc::VideoSourceInterface> adapter_;
- int width_;
- int height_;
- base::TimeDelta first_frame_timestamp_;
-
+ void OnSupportedFormats(const media::VideoCaptureFormats& formats);
+
+ // Finds the first constraints in |requested_constraints_| that can be
+ // fulfilled. |best_format| is set to the video resolution that can be
+ // fulfilled. |frame_output_size| is the requested frame size after cropping.
+ // |resulting_constraints| is set to the found constraints in
+ // |requested_constraints_|.
+ bool FindBestFormatWithConstraints(
+ const media::VideoCaptureFormats& formats,
+ media::VideoCaptureFormat* best_format,
+ gfx::Size* frame_output_size,
+ blink::WebMediaConstraints* resulting_constraints);
+
+ // Trigger all cached callbacks from AddTrack. AddTrack is successful
+ // if the capture delegate has started and the constraints provided in
+ // AddTrack match the format that was used to start the device.
+ // Note that it must be ok to delete the MediaStreamVideoSource object
+ // in the context of the callback. If gUM fail, the implementation will
+ // simply drop the references to the blink source and track which will lead
+ // to that this object is deleted.
+ void FinalizeAddTrack();
+
+ State state_;
+
+ media::VideoCaptureFormat current_format_;
blink::WebMediaConstraints current_constraints_;
- std::vector<ConstraintsCallback> constraints_callbacks_;
+ // |max_frame_output_size_| is the maximum frame size allowed by
+ // |current_constraints_|.
+ gfx::Size max_frame_output_size_;
+
+ struct RequestedConstraints {
+ RequestedConstraints(MediaStreamVideoTrack* track,
+ const VideoCaptureDeliverFrameCB& frame_callback,
+ const blink::WebMediaConstraints& constraints,
+ const ConstraintsCallback& callback);
+ ~RequestedConstraints();
+
+ MediaStreamVideoTrack* track;
+ VideoCaptureDeliverFrameCB frame_callback;
+ blink::WebMediaConstraints constraints;
+ ConstraintsCallback callback;
+ };
+ std::vector<RequestedConstraints> requested_constraints_;
+
+ media::VideoCaptureFormats supported_formats_;
+
+ // |FrameDeliverer| is an internal helper object used for delivering video
+ // frames using callbacks to all registered tracks on the IO thread.
+ class FrameDeliverer;
+ scoped_refptr<FrameDeliverer> frame_deliverer_;
+
+ // Tracks that currently are receiving video frames.
+ std::vector<MediaStreamVideoTrack*> tracks_;
+
+ // NOTE: Weak pointers must be invalidated before all other member variables.
+ base::WeakPtrFactory<MediaStreamVideoSource> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoSource);
};