OLD | NEW |
---|---|
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/media/cast_rtp_stream.h" | 5 #include "chrome/renderer/media/cast_rtp_stream.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <memory> | 10 #include <memory> |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
55 // limit (60 * 250ms = 15 seconds), refresh frame requests will stop being made. | 55 // limit (60 * 250ms = 15 seconds), refresh frame requests will stop being made. |
56 const int kMaxConsecutiveRefreshFrames = 60; | 56 const int kMaxConsecutiveRefreshFrames = 60; |
57 | 57 |
58 FrameSenderConfig DefaultOpusConfig() { | 58 FrameSenderConfig DefaultOpusConfig() { |
59 FrameSenderConfig config; | 59 FrameSenderConfig config; |
60 config.rtp_payload_type = media::cast::RtpPayloadType::AUDIO_OPUS; | 60 config.rtp_payload_type = media::cast::RtpPayloadType::AUDIO_OPUS; |
61 config.sender_ssrc = 1; | 61 config.sender_ssrc = 1; |
62 config.receiver_ssrc = 2; | 62 config.receiver_ssrc = 2; |
63 config.rtp_timebase = media::cast::kDefaultAudioSamplingRate; | 63 config.rtp_timebase = media::cast::kDefaultAudioSamplingRate; |
64 config.channels = 2; | 64 config.channels = 2; |
65 // The value is 0 which means VBR. | |
66 config.min_bitrate = config.max_bitrate = config.start_bitrate = | 65 config.min_bitrate = config.max_bitrate = config.start_bitrate = |
67 media::cast::kDefaultAudioEncoderBitrate; | 66 media::cast::kDefaultAudioEncoderBitrate; |
68 config.max_frame_rate = 100; // 10 ms audio frames | 67 config.max_frame_rate = 100; // 10 ms audio frames |
69 config.codec = media::cast::CODEC_AUDIO_OPUS; | 68 config.codec = media::cast::CODEC_AUDIO_OPUS; |
70 return config; | 69 return config; |
71 } | 70 } |
72 | 71 |
73 FrameSenderConfig DefaultVp8Config() { | 72 FrameSenderConfig DefaultVp8Config() { |
74 FrameSenderConfig config; | 73 FrameSenderConfig config; |
75 config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_VP8; | 74 config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_VP8; |
(...skipping 15 matching lines...) Expand all Loading... | |
91 config.receiver_ssrc = 12; | 90 config.receiver_ssrc = 12; |
92 config.rtp_timebase = media::cast::kVideoFrequency; | 91 config.rtp_timebase = media::cast::kVideoFrequency; |
93 config.channels = 1; | 92 config.channels = 1; |
94 config.max_bitrate = media::cast::kDefaultMaxVideoBitrate; | 93 config.max_bitrate = media::cast::kDefaultMaxVideoBitrate; |
95 config.min_bitrate = media::cast::kDefaultMinVideoBitrate; | 94 config.min_bitrate = media::cast::kDefaultMinVideoBitrate; |
96 config.max_frame_rate = media::cast::kDefaultMaxFrameRate; | 95 config.max_frame_rate = media::cast::kDefaultMaxFrameRate; |
97 config.codec = media::cast::CODEC_VIDEO_H264; | 96 config.codec = media::cast::CODEC_VIDEO_H264; |
98 return config; | 97 return config; |
99 } | 98 } |
100 | 99 |
101 std::vector<FrameSenderConfig> SupportedAudioConfigs() { | 100 FrameSenderConfig DefaultRemotingAudioConfig() { |
102 // TODO(hclam): Fill in more codecs here. | 101 FrameSenderConfig config; |
103 return std::vector<FrameSenderConfig>(1, DefaultOpusConfig()); | 102 config.rtp_payload_type = media::cast::RtpPayloadType::REMOTE_AUDIO; |
103 config.sender_ssrc = 3; | |
104 config.receiver_ssrc = 4; | |
105 config.codec = media::cast::CODEC_AUDIO_REMOTE; | |
106 config.rtp_timebase = media::cast::kRemotingRtpTimebase; | |
107 config.max_bitrate = 1000000; | |
108 config.min_bitrate = 0; | |
109 config.channels = 2; | |
110 config.max_frame_rate = 100; // 10 ms audio frames | |
111 | |
112 return config; | |
104 } | 113 } |
105 | 114 |
106 std::vector<FrameSenderConfig> SupportedVideoConfigs() { | 115 FrameSenderConfig DefaultRemotingVideoConfig() { |
116 FrameSenderConfig config; | |
117 config.rtp_payload_type = media::cast::RtpPayloadType::REMOTE_VIDEO; | |
118 config.sender_ssrc = 13; | |
119 config.receiver_ssrc = 14; | |
120 config.codec = media::cast::CODEC_VIDEO_REMOTE; | |
121 config.rtp_timebase = media::cast::kRemotingRtpTimebase; | |
122 config.max_bitrate = 10000000; | |
123 config.min_bitrate = 0; | |
124 config.channels = 1; | |
125 config.max_frame_rate = media::cast::kDefaultMaxFrameRate; | |
126 return config; | |
127 } | |
128 | |
129 std::vector<FrameSenderConfig> SupportedAudioConfigs(bool for_remoting_stream) { | |
130 if (for_remoting_stream) | |
131 return std::vector<FrameSenderConfig>(1, DefaultRemotingAudioConfig()); | |
dcheng
2016/09/10 02:31:36
return {DefaultRemotingAudioConfig()}
should work
xjz
2016/09/12 18:22:06
Done.
| |
132 else | |
133 return std::vector<FrameSenderConfig>(1, DefaultOpusConfig()); | |
134 } | |
135 | |
136 std::vector<FrameSenderConfig> SupportedVideoConfigs(bool for_remoting_stream) { | |
137 if (for_remoting_stream) | |
138 return std::vector<FrameSenderConfig>(1, DefaultRemotingVideoConfig()); | |
139 | |
107 std::vector<FrameSenderConfig> supported_configs; | 140 std::vector<FrameSenderConfig> supported_configs; |
108 | |
109 // Prefer VP8 over H.264 for hardware encoder. | 141 // Prefer VP8 over H.264 for hardware encoder. |
110 if (CastRtpStream::IsHardwareVP8EncodingSupported()) | 142 if (CastRtpStream::IsHardwareVP8EncodingSupported()) |
111 supported_configs.push_back(DefaultVp8Config()); | 143 supported_configs.push_back(DefaultVp8Config()); |
112 if (CastRtpStream::IsHardwareH264EncodingSupported()) | 144 if (CastRtpStream::IsHardwareH264EncodingSupported()) |
113 supported_configs.push_back(DefaultH264Config()); | 145 supported_configs.push_back(DefaultH264Config()); |
114 | 146 |
115 // Propose the default software VP8 encoder, if no hardware encoders are | 147 // Propose the default software VP8 encoder, if no hardware encoders are |
116 // available. | 148 // available. |
117 if (supported_configs.empty()) | 149 if (supported_configs.empty()) |
118 supported_configs.push_back(DefaultVp8Config()); | 150 supported_configs.push_back(DefaultVp8Config()); |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
440 vea_profile.profile <= media::H264PROFILE_MAX) { | 472 vea_profile.profile <= media::H264PROFILE_MAX) { |
441 return true; | 473 return true; |
442 } | 474 } |
443 } | 475 } |
444 #endif // !defined(OS_MACOSX) | 476 #endif // !defined(OS_MACOSX) |
445 return false; | 477 return false; |
446 } | 478 } |
447 | 479 |
448 CastRtpStream::CastRtpStream(const blink::WebMediaStreamTrack& track, | 480 CastRtpStream::CastRtpStream(const blink::WebMediaStreamTrack& track, |
449 const scoped_refptr<CastSession>& session) | 481 const scoped_refptr<CastSession>& session) |
450 : track_(track), cast_session_(session), weak_factory_(this) {} | 482 : track_(track), |
483 cast_session_(session), | |
484 is_audio_(track_.source().getType() == | |
485 blink::WebMediaStreamSource::TypeAudio), | |
486 weak_factory_(this) {} | |
487 | |
488 CastRtpStream::CastRtpStream(bool is_audio, | |
489 const scoped_refptr<CastSession>& session) | |
490 : cast_session_(session), is_audio_(is_audio), weak_factory_(this) {} | |
451 | 491 |
452 CastRtpStream::~CastRtpStream() { | 492 CastRtpStream::~CastRtpStream() { |
453 Stop(); | 493 Stop(); |
454 } | 494 } |
455 | 495 |
456 std::vector<FrameSenderConfig> CastRtpStream::GetSupportedConfigs() { | 496 std::vector<FrameSenderConfig> CastRtpStream::GetSupportedConfigs() { |
457 if (IsAudio()) | 497 if (is_audio_) |
458 return SupportedAudioConfigs(); | 498 return SupportedAudioConfigs(track_.isNull()); |
459 else | 499 else |
460 return SupportedVideoConfigs(); | 500 return SupportedVideoConfigs(track_.isNull()); |
461 } | 501 } |
462 | 502 |
463 void CastRtpStream::Start(const FrameSenderConfig& config, | 503 void CastRtpStream::Start(int32_t stream_id, |
504 const FrameSenderConfig& config, | |
464 const base::Closure& start_callback, | 505 const base::Closure& start_callback, |
465 const base::Closure& stop_callback, | 506 const base::Closure& stop_callback, |
466 const ErrorCallback& error_callback) { | 507 const ErrorCallback& error_callback) { |
467 DCHECK(!start_callback.is_null()); | 508 DCHECK(!start_callback.is_null()); |
468 DCHECK(!stop_callback.is_null()); | 509 DCHECK(!stop_callback.is_null()); |
469 DCHECK(!error_callback.is_null()); | 510 DCHECK(!error_callback.is_null()); |
470 | 511 |
471 DVLOG(1) << "CastRtpStream::Start = " << (IsAudio() ? "audio" : "video"); | 512 DVLOG(1) << "CastRtpStream::Start = " << (is_audio_ ? "audio" : "video"); |
472 stop_callback_ = stop_callback; | 513 stop_callback_ = stop_callback; |
473 error_callback_ = error_callback; | 514 error_callback_ = error_callback; |
474 | 515 |
475 if (IsAudio()) { | 516 if (track_.isNull()) { |
517 cast_session_->StartRemotingStream( | |
518 stream_id, config, base::Bind(&CastRtpStream::DidEncounterError, | |
519 weak_factory_.GetWeakPtr())); | |
520 } else if (is_audio_) { | |
476 // In case of error we have to go through DidEncounterError() to stop | 521 // In case of error we have to go through DidEncounterError() to stop |
477 // the streaming after reporting the error. | 522 // the streaming after reporting the error. |
478 audio_sink_.reset( | 523 audio_sink_.reset( |
479 new CastAudioSink(track_, config.channels, config.rtp_timebase)); | 524 new CastAudioSink(track_, config.channels, config.rtp_timebase)); |
480 cast_session_->StartAudio( | 525 cast_session_->StartAudio( |
481 config, | 526 config, |
482 base::Bind(&CastAudioSink::AddToTrack, audio_sink_->AsWeakPtr()), | 527 base::Bind(&CastAudioSink::AddToTrack, audio_sink_->AsWeakPtr()), |
483 base::Bind(&CastRtpStream::DidEncounterError, | 528 base::Bind(&CastRtpStream::DidEncounterError, |
484 weak_factory_.GetWeakPtr())); | 529 weak_factory_.GetWeakPtr())); |
485 start_callback.Run(); | |
486 } else { | 530 } else { |
487 // See the code for audio above for explanation of callbacks. | 531 // See the code for audio above for explanation of callbacks. |
488 video_sink_.reset(new CastVideoSink( | 532 video_sink_.reset(new CastVideoSink( |
489 track_, | 533 track_, |
490 media::BindToCurrentLoop(base::Bind(&CastRtpStream::DidEncounterError, | 534 media::BindToCurrentLoop(base::Bind(&CastRtpStream::DidEncounterError, |
491 weak_factory_.GetWeakPtr())))); | 535 weak_factory_.GetWeakPtr())))); |
492 cast_session_->StartVideo( | 536 cast_session_->StartVideo( |
493 config, base::Bind(&CastVideoSink::AddToTrack, video_sink_->AsWeakPtr(), | 537 config, base::Bind(&CastVideoSink::AddToTrack, video_sink_->AsWeakPtr(), |
494 !config.aes_key.empty()), | 538 !config.aes_key.empty()), |
495 base::Bind(&CastRtpStream::DidEncounterError, | 539 base::Bind(&CastRtpStream::DidEncounterError, |
496 weak_factory_.GetWeakPtr())); | 540 weak_factory_.GetWeakPtr())); |
497 start_callback.Run(); | |
498 } | 541 } |
542 start_callback.Run(); | |
499 } | 543 } |
500 | 544 |
501 void CastRtpStream::Stop() { | 545 void CastRtpStream::Stop() { |
502 DVLOG(1) << "CastRtpStream::Stop = " << (IsAudio() ? "audio" : "video"); | 546 DVLOG(1) << "CastRtpStream::Stop = " << (is_audio_ ? "audio" : "video"); |
503 if (stop_callback_.is_null()) | 547 if (stop_callback_.is_null()) |
504 return; // Already stopped. | 548 return; // Already stopped. |
505 weak_factory_.InvalidateWeakPtrs(); | 549 weak_factory_.InvalidateWeakPtrs(); |
506 error_callback_.Reset(); | 550 error_callback_.Reset(); |
507 audio_sink_.reset(); | 551 audio_sink_.reset(); |
508 video_sink_.reset(); | 552 video_sink_.reset(); |
509 base::ResetAndReturn(&stop_callback_).Run(); | 553 base::ResetAndReturn(&stop_callback_).Run(); |
510 } | 554 } |
511 | 555 |
512 void CastRtpStream::ToggleLogging(bool enable) { | 556 void CastRtpStream::ToggleLogging(bool enable) { |
513 DVLOG(1) << "CastRtpStream::ToggleLogging(" << enable << ") = " | 557 DVLOG(1) << "CastRtpStream::ToggleLogging(" << enable |
514 << (IsAudio() ? "audio" : "video"); | 558 << ") = " << (is_audio_ ? "audio" : "video"); |
515 cast_session_->ToggleLogging(IsAudio(), enable); | 559 cast_session_->ToggleLogging(is_audio_, enable); |
516 } | 560 } |
517 | 561 |
518 void CastRtpStream::GetRawEvents( | 562 void CastRtpStream::GetRawEvents( |
519 const base::Callback<void(std::unique_ptr<base::BinaryValue>)>& callback, | 563 const base::Callback<void(std::unique_ptr<base::BinaryValue>)>& callback, |
520 const std::string& extra_data) { | 564 const std::string& extra_data) { |
521 DVLOG(1) << "CastRtpStream::GetRawEvents = " | 565 DVLOG(1) << "CastRtpStream::GetRawEvents = " |
522 << (IsAudio() ? "audio" : "video"); | 566 << (is_audio_ ? "audio" : "video"); |
523 cast_session_->GetEventLogsAndReset(IsAudio(), extra_data, callback); | 567 cast_session_->GetEventLogsAndReset(is_audio_, extra_data, callback); |
524 } | 568 } |
525 | 569 |
526 void CastRtpStream::GetStats( | 570 void CastRtpStream::GetStats( |
527 const base::Callback<void(std::unique_ptr<base::DictionaryValue>)>& | 571 const base::Callback<void(std::unique_ptr<base::DictionaryValue>)>& |
528 callback) { | 572 callback) { |
529 DVLOG(1) << "CastRtpStream::GetStats = " | 573 DVLOG(1) << "CastRtpStream::GetStats = " << (is_audio_ ? "audio" : "video"); |
530 << (IsAudio() ? "audio" : "video"); | 574 cast_session_->GetStatsAndReset(is_audio_, callback); |
531 cast_session_->GetStatsAndReset(IsAudio(), callback); | |
532 } | |
533 | |
534 bool CastRtpStream::IsAudio() const { | |
535 return track_.source().getType() == blink::WebMediaStreamSource::TypeAudio; | |
536 } | 575 } |
537 | 576 |
538 void CastRtpStream::DidEncounterError(const std::string& message) { | 577 void CastRtpStream::DidEncounterError(const std::string& message) { |
539 DCHECK(content::RenderThread::Get()); | 578 DCHECK(content::RenderThread::Get()); |
540 DVLOG(1) << "CastRtpStream::DidEncounterError(" << message << ") = " | 579 DVLOG(1) << "CastRtpStream::DidEncounterError(" << message |
541 << (IsAudio() ? "audio" : "video"); | 580 << ") = " << (is_audio_ ? "audio" : "video"); |
542 // Save the WeakPtr first because the error callback might delete this object. | 581 // Save the WeakPtr first because the error callback might delete this object. |
543 base::WeakPtr<CastRtpStream> ptr = weak_factory_.GetWeakPtr(); | 582 base::WeakPtr<CastRtpStream> ptr = weak_factory_.GetWeakPtr(); |
544 error_callback_.Run(message); | 583 error_callback_.Run(message); |
545 base::ThreadTaskRunnerHandle::Get()->PostTask( | 584 base::ThreadTaskRunnerHandle::Get()->PostTask( |
546 FROM_HERE, | 585 FROM_HERE, |
547 base::Bind(&CastRtpStream::Stop, ptr)); | 586 base::Bind(&CastRtpStream::Stop, ptr)); |
548 } | 587 } |
OLD | NEW |