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

Side by Side Diff: chrome/renderer/extensions/cast_streaming_native_handler.cc

Issue 2307653002: Adding CastRemotingSender for media remoting. (Closed)
Patch Set: Rebased. Created 4 years, 3 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/extensions/cast_streaming_native_handler.h" 5 #include "chrome/renderer/extensions/cast_streaming_native_handler.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 14 matching lines...) Expand all
25 #include "base/threading/thread_task_runner_handle.h" 25 #include "base/threading/thread_task_runner_handle.h"
26 #include "chrome/common/extensions/api/cast_streaming_receiver_session.h" 26 #include "chrome/common/extensions/api/cast_streaming_receiver_session.h"
27 #include "chrome/common/extensions/api/cast_streaming_rtp_stream.h" 27 #include "chrome/common/extensions/api/cast_streaming_rtp_stream.h"
28 #include "chrome/common/extensions/api/cast_streaming_udp_transport.h" 28 #include "chrome/common/extensions/api/cast_streaming_udp_transport.h"
29 #include "chrome/renderer/media/cast_receiver_session.h" 29 #include "chrome/renderer/media/cast_receiver_session.h"
30 #include "chrome/renderer/media/cast_rtp_stream.h" 30 #include "chrome/renderer/media/cast_rtp_stream.h"
31 #include "chrome/renderer/media/cast_session.h" 31 #include "chrome/renderer/media/cast_session.h"
32 #include "chrome/renderer/media/cast_udp_transport.h" 32 #include "chrome/renderer/media/cast_udp_transport.h"
33 #include "content/public/child/v8_value_converter.h" 33 #include "content/public/child/v8_value_converter.h"
34 #include "content/public/renderer/media_stream_utils.h" 34 #include "content/public/renderer/media_stream_utils.h"
35 #include "extensions/common/extension.h"
35 #include "extensions/renderer/script_context.h" 36 #include "extensions/renderer/script_context.h"
36 #include "media/base/audio_parameters.h" 37 #include "media/base/audio_parameters.h"
37 #include "media/base/limits.h" 38 #include "media/base/limits.h"
38 #include "net/base/host_port_pair.h" 39 #include "net/base/host_port_pair.h"
39 #include "net/base/ip_address.h" 40 #include "net/base/ip_address.h"
40 #include "third_party/WebKit/public/platform/WebMediaStream.h" 41 #include "third_party/WebKit/public/platform/WebMediaStream.h"
41 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" 42 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
42 #include "third_party/WebKit/public/platform/WebURL.h" 43 #include "third_party/WebKit/public/platform/WebURL.h"
43 #include "third_party/WebKit/public/web/WebDOMMediaStreamTrack.h" 44 #include "third_party/WebKit/public/web/WebDOMMediaStreamTrack.h"
44 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h" 45 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
(...skipping 22 matching lines...) Expand all
67 constexpr char kInvalidLatency[] = "Invalid value for max_latency. (0-1000)"; 68 constexpr char kInvalidLatency[] = "Invalid value for max_latency. (0-1000)";
68 constexpr char kInvalidRtpTimebase[] = "Invalid rtp_timebase. (1000-1000000)"; 69 constexpr char kInvalidRtpTimebase[] = "Invalid rtp_timebase. (1000-1000000)";
69 constexpr char kInvalidStreamArgs[] = "Invalid stream arguments"; 70 constexpr char kInvalidStreamArgs[] = "Invalid stream arguments";
70 constexpr char kRtpStreamNotFound[] = "The RTP stream cannot be found"; 71 constexpr char kRtpStreamNotFound[] = "The RTP stream cannot be found";
71 constexpr char kUdpTransportNotFound[] = "The UDP transport cannot be found"; 72 constexpr char kUdpTransportNotFound[] = "The UDP transport cannot be found";
72 constexpr char kUnableToConvertArgs[] = "Unable to convert arguments"; 73 constexpr char kUnableToConvertArgs[] = "Unable to convert arguments";
73 constexpr char kUnableToConvertParams[] = "Unable to convert params"; 74 constexpr char kUnableToConvertParams[] = "Unable to convert params";
74 constexpr char kCodecNameOpus[] = "OPUS"; 75 constexpr char kCodecNameOpus[] = "OPUS";
75 constexpr char kCodecNameVp8[] = "VP8"; 76 constexpr char kCodecNameVp8[] = "VP8";
76 constexpr char kCodecNameH264[] = "H264"; 77 constexpr char kCodecNameH264[] = "H264";
78 constexpr char kCodecNameRemoteAudio[] = "REMOTE_AUDIO";
79 constexpr char kCodecNameRemoteVideo[] = "REMOTE_VIDEO";
77 80
78 // To convert from kilobits per second to bits per second. 81 // To convert from kilobits per second to bits per second.
79 constexpr int kBitsPerKilobit = 1000; 82 constexpr int kBitsPerKilobit = 1000;
80 83
81 bool HexDecode(const std::string& input, std::string* output) { 84 bool HexDecode(const std::string& input, std::string* output) {
82 std::vector<uint8_t> bytes; 85 std::vector<uint8_t> bytes;
83 if (!base::HexStringToBytes(input, &bytes)) 86 if (!base::HexStringToBytes(input, &bytes))
84 return false; 87 return false;
85 output->assign(reinterpret_cast<const char*>(&bytes[0]), bytes.size()); 88 output->assign(reinterpret_cast<const char*>(&bytes[0]), bytes.size());
86 return true; 89 return true;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 CastRtpStream::IsHardwareVP8EncodingSupported(); 209 CastRtpStream::IsHardwareVP8EncodingSupported();
207 } else { 210 } else {
208 config->rtp_payload_type = media::cast::RtpPayloadType::VIDEO_H264; 211 config->rtp_payload_type = media::cast::RtpPayloadType::VIDEO_H264;
209 config->codec = media::cast::CODEC_VIDEO_H264; 212 config->codec = media::cast::CODEC_VIDEO_H264;
210 config->use_external_encoder = 213 config->use_external_encoder =
211 CastRtpStream::IsHardwareH264EncodingSupported(); 214 CastRtpStream::IsHardwareH264EncodingSupported();
212 } 215 }
213 if (!config->use_external_encoder) 216 if (!config->use_external_encoder)
214 config->video_codec_params.number_of_encode_threads = 217 config->video_codec_params.number_of_encode_threads =
215 NumberOfEncodeThreads(); 218 NumberOfEncodeThreads();
219 } else if (ext_params.codec_name == kCodecNameRemoteAudio) {
220 config->rtp_payload_type = media::cast::RtpPayloadType::REMOTE_AUDIO;
221 config->codec = media::cast::CODEC_AUDIO_REMOTE;
222 } else if (ext_params.codec_name == kCodecNameRemoteVideo) {
223 config->rtp_payload_type = media::cast::RtpPayloadType::REMOTE_VIDEO;
224 config->codec = media::cast::CODEC_VIDEO_REMOTE;
216 } else { 225 } else {
217 DVLOG(1) << "codec_name " << ext_params.codec_name << " is invalid"; 226 DVLOG(1) << "codec_name " << ext_params.codec_name << " is invalid";
218 isolate->ThrowException(v8::Exception::Error( 227 isolate->ThrowException(v8::Exception::Error(
219 v8::String::NewFromUtf8(isolate, kInvalidRtpParams))); 228 v8::String::NewFromUtf8(isolate, kInvalidRtpParams)));
220 return false; 229 return false;
221 } 230 }
222 if (ext_params.aes_key && !HexDecode(*ext_params.aes_key, &config->aes_key)) { 231 if (ext_params.aes_key && !HexDecode(*ext_params.aes_key, &config->aes_key)) {
223 isolate->ThrowException(v8::Exception::Error( 232 isolate->ThrowException(v8::Exception::Error(
224 v8::String::NewFromUtf8(isolate, kInvalidAesKey))); 233 v8::String::NewFromUtf8(isolate, kInvalidAesKey)));
225 return false; 234 return false;
(...skipping 18 matching lines...) Expand all
244 switch (config.codec) { 253 switch (config.codec) {
245 case media::cast::CODEC_AUDIO_OPUS: 254 case media::cast::CODEC_AUDIO_OPUS:
246 ext_params->codec_name = kCodecNameOpus; 255 ext_params->codec_name = kCodecNameOpus;
247 break; 256 break;
248 case media::cast::CODEC_VIDEO_VP8: 257 case media::cast::CODEC_VIDEO_VP8:
249 ext_params->codec_name = kCodecNameVp8; 258 ext_params->codec_name = kCodecNameVp8;
250 break; 259 break;
251 case media::cast::CODEC_VIDEO_H264: 260 case media::cast::CODEC_VIDEO_H264:
252 ext_params->codec_name = kCodecNameH264; 261 ext_params->codec_name = kCodecNameH264;
253 break; 262 break;
263 case media::cast::CODEC_AUDIO_REMOTE:
264 ext_params->codec_name = kCodecNameRemoteAudio;
265 break;
266 case media::cast::CODEC_VIDEO_REMOTE:
267 ext_params->codec_name = kCodecNameRemoteVideo;
268 break;
254 default: 269 default:
255 NOTREACHED(); 270 NOTREACHED();
256 } 271 }
257 ext_params->ssrc = config.sender_ssrc; 272 ext_params->ssrc = config.sender_ssrc;
258 ext_params->feedback_ssrc = config.receiver_ssrc; 273 ext_params->feedback_ssrc = config.receiver_ssrc;
259 if (config.rtp_timebase) 274 if (config.rtp_timebase)
260 ext_params->clock_rate.reset(new int(config.rtp_timebase)); 275 ext_params->clock_rate.reset(new int(config.rtp_timebase));
261 if (config.min_bitrate) 276 if (config.min_bitrate)
262 ext_params->min_bitrate.reset( 277 ext_params->min_bitrate.reset(
263 new int(config.min_bitrate / kBitsPerKilobit)); 278 new int(config.min_bitrate / kBitsPerKilobit));
264 if (config.max_bitrate) 279 if (config.max_bitrate)
265 ext_params->max_bitrate.reset( 280 ext_params->max_bitrate.reset(
266 new int(config.max_bitrate / kBitsPerKilobit)); 281 new int(config.max_bitrate / kBitsPerKilobit));
267 if (config.channels) 282 if (config.channels)
268 ext_params->channels.reset(new int(config.channels)); 283 ext_params->channels.reset(new int(config.channels));
269 if (config.max_frame_rate > 0.0) 284 if (config.max_frame_rate > 0.0)
270 ext_params->max_frame_rate.reset(new double(config.max_frame_rate)); 285 ext_params->max_frame_rate.reset(new double(config.max_frame_rate));
271 } 286 }
272 287
273 } // namespace 288 } // namespace
274 289
290 // |last_transport_id_| is the identifier for the next created RTP stream. To
291 // create globally unique IDs used for referring to RTP stream objects in
292 // browser process, we set its higher 16 bits as HASH(extension_id)&0x7fff, and
293 // lower 16 bits as the sequence number of the RTP stream created in the same
294 // extension. Collision will happen when the first RTP stream keeps alive after
295 // creating another 64k-1 RTP streams in the same extension, which is very
296 // unlikely to happen in normal use cases.
275 CastStreamingNativeHandler::CastStreamingNativeHandler(ScriptContext* context) 297 CastStreamingNativeHandler::CastStreamingNativeHandler(ScriptContext* context)
276 : ObjectBackedNativeHandler(context), 298 : ObjectBackedNativeHandler(context),
277 last_transport_id_(1), 299 last_transport_id_(
300 context->extension()
301 ? (((base::Hash(context->extension()->id()) & 0x7fff) << 16) + 1)
302 : 1),
278 weak_factory_(this) { 303 weak_factory_(this) {
279 RouteFunction("CreateSession", "cast.streaming.session", 304 RouteFunction("CreateSession", "cast.streaming.session",
280 base::Bind(&CastStreamingNativeHandler::CreateCastSession, 305 base::Bind(&CastStreamingNativeHandler::CreateCastSession,
281 weak_factory_.GetWeakPtr())); 306 weak_factory_.GetWeakPtr()));
282 RouteFunction("DestroyCastRtpStream", "cast.streaming.rtpStream", 307 RouteFunction("DestroyCastRtpStream", "cast.streaming.rtpStream",
283 base::Bind(&CastStreamingNativeHandler::DestroyCastRtpStream, 308 base::Bind(&CastStreamingNativeHandler::DestroyCastRtpStream,
284 weak_factory_.GetWeakPtr())); 309 weak_factory_.GetWeakPtr()));
285 RouteFunction( 310 RouteFunction(
286 "GetSupportedParamsCastRtpStream", "cast.streaming.rtpStream", 311 "GetSupportedParamsCastRtpStream", "cast.streaming.rtpStream",
287 base::Bind(&CastStreamingNativeHandler::GetSupportedParamsCastRtpStream, 312 base::Bind(&CastStreamingNativeHandler::GetSupportedParamsCastRtpStream,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 361
337 ObjectBackedNativeHandler::Invalidate(); 362 ObjectBackedNativeHandler::Invalidate();
338 } 363 }
339 364
340 void CastStreamingNativeHandler::CreateCastSession( 365 void CastStreamingNativeHandler::CreateCastSession(
341 const v8::FunctionCallbackInfo<v8::Value>& args) { 366 const v8::FunctionCallbackInfo<v8::Value>& args) {
342 CHECK_EQ(3, args.Length()); 367 CHECK_EQ(3, args.Length());
343 CHECK(args[2]->IsFunction()); 368 CHECK(args[2]->IsFunction());
344 369
345 v8::Isolate* isolate = context()->v8_context()->GetIsolate(); 370 v8::Isolate* isolate = context()->v8_context()->GetIsolate();
346 if ((args[0]->IsNull() || args[0]->IsUndefined()) &&
347 (args[1]->IsNull() || args[1]->IsUndefined())) {
348 isolate->ThrowException(v8::Exception::Error(
349 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
350 return;
351 }
352 371
353 scoped_refptr<CastSession> session(new CastSession()); 372 scoped_refptr<CastSession> session(new CastSession());
354 std::unique_ptr<CastRtpStream> stream1, stream2; 373 std::unique_ptr<CastRtpStream> stream1, stream2;
355 if (!args[0]->IsNull() && !args[0]->IsUndefined()) { 374 if ((args[0]->IsNull() || args[0]->IsUndefined()) &&
356 CHECK(args[0]->IsObject()); 375 (args[1]->IsNull() || args[1]->IsUndefined())) {
357 blink::WebDOMMediaStreamTrack track = 376 DVLOG(3) << "CreateCastSession for remoting.";
358 blink::WebDOMMediaStreamTrack::fromV8Value(args[0]); 377 // Creates audio/video RTP streams for media remoting.
359 if (track.isNull()) { 378 stream1.reset(new CastRtpStream(true, session));
360 isolate->ThrowException(v8::Exception::Error( 379 stream2.reset(new CastRtpStream(false, session));
361 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs))); 380 } else {
362 return; 381 // Creates RTP streams that consume from an audio and/or a video
382 // MediaStreamTrack.
383 if (!args[0]->IsNull() && !args[0]->IsUndefined()) {
384 CHECK(args[0]->IsObject());
385 blink::WebDOMMediaStreamTrack track =
386 blink::WebDOMMediaStreamTrack::fromV8Value(args[0]);
387 if (track.isNull()) {
388 isolate->ThrowException(v8::Exception::Error(
389 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
390 return;
391 }
392 stream1.reset(new CastRtpStream(track.component(), session));
363 } 393 }
364 stream1.reset(new CastRtpStream(track.component(), session)); 394 if (!args[1]->IsNull() && !args[1]->IsUndefined()) {
365 } 395 CHECK(args[1]->IsObject());
366 if (!args[1]->IsNull() && !args[1]->IsUndefined()) { 396 blink::WebDOMMediaStreamTrack track =
367 CHECK(args[1]->IsObject()); 397 blink::WebDOMMediaStreamTrack::fromV8Value(args[1]);
368 blink::WebDOMMediaStreamTrack track = 398 if (track.isNull()) {
369 blink::WebDOMMediaStreamTrack::fromV8Value(args[1]); 399 isolate->ThrowException(v8::Exception::Error(
370 if (track.isNull()) { 400 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs)));
371 isolate->ThrowException(v8::Exception::Error( 401 return;
372 v8::String::NewFromUtf8(isolate, kInvalidStreamArgs))); 402 }
373 return; 403 stream2.reset(new CastRtpStream(track.component(), session));
374 } 404 }
375 stream2.reset(new CastRtpStream(track.component(), session));
376 } 405 }
377 std::unique_ptr<CastUdpTransport> udp_transport( 406 std::unique_ptr<CastUdpTransport> udp_transport(
378 new CastUdpTransport(session)); 407 new CastUdpTransport(session));
379 408
380 create_callback_.Reset(isolate, args[2].As<v8::Function>()); 409 create_callback_.Reset(isolate, args[2].As<v8::Function>());
381 410
382 base::ThreadTaskRunnerHandle::Get()->PostTask( 411 base::ThreadTaskRunnerHandle::Get()->PostTask(
383 FROM_HERE, 412 FROM_HERE,
384 base::Bind(&CastStreamingNativeHandler::CallCreateCallback, 413 base::Bind(&CastStreamingNativeHandler::CallCreateCallback,
385 weak_factory_.GetWeakPtr(), base::Passed(&stream1), 414 weak_factory_.GetWeakPtr(), base::Passed(&stream1),
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 weak_factory_.GetWeakPtr(), 551 weak_factory_.GetWeakPtr(),
523 transport_id); 552 transport_id);
524 base::Closure stop_callback = 553 base::Closure stop_callback =
525 base::Bind(&CastStreamingNativeHandler::CallStopCallback, 554 base::Bind(&CastStreamingNativeHandler::CallStopCallback,
526 weak_factory_.GetWeakPtr(), 555 weak_factory_.GetWeakPtr(),
527 transport_id); 556 transport_id);
528 CastRtpStream::ErrorCallback error_callback = 557 CastRtpStream::ErrorCallback error_callback =
529 base::Bind(&CastStreamingNativeHandler::CallErrorCallback, 558 base::Bind(&CastStreamingNativeHandler::CallErrorCallback,
530 weak_factory_.GetWeakPtr(), 559 weak_factory_.GetWeakPtr(),
531 transport_id); 560 transport_id);
532 transport->Start(config, start_callback, stop_callback, error_callback); 561
562 // |transport_id| is a globally unique identifier for the RTP stream.
563 transport->Start(transport_id, config, start_callback, stop_callback,
564 error_callback);
533 } 565 }
534 566
535 void CastStreamingNativeHandler::StopCastRtpStream( 567 void CastStreamingNativeHandler::StopCastRtpStream(
536 const v8::FunctionCallbackInfo<v8::Value>& args) { 568 const v8::FunctionCallbackInfo<v8::Value>& args) {
537 CHECK_EQ(1, args.Length()); 569 CHECK_EQ(1, args.Length());
538 CHECK(args[0]->IsInt32()); 570 CHECK(args[0]->IsInt32());
539 571
540 const int transport_id = args[0]->ToInt32(args.GetIsolate())->Value(); 572 const int transport_id = args[0]->ToInt32(args.GetIsolate())->Value();
541 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id); 573 CastRtpStream* transport = GetRtpStreamOrThrow(transport_id);
542 if (!transport) 574 if (!transport)
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 LOG(ERROR) << "Failed to add Cast audio track to media stream."; 994 LOG(ERROR) << "Failed to add Cast audio track to media stream.";
963 } 995 }
964 if (!content::AddVideoTrackToMediaStream(std::move(video), true, // is_remote 996 if (!content::AddVideoTrackToMediaStream(std::move(video), true, // is_remote
965 true, // is_readonly 997 true, // is_readonly
966 &web_stream)) { 998 &web_stream)) {
967 LOG(ERROR) << "Failed to add Cast video track to media stream."; 999 LOG(ERROR) << "Failed to add Cast video track to media stream.";
968 } 1000 }
969 } 1001 }
970 1002
971 } // namespace extensions 1003 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698