Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4200)

Unified Diff: chrome/renderer/extensions/cast_streaming_native_handler.cc

Issue 938903003: Cast: Javascript bindings for cast receiver (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cast_receiver_session
Patch Set: merged Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/renderer/extensions/cast_streaming_native_handler.cc
diff --git a/chrome/renderer/extensions/cast_streaming_native_handler.cc b/chrome/renderer/extensions/cast_streaming_native_handler.cc
index a10a15446d58ba9b441b07204e2cdd3e4137e573..50a1ace69f8cbb4a1c32848044771146e7d6d810 100644
--- a/chrome/renderer/extensions/cast_streaming_native_handler.cc
+++ b/chrome/renderer/extensions/cast_streaming_native_handler.cc
@@ -10,20 +10,29 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "chrome/common/extensions/api/cast_streaming_receiver_session.h"
#include "chrome/common/extensions/api/cast_streaming_rtp_stream.h"
#include "chrome/common/extensions/api/cast_streaming_udp_transport.h"
+#include "chrome/renderer/media/cast_receiver_session.h"
#include "chrome/renderer/media/cast_rtp_stream.h"
#include "chrome/renderer/media/cast_session.h"
#include "chrome/renderer/media/cast_udp_transport.h"
#include "content/public/child/v8_value_converter.h"
+#include "content/public/renderer/media_stream_api.h"
#include "extensions/renderer/script_context.h"
+#include "media/audio/audio_parameters.h"
#include "net/base/host_port_pair.h"
+#include "third_party/WebKit/public/platform/WebMediaStream.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDOMMediaStreamTrack.h"
+#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
+#include "url/gurl.h"
using content::V8ValueConverter;
// Extension types.
+using extensions::api::cast_streaming_receiver_session::RtpReceiverParams;
using extensions::api::cast_streaming_rtp_stream::CodecSpecificParams;
using extensions::api::cast_streaming_rtp_stream::RtpParams;
using extensions::api::cast_streaming_rtp_stream::RtpPayloadParams;
@@ -32,13 +41,16 @@ using extensions::api::cast_streaming_udp_transport::IPEndPoint;
namespace extensions {
namespace {
-const char kRtpStreamNotFound[] = "The RTP stream cannot be found";
-const char kUdpTransportNotFound[] = "The UDP transport cannot be found";
+const char kInvalidAesIvMask[] = "Invalid value for AES IV mask";
+const char kInvalidAesKey[] = "Invalid value for AES key";
+const char kInvalidAudioParams[] = "Invalid audio params";
const char kInvalidDestination[] = "Invalid destination";
+const char kInvalidFPS[] = "Invalid FPS";
+const char kInvalidMediaStreamURL[] = "Invalid MediaStream URL";
const char kInvalidRtpParams[] = "Invalid value for RTP params";
-const char kInvalidAesKey[] = "Invalid value for AES key";
-const char kInvalidAesIvMask[] = "Invalid value for AES IV mask";
const char kInvalidStreamArgs[] = "Invalid stream arguments";
+const char kRtpStreamNotFound[] = "The RTP stream cannot be found";
+const char kUdpTransportNotFound[] = "The UDP transport cannot be found";
const char kUnableToConvertArgs[] = "Unable to convert arguments";
const char kUnableToConvertParams[] = "Unable to convert params";
@@ -199,6 +211,9 @@ CastStreamingNativeHandler::CastStreamingNativeHandler(ScriptContext* context)
RouteFunction("GetStats",
base::Bind(&CastStreamingNativeHandler::GetStats,
base::Unretained(this)));
+ RouteFunction("StartCastRtpReceiver",
+ base::Bind(&CastStreamingNativeHandler::StartCastRtpReceiver,
+ base::Unretained(this)));
}
CastStreamingNativeHandler::~CastStreamingNativeHandler() {
@@ -440,28 +455,14 @@ void CastStreamingNativeHandler::SetDestinationCastUdpTransport(
if (!transport)
return;
- scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
- scoped_ptr<base::Value> destination_value(
- converter->FromV8Value(args[1], context()->v8_context()));
- if (!destination_value) {
- args.GetIsolate()->ThrowException(v8::Exception::TypeError(
- v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertArgs)));
+ net::IPEndPoint dest;
+ if (!IPEndPointFromArg(args.GetIsolate(),
+ args[1],
+ false,
+ &dest)) {
return;
}
- scoped_ptr<IPEndPoint> destination =
- IPEndPoint::FromValue(*destination_value);
- if (!destination) {
- args.GetIsolate()->ThrowException(v8::Exception::TypeError(
- v8::String::NewFromUtf8(args.GetIsolate(), kInvalidDestination)));
- return;
- }
- net::IPAddressNumber ip;
- if (!net::ParseIPLiteralToNumber(destination->address, &ip)) {
- args.GetIsolate()->ThrowException(v8::Exception::TypeError(
- v8::String::NewFromUtf8(args.GetIsolate(), kInvalidDestination)));
- return;
- }
- transport->SetDestination(net::IPEndPoint(ip, destination->port));
+ transport->SetDestination(dest);
}
void CastStreamingNativeHandler::SetOptionsCastUdpTransport(
@@ -616,4 +617,209 @@ CastUdpTransport* CastStreamingNativeHandler::GetUdpTransportOrThrow(
return NULL;
}
+bool CastStreamingNativeHandler::FrameReceiverFromArg(
+ v8::Isolate* isolate,
+ const v8::Handle<v8::Value>& arg,
+ media::cast::FrameReceiverConfig* config) {
+
+ scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
+ scoped_ptr<base::Value> params_value(
+ converter->FromV8Value(arg, context()->v8_context()));
+ if (!params_value) {
+ isolate->ThrowException(v8::Exception::TypeError(
+ v8::String::NewFromUtf8(isolate, kUnableToConvertParams)));
+ return false;
+ }
+ scoped_ptr<RtpReceiverParams> params =
+ RtpReceiverParams::FromValue(*params_value);
+ if (!params) {
+ isolate->ThrowException(v8::Exception::TypeError(
+ v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
+ return false;
+ }
+
+ config->feedback_ssrc = params->feedback_ssrc;
+ config->incoming_ssrc = params->ssrc;
+ config->rtp_max_delay_ms = params->max_latency;
miu 2015/02/26 06:23:34 Please range-check this value, and throw a v8 exce
hubbe 2015/02/28 00:17:12 Done.
+ config->rtp_payload_type = params->payload_type;
+ config->channels = params->channels ? *params->channels : 0;
+ if (params->codec_name == "OPUS") {
+ config->codec = media::cast::CODEC_AUDIO_OPUS;
+ config->rtp_timebase = 48000;
+ } else if (params->codec_name == "PCM16") {
+ config->codec = media::cast::CODEC_AUDIO_PCM16;
+ config->rtp_timebase = 48000;
+ } else if (params->codec_name == "AAC") {
+ config->codec = media::cast::CODEC_AUDIO_AAC;
+ config->rtp_timebase = 48000;
+ } else if (params->codec_name == "VP8") {
+ config->codec = media::cast::CODEC_VIDEO_VP8;
+ config->rtp_timebase = 90000;
+ } else if (params->codec_name == "H264") {
+ config->codec = media::cast::CODEC_VIDEO_H264;
+ config->rtp_timebase = 90000;
+ }
+ config->rtp_timebase = params->clock_rate ? *params->clock_rate : 0;
miu 2015/02/26 06:23:34 This overwrites the previous assignments of config
hubbe 2015/02/28 00:17:11 Done.
+ if (params->aes_key &&
+ !HexDecode(*params->aes_key, &config->aes_key)) {
+ isolate->ThrowException(v8::Exception::Error(
+ v8::String::NewFromUtf8(isolate, kInvalidAesKey)));
+ return false;
+ }
+ if (params->aes_iv_mask &&
+ !HexDecode(*params->aes_iv_mask, &config->aes_iv_mask)) {
+ isolate->ThrowException(v8::Exception::Error(
+ v8::String::NewFromUtf8(isolate, kInvalidAesIvMask)));
+ return false;
+ }
+ return true;
+}
+
+bool CastStreamingNativeHandler::IPEndPointFromArg(
+ v8::Isolate* isolate,
+ const v8::Handle<v8::Value>& arg,
+ bool empty_ok,
+ net::IPEndPoint* ip_endpoint) {
+ scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
+ scoped_ptr<base::Value> destination_value(
+ converter->FromV8Value(arg, context()->v8_context()));
+ if (!destination_value) {
+ isolate->ThrowException(v8::Exception::TypeError(
+ v8::String::NewFromUtf8(isolate, kInvalidAesIvMask)));
+ return false;
+ }
+ scoped_ptr<IPEndPoint> destination =
+ IPEndPoint::FromValue(*destination_value);
+ if (!destination) {
+ isolate->ThrowException(v8::Exception::TypeError(
+ v8::String::NewFromUtf8(isolate, kInvalidDestination)));
+ return false;
+ }
+ net::IPAddressNumber ip;
+ if (destination->address != "" || !empty_ok) {
+ if (!net::ParseIPLiteralToNumber(destination->address, &ip)) {
+ isolate->ThrowException(v8::Exception::TypeError(
+ v8::String::NewFromUtf8(isolate, kInvalidDestination)));
+ return false;
+ }
+ }
+ *ip_endpoint = net::IPEndPoint(ip, destination->port);
+ return true;
+}
+
+void CastStreamingNativeHandler::StartCastRtpReceiver(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() < 8 || args.Length() > 9 ||
+ !args[0]->IsObject() ||
+ !args[1]->IsObject() ||
+ !args[2]->IsObject() ||
+ !args[3]->IsObject() ||
+ !args[4]->IsInt32() ||
+ !args[5]->IsInt32() ||
+ !args[6]->IsNumber() ||
+ !args[7]->IsString()) {
+ args.GetIsolate()->ThrowException(v8::Exception::TypeError(
+ v8::String::NewFromUtf8(args.GetIsolate(), "ARG!!!")));
Alpha Left Google 2015/02/25 20:37:28 Should be a more user friendly string.
hubbe 2015/02/28 00:17:11 OOps, fixed.
+ return;
+ }
+
+ v8::Isolate* isolate = context()->v8_context()->GetIsolate();
+
+ scoped_refptr<CastReceiverSession> session(
+ new CastReceiverSession());
+ media::cast::FrameReceiverConfig audio_config;
+ media::cast::FrameReceiverConfig video_config;
+ net::IPEndPoint local_endpoint;
+ net::IPEndPoint remote_endpoint;
+
+ if (!FrameReceiverFromArg(isolate, args[0], &audio_config) ||
+ !FrameReceiverFromArg(isolate, args[1], &video_config) ||
+ !IPEndPointFromArg(isolate, args[2], true, &local_endpoint) ||
+ !IPEndPointFromArg(isolate, args[3], true, &remote_endpoint)) {
+ return;
miu 2015/02/26 06:23:34 Throw error exception here?
hubbe 2015/02/28 00:17:12 An exception will have already been raised in this
+ }
+
+ const std::string url = *v8::String::Utf8Value(args[7]);
+ blink::WebMediaStream stream =
+ blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
+
+ if (stream.isNull()) {
+ args.GetIsolate()->ThrowException(v8::Exception::TypeError(
+ v8::String::NewFromUtf8(args.GetIsolate(), kInvalidMediaStreamURL)));
+ return;
+ }
+
+ const int width = args[4]->ToInt32(args.GetIsolate())->Value();
+ const int height = args[5]->ToInt32(args.GetIsolate())->Value();
+ const double fps = args[6]->NumberValue();
+
+ if (fps <= 1) {
+ args.GetIsolate()->ThrowException(v8::Exception::TypeError(
+ v8::String::NewFromUtf8(args.GetIsolate(), kInvalidFPS)));
+ return;
+ }
+
+ media::VideoCaptureFormat capture_format(
+ gfx::Size(width, height),
+ fps,
+ media::PIXEL_FORMAT_I420);
+
+ video_config.target_frame_rate = fps;
Alpha Left Google 2015/02/25 20:37:28 I think the fps parameter in VideoCaptureFormat ha
miu 2015/02/26 06:23:34 Doesn't a Cast Receiver have NO concept of frame r
hubbe 2015/02/28 00:17:12 That might be true, but I don't actually know how
hubbe 2015/02/28 00:17:12 Unfortunately capture_format.IsValid() must be tru
+ audio_config.target_frame_rate = 100;
+
+ media::AudioParameters params(
+ media::AudioParameters::AUDIO_PCM_LINEAR,
+ media::CHANNEL_LAYOUT_STEREO,
+ audio_config.rtp_timebase, // sampling rate
+ 16,
+ audio_config.rtp_timebase / 100); // frames per buffer,
Alpha Left Google 2015/02/25 20:37:28 Divide by audio_config.target_frame_rate instead.
hubbe 2015/02/28 00:17:11 Done.
+
+ if (!params.IsValid()) {
+ args.GetIsolate()->ThrowException(v8::Exception::TypeError(
+ v8::String::NewFromUtf8(args.GetIsolate(), kInvalidAudioParams)));
+ return;
+ }
+
+ base::DictionaryValue* options = NULL;
+ if (args.Length() >= 9) {
+ scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
+ base::Value* options_value =
+ converter->FromV8Value(args[8], context()->v8_context());
+ if (!options_value->IsType(base::Value::TYPE_NULL)) {
+ if (!options_value || !options_value->GetAsDictionary(&options)) {
+ delete options_value;
+ args.GetIsolate()->ThrowException(v8::Exception::TypeError(
+ v8::String::NewFromUtf8(args.GetIsolate(), kUnableToConvertArgs)));
+ return;
+ }
+ }
+ }
+
+ if (!options) {
+ options = new base::DictionaryValue();
+ }
+
+ session->Start(audio_config,
+ video_config,
+ local_endpoint,
+ remote_endpoint,
+ make_scoped_ptr(options),
+ capture_format,
+ base::Bind(&CastStreamingNativeHandler::CallReceiverCB,
+ weak_factory_.GetWeakPtr(),
+ url,
+ params));
+}
+
+void CastStreamingNativeHandler::CallReceiverCB(
+ const std::string& url,
+ const media::AudioParameters& params,
+ scoped_refptr<media::AudioCapturerSource> audio,
+ scoped_ptr<media::VideoCapturerSource> video) {
+
+ content::AddAudioTrackToMediaStream(audio, params, true, true, url);
+ content::AddVideoTrackToMediaStream(video.Pass(), true, true, url);
+}
+
+
Alpha Left Google 2015/02/25 20:37:28 nit: remove this extra empty line.
hubbe 2015/02/28 00:17:12 Done.
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698