Commit ef7927fa authored by xjz's avatar xjz Committed by Commit Bot

Media Remoting: Add mojo interfaces between browser and extension.

Currently media remoting communicates with extension by text strings
through Media Router mojo API. This CL adds mojo interfaces to allow
CastRemotingConnector in browser talk directly to MediaRemoter in
extension after connected through the Media Router mojo API. These
changes also enable passing the receiver's capablities to remoting
control logic in renderer, which will be done in a follow up CL.

BUG=734672

Review-Url: https://codereview.chromium.org/2951523002
Cr-Commit-Position: refs/heads/master@{#485043}
parent 7accad67
......@@ -675,12 +675,6 @@ group("gn_all") {
"//third_party/icu/fuzzers",
"//third_party/qcms:fuzzers",
]
# TODO(miu): Remove this dependency once the build configuration in
# chrome/browser/BUILD.gn is migrated to chrome/browser/media/BUILD.gn.
# This dependency here only exists to allow GN to discover the
# fuzzer_test target there.
deps += [ "//chrome/browser/media:cast_remoting_connector_fuzzer" ]
}
if (enable_nacl) {
......
......@@ -568,8 +568,6 @@ split_static_library("browser") {
"mac/security_wrappers.h",
"media/cast_remoting_connector.cc",
"media/cast_remoting_connector.h",
"media/cast_remoting_connector_messaging.cc",
"media/cast_remoting_connector_messaging.h",
"media/cast_remoting_sender.cc",
"media/cast_remoting_sender.h",
"media/media_access_handler.cc",
......@@ -1637,6 +1635,7 @@ split_static_library("browser") {
"//media/cast:net",
"//media/midi",
"//media/mojo:features",
"//media/mojo/interfaces:mirror_service_remoting",
"//media/mojo/interfaces:remoting",
"//mojo/common",
"//mojo/edk/system",
......
# Copyright 2016 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.
# TODO(miu): Decentralize build configuration: Move source files and deps
# specific to chrome/browser/media sources from chrome/browser/BULID.gn and
# chrome/test/BUILD.gn into this BUILD.gn file. Also, remove the root BUILD.gn
# dependency on the cast_remoting_connector_fuzzer target after this is done.
import("//testing/libfuzzer/fuzzer_test.gni")
fuzzer_test("cast_remoting_connector_fuzzer") {
sources = [
"cast_remoting_connector_fuzzertest.cc",
"cast_remoting_connector_messaging.cc",
"cast_remoting_connector_messaging.h",
]
deps = [
"//base",
]
libfuzzer_options = [ "max_len = 128" ]
seed_corpus = "../../test/data/cast/cast_remoting_connector_fuzz_corpus"
}
// Copyright 2016 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 "chrome/browser/media/cast_remoting_connector_messaging.h"
#include <stdio.h>
#include <limits>
#include "base/strings/string_number_conversions.h"
const char CastRemotingConnectorMessaging::kMessageFieldSeparator = ':';
const char CastRemotingConnectorMessaging::kStartRemotingMessageFormat[] =
"START_CAST_REMOTING:session=%x";
const char CastRemotingConnectorMessaging::kStartStreamsMessageFormat[] =
"START_CAST_REMOTING_STREAMS:session=%x:audio=%c:video=%c";
const char
CastRemotingConnectorMessaging::kStartedStreamsMessageFormatPartial[] =
"STARTED_CAST_REMOTING_STREAMS:session=%x";
const char
CastRemotingConnectorMessaging::kStartedStreamsMessageAudioIdSpecifier[] =
":audio_stream_id=";
const char
CastRemotingConnectorMessaging::kStartedStreamsMessageVideoIdSpecifier[] =
":video_stream_id=";
const char CastRemotingConnectorMessaging::kStopRemotingMessageFormat[] =
"STOP_CAST_REMOTING:session=%x";
const char CastRemotingConnectorMessaging::kStoppedMessageFormat[] =
"STOPPED_CAST_REMOTING:session=%x";
const char CastRemotingConnectorMessaging::kFailedMessageFormat[] =
"FAILED_CAST_REMOTING:session=%x";
// static
bool CastRemotingConnectorMessaging::IsMessageForSession(
const std::string& message, const char* format,
unsigned int expected_session_id) {
unsigned int session_id;
if (sscanf(message.c_str(), format, &session_id) == 1)
return session_id == expected_session_id;
return false;
}
// static
int32_t CastRemotingConnectorMessaging::GetStreamIdFromStartedMessage(
base::StringPiece message, base::StringPiece specifier) {
auto start = message.find(specifier);
if (start == std::string::npos)
return -1;
start += specifier.size();
if (start + 1 >= message.size())
return -1; // Must be at least one hex digit following the specifier.
const auto length = message.find(kMessageFieldSeparator, start) - start;
int parsed_value;
if (!base::HexStringToInt(message.substr(start, length), &parsed_value) ||
parsed_value < 0 ||
parsed_value > std::numeric_limits<int32_t>::max()) {
return -1; // Non-hex digits, or outside valid range.
}
return static_cast<int32_t>(parsed_value);
}
// Copyright 2016 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 CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_MESSAGING_H_
#define CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_MESSAGING_H_
#include <stdint.h>
#include <string>
#include "base/strings/string_piece.h"
// Utility functions for parsing messages from the Cast Provider to
// CastRemotingConnector. These have been broken-out into this separate module
// to allow for efficient building, linking and execution of these routines for
// fuzzer testing.
//
// Note: If any additions/changes are made here, please update
// cast_remoting_connector_fuzzertest.cc as well!
class CastRemotingConnectorMessaging {
public:
// Returns true if the given |message| from the Cast Provider matches the
// given |format| and the session ID in the |message| is equal to the
// |expected_session_id|.
static bool IsMessageForSession(const std::string& message,
const char* format,
unsigned int expected_session_id);
// Scans |message| for |specifier| and extracts the remoting stream ID that
// follows the specifier. Returns a negative value on error.
static int32_t GetStreamIdFromStartedMessage(base::StringPiece message,
base::StringPiece specifier);
// Simple command messages sent from/to the CastRemotingConnector to/from the
// Media Router Cast Provider to start/stop media remoting to a Cast device.
//
// Field separator (for tokenizing parts of messages).
static const char kMessageFieldSeparator;
// Message sent by CastRemotingConnector to Cast provider to start remoting.
// Example:
// "START_CAST_REMOTING:session=1f"
static const char kStartRemotingMessageFormat[];
// Message sent by CastRemotingConnector to Cast provider to start the
// remoting RTP stream(s). Example:
// "START_CAST_REMOTING_STREAMS:session=1f:audio=N:video=Y"
static const char kStartStreamsMessageFormat[];
// Start acknowledgement message sent by Cast provider to
// CastRemotingConnector once remoting RTP streams have been set up. Examples:
// "STARTED_CAST_REMOTING_STREAMS:session=1f:audio_stream_id=2e:"
// "video_stream_id=3d"
// "STARTED_CAST_REMOTING_STREAMS:session=1f:video_stream_id=b33f"
static const char kStartedStreamsMessageFormatPartial[];
static const char kStartedStreamsMessageAudioIdSpecifier[];
static const char kStartedStreamsMessageVideoIdSpecifier[];
// Stop message sent by CastRemotingConnector to Cast provider. Example:
// "STOP_CAST_REMOTING:session=1f"
static const char kStopRemotingMessageFormat[];
// Stop acknowledgement message sent by Cast provider to CastRemotingConnector
// once remoting is available again after the last session ended. Example:
// "STOPPED_CAST_REMOTING:session=1f"
static const char kStoppedMessageFormat[];
// Failure message sent by Cast provider to CastRemotingConnector any time
// there was a fatal error (e.g., the Cast provider failed to set up the RTP
// streams, or there was some unexpected external event). Example:
// "FAILED_CAST_REMOTING:session=1f"
static const char kFailedMessageFormat[];
};
#endif // CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_MESSAGING_H_
......@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "base/callback_list.h"
#include "base/time/time.h"
#include "chrome/browser/media/cast_remoting_connector.h"
#include "chrome/browser/media/router/route_message_observer.h"
#include "chrome/common/media_router/discovery/media_sink_internal.h"
#include "chrome/common/media_router/issue.h"
......@@ -199,6 +200,14 @@ class MediaRouter : public KeyedService {
virtual scoped_refptr<MediaRouteController> GetRouteController(
const MediaRoute::Id& route_id) = 0;
// Registers/Unregisters a CastRemotingConnector with the |tab_id|. For a
// given |tab_id|, only one CastRemotingConnector can be registered. The
// registered CastRemotingConnector should be removed before it is destroyed.
virtual void RegisterRemotingSource(
int32_t tab_id,
CastRemotingConnector* remoting_source) = 0;
virtual void UnregisterRemotingSource(int32_t tab_id) = 0;
private:
friend class IssuesObserver;
friend class MediaSinksObserver;
......
......@@ -155,4 +155,21 @@ void MediaRouterBase::Shutdown() {
void MediaRouterBase::DetachRouteController(const MediaRoute::Id& route_id,
MediaRouteController* controller) {}
void MediaRouterBase::RegisterRemotingSource(
int32_t tab_id,
CastRemotingConnector* remoting_source) {
auto it = remoting_sources_.find(tab_id);
if (it != remoting_sources_.end()) {
DCHECK(remoting_source == it->second);
return;
}
remoting_sources_.emplace(tab_id, remoting_source);
}
void MediaRouterBase::UnregisterRemotingSource(int32_t tab_id) {
auto it = remoting_sources_.find(tab_id);
DCHECK(it != remoting_sources_.end());
remoting_sources_.erase(it);
}
} // namespace media_router
......@@ -37,6 +37,10 @@ class MediaRouterBase : public MediaRouter {
scoped_refptr<MediaRouteController> GetRouteController(
const MediaRoute::Id& route_id) override;
void RegisterRemotingSource(int32_t tab_id,
CastRemotingConnector* remoting_source) override;
void UnregisterRemotingSource(int32_t tab_id) override;
protected:
FRIEND_TEST_ALL_PREFIXES(MediaRouterMojoImplTest,
PresentationConnectionStateChangedCallback);
......@@ -73,6 +77,11 @@ class MediaRouterBase : public MediaRouter {
std::unique_ptr<PresentationConnectionStateChangedCallbacks>>
presentation_connection_state_callbacks_;
// Stores CastRemotingConnectors that can be connected to the MediaRemoter
// for media remoting when MediaRemoter is started. The map uses the tab ID
// as the key.
std::unordered_map<int32_t, CastRemotingConnector*> remoting_sources_;
private:
friend class MediaRouterBaseTest;
friend class MediaRouterFactory;
......
......@@ -1021,4 +1021,21 @@ void MediaRouterMojoImpl::OnMediaControllerCreated(
MediaRouterMojoMetrics::RecordMediaRouteControllerCreationResult(success);
}
void MediaRouterMojoImpl::OnMediaRemoterCreated(
int32_t tab_id,
media::mojom::MirrorServiceRemoterPtr remoter,
media::mojom::MirrorServiceRemotingSourceRequest source_request) {
DVLOG_WITH_INSTANCE(1) << __func__ << ": tab_id = " << tab_id;
auto it = remoting_sources_.find(tab_id);
if (it == remoting_sources_.end()) {
LOG(WARNING) << __func__
<< ": No registered remoting source for tab_id = " << tab_id;
return;
}
CastRemotingConnector* connector = it->second;
connector->ConnectToService(std::move(source_request), std::move(remoter));
}
} // namespace media_router
......@@ -328,6 +328,10 @@ class MediaRouterMojoImpl : public MediaRouterBase,
const std::string& route_id,
const std::vector<content::PresentationConnectionMessage>& messages)
override;
void OnMediaRemoterCreated(
int32_t tab_id,
media::mojom::MirrorServiceRemoterPtr remoter,
media::mojom::MirrorServiceRemotingSourceRequest source_request) override;
// Result callback when Mojo terminateRoute is invoked. |route_id| is bound
// to the ID of the route that was terminated.
......
......@@ -35,6 +35,7 @@ mojom("media_router") {
public_deps = [
":media_controller",
"//media/mojo/interfaces:mirror_service_remoting",
"//mojo/common:common_custom_types",
"//net/interfaces:interfaces",
"//url/mojo:url_mojom_gurl",
......
......@@ -6,6 +6,7 @@ module media_router.mojom;
import "chrome/common/media_router/mojo/media_controller.mojom";
import "chrome/common/media_router/mojo/media_status.mojom";
import "media/mojo/interfaces/mirror_service_remoting.mojom";
import "mojo/common/time.mojom";
import "net/interfaces/ip_address.mojom";
import "url/mojo/origin.mojom";
......@@ -474,4 +475,11 @@ interface MediaRouter {
// |messages|: A non-empty list of messages received.
OnRouteMessagesReceived(string route_id,
array<RouteMessage> messages);
// Called when a MediaRemoter for a tab with |tab_id| is started. |remoter|
// can be used to access the MediaRemoter to control a media remoting session
// and send RPC messages to the remote device. |remoting_source| is bound to
// receive the updates/messages from MediaRemoter.
OnMediaRemoterCreated(int32 tab_id, media.mojom.MirrorServiceRemoter remoter,
media.mojom.MirrorServiceRemotingSource& remoting_source);
};
......@@ -275,6 +275,11 @@ void ChromeExtensionsDispatcherDelegate::PopulateSourceMap(
IDR_MOJO_IP_ADDRESS_MOJOM_JS);
source_map->RegisterSource("url/mojo/origin.mojom", IDR_ORIGIN_MOJOM_JS);
source_map->RegisterSource("url/mojo/url.mojom", IDR_MOJO_URL_MOJOM_JS);
source_map->RegisterSource("media/mojo/interfaces/remoting_common.mojom",
IDR_REMOTING_COMMON_JS);
source_map->RegisterSource(
"media/mojo/interfaces/mirror_service_remoting.mojom",
IDR_MEDIA_REMOTING_JS);
// These bindings are unnecessary with native bindings enabled.
if (!extensions::FeatureSwitch::native_crx_bindings()->IsEnabled()) {
......
......@@ -10,6 +10,8 @@ define('media_router_bindings', [
'chrome/common/media_router/mojo/media_status.mojom',
'content/public/renderer/frame_interfaces',
'extensions/common/mojo/keep_alive.mojom',
'media/mojo/interfaces/mirror_service_remoting.mojom',
'media/mojo/interfaces/remoting_common.mojom',
'mojo/common/time.mojom',
'mojo/public/js/bindings',
'net/interfaces/ip_address.mojom',
......@@ -20,6 +22,8 @@ define('media_router_bindings', [
mediaStatusMojom,
frameInterfaces,
keepAliveMojom,
remotingMojom,
remotingCommonMojom,
timeMojom,
bindings,
ipAddressMojom,
......@@ -279,11 +283,24 @@ define('media_router_bindings', [
MediaController: mediaControllerMojom.MediaController,
MediaStatus: mediaStatusMojom.MediaStatus,
MediaStatusObserverPtr: mediaStatusMojom.MediaStatusObserverPtr,
MirrorServiceRemoter: remotingMojom.MirrorServiceRemoter,
MirrorServiceRemoterPtr: remotingMojom.MirrorServiceRemoterPtr,
MirrorServiceRemotingSourcePtr:
remotingMojom.MirrorServiceRemotingSourcePtr,
RemotingStopReason: remotingCommonMojom.RemotingStopReason,
RemotingStartFailReason: remotingCommonMojom.RemotingStartFailReason,
RemotingSinkFeatures: remotingCommonMojom.RemotingSinkFeatures,
RemotingSinkAudioCapabilities:
remotingCommonMojom.RemotingSinkAudioCapabilities,
RemotingSinkVideoCapabilities:
remotingCommonMojom.RemotingSinkVideoCapabilities,
SinkCapabilities: remotingCommonMojom.SinkCapabilities,
Origin: originMojom.Origin,
Sink: mediaRouterMojom.MediaSink,
SinkExtraData: mediaRouterMojom.MediaSinkExtraData,
TimeDelta: timeMojom.TimeDelta,
Url: urlMojom.Url,
makeRequest: bindings.makeRequest,
};
};
......@@ -464,6 +481,16 @@ define('media_router_bindings', [
routeId, messages.map(messageToMojo_));
};
/**
* @param {number} tabId
* @param {!remotingMojom.MirrorServiceRemoterPtr} remoter
* @param {!remotingMojom.MirrorServiceRemotingSourcePtr} remotingSource
*/
MediaRouter.prototype.onMediaRemoterCreated = function(tabId, remoter,
remotingSource) {
this.service_.onMediaRemoterCreated(tabId, remoter, remotingSource);
}
/**
* Object containing callbacks set by the provider manager.
*
......
......@@ -93,6 +93,8 @@
<include name="IDR_MOJO_IP_ADDRESS_MOJOM_JS" file="${mojom_root}\net\interfaces\ip_address.mojom.js" use_base_dir="false" type="BINDATA" />
<include name="IDR_ORIGIN_MOJOM_JS" file="${mojom_root}\url\mojo\origin.mojom.js" use_base_dir="false" type="BINDATA" />
<include name="IDR_MOJO_URL_MOJOM_JS" file="${mojom_root}\url\mojo\url.mojom.js" use_base_dir="false" type="BINDATA" />
<include name="IDR_MEDIA_REMOTING_JS" file="${mojom_root}\media\mojo\interfaces\mirror_service_remoting.mojom.js" use_base_dir="false" type="BINDATA" />
<include name="IDR_REMOTING_COMMON_JS" file="${mojom_root}\media\mojo\interfaces\remoting_common.mojom.js" use_base_dir="false" type="BINDATA" />
</if>
</includes>
</release>
......
......@@ -52,10 +52,36 @@ mojom("constants") {
]
}
mojom("remoting_common") {
sources = [
"remoting_common.mojom",
]
# TODO(crbug.com/699569): Convert to use the new JS bindings.
use_new_js_bindings = false
}
mojom("mirror_service_remoting") {
sources = [
"mirror_service_remoting.mojom",
]
public_deps = [
":remoting_common",
]
# TODO(crbug.com/699569): Convert to use the new JS bindings.
use_new_js_bindings = false
}
mojom("remoting") {
sources = [
"remoting.mojom",
]
public_deps = [
":remoting_common",
]
}
mojom("test_interfaces") {
......
// 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.
module media.mojom;
import "media/mojo/interfaces/remoting_common.mojom";
// Interface used by the source to start/stop remoting and send data to the
// sink.
interface MirrorServiceRemoter {
// Starts a remoting session. Always assumes the remoting session will be
// stared successfully. If any failure happens,
// MirrorServiceRemotingSource::OnError() will be called.
Start();
// Starts remoting the media data streams. This is called after Start() to
// indicate audio/video bitstream data is ready to be consumed. Returns
// audio/video stream IDs. A valid stream ID should be greater than 0. When
// there is no audio/video, or if the data stream is not successfully started,
// the returned stream ID is -1.
StartDataStreams(bool has_audio, bool has_video)
=> (int32 audio_stream_id, int32 video_stream_id);
// Stops remoting media. Messages in both directions will be dropped after
// this point as well as any pending or in-transit media bitstream data.
Stop(RemotingStopReason reason);
// Sends|message| to the sink. |message| is a serialized protobuf from
// src/media/remoting/proto.
SendMessageToSink(array<uint8> message);
};
// Interface used for sending notifications back to the source's control logic,
// and to pass messages from the sink back to the source.
interface MirrorServiceRemotingSource {
// Notifies the source that the sink is now available to start remoting and
// passes the receiver's capabilities. It is up to the source's control logic
// to decide whether/when to start remoting.
OnSinkAvailable(SinkCapabilities capabilities);
// Passes a |message| from the sink back to the source. The |message| consists
// of a serialized protobuf from src/media/remoting/proto. This will only be
// called after OnStarted() and before OnStopped().
OnMessageFromSink(array<uint8> message);
// Notifies the source that remoting has terminated. This may or may not be in
// response to a MirrorServiceRemoter.Stop() call, as other events (possibly
// external) may have caused remoting to end.
OnStopped(RemotingStopReason reason);
// Notifies the source that a fatal error has occurred. Remoting session will
// be stopped immediately once this is called.
// TODO(xjz): Add error codes in future to indicate different errors.
OnError();
};
......@@ -4,6 +4,8 @@
module media.mojom;
import "media/mojo/interfaces/remoting_common.mojom";
interface RemoterFactory {
// Create a new Remoter associated with the given RemotingSource and bind it
// to the given interface request. The RemotingSource will be notified when
......@@ -32,7 +34,7 @@ interface RemotingDataStreamSender {
// provide all of the frame's data.
SendFrame();
// Cancel the transmission of all in-flight data to the remote, up to and
// Cancels the transmission of all in-flight data to the remote, up to and
// including the last SendFrame() call; and also discard any data chunks
// that were consumed from the data pipe for the next frame. This is used to
// optimize seeking, when it is known that any in-flight data is no longer
......@@ -41,26 +43,17 @@ interface RemotingDataStreamSender {
CancelInFlightData();
};
enum RemotingStopReason {
ROUTE_TERMINATED, // User-initiated disconnect, etc.
LOCAL_PLAYBACK, // Media switched back to local playback.
SOURCE_GONE, // RemotingSource has been destroyed.
MESSAGE_SEND_FAILED, // Failed to send a message to the sink.
DATA_SEND_FAILED, // Failed to consume from a data pipe or send to the sink.
UNEXPECTED_FAILURE, // Unexpected failure or inconsistent state encountered.
};
// Interface used by the source to start/stop remoting and send data to the
// sink.
interface Remoter {
// Start a remoting session (once the sink has been reported to be available;
// Starts a remoting session (once the sink has been reported to be available;
// see RemotingSource). Either RemotingSource.OnStarted() or OnStartFailed()
// will be called to indicate success or failure. Once OnStarted() has been
// invoked, the source may then make calls to SendMessageToSink() and expect
// messages from the remote via RemotingSource.OnMessageFromSink().
Start();
// Start remoting the media data streams. This is called after Start() to
// Starts remoting the media data streams. This is called after Start() to
// provide data pipes from which the audio/video bitstream data is consumed
// and then transported to the remote device. RemotingDataStreamSenders are
// used by the source to control when data should be consumed from the data
......@@ -71,37 +64,34 @@ interface Remoter {
RemotingDataStreamSender&? audio_sender,
RemotingDataStreamSender&? video_sender);
// Stop remoting media. Messages in both directions will be dropped after this
// Stops remoting media. Messages in both directions will be dropped after this
// point as well as any pending or in-transit media bitstream data.
Stop(RemotingStopReason reason);
// Send |message| to the sink. |message| is a serialized protobuf from
// Sends |message| to the sink. |message| is a serialized protobuf from
// src/media/remoting/proto.
SendMessageToSink(array<uint8> message);
};
// TODO(xjz): Replace this with the SinkCapabilities struct defined in
// remoting_common.mojom.
enum RemotingSinkCapabilities {
NONE,
RENDERING_ONLY,
CONTENT_DECRYPTION_AND_RENDERING,
};
enum RemotingStartFailReason {
CANNOT_START_MULTIPLE, // Remoting was already active.
ROUTE_TERMINATED, // User-initated disconnect while starting remoting.
};
// Interface used for sending notifications back to the local source's control
// logic, and to pass messages from the sink back to the local media pipeline.
interface RemotingSource {
// Notify the source that the sink is now available to start remoting. It is
// Notifies the source that the sink is now available to start remoting. It is
// up to the source's control logic to decide whether/when to start remoting.
//
// TODO(miu): In a later change, pass detailed information about the sink's
// capabilities (e.g., codec support, DRM keysystem support, etc.).
OnSinkAvailable(RemotingSinkCapabilities capabilities);
// Notify the source that the sink is no longer available for remoting. This
// Notifies the source that the sink is no longer available for remoting. This
// may happen, for example, because the sink has been shut down, or because
// another source has started remoting.
OnSinkGone();
......@@ -114,12 +104,12 @@ interface RemotingSource {
OnStarted();
OnStartFailed(RemotingStartFailReason reason);
// Pass a |message| from the sink back to the source. The |message| consists
// Passes a |message| from the sink back to the source. The |message| consists
// of a serialized protobuf from src/media/remoting/proto. This will only be
// called after OnStarted() and before OnStopped().
OnMessageFromSink(array<uint8> message);
// Notify the source that remoting has terminated. This may or may not be in
// Notifies the source that remoting has terminated. This may or may not be in
// response to a Remoter.Stop() call, as other events (possibly external) may
// have caused remoting to end.
OnStopped(RemotingStopReason reason);
......
// 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.
module media.mojom;
enum RemotingStopReason {
ROUTE_TERMINATED, // User-initiated disconnect, etc.
LOCAL_PLAYBACK, // Media switched back to local playback.
SOURCE_GONE, // RemotingSource has been destroyed.
MESSAGE_SEND_FAILED, // Failed to send a message to the sink.
DATA_SEND_FAILED, // Failed to consume from a data pipe or send to the sink.
UNEXPECTED_FAILURE, // Unexpected failure or inconsistent state encountered.
SERVICE_GONE, // Mirror service disconnected.
};
enum RemotingStartFailReason {
CANNOT_START_MULTIPLE, // Remoting was already active.
ROUTE_TERMINATED, // User-initated disconnect while starting remoting.
SERVICE_NOT_CONNECTED, // Mirror service was not connected.
};
enum RemotingSinkFeatures {
RENDERING,
CONTENT_DECRYPTION,
};
enum RemotingSinkAudioCapabilities {
CODEC_BASELINE_SET,
CODEC_AAC,
CODEC_OPUS,
};
enum RemotingSinkVideoCapabilities {
SUPPORT_4K,
CODEC_BASELINE_SET,
CODEC_H264,
CODEC_VP8,
CODEC_VP9,
CODEC_HEVC,
};
struct SinkCapabilities {
array<RemotingSinkFeatures> features;
array<RemotingSinkAudioCapabilities> audio;
array<RemotingSinkVideoCapabilities> video;
};
......@@ -118,6 +118,7 @@ void RendererController::OnBecameDominantVisibleContent(bool is_dominant) {
}
void RendererController::OnSetCdm(CdmContext* cdm_context) {
VLOG(2) << __func__;
DCHECK(thread_checker_.CalledOnValidThread());
auto* remoting_cdm_context = RemotingCdmContext::From(cdm_context);
......@@ -131,6 +132,7 @@ void RendererController::OnSetCdm(CdmContext* cdm_context) {
}
void RendererController::OnRemotePlaybackDisabled(bool disabled) {
VLOG(2) << __func__ << ": disabled = " << disabled;
DCHECK(thread_checker_.CalledOnValidThread());
is_remote_playback_disabled_ = disabled;
......@@ -290,6 +292,10 @@ bool RendererController::ShouldBeRemoting() {
case mojom::RemotingSinkCapabilities::RENDERING_ONLY:
case mojom::RemotingSinkCapabilities::CONTENT_DECRYPTION_AND_RENDERING:
break; // The sink is capable of remote rendering.
default:
// TODO(xjz): Will be changed in a coming CL that passes the receiver's
// capabilities.
NOTREACHED();
}
if ((!has_audio() && !has_video()) ||
......@@ -352,6 +358,7 @@ void RendererController::UpdateAndMaybeSwitch(StartTrigger start_trigger,
}
void RendererController::OnRendererFatalError(StopTrigger stop_trigger) {
VLOG(2) << __func__ << ": stop_trigger= " << stop_trigger;
DCHECK(thread_checker_.CalledOnValidThread());
// Do not act on errors caused by things like Mojo pipes being closed during
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment