blob: 8a7c93a2b4c8d0b42fa82136bf4034fc482b1049 [file] [log] [blame]
// Copyright 2017 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_RENDERER_MEDIA_STREAM_USER_MEDIA_PROCESSOR_H_
#define CONTENT_RENDERER_MEDIA_STREAM_USER_MEDIA_PROCESSOR_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "content/common/content_export.h"
#include "content/renderer/media/stream/media_stream_dispatcher_eventhandler.h"
#include "third_party/blink/public/mojom/mediastream/media_devices.mojom.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
#include "third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_user_media_request.h"
namespace gfx {
class Size;
}
namespace blink {
class MediaStreamAudioSource;
class WebMediaStream;
class WebMediaStreamSource;
class WebString;
} // namespace blink
namespace content {
class AudioCaptureSettings;
class AudioDeviceCaptureCapability;
class MediaStreamDeviceObserver;
class MediaStreamVideoSource;
class PeerConnectionDependencyFactory;
class VideoCaptureSettings;
class RenderFrameImpl;
// TODO(guidou): Add |request_id| and |is_processing_user_gesture| to
// blink::WebUserMediaRequest and remove this struct.
struct UserMediaRequest {
UserMediaRequest(int request_id,
const blink::WebUserMediaRequest& web_request,
bool is_processing_user_gesture);
const int request_id;
const blink::WebUserMediaRequest web_request;
const bool is_processing_user_gesture;
};
// UserMediaProcessor is responsible for processing getUserMedia() requests.
// It also keeps tracks of all sources used by streams created with
// getUserMedia().
// It communicates with the browser via MediaStreamDispatcherHost.
// Only one MediaStream at a time can be in the process of being created.
// UserMediaProcessor must be created, called and destroyed on the main render
// thread. There should be only one UserMediaProcessor per frame.
class CONTENT_EXPORT UserMediaProcessor
: public MediaStreamDispatcherEventHandler {
public:
using MediaDevicesDispatcherCallback = base::RepeatingCallback<
const blink::mojom::MediaDevicesDispatcherHostPtr&()>;
// |render_frame| and |dependency_factory| must outlive this instance.
UserMediaProcessor(
RenderFrameImpl* render_frame,
PeerConnectionDependencyFactory* dependency_factory,
std::unique_ptr<MediaStreamDeviceObserver> media_stream_device_observer,
MediaDevicesDispatcherCallback media_devices_dispatcher_cb,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~UserMediaProcessor() override;
// It can be assumed that the output of CurrentRequest() remains the same
// during the execution of a task on the main thread unless ProcessRequest or
// DeleteWebRequest are invoked.
// TODO(guidou): Remove this method. https://crbug.com/764293
UserMediaRequest* CurrentRequest();
// Starts processing |request| in order to create a new MediaStream. When
// processing of |request| is complete, it notifies by invoking |callback|.
// This method must be called only if there is no request currently being
// processed.
void ProcessRequest(std::unique_ptr<UserMediaRequest> request,
base::OnceClosure callback);
// If |web_request| is the request currently being processed, stops processing
// the request and returns true. Otherwise, performs no action and returns
// false.
// TODO(guidou): Make this method private and replace with a public
// CancelRequest() method that deletes the request only if it has not been
// generated yet. https://crbug.com/764293
bool DeleteWebRequest(const blink::WebUserMediaRequest& web_request);
// Stops processing the current request, if any, and stops all sources
// currently being tracked, effectively stopping all tracks associated with
// those sources.
void StopAllProcessing();
MediaStreamDeviceObserver* media_stream_device_observer() const {
return media_stream_device_observer_.get();
}
bool HasActiveSources() const;
// MediaStreamDispatcherEventHandler implementation.
void OnDeviceStopped(const blink::MediaStreamDevice& device) override;
void OnDeviceChanged(const blink::MediaStreamDevice& old_device,
const blink::MediaStreamDevice& new_device) override;
void set_media_stream_dispatcher_host_for_testing(
blink::mojom::MediaStreamDispatcherHostPtr dispatcher_host) {
dispatcher_host_ = std::move(dispatcher_host);
}
protected:
// These methods are virtual for test purposes. A test can override them to
// test requesting local media streams. The function notifies WebKit that the
// |request| have completed.
virtual void GetUserMediaRequestSucceeded(
const blink::WebMediaStream& stream,
blink::WebUserMediaRequest web_request);
virtual void GetUserMediaRequestFailed(
blink::MediaStreamRequestResult result,
const blink::WebString& constraint_name = blink::WebString());
// Creates a MediaStreamAudioSource/MediaStreamVideoSource objects.
// These are virtual for test purposes.
virtual std::unique_ptr<blink::MediaStreamAudioSource> CreateAudioSource(
const blink::MediaStreamDevice& device,
const blink::WebPlatformMediaStreamSource::ConstraintsCallback&
source_ready);
virtual std::unique_ptr<MediaStreamVideoSource> CreateVideoSource(
const blink::MediaStreamDevice& device,
const blink::WebPlatformMediaStreamSource::SourceStoppedCallback&
stop_callback);
// Intended to be used only for testing.
const AudioCaptureSettings& AudioCaptureSettingsForTesting() const;
const VideoCaptureSettings& VideoCaptureSettingsForTesting() const;
private:
class RequestInfo;
using LocalStreamSources = std::vector<blink::WebMediaStreamSource>;
void OnStreamGenerated(int request_id,
blink::MediaStreamRequestResult result,
const std::string& label,
const blink::MediaStreamDevices& audio_devices,
const blink::MediaStreamDevices& video_devices);
void GotAllVideoInputFormatsForDevice(
const blink::WebUserMediaRequest& web_request,
const std::string& label,
const std::string& device_id,
const media::VideoCaptureFormats& formats);
gfx::Size GetScreenSize();
void OnStreamGenerationFailed(int request_id,
blink::MediaStreamRequestResult result);
bool IsCurrentRequestInfo(int request_id) const;
bool IsCurrentRequestInfo(
const blink::WebUserMediaRequest& web_request) const;
void DelayedGetUserMediaRequestSucceeded(
const blink::WebMediaStream& stream,
blink::WebUserMediaRequest web_request);
void DelayedGetUserMediaRequestFailed(
blink::WebUserMediaRequest web_request,
blink::MediaStreamRequestResult result,
const blink::WebString& constraint_name);
// Called when |source| has been stopped from JavaScript.
void OnLocalSourceStopped(const blink::WebMediaStreamSource& source);
// Creates a WebKit representation of a stream source based on
// |device| from the MediaStreamDispatcherHost.
blink::WebMediaStreamSource InitializeVideoSourceObject(
const blink::MediaStreamDevice& device);
blink::WebMediaStreamSource InitializeAudioSourceObject(
const blink::MediaStreamDevice& device,
bool* is_pending);
void StartTracks(const std::string& label);
void CreateVideoTracks(
const blink::MediaStreamDevices& devices,
blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks);
void CreateAudioTracks(
const blink::MediaStreamDevices& devices,
blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks);
// Callback function triggered when all native versions of the
// underlying media sources and tracks have been created and started.
void OnCreateNativeTracksCompleted(const std::string& label,
RequestInfo* request,
blink::MediaStreamRequestResult result,
const blink::WebString& result_name);
void OnStreamGeneratedForCancelledRequest(
const blink::MediaStreamDevices& audio_devices,
const blink::MediaStreamDevices& video_devices);
static void OnAudioSourceStartedOnAudioThread(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
base::WeakPtr<UserMediaProcessor> weak_ptr,
blink::WebPlatformMediaStreamSource* source,
blink::MediaStreamRequestResult result,
const blink::WebString& result_name);
void OnAudioSourceStarted(blink::WebPlatformMediaStreamSource* source,
blink::MediaStreamRequestResult result,
const blink::WebString& result_name);
void NotifyCurrentRequestInfoOfAudioSourceStarted(
blink::WebPlatformMediaStreamSource* source,
blink::MediaStreamRequestResult result,
const blink::WebString& result_name);
void DeleteAllUserMediaRequests();
// Returns the source that use a device with |device.session_id|
// and |device.device.id|. NULL if such source doesn't exist.
const blink::WebMediaStreamSource* FindLocalSource(
const blink::MediaStreamDevice& device) const {
return FindLocalSource(local_sources_, device);
}
const blink::WebMediaStreamSource* FindPendingLocalSource(
const blink::MediaStreamDevice& device) const {
return FindLocalSource(pending_local_sources_, device);
}
const blink::WebMediaStreamSource* FindLocalSource(
const LocalStreamSources& sources,
const blink::MediaStreamDevice& device) const;
// Looks up a local source and returns it if found. If not found, prepares
// a new WebMediaStreamSource with a NULL extraData pointer.
blink::WebMediaStreamSource FindOrInitializeSourceObject(
const blink::MediaStreamDevice& device);
// Returns true if we do find and remove the |source|.
// Otherwise returns false.
bool RemoveLocalSource(const blink::WebMediaStreamSource& source);
void StopLocalSource(const blink::WebMediaStreamSource& source,
bool notify_dispatcher);
const blink::mojom::MediaStreamDispatcherHostPtr&
GetMediaStreamDispatcherHost();
const blink::mojom::MediaDevicesDispatcherHostPtr&
GetMediaDevicesDispatcher();
void SetupAudioInput();
void SelectAudioDeviceSettings(
const blink::WebUserMediaRequest& web_request,
std::vector<blink::mojom::AudioInputDeviceCapabilitiesPtr>
audio_input_capabilities);
void SelectAudioSettings(
const blink::WebUserMediaRequest& web_request,
const std::vector<AudioDeviceCaptureCapability>& capabilities);
void SetupVideoInput();
void SelectVideoDeviceSettings(
const blink::WebUserMediaRequest& web_request,
std::vector<blink::mojom::VideoInputDeviceCapabilitiesPtr>
video_input_capabilities);
void FinalizeSelectVideoDeviceSettings(
const blink::WebUserMediaRequest& web_request,
const VideoCaptureSettings& settings);
void SelectVideoContentSettings();
void GenerateStreamForCurrentRequestInfo();
// Weak ref to a PeerConnectionDependencyFactory, owned by the RenderThread.
// It's valid for the lifetime of RenderThread.
// TODO(xians): Remove this dependency once audio do not need it for local
// audio.
PeerConnectionDependencyFactory* const dependency_factory_;
// UserMediaProcessor owns MediaStreamDeviceObserver instead of
// RenderFrameImpl (or RenderFrameObserver) to ensure tear-down occurs in the
// right order.
const std::unique_ptr<MediaStreamDeviceObserver>
media_stream_device_observer_;
LocalStreamSources local_sources_;
LocalStreamSources pending_local_sources_;
blink::mojom::MediaStreamDispatcherHostPtr dispatcher_host_;
// UserMedia requests are processed sequentially. |current_request_info_|
// contains the request currently being processed, if any, and
// |pending_request_infos_| is a list of queued requests.
std::unique_ptr<RequestInfo> current_request_info_;
MediaDevicesDispatcherCallback media_devices_dispatcher_cb_;
base::OnceClosure request_completed_cb_;
RenderFrameImpl* const render_frame_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
SEQUENCE_CHECKER(sequence_checker_);
// Note: This member must be the last to ensure all outstanding weak pointers
// are invalidated first.
base::WeakPtrFactory<UserMediaProcessor> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(UserMediaProcessor);
};
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_STREAM_USER_MEDIA_PROCESSOR_H_