webrtcvideoengine2.cc revision f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50e
1/* 2 * libjingle 3 * Copyright 2014 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#ifdef HAVE_WEBRTC_VIDEO 29#include "talk/media/webrtc/webrtcvideoengine2.h" 30 31#include <algorithm> 32#include <set> 33#include <string> 34 35#include "libyuv/convert_from.h" 36#include "talk/media/base/videocapturer.h" 37#include "talk/media/base/videorenderer.h" 38#include "talk/media/webrtc/constants.h" 39#include "talk/media/webrtc/simulcast.h" 40#include "talk/media/webrtc/webrtcvideocapturer.h" 41#include "talk/media/webrtc/webrtcvideoengine.h" 42#include "talk/media/webrtc/webrtcvideoframe.h" 43#include "talk/media/webrtc/webrtcvoiceengine.h" 44#include "webrtc/base/buffer.h" 45#include "webrtc/base/logging.h" 46#include "webrtc/base/stringutils.h" 47#include "webrtc/call.h" 48#include "webrtc/video_decoder.h" 49#include "webrtc/video_encoder.h" 50 51#define UNIMPLEMENTED \ 52 LOG(LS_ERROR) << "Call to unimplemented function " << __FUNCTION__; \ 53 ASSERT(false) 54 55namespace cricket { 56namespace { 57static std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) { 58 std::stringstream out; 59 out << '{'; 60 for (size_t i = 0; i < codecs.size(); ++i) { 61 out << codecs[i].ToString(); 62 if (i != codecs.size() - 1) { 63 out << ", "; 64 } 65 } 66 out << '}'; 67 return out.str(); 68} 69 70static bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) { 71 bool has_video = false; 72 for (size_t i = 0; i < codecs.size(); ++i) { 73 if (!codecs[i].ValidateCodecFormat()) { 74 return false; 75 } 76 if (codecs[i].GetCodecType() == VideoCodec::CODEC_VIDEO) { 77 has_video = true; 78 } 79 } 80 if (!has_video) { 81 LOG(LS_ERROR) << "Setting codecs without a video codec is invalid: " 82 << CodecVectorToString(codecs); 83 return false; 84 } 85 return true; 86} 87 88static std::string RtpExtensionsToString( 89 const std::vector<RtpHeaderExtension>& extensions) { 90 std::stringstream out; 91 out << '{'; 92 for (size_t i = 0; i < extensions.size(); ++i) { 93 out << "{" << extensions[i].uri << ": " << extensions[i].id << "}"; 94 if (i != extensions.size() - 1) { 95 out << ", "; 96 } 97 } 98 out << '}'; 99 return out.str(); 100} 101 102// Merges two fec configs and logs an error if a conflict arises 103// such that merging in diferent order would trigger a diferent output. 104static void MergeFecConfig(const webrtc::FecConfig& other, 105 webrtc::FecConfig* output) { 106 if (other.ulpfec_payload_type != -1) { 107 if (output->ulpfec_payload_type != -1 && 108 output->ulpfec_payload_type != other.ulpfec_payload_type) { 109 LOG(LS_WARNING) << "Conflict merging ulpfec_payload_type configs: " 110 << output->ulpfec_payload_type << " and " 111 << other.ulpfec_payload_type; 112 } 113 output->ulpfec_payload_type = other.ulpfec_payload_type; 114 } 115 if (other.red_payload_type != -1) { 116 if (output->red_payload_type != -1 && 117 output->red_payload_type != other.red_payload_type) { 118 LOG(LS_WARNING) << "Conflict merging red_payload_type configs: " 119 << output->red_payload_type << " and " 120 << other.red_payload_type; 121 } 122 output->red_payload_type = other.red_payload_type; 123 } 124} 125} // namespace 126 127// This constant is really an on/off, lower-level configurable NACK history 128// duration hasn't been implemented. 129static const int kNackHistoryMs = 1000; 130 131static const int kDefaultQpMax = 56; 132 133static const int kDefaultRtcpReceiverReportSsrc = 1; 134 135// External video encoders are given payloads 120-127. This also means that we 136// only support up to 8 external payload types. 137static const int kExternalVideoPayloadTypeBase = 120; 138#ifndef NDEBUG 139static const size_t kMaxExternalVideoCodecs = 8; 140#endif 141 142const char kH264CodecName[] = "H264"; 143 144static bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs, 145 const VideoCodec& requested_codec, 146 VideoCodec* matching_codec) { 147 for (size_t i = 0; i < codecs.size(); ++i) { 148 if (requested_codec.Matches(codecs[i])) { 149 *matching_codec = codecs[i]; 150 return true; 151 } 152 } 153 return false; 154} 155 156static bool ValidateRtpHeaderExtensionIds( 157 const std::vector<RtpHeaderExtension>& extensions) { 158 std::set<int> extensions_used; 159 for (size_t i = 0; i < extensions.size(); ++i) { 160 if (extensions[i].id < 0 || extensions[i].id >= 15 || 161 !extensions_used.insert(extensions[i].id).second) { 162 LOG(LS_ERROR) << "RTP extensions are with incorrect or duplicate ids."; 163 return false; 164 } 165 } 166 return true; 167} 168 169static bool CompareRtpHeaderExtensionIds( 170 const webrtc::RtpExtension& extension1, 171 const webrtc::RtpExtension& extension2) { 172 // Sorting on ID is sufficient, more than one extension per ID is unsupported. 173 return extension1.id > extension2.id; 174} 175 176static std::vector<webrtc::RtpExtension> FilterRtpExtensions( 177 const std::vector<RtpHeaderExtension>& extensions) { 178 std::vector<webrtc::RtpExtension> webrtc_extensions; 179 for (size_t i = 0; i < extensions.size(); ++i) { 180 // Unsupported extensions will be ignored. 181 if (webrtc::RtpExtension::IsSupported(extensions[i].uri)) { 182 webrtc_extensions.push_back(webrtc::RtpExtension( 183 extensions[i].uri, extensions[i].id)); 184 } else { 185 LOG(LS_WARNING) << "Unsupported RTP extension: " << extensions[i].uri; 186 } 187 } 188 189 // Sort filtered headers to make sure that they can later be compared 190 // regardless of in which order they were entered. 191 std::sort(webrtc_extensions.begin(), webrtc_extensions.end(), 192 CompareRtpHeaderExtensionIds); 193 return webrtc_extensions; 194} 195 196static bool RtpExtensionsHaveChanged( 197 const std::vector<webrtc::RtpExtension>& before, 198 const std::vector<webrtc::RtpExtension>& after) { 199 if (before.size() != after.size()) 200 return true; 201 for (size_t i = 0; i < before.size(); ++i) { 202 if (before[i].id != after[i].id) 203 return true; 204 if (before[i].name != after[i].name) 205 return true; 206 } 207 return false; 208} 209 210WebRtcVideoEncoderFactory2::~WebRtcVideoEncoderFactory2() { 211} 212 213std::vector<webrtc::VideoStream> 214WebRtcVideoEncoderFactory2::CreateSimulcastVideoStreams( 215 const VideoCodec& codec, 216 const VideoOptions& options, 217 size_t num_streams) { 218 // Use default factory for non-simulcast. 219 int max_qp = kDefaultQpMax; 220 codec.GetParam(kCodecParamMaxQuantization, &max_qp); 221 222 int min_bitrate_kbps; 223 if (!codec.GetParam(kCodecParamMinBitrate, &min_bitrate_kbps) || 224 min_bitrate_kbps < kMinVideoBitrate) { 225 min_bitrate_kbps = kMinVideoBitrate; 226 } 227 228 int max_bitrate_kbps; 229 if (!codec.GetParam(kCodecParamMaxBitrate, &max_bitrate_kbps)) { 230 max_bitrate_kbps = 0; 231 } 232 233 return GetSimulcastConfig( 234 num_streams, 235 GetSimulcastBitrateMode(options), 236 codec.width, 237 codec.height, 238 max_bitrate_kbps * 1000, 239 max_qp, 240 codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate); 241} 242 243std::vector<webrtc::VideoStream> WebRtcVideoEncoderFactory2::CreateVideoStreams( 244 const VideoCodec& codec, 245 const VideoOptions& options, 246 size_t num_streams) { 247 if (num_streams != 1) 248 return CreateSimulcastVideoStreams(codec, options, num_streams); 249 250 webrtc::VideoStream stream; 251 stream.width = codec.width; 252 stream.height = codec.height; 253 stream.max_framerate = 254 codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate; 255 256 stream.min_bitrate_bps = kMinVideoBitrate * 1000; 257 stream.target_bitrate_bps = stream.max_bitrate_bps = kMaxVideoBitrate * 1000; 258 259 int max_qp = kDefaultQpMax; 260 codec.GetParam(kCodecParamMaxQuantization, &max_qp); 261 stream.max_qp = max_qp; 262 std::vector<webrtc::VideoStream> streams; 263 streams.push_back(stream); 264 return streams; 265} 266 267void* WebRtcVideoEncoderFactory2::CreateVideoEncoderSettings( 268 const VideoCodec& codec, 269 const VideoOptions& options) { 270 if (CodecNameMatches(codec.name, kVp8CodecName)) { 271 webrtc::VideoCodecVP8* settings = new webrtc::VideoCodecVP8( 272 webrtc::VideoEncoder::GetDefaultVp8Settings()); 273 options.video_noise_reduction.Get(&settings->denoisingOn); 274 return settings; 275 } 276 if (CodecNameMatches(codec.name, kVp9CodecName)) { 277 webrtc::VideoCodecVP9* settings = new webrtc::VideoCodecVP9( 278 webrtc::VideoEncoder::GetDefaultVp9Settings()); 279 options.video_noise_reduction.Get(&settings->denoisingOn); 280 return settings; 281 } 282 return NULL; 283} 284 285void WebRtcVideoEncoderFactory2::DestroyVideoEncoderSettings( 286 const VideoCodec& codec, 287 void* encoder_settings) { 288 if (encoder_settings == NULL) { 289 return; 290 } 291 if (CodecNameMatches(codec.name, kVp8CodecName)) { 292 delete reinterpret_cast<webrtc::VideoCodecVP8*>(encoder_settings); 293 } 294 if (CodecNameMatches(codec.name, kVp9CodecName)) { 295 delete reinterpret_cast<webrtc::VideoCodecVP9*>(encoder_settings); 296 } 297} 298 299DefaultUnsignalledSsrcHandler::DefaultUnsignalledSsrcHandler() 300 : default_recv_ssrc_(0), default_renderer_(NULL) {} 301 302UnsignalledSsrcHandler::Action DefaultUnsignalledSsrcHandler::OnUnsignalledSsrc( 303 VideoMediaChannel* channel, 304 uint32_t ssrc) { 305 if (default_recv_ssrc_ != 0) { // Already one default stream. 306 LOG(LS_WARNING) << "Unknown SSRC, but default receive stream already set."; 307 return kDropPacket; 308 } 309 310 StreamParams sp; 311 sp.ssrcs.push_back(ssrc); 312 LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << "."; 313 if (!channel->AddRecvStream(sp)) { 314 LOG(LS_WARNING) << "Could not create default receive stream."; 315 } 316 317 channel->SetRenderer(ssrc, default_renderer_); 318 default_recv_ssrc_ = ssrc; 319 return kDeliverPacket; 320} 321 322WebRtcCallFactory::~WebRtcCallFactory() { 323} 324webrtc::Call* WebRtcCallFactory::CreateCall( 325 const webrtc::Call::Config& config) { 326 return webrtc::Call::Create(config); 327} 328 329VideoRenderer* DefaultUnsignalledSsrcHandler::GetDefaultRenderer() const { 330 return default_renderer_; 331} 332 333void DefaultUnsignalledSsrcHandler::SetDefaultRenderer( 334 VideoMediaChannel* channel, 335 VideoRenderer* renderer) { 336 default_renderer_ = renderer; 337 if (default_recv_ssrc_ != 0) { 338 channel->SetRenderer(default_recv_ssrc_, default_renderer_); 339 } 340} 341 342WebRtcVideoEngine2::WebRtcVideoEngine2() 343 : worker_thread_(NULL), 344 voice_engine_(NULL), 345 default_codec_format_(kDefaultVideoMaxWidth, 346 kDefaultVideoMaxHeight, 347 FPS_TO_INTERVAL(kDefaultVideoMaxFramerate), 348 FOURCC_ANY), 349 initialized_(false), 350 cpu_monitor_(new rtc::CpuMonitor(NULL)), 351 call_factory_(&default_call_factory_), 352 external_decoder_factory_(NULL), 353 external_encoder_factory_(NULL) { 354 LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()"; 355 video_codecs_ = GetSupportedCodecs(); 356 rtp_header_extensions_.push_back( 357 RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 358 kRtpTimestampOffsetHeaderExtensionDefaultId)); 359 rtp_header_extensions_.push_back( 360 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 361 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); 362} 363 364WebRtcVideoEngine2::~WebRtcVideoEngine2() { 365 LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2"; 366 367 if (initialized_) { 368 Terminate(); 369 } 370} 371 372void WebRtcVideoEngine2::SetCallFactory(WebRtcCallFactory* call_factory) { 373 assert(!initialized_); 374 call_factory_ = call_factory; 375} 376 377bool WebRtcVideoEngine2::Init(rtc::Thread* worker_thread) { 378 LOG(LS_INFO) << "WebRtcVideoEngine2::Init"; 379 worker_thread_ = worker_thread; 380 ASSERT(worker_thread_ != NULL); 381 382 cpu_monitor_->set_thread(worker_thread_); 383 if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) { 384 LOG(LS_ERROR) << "Failed to start CPU monitor."; 385 cpu_monitor_.reset(); 386 } 387 388 initialized_ = true; 389 return true; 390} 391 392void WebRtcVideoEngine2::Terminate() { 393 LOG(LS_INFO) << "WebRtcVideoEngine2::Terminate"; 394 395 if (cpu_monitor_.get() != NULL) 396 cpu_monitor_->Stop(); 397 398 initialized_ = false; 399} 400 401int WebRtcVideoEngine2::GetCapabilities() { return VIDEO_RECV | VIDEO_SEND; } 402 403bool WebRtcVideoEngine2::SetDefaultEncoderConfig( 404 const VideoEncoderConfig& config) { 405 const VideoCodec& codec = config.max_codec; 406 bool supports_codec = false; 407 for (size_t i = 0; i < video_codecs_.size(); ++i) { 408 if (CodecNameMatches(video_codecs_[i].name, codec.name)) { 409 video_codecs_[i] = codec; 410 supports_codec = true; 411 break; 412 } 413 } 414 415 if (!supports_codec) { 416 LOG(LS_ERROR) << "SetDefaultEncoderConfig, codec not supported: " 417 << codec.ToString(); 418 return false; 419 } 420 421 default_codec_format_ = 422 VideoFormat(codec.width, 423 codec.height, 424 VideoFormat::FpsToInterval(codec.framerate), 425 FOURCC_ANY); 426 return true; 427} 428 429WebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel( 430 const VideoOptions& options, 431 VoiceMediaChannel* voice_channel) { 432 assert(initialized_); 433 LOG(LS_INFO) << "CreateChannel: " 434 << (voice_channel != NULL ? "With" : "Without") 435 << " voice channel. Options: " << options.ToString(); 436 WebRtcVideoChannel2* channel = 437 new WebRtcVideoChannel2(call_factory_, 438 voice_engine_, 439 voice_channel, 440 options, 441 external_encoder_factory_, 442 external_decoder_factory_, 443 GetVideoEncoderFactory()); 444 if (!channel->Init()) { 445 delete channel; 446 return NULL; 447 } 448 channel->SetRecvCodecs(video_codecs_); 449 return channel; 450} 451 452const std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const { 453 return video_codecs_; 454} 455 456const std::vector<RtpHeaderExtension>& 457WebRtcVideoEngine2::rtp_header_extensions() const { 458 return rtp_header_extensions_; 459} 460 461void WebRtcVideoEngine2::SetLogging(int min_sev, const char* filter) { 462 // TODO(pbos): Set up logging. 463 LOG(LS_VERBOSE) << "SetLogging: " << min_sev << '"' << filter << '"'; 464 // if min_sev == -1, we keep the current log level. 465 if (min_sev < 0) { 466 assert(min_sev == -1); 467 return; 468 } 469} 470 471void WebRtcVideoEngine2::SetExternalDecoderFactory( 472 WebRtcVideoDecoderFactory* decoder_factory) { 473 assert(!initialized_); 474 external_decoder_factory_ = decoder_factory; 475} 476 477void WebRtcVideoEngine2::SetExternalEncoderFactory( 478 WebRtcVideoEncoderFactory* encoder_factory) { 479 assert(!initialized_); 480 if (external_encoder_factory_ == encoder_factory) 481 return; 482 483 // No matter what happens we shouldn't hold on to a stale 484 // WebRtcSimulcastEncoderFactory. 485 simulcast_encoder_factory_.reset(); 486 487 if (encoder_factory && 488 WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory( 489 encoder_factory->codecs())) { 490 simulcast_encoder_factory_.reset( 491 new WebRtcSimulcastEncoderFactory(encoder_factory)); 492 encoder_factory = simulcast_encoder_factory_.get(); 493 } 494 external_encoder_factory_ = encoder_factory; 495 496 video_codecs_ = GetSupportedCodecs(); 497} 498 499bool WebRtcVideoEngine2::EnableTimedRender() { 500 // TODO(pbos): Figure out whether this can be removed. 501 return true; 502} 503 504// Checks to see whether we comprehend and could receive a particular codec 505bool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) { 506 // TODO(pbos): Probe encoder factory to figure out that the codec is supported 507 // if supported by the encoder factory. Add a corresponding test that fails 508 // with this code (that doesn't ask the factory). 509 for (size_t j = 0; j < video_codecs_.size(); ++j) { 510 VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0); 511 if (codec.Matches(in)) { 512 return true; 513 } 514 } 515 return false; 516} 517 518// Tells whether the |requested| codec can be transmitted or not. If it can be 519// transmitted |out| is set with the best settings supported. Aspect ratio will 520// be set as close to |current|'s as possible. If not set |requested|'s 521// dimensions will be used for aspect ratio matching. 522bool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested, 523 const VideoCodec& current, 524 VideoCodec* out) { 525 assert(out != NULL); 526 527 if (requested.width != requested.height && 528 (requested.height == 0 || requested.width == 0)) { 529 // 0xn and nx0 are invalid resolutions. 530 return false; 531 } 532 533 VideoCodec matching_codec; 534 if (!FindFirstMatchingCodec(video_codecs_, requested, &matching_codec)) { 535 // Codec not supported. 536 return false; 537 } 538 539 out->id = requested.id; 540 out->name = requested.name; 541 out->preference = requested.preference; 542 out->params = requested.params; 543 out->framerate = 544 rtc::_min(requested.framerate, matching_codec.framerate); 545 out->params = requested.params; 546 out->feedback_params = requested.feedback_params; 547 out->width = requested.width; 548 out->height = requested.height; 549 if (requested.width == 0 && requested.height == 0) { 550 return true; 551 } 552 553 while (out->width > matching_codec.width) { 554 out->width /= 2; 555 out->height /= 2; 556 } 557 558 return out->width > 0 && out->height > 0; 559} 560 561bool WebRtcVideoEngine2::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) { 562 if (initialized_) { 563 LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init"; 564 return false; 565 } 566 voice_engine_ = voice_engine; 567 return true; 568} 569 570// Ignore spammy trace messages, mostly from the stats API when we haven't 571// gotten RTCP info yet from the remote side. 572bool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) { 573 static const char* const kTracesToIgnore[] = {NULL}; 574 for (const char* const* p = kTracesToIgnore; *p; ++p) { 575 if (trace.find(*p) == 0) { 576 return true; 577 } 578 } 579 return false; 580} 581 582WebRtcVideoEncoderFactory2* WebRtcVideoEngine2::GetVideoEncoderFactory() { 583 return &default_video_encoder_factory_; 584} 585 586std::vector<VideoCodec> WebRtcVideoEngine2::GetSupportedCodecs() const { 587 std::vector<VideoCodec> supported_codecs = DefaultVideoCodecList(); 588 589 if (external_encoder_factory_ == NULL) { 590 return supported_codecs; 591 } 592 593 assert(external_encoder_factory_->codecs().size() <= kMaxExternalVideoCodecs); 594 const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs = 595 external_encoder_factory_->codecs(); 596 for (size_t i = 0; i < codecs.size(); ++i) { 597 // Don't add internally-supported codecs twice. 598 if (CodecIsInternallySupported(codecs[i].name)) { 599 continue; 600 } 601 602 VideoCodec codec(kExternalVideoPayloadTypeBase + static_cast<int>(i), 603 codecs[i].name, 604 codecs[i].max_width, 605 codecs[i].max_height, 606 codecs[i].max_fps, 607 0); 608 609 AddDefaultFeedbackParams(&codec); 610 supported_codecs.push_back(codec); 611 } 612 return supported_codecs; 613} 614 615WebRtcVideoChannel2::WebRtcVideoChannel2( 616 WebRtcCallFactory* call_factory, 617 WebRtcVoiceEngine* voice_engine, 618 VoiceMediaChannel* voice_channel, 619 const VideoOptions& options, 620 WebRtcVideoEncoderFactory* external_encoder_factory, 621 WebRtcVideoDecoderFactory* external_decoder_factory, 622 WebRtcVideoEncoderFactory2* encoder_factory) 623 : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_), 624 voice_channel_(voice_channel), 625 external_encoder_factory_(external_encoder_factory), 626 external_decoder_factory_(external_decoder_factory), 627 encoder_factory_(encoder_factory) { 628 SetDefaultOptions(); 629 options_.SetAll(options); 630 webrtc::Call::Config config(this); 631 config.overuse_callback = this; 632 if (voice_engine != NULL) { 633 config.voice_engine = voice_engine->voe()->engine(); 634 } 635 636 call_.reset(call_factory->CreateCall(config)); 637 638 rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc; 639 sending_ = false; 640 default_send_ssrc_ = 0; 641} 642 643void WebRtcVideoChannel2::SetDefaultOptions() { 644 options_.cpu_overuse_detection.Set(false); 645 options_.dscp.Set(false); 646 options_.suspend_below_min_bitrate.Set(false); 647 options_.video_noise_reduction.Set(true); 648 options_.screencast_min_bitrate.Set(0); 649} 650 651WebRtcVideoChannel2::~WebRtcVideoChannel2() { 652 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 653 send_streams_.begin(); 654 it != send_streams_.end(); 655 ++it) { 656 delete it->second; 657 } 658 659 for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 660 receive_streams_.begin(); 661 it != receive_streams_.end(); 662 ++it) { 663 delete it->second; 664 } 665} 666 667bool WebRtcVideoChannel2::Init() { return true; } 668 669bool WebRtcVideoChannel2::CodecIsExternallySupported( 670 const std::string& name) const { 671 if (external_encoder_factory_ == NULL) { 672 return false; 673 } 674 675 const std::vector<WebRtcVideoEncoderFactory::VideoCodec> external_codecs = 676 external_encoder_factory_->codecs(); 677 for (size_t c = 0; c < external_codecs.size(); ++c) { 678 if (CodecNameMatches(name, external_codecs[c].name)) { 679 return true; 680 } 681 } 682 return false; 683} 684 685std::vector<WebRtcVideoChannel2::VideoCodecSettings> 686WebRtcVideoChannel2::FilterSupportedCodecs( 687 const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs) 688 const { 689 std::vector<VideoCodecSettings> supported_codecs; 690 for (size_t i = 0; i < mapped_codecs.size(); ++i) { 691 const VideoCodecSettings& codec = mapped_codecs[i]; 692 if (CodecIsInternallySupported(codec.codec.name) || 693 CodecIsExternallySupported(codec.codec.name)) { 694 supported_codecs.push_back(codec); 695 } 696 } 697 return supported_codecs; 698} 699 700bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) { 701 LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs); 702 if (!ValidateCodecFormats(codecs)) { 703 return false; 704 } 705 706 const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs); 707 if (mapped_codecs.empty()) { 708 LOG(LS_ERROR) << "SetRecvCodecs called without any video codecs."; 709 return false; 710 } 711 712 const std::vector<VideoCodecSettings> supported_codecs = 713 FilterSupportedCodecs(mapped_codecs); 714 715 if (mapped_codecs.size() != supported_codecs.size()) { 716 LOG(LS_ERROR) << "SetRecvCodecs called with unsupported video codecs."; 717 return false; 718 } 719 720 recv_codecs_ = supported_codecs; 721 722 rtc::CritScope stream_lock(&stream_crit_); 723 for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 724 receive_streams_.begin(); 725 it != receive_streams_.end(); 726 ++it) { 727 it->second->SetRecvCodecs(recv_codecs_); 728 } 729 730 return true; 731} 732 733bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) { 734 LOG(LS_INFO) << "SetSendCodecs: " << CodecVectorToString(codecs); 735 if (!ValidateCodecFormats(codecs)) { 736 return false; 737 } 738 739 const std::vector<VideoCodecSettings> supported_codecs = 740 FilterSupportedCodecs(MapCodecs(codecs)); 741 742 if (supported_codecs.empty()) { 743 LOG(LS_ERROR) << "No video codecs supported by encoder factory."; 744 return false; 745 } 746 747 LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString(); 748 749 VideoCodecSettings old_codec; 750 if (send_codec_.Get(&old_codec) && supported_codecs.front() == old_codec) { 751 // Using same codec, avoid reconfiguring. 752 return true; 753 } 754 755 send_codec_.Set(supported_codecs.front()); 756 757 rtc::CritScope stream_lock(&stream_crit_); 758 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 759 send_streams_.begin(); 760 it != send_streams_.end(); 761 ++it) { 762 assert(it->second != NULL); 763 it->second->SetCodec(supported_codecs.front()); 764 } 765 766 VideoCodec codec = supported_codecs.front().codec; 767 int bitrate_kbps; 768 if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) && 769 bitrate_kbps > 0) { 770 bitrate_config_.min_bitrate_bps = bitrate_kbps * 1000; 771 } else { 772 bitrate_config_.min_bitrate_bps = 0; 773 } 774 if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) && 775 bitrate_kbps > 0) { 776 bitrate_config_.start_bitrate_bps = bitrate_kbps * 1000; 777 } else { 778 // Do not reconfigure start bitrate unless it's specified and positive. 779 bitrate_config_.start_bitrate_bps = -1; 780 } 781 if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) && 782 bitrate_kbps > 0) { 783 bitrate_config_.max_bitrate_bps = bitrate_kbps * 1000; 784 } else { 785 bitrate_config_.max_bitrate_bps = -1; 786 } 787 call_->SetBitrateConfig(bitrate_config_); 788 789 return true; 790} 791 792bool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) { 793 VideoCodecSettings codec_settings; 794 if (!send_codec_.Get(&codec_settings)) { 795 LOG(LS_VERBOSE) << "GetSendCodec: No send codec set."; 796 return false; 797 } 798 *codec = codec_settings.codec; 799 return true; 800} 801 802bool WebRtcVideoChannel2::SetSendStreamFormat(uint32 ssrc, 803 const VideoFormat& format) { 804 LOG(LS_VERBOSE) << "SetSendStreamFormat:" << ssrc << " -> " 805 << format.ToString(); 806 rtc::CritScope stream_lock(&stream_crit_); 807 if (send_streams_.find(ssrc) == send_streams_.end()) { 808 return false; 809 } 810 return send_streams_[ssrc]->SetVideoFormat(format); 811} 812 813bool WebRtcVideoChannel2::SetRender(bool render) { 814 // TODO(pbos): Implement. Or refactor away as it shouldn't be needed. 815 LOG(LS_VERBOSE) << "SetRender: " << (render ? "true" : "false"); 816 return true; 817} 818 819bool WebRtcVideoChannel2::SetSend(bool send) { 820 LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false"); 821 if (send && !send_codec_.IsSet()) { 822 LOG(LS_ERROR) << "SetSend(true) called before setting codec."; 823 return false; 824 } 825 if (send) { 826 StartAllSendStreams(); 827 } else { 828 StopAllSendStreams(); 829 } 830 sending_ = send; 831 return true; 832} 833 834bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) { 835 LOG(LS_INFO) << "AddSendStream: " << sp.ToString(); 836 if (sp.ssrcs.empty()) { 837 LOG(LS_ERROR) << "No SSRCs in stream parameters."; 838 return false; 839 } 840 841 uint32 ssrc = sp.first_ssrc(); 842 assert(ssrc != 0); 843 // TODO(pbos): Make sure none of sp.ssrcs are used, not just the identifying 844 // ssrc. 845 rtc::CritScope stream_lock(&stream_crit_); 846 if (send_streams_.find(ssrc) != send_streams_.end()) { 847 LOG(LS_ERROR) << "Send stream with ssrc '" << ssrc << "' already exists."; 848 return false; 849 } 850 851 std::vector<uint32> primary_ssrcs; 852 sp.GetPrimarySsrcs(&primary_ssrcs); 853 std::vector<uint32> rtx_ssrcs; 854 sp.GetFidSsrcs(primary_ssrcs, &rtx_ssrcs); 855 if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) { 856 LOG(LS_ERROR) 857 << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): " 858 << sp.ToString(); 859 return false; 860 } 861 862 WebRtcVideoSendStream* stream = 863 new WebRtcVideoSendStream(call_.get(), 864 external_encoder_factory_, 865 encoder_factory_, 866 options_, 867 send_codec_, 868 sp, 869 send_rtp_extensions_); 870 871 send_streams_[ssrc] = stream; 872 873 if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) { 874 rtcp_receiver_report_ssrc_ = ssrc; 875 } 876 if (default_send_ssrc_ == 0) { 877 default_send_ssrc_ = ssrc; 878 } 879 if (sending_) { 880 stream->Start(); 881 } 882 883 return true; 884} 885 886bool WebRtcVideoChannel2::RemoveSendStream(uint32 ssrc) { 887 LOG(LS_INFO) << "RemoveSendStream: " << ssrc; 888 889 if (ssrc == 0) { 890 if (default_send_ssrc_ == 0) { 891 LOG(LS_ERROR) << "No default send stream active."; 892 return false; 893 } 894 895 LOG(LS_VERBOSE) << "Removing default stream: " << default_send_ssrc_; 896 ssrc = default_send_ssrc_; 897 } 898 899 WebRtcVideoSendStream* removed_stream; 900 { 901 rtc::CritScope stream_lock(&stream_crit_); 902 std::map<uint32, WebRtcVideoSendStream*>::iterator it = 903 send_streams_.find(ssrc); 904 if (it == send_streams_.end()) { 905 return false; 906 } 907 908 removed_stream = it->second; 909 send_streams_.erase(it); 910 } 911 912 delete removed_stream; 913 914 if (ssrc == default_send_ssrc_) { 915 default_send_ssrc_ = 0; 916 } 917 918 return true; 919} 920 921bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) { 922 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString(); 923 assert(sp.ssrcs.size() > 0); 924 925 uint32 ssrc = sp.first_ssrc(); 926 assert(ssrc != 0); // TODO(pbos): Is this ever valid? 927 928 // TODO(pbos): Check if any of the SSRCs overlap. 929 rtc::CritScope stream_lock(&stream_crit_); 930 if (receive_streams_.find(ssrc) != receive_streams_.end()) { 931 LOG(LS_ERROR) << "Receive stream for SSRC " << ssrc << "already exists."; 932 return false; 933 } 934 935 webrtc::VideoReceiveStream::Config config; 936 ConfigureReceiverRtp(&config, sp); 937 938 // Set up A/V sync if there is a VoiceChannel. 939 // TODO(pbos): The A/V is synched by the receiving channel. So we need to know 940 // the SSRC of the remote audio channel in order to sync the correct webrtc 941 // VoiceEngine channel. For now sync the first channel in non-conference to 942 // match existing behavior in WebRtcVideoEngine. 943 if (voice_channel_ != NULL && receive_streams_.empty() && 944 !options_.conference_mode.GetWithDefaultIfUnset(false)) { 945 config.audio_channel_id = 946 static_cast<WebRtcVoiceMediaChannel*>(voice_channel_)->voe_channel(); 947 } 948 949 receive_streams_[ssrc] = new WebRtcVideoReceiveStream( 950 call_.get(), external_decoder_factory_, config, recv_codecs_); 951 952 return true; 953} 954 955void WebRtcVideoChannel2::ConfigureReceiverRtp( 956 webrtc::VideoReceiveStream::Config* config, 957 const StreamParams& sp) const { 958 uint32 ssrc = sp.first_ssrc(); 959 960 config->rtp.remote_ssrc = ssrc; 961 config->rtp.local_ssrc = rtcp_receiver_report_ssrc_; 962 963 config->rtp.extensions = recv_rtp_extensions_; 964 965 // TODO(pbos): This protection is against setting the same local ssrc as 966 // remote which is not permitted by the lower-level API. RTCP requires a 967 // corresponding sender SSRC. Figure out what to do when we don't have 968 // (receive-only) or know a good local SSRC. 969 if (config->rtp.remote_ssrc == config->rtp.local_ssrc) { 970 if (config->rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) { 971 config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc; 972 } else { 973 config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1; 974 } 975 } 976 977 for (size_t i = 0; i < recv_codecs_.size(); ++i) { 978 MergeFecConfig(recv_codecs_[i].fec, &config->rtp.fec); 979 } 980 981 for (size_t i = 0; i < recv_codecs_.size(); ++i) { 982 uint32 rtx_ssrc; 983 if (recv_codecs_[i].rtx_payload_type != -1 && 984 sp.GetFidSsrc(ssrc, &rtx_ssrc)) { 985 webrtc::VideoReceiveStream::Config::Rtp::Rtx& rtx = 986 config->rtp.rtx[recv_codecs_[i].codec.id]; 987 rtx.ssrc = rtx_ssrc; 988 rtx.payload_type = recv_codecs_[i].rtx_payload_type; 989 } 990 } 991} 992 993bool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) { 994 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; 995 if (ssrc == 0) { 996 LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported."; 997 return false; 998 } 999 1000 rtc::CritScope stream_lock(&stream_crit_); 1001 std::map<uint32, WebRtcVideoReceiveStream*>::iterator stream = 1002 receive_streams_.find(ssrc); 1003 if (stream == receive_streams_.end()) { 1004 LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc; 1005 return false; 1006 } 1007 delete stream->second; 1008 receive_streams_.erase(stream); 1009 1010 return true; 1011} 1012 1013bool WebRtcVideoChannel2::SetRenderer(uint32 ssrc, VideoRenderer* renderer) { 1014 LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " " 1015 << (renderer ? "(ptr)" : "NULL"); 1016 if (ssrc == 0) { 1017 default_unsignalled_ssrc_handler_.SetDefaultRenderer(this, renderer); 1018 return true; 1019 } 1020 1021 rtc::CritScope stream_lock(&stream_crit_); 1022 std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 1023 receive_streams_.find(ssrc); 1024 if (it == receive_streams_.end()) { 1025 return false; 1026 } 1027 1028 it->second->SetRenderer(renderer); 1029 return true; 1030} 1031 1032bool WebRtcVideoChannel2::GetRenderer(uint32 ssrc, VideoRenderer** renderer) { 1033 if (ssrc == 0) { 1034 *renderer = default_unsignalled_ssrc_handler_.GetDefaultRenderer(); 1035 return *renderer != NULL; 1036 } 1037 1038 rtc::CritScope stream_lock(&stream_crit_); 1039 std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 1040 receive_streams_.find(ssrc); 1041 if (it == receive_streams_.end()) { 1042 return false; 1043 } 1044 *renderer = it->second->GetRenderer(); 1045 return true; 1046} 1047 1048bool WebRtcVideoChannel2::GetStats(const StatsOptions& options, 1049 VideoMediaInfo* info) { 1050 info->Clear(); 1051 FillSenderStats(info); 1052 FillReceiverStats(info); 1053 webrtc::Call::Stats stats = call_->GetStats(); 1054 FillBandwidthEstimationStats(stats, info); 1055 if (stats.rtt_ms != -1) { 1056 for (size_t i = 0; i < info->senders.size(); ++i) { 1057 info->senders[i].rtt_ms = stats.rtt_ms; 1058 } 1059 } 1060 return true; 1061} 1062 1063void WebRtcVideoChannel2::FillSenderStats(VideoMediaInfo* video_media_info) { 1064 rtc::CritScope stream_lock(&stream_crit_); 1065 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 1066 send_streams_.begin(); 1067 it != send_streams_.end(); 1068 ++it) { 1069 video_media_info->senders.push_back(it->second->GetVideoSenderInfo()); 1070 } 1071} 1072 1073void WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) { 1074 rtc::CritScope stream_lock(&stream_crit_); 1075 for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 1076 receive_streams_.begin(); 1077 it != receive_streams_.end(); 1078 ++it) { 1079 video_media_info->receivers.push_back(it->second->GetVideoReceiverInfo()); 1080 } 1081} 1082 1083void WebRtcVideoChannel2::FillBandwidthEstimationStats( 1084 const webrtc::Call::Stats& stats, 1085 VideoMediaInfo* video_media_info) { 1086 BandwidthEstimationInfo bwe_info; 1087 bwe_info.available_send_bandwidth = stats.send_bandwidth_bps; 1088 bwe_info.available_recv_bandwidth = stats.recv_bandwidth_bps; 1089 bwe_info.bucket_delay = stats.pacer_delay_ms; 1090 1091 // Get send stream bitrate stats. 1092 rtc::CritScope stream_lock(&stream_crit_); 1093 for (std::map<uint32, WebRtcVideoSendStream*>::iterator stream = 1094 send_streams_.begin(); 1095 stream != send_streams_.end(); 1096 ++stream) { 1097 stream->second->FillBandwidthEstimationInfo(&bwe_info); 1098 } 1099 video_media_info->bw_estimations.push_back(bwe_info); 1100} 1101 1102bool WebRtcVideoChannel2::SetCapturer(uint32 ssrc, VideoCapturer* capturer) { 1103 LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> " 1104 << (capturer != NULL ? "(capturer)" : "NULL"); 1105 assert(ssrc != 0); 1106 rtc::CritScope stream_lock(&stream_crit_); 1107 if (send_streams_.find(ssrc) == send_streams_.end()) { 1108 LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc; 1109 return false; 1110 } 1111 return send_streams_[ssrc]->SetCapturer(capturer); 1112} 1113 1114bool WebRtcVideoChannel2::SendIntraFrame() { 1115 // TODO(pbos): Implement. 1116 LOG(LS_VERBOSE) << "SendIntraFrame()."; 1117 return true; 1118} 1119 1120bool WebRtcVideoChannel2::RequestIntraFrame() { 1121 // TODO(pbos): Implement. 1122 LOG(LS_VERBOSE) << "SendIntraFrame()."; 1123 return true; 1124} 1125 1126void WebRtcVideoChannel2::OnPacketReceived( 1127 rtc::Buffer* packet, 1128 const rtc::PacketTime& packet_time) { 1129 const webrtc::PacketReceiver::DeliveryStatus delivery_result = 1130 call_->Receiver()->DeliverPacket( 1131 reinterpret_cast<const uint8_t*>(packet->data()), packet->length()); 1132 switch (delivery_result) { 1133 case webrtc::PacketReceiver::DELIVERY_OK: 1134 return; 1135 case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR: 1136 return; 1137 case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC: 1138 break; 1139 } 1140 1141 uint32 ssrc = 0; 1142 if (!GetRtpSsrc(packet->data(), packet->length(), &ssrc)) { 1143 return; 1144 } 1145 1146 // TODO(pbos): Make sure that the unsignalled SSRC uses the video payload. 1147 // Also figure out whether RTX needs to be handled. 1148 switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) { 1149 case UnsignalledSsrcHandler::kDropPacket: 1150 return; 1151 case UnsignalledSsrcHandler::kDeliverPacket: 1152 break; 1153 } 1154 1155 if (call_->Receiver()->DeliverPacket( 1156 reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) != 1157 webrtc::PacketReceiver::DELIVERY_OK) { 1158 LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery."; 1159 return; 1160 } 1161} 1162 1163void WebRtcVideoChannel2::OnRtcpReceived( 1164 rtc::Buffer* packet, 1165 const rtc::PacketTime& packet_time) { 1166 if (call_->Receiver()->DeliverPacket( 1167 reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) != 1168 webrtc::PacketReceiver::DELIVERY_OK) { 1169 LOG(LS_WARNING) << "Failed to deliver RTCP packet."; 1170 } 1171} 1172 1173void WebRtcVideoChannel2::OnReadyToSend(bool ready) { 1174 LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready."); 1175 call_->SignalNetworkState(ready ? webrtc::Call::kNetworkUp 1176 : webrtc::Call::kNetworkDown); 1177} 1178 1179bool WebRtcVideoChannel2::MuteStream(uint32 ssrc, bool mute) { 1180 LOG(LS_VERBOSE) << "MuteStream: " << ssrc << " -> " 1181 << (mute ? "mute" : "unmute"); 1182 assert(ssrc != 0); 1183 rtc::CritScope stream_lock(&stream_crit_); 1184 if (send_streams_.find(ssrc) == send_streams_.end()) { 1185 LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc; 1186 return false; 1187 } 1188 1189 send_streams_[ssrc]->MuteStream(mute); 1190 return true; 1191} 1192 1193bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions( 1194 const std::vector<RtpHeaderExtension>& extensions) { 1195 LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: " 1196 << RtpExtensionsToString(extensions); 1197 if (!ValidateRtpHeaderExtensionIds(extensions)) 1198 return false; 1199 1200 std::vector<webrtc::RtpExtension> filtered_extensions = 1201 FilterRtpExtensions(extensions); 1202 if (!RtpExtensionsHaveChanged(recv_rtp_extensions_, filtered_extensions)) 1203 return true; 1204 1205 recv_rtp_extensions_ = filtered_extensions; 1206 1207 rtc::CritScope stream_lock(&stream_crit_); 1208 for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 1209 receive_streams_.begin(); 1210 it != receive_streams_.end(); 1211 ++it) { 1212 it->second->SetRtpExtensions(recv_rtp_extensions_); 1213 } 1214 return true; 1215} 1216 1217bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions( 1218 const std::vector<RtpHeaderExtension>& extensions) { 1219 LOG(LS_INFO) << "SetSendRtpHeaderExtensions: " 1220 << RtpExtensionsToString(extensions); 1221 if (!ValidateRtpHeaderExtensionIds(extensions)) 1222 return false; 1223 1224 std::vector<webrtc::RtpExtension> filtered_extensions = 1225 FilterRtpExtensions(extensions); 1226 if (!RtpExtensionsHaveChanged(send_rtp_extensions_, filtered_extensions)) 1227 return true; 1228 1229 send_rtp_extensions_ = filtered_extensions; 1230 1231 rtc::CritScope stream_lock(&stream_crit_); 1232 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 1233 send_streams_.begin(); 1234 it != send_streams_.end(); 1235 ++it) { 1236 it->second->SetRtpExtensions(send_rtp_extensions_); 1237 } 1238 return true; 1239} 1240 1241bool WebRtcVideoChannel2::SetMaxSendBandwidth(int max_bitrate_bps) { 1242 LOG(LS_INFO) << "SetMaxSendBandwidth: " << max_bitrate_bps << "bps."; 1243 if (max_bitrate_bps <= 0) { 1244 // Unsetting max bitrate. 1245 max_bitrate_bps = -1; 1246 } 1247 bitrate_config_.start_bitrate_bps = -1; 1248 bitrate_config_.max_bitrate_bps = max_bitrate_bps; 1249 if (max_bitrate_bps > 0 && 1250 bitrate_config_.min_bitrate_bps > max_bitrate_bps) { 1251 bitrate_config_.min_bitrate_bps = max_bitrate_bps; 1252 } 1253 call_->SetBitrateConfig(bitrate_config_); 1254 return true; 1255} 1256 1257bool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) { 1258 LOG(LS_INFO) << "SetOptions: " << options.ToString(); 1259 VideoOptions old_options = options_; 1260 options_.SetAll(options); 1261 if (options_ == old_options) { 1262 // No new options to set. 1263 return true; 1264 } 1265 rtc::DiffServCodePoint dscp = options_.dscp.GetWithDefaultIfUnset(false) 1266 ? rtc::DSCP_AF41 1267 : rtc::DSCP_DEFAULT; 1268 MediaChannel::SetDscp(dscp); 1269 rtc::CritScope stream_lock(&stream_crit_); 1270 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 1271 send_streams_.begin(); 1272 it != send_streams_.end(); 1273 ++it) { 1274 it->second->SetOptions(options_); 1275 } 1276 return true; 1277} 1278 1279void WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) { 1280 MediaChannel::SetInterface(iface); 1281 // Set the RTP recv/send buffer to a bigger size 1282 MediaChannel::SetOption(NetworkInterface::ST_RTP, 1283 rtc::Socket::OPT_RCVBUF, 1284 kVideoRtpBufferSize); 1285 1286 // Speculative change to increase the outbound socket buffer size. 1287 // In b/15152257, we are seeing a significant number of packets discarded 1288 // due to lack of socket buffer space, although it's not yet clear what the 1289 // ideal value should be. 1290 MediaChannel::SetOption(NetworkInterface::ST_RTP, 1291 rtc::Socket::OPT_SNDBUF, 1292 kVideoRtpBufferSize); 1293} 1294 1295void WebRtcVideoChannel2::UpdateAspectRatio(int ratio_w, int ratio_h) { 1296 // TODO(pbos): Implement. 1297} 1298 1299void WebRtcVideoChannel2::OnMessage(rtc::Message* msg) { 1300 // Ignored. 1301} 1302 1303void WebRtcVideoChannel2::OnLoadUpdate(Load load) { 1304 rtc::CritScope stream_lock(&stream_crit_); 1305 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 1306 send_streams_.begin(); 1307 it != send_streams_.end(); 1308 ++it) { 1309 it->second->OnCpuResolutionRequest(load == kOveruse 1310 ? CoordinatedVideoAdapter::DOWNGRADE 1311 : CoordinatedVideoAdapter::UPGRADE); 1312 } 1313} 1314 1315bool WebRtcVideoChannel2::SendRtp(const uint8_t* data, size_t len) { 1316 rtc::Buffer packet(data, len, kMaxRtpPacketLen); 1317 return MediaChannel::SendPacket(&packet); 1318} 1319 1320bool WebRtcVideoChannel2::SendRtcp(const uint8_t* data, size_t len) { 1321 rtc::Buffer packet(data, len, kMaxRtpPacketLen); 1322 return MediaChannel::SendRtcp(&packet); 1323} 1324 1325void WebRtcVideoChannel2::StartAllSendStreams() { 1326 rtc::CritScope stream_lock(&stream_crit_); 1327 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 1328 send_streams_.begin(); 1329 it != send_streams_.end(); 1330 ++it) { 1331 it->second->Start(); 1332 } 1333} 1334 1335void WebRtcVideoChannel2::StopAllSendStreams() { 1336 rtc::CritScope stream_lock(&stream_crit_); 1337 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 1338 send_streams_.begin(); 1339 it != send_streams_.end(); 1340 ++it) { 1341 it->second->Stop(); 1342 } 1343} 1344 1345WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters:: 1346 VideoSendStreamParameters( 1347 const webrtc::VideoSendStream::Config& config, 1348 const VideoOptions& options, 1349 const Settable<VideoCodecSettings>& codec_settings) 1350 : config(config), options(options), codec_settings(codec_settings) { 1351} 1352 1353WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream( 1354 webrtc::Call* call, 1355 WebRtcVideoEncoderFactory* external_encoder_factory, 1356 WebRtcVideoEncoderFactory2* encoder_factory, 1357 const VideoOptions& options, 1358 const Settable<VideoCodecSettings>& codec_settings, 1359 const StreamParams& sp, 1360 const std::vector<webrtc::RtpExtension>& rtp_extensions) 1361 : call_(call), 1362 external_encoder_factory_(external_encoder_factory), 1363 encoder_factory_(encoder_factory), 1364 stream_(NULL), 1365 parameters_(webrtc::VideoSendStream::Config(), options, codec_settings), 1366 allocated_encoder_(NULL, webrtc::kVideoCodecUnknown, false), 1367 capturer_(NULL), 1368 sending_(false), 1369 muted_(false) { 1370 parameters_.config.rtp.max_packet_size = kVideoMtu; 1371 1372 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); 1373 sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, 1374 ¶meters_.config.rtp.rtx.ssrcs); 1375 parameters_.config.rtp.c_name = sp.cname; 1376 parameters_.config.rtp.extensions = rtp_extensions; 1377 1378 VideoCodecSettings params; 1379 if (codec_settings.Get(¶ms)) { 1380 SetCodec(params); 1381 } 1382} 1383 1384WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() { 1385 DisconnectCapturer(); 1386 if (stream_ != NULL) { 1387 call_->DestroyVideoSendStream(stream_); 1388 } 1389 DestroyVideoEncoder(&allocated_encoder_); 1390} 1391 1392static void SetWebRtcFrameToBlack(webrtc::I420VideoFrame* video_frame) { 1393 assert(video_frame != NULL); 1394 memset(video_frame->buffer(webrtc::kYPlane), 1395 16, 1396 video_frame->allocated_size(webrtc::kYPlane)); 1397 memset(video_frame->buffer(webrtc::kUPlane), 1398 128, 1399 video_frame->allocated_size(webrtc::kUPlane)); 1400 memset(video_frame->buffer(webrtc::kVPlane), 1401 128, 1402 video_frame->allocated_size(webrtc::kVPlane)); 1403} 1404 1405static void CreateBlackFrame(webrtc::I420VideoFrame* video_frame, 1406 int width, 1407 int height) { 1408 video_frame->CreateEmptyFrame( 1409 width, height, width, (width + 1) / 2, (width + 1) / 2); 1410 SetWebRtcFrameToBlack(video_frame); 1411} 1412 1413static void ConvertToI420VideoFrame(const VideoFrame& frame, 1414 webrtc::I420VideoFrame* i420_frame) { 1415 i420_frame->CreateFrame( 1416 static_cast<int>(frame.GetYPitch() * frame.GetHeight()), 1417 frame.GetYPlane(), 1418 static_cast<int>(frame.GetUPitch() * ((frame.GetHeight() + 1) / 2)), 1419 frame.GetUPlane(), 1420 static_cast<int>(frame.GetVPitch() * ((frame.GetHeight() + 1) / 2)), 1421 frame.GetVPlane(), 1422 static_cast<int>(frame.GetWidth()), 1423 static_cast<int>(frame.GetHeight()), 1424 static_cast<int>(frame.GetYPitch()), 1425 static_cast<int>(frame.GetUPitch()), 1426 static_cast<int>(frame.GetVPitch())); 1427} 1428 1429void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame( 1430 VideoCapturer* capturer, 1431 const VideoFrame* frame) { 1432 LOG(LS_VERBOSE) << "InputFrame: " << frame->GetWidth() << "x" 1433 << frame->GetHeight(); 1434 // Lock before copying, can be called concurrently when swapping input source. 1435 rtc::CritScope frame_cs(&frame_lock_); 1436 ConvertToI420VideoFrame(*frame, &video_frame_); 1437 1438 rtc::CritScope cs(&lock_); 1439 if (stream_ == NULL) { 1440 LOG(LS_WARNING) << "Capturer inputting frames before send codecs are " 1441 "configured, dropping."; 1442 return; 1443 } 1444 if (format_.width == 0) { // Dropping frames. 1445 assert(format_.height == 0); 1446 LOG(LS_VERBOSE) << "VideoFormat 0x0 set, Dropping frame."; 1447 return; 1448 } 1449 if (muted_) { 1450 // Create a black frame to transmit instead. 1451 CreateBlackFrame(&video_frame_, 1452 static_cast<int>(frame->GetWidth()), 1453 static_cast<int>(frame->GetHeight())); 1454 } 1455 // Reconfigure codec if necessary. 1456 SetDimensions( 1457 video_frame_.width(), video_frame_.height(), capturer->IsScreencast()); 1458 1459 LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x" 1460 << video_frame_.height() << " -> (codec) " 1461 << parameters_.encoder_config.streams.back().width << "x" 1462 << parameters_.encoder_config.streams.back().height; 1463 stream_->Input()->SwapFrame(&video_frame_); 1464} 1465 1466bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer( 1467 VideoCapturer* capturer) { 1468 if (!DisconnectCapturer() && capturer == NULL) { 1469 return false; 1470 } 1471 1472 { 1473 rtc::CritScope cs(&lock_); 1474 1475 if (capturer == NULL) { 1476 if (stream_ != NULL) { 1477 LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; 1478 webrtc::I420VideoFrame black_frame; 1479 1480 // TODO(pbos): Base width/height on last_dimensions_. This will however 1481 // fail the test AddRemoveCapturer which needs to be fixed to permit 1482 // sending black frames in the same size that was previously sent. 1483 int width = format_.width; 1484 int height = format_.height; 1485 int half_width = (width + 1) / 2; 1486 black_frame.CreateEmptyFrame( 1487 width, height, width, half_width, half_width); 1488 SetWebRtcFrameToBlack(&black_frame); 1489 SetDimensions(width, height, last_dimensions_.is_screencast); 1490 stream_->Input()->SwapFrame(&black_frame); 1491 } 1492 1493 capturer_ = NULL; 1494 return true; 1495 } 1496 1497 capturer_ = capturer; 1498 } 1499 // Lock cannot be held while connecting the capturer to prevent lock-order 1500 // violations. 1501 capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame); 1502 return true; 1503} 1504 1505bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat( 1506 const VideoFormat& format) { 1507 if ((format.width == 0 || format.height == 0) && 1508 format.width != format.height) { 1509 LOG(LS_ERROR) << "Can't set VideoFormat, width or height is zero (but not " 1510 "both, 0x0 drops frames)."; 1511 return false; 1512 } 1513 1514 rtc::CritScope cs(&lock_); 1515 if (format.width == 0 && format.height == 0) { 1516 LOG(LS_INFO) 1517 << "0x0 resolution selected. Captured frames will be dropped for ssrc: " 1518 << parameters_.config.rtp.ssrcs[0] << "."; 1519 } else { 1520 // TODO(pbos): Fix me, this only affects the last stream! 1521 parameters_.encoder_config.streams.back().max_framerate = 1522 VideoFormat::IntervalToFps(format.interval); 1523 SetDimensions(format.width, format.height, false); 1524 } 1525 1526 format_ = format; 1527 return true; 1528} 1529 1530void WebRtcVideoChannel2::WebRtcVideoSendStream::MuteStream(bool mute) { 1531 rtc::CritScope cs(&lock_); 1532 muted_ = mute; 1533} 1534 1535bool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() { 1536 cricket::VideoCapturer* capturer; 1537 { 1538 rtc::CritScope cs(&lock_); 1539 if (capturer_ == NULL) { 1540 return false; 1541 } 1542 capturer = capturer_; 1543 capturer_ = NULL; 1544 } 1545 capturer->SignalVideoFrame.disconnect(this); 1546 return true; 1547} 1548 1549void WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions( 1550 const VideoOptions& options) { 1551 rtc::CritScope cs(&lock_); 1552 VideoCodecSettings codec_settings; 1553 if (parameters_.codec_settings.Get(&codec_settings)) { 1554 SetCodecAndOptions(codec_settings, options); 1555 } else { 1556 parameters_.options = options; 1557 } 1558} 1559 1560void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec( 1561 const VideoCodecSettings& codec_settings) { 1562 rtc::CritScope cs(&lock_); 1563 SetCodecAndOptions(codec_settings, parameters_.options); 1564} 1565 1566webrtc::VideoCodecType CodecTypeFromName(const std::string& name) { 1567 if (CodecNameMatches(name, kVp8CodecName)) { 1568 return webrtc::kVideoCodecVP8; 1569 } else if (CodecNameMatches(name, kVp9CodecName)) { 1570 return webrtc::kVideoCodecVP9; 1571 } else if (CodecNameMatches(name, kH264CodecName)) { 1572 return webrtc::kVideoCodecH264; 1573 } 1574 return webrtc::kVideoCodecUnknown; 1575} 1576 1577WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder 1578WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder( 1579 const VideoCodec& codec) { 1580 webrtc::VideoCodecType type = CodecTypeFromName(codec.name); 1581 1582 // Do not re-create encoders of the same type. 1583 if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) { 1584 return allocated_encoder_; 1585 } 1586 1587 if (external_encoder_factory_ != NULL) { 1588 webrtc::VideoEncoder* encoder = 1589 external_encoder_factory_->CreateVideoEncoder(type); 1590 if (encoder != NULL) { 1591 return AllocatedEncoder(encoder, type, true); 1592 } 1593 } 1594 1595 if (type == webrtc::kVideoCodecVP8) { 1596 return AllocatedEncoder( 1597 webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp8), type, false); 1598 } else if (type == webrtc::kVideoCodecVP9) { 1599 return AllocatedEncoder( 1600 webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp9), type, false); 1601 } 1602 1603 // This shouldn't happen, we should not be trying to create something we don't 1604 // support. 1605 assert(false); 1606 return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false); 1607} 1608 1609void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder( 1610 AllocatedEncoder* encoder) { 1611 if (encoder->external) { 1612 external_encoder_factory_->DestroyVideoEncoder(encoder->encoder); 1613 } else { 1614 delete encoder->encoder; 1615 } 1616} 1617 1618void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions( 1619 const VideoCodecSettings& codec_settings, 1620 const VideoOptions& options) { 1621 if (last_dimensions_.width == -1) { 1622 last_dimensions_.width = codec_settings.codec.width; 1623 last_dimensions_.height = codec_settings.codec.height; 1624 last_dimensions_.is_screencast = false; 1625 } 1626 parameters_.encoder_config = 1627 CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec); 1628 if (parameters_.encoder_config.streams.empty()) { 1629 return; 1630 } 1631 1632 format_ = VideoFormat(codec_settings.codec.width, 1633 codec_settings.codec.height, 1634 VideoFormat::FpsToInterval(30), 1635 FOURCC_I420); 1636 1637 AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec); 1638 parameters_.config.encoder_settings.encoder = new_encoder.encoder; 1639 parameters_.config.encoder_settings.payload_name = codec_settings.codec.name; 1640 parameters_.config.encoder_settings.payload_type = codec_settings.codec.id; 1641 parameters_.config.rtp.fec = codec_settings.fec; 1642 1643 // Set RTX payload type if RTX is enabled. 1644 if (!parameters_.config.rtp.rtx.ssrcs.empty()) { 1645 parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type; 1646 } 1647 1648 if (IsNackEnabled(codec_settings.codec)) { 1649 parameters_.config.rtp.nack.rtp_history_ms = kNackHistoryMs; 1650 } 1651 1652 options.suspend_below_min_bitrate.Get( 1653 ¶meters_.config.suspend_below_min_bitrate); 1654 1655 parameters_.codec_settings.Set(codec_settings); 1656 parameters_.options = options; 1657 1658 RecreateWebRtcStream(); 1659 if (allocated_encoder_.encoder != new_encoder.encoder) { 1660 DestroyVideoEncoder(&allocated_encoder_); 1661 allocated_encoder_ = new_encoder; 1662 } 1663} 1664 1665void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions( 1666 const std::vector<webrtc::RtpExtension>& rtp_extensions) { 1667 rtc::CritScope cs(&lock_); 1668 parameters_.config.rtp.extensions = rtp_extensions; 1669 RecreateWebRtcStream(); 1670} 1671 1672webrtc::VideoEncoderConfig 1673WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig( 1674 const Dimensions& dimensions, 1675 const VideoCodec& codec) const { 1676 webrtc::VideoEncoderConfig encoder_config; 1677 if (dimensions.is_screencast) { 1678 int screencast_min_bitrate_kbps; 1679 parameters_.options.screencast_min_bitrate.Get( 1680 &screencast_min_bitrate_kbps); 1681 encoder_config.min_transmit_bitrate_bps = 1682 screencast_min_bitrate_kbps * 1000; 1683 encoder_config.content_type = webrtc::VideoEncoderConfig::kScreenshare; 1684 } else { 1685 encoder_config.min_transmit_bitrate_bps = 0; 1686 encoder_config.content_type = webrtc::VideoEncoderConfig::kRealtimeVideo; 1687 } 1688 1689 // Restrict dimensions according to codec max. 1690 int width = dimensions.width; 1691 int height = dimensions.height; 1692 if (!dimensions.is_screencast) { 1693 if (codec.width < width) 1694 width = codec.width; 1695 if (codec.height < height) 1696 height = codec.height; 1697 } 1698 1699 VideoCodec clamped_codec = codec; 1700 clamped_codec.width = width; 1701 clamped_codec.height = height; 1702 1703 encoder_config.streams = encoder_factory_->CreateVideoStreams( 1704 clamped_codec, parameters_.options, parameters_.config.rtp.ssrcs.size()); 1705 1706 // Conference mode screencast uses 2 temporal layers split at 100kbit. 1707 if (parameters_.options.conference_mode.GetWithDefaultIfUnset(false) && 1708 dimensions.is_screencast && encoder_config.streams.size() == 1) { 1709 ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault(); 1710 1711 // For screenshare in conference mode, tl0 and tl1 bitrates are piggybacked 1712 // on the VideoCodec struct as target and max bitrates, respectively. 1713 // See eg. webrtc::VP8EncoderImpl::SetRates(). 1714 encoder_config.streams[0].target_bitrate_bps = 1715 config.tl0_bitrate_kbps * 1000; 1716 encoder_config.streams[0].max_bitrate_bps = config.tl1_bitrate_kbps * 1000; 1717 encoder_config.streams[0].temporal_layer_thresholds_bps.clear(); 1718 encoder_config.streams[0].temporal_layer_thresholds_bps.push_back( 1719 config.tl0_bitrate_kbps * 1000); 1720 } 1721 return encoder_config; 1722} 1723 1724void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions( 1725 int width, 1726 int height, 1727 bool is_screencast) { 1728 if (last_dimensions_.width == width && last_dimensions_.height == height && 1729 last_dimensions_.is_screencast == is_screencast) { 1730 // Configured using the same parameters, do not reconfigure. 1731 return; 1732 } 1733 LOG(LS_INFO) << "SetDimensions: " << width << "x" << height 1734 << (is_screencast ? " (screencast)" : " (not screencast)"); 1735 1736 last_dimensions_.width = width; 1737 last_dimensions_.height = height; 1738 last_dimensions_.is_screencast = is_screencast; 1739 1740 assert(!parameters_.encoder_config.streams.empty()); 1741 1742 VideoCodecSettings codec_settings; 1743 parameters_.codec_settings.Get(&codec_settings); 1744 1745 webrtc::VideoEncoderConfig encoder_config = 1746 CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec); 1747 1748 encoder_config.encoder_specific_settings = 1749 encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec, 1750 parameters_.options); 1751 1752 bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config); 1753 1754 encoder_factory_->DestroyVideoEncoderSettings( 1755 codec_settings.codec, 1756 encoder_config.encoder_specific_settings); 1757 1758 encoder_config.encoder_specific_settings = NULL; 1759 1760 if (!stream_reconfigured) { 1761 LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: " 1762 << width << "x" << height; 1763 return; 1764 } 1765 1766 parameters_.encoder_config = encoder_config; 1767} 1768 1769void WebRtcVideoChannel2::WebRtcVideoSendStream::Start() { 1770 rtc::CritScope cs(&lock_); 1771 assert(stream_ != NULL); 1772 stream_->Start(); 1773 sending_ = true; 1774} 1775 1776void WebRtcVideoChannel2::WebRtcVideoSendStream::Stop() { 1777 rtc::CritScope cs(&lock_); 1778 if (stream_ != NULL) { 1779 stream_->Stop(); 1780 } 1781 sending_ = false; 1782} 1783 1784VideoSenderInfo 1785WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() { 1786 VideoSenderInfo info; 1787 rtc::CritScope cs(&lock_); 1788 for (size_t i = 0; i < parameters_.config.rtp.ssrcs.size(); ++i) { 1789 info.add_ssrc(parameters_.config.rtp.ssrcs[i]); 1790 } 1791 1792 if (stream_ == NULL) { 1793 return info; 1794 } 1795 1796 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); 1797 info.framerate_input = stats.input_frame_rate; 1798 info.framerate_sent = stats.encode_frame_rate; 1799 1800 info.send_frame_width = 0; 1801 info.send_frame_height = 0; 1802 for (std::map<uint32_t, webrtc::SsrcStats>::iterator it = 1803 stats.substreams.begin(); 1804 it != stats.substreams.end(); 1805 ++it) { 1806 // TODO(pbos): Wire up additional stats, such as padding bytes. 1807 webrtc::SsrcStats stream_stats = it->second; 1808 info.bytes_sent += stream_stats.rtp_stats.bytes + 1809 stream_stats.rtp_stats.header_bytes + 1810 stream_stats.rtp_stats.padding_bytes; 1811 info.packets_sent += stream_stats.rtp_stats.packets; 1812 info.packets_lost += stream_stats.rtcp_stats.cumulative_lost; 1813 if (stream_stats.sent_width > info.send_frame_width) 1814 info.send_frame_width = stream_stats.sent_width; 1815 if (stream_stats.sent_height > info.send_frame_height) 1816 info.send_frame_height = stream_stats.sent_height; 1817 } 1818 1819 if (!stats.substreams.empty()) { 1820 // TODO(pbos): Report fraction lost per SSRC. 1821 webrtc::SsrcStats first_stream_stats = stats.substreams.begin()->second; 1822 info.fraction_lost = 1823 static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) / 1824 (1 << 8); 1825 } 1826 1827 if (capturer_ != NULL && !capturer_->IsMuted()) { 1828 VideoFormat last_captured_frame_format; 1829 capturer_->GetStats(&info.adapt_frame_drops, 1830 &info.effects_frame_drops, 1831 &info.capturer_frame_time, 1832 &last_captured_frame_format); 1833 info.input_frame_width = last_captured_frame_format.width; 1834 info.input_frame_height = last_captured_frame_format.height; 1835 } 1836 1837 // TODO(pbos): Support or remove the following stats. 1838 info.packets_cached = -1; 1839 1840 return info; 1841} 1842 1843void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo( 1844 BandwidthEstimationInfo* bwe_info) { 1845 rtc::CritScope cs(&lock_); 1846 if (stream_ == NULL) { 1847 return; 1848 } 1849 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); 1850 for (std::map<uint32_t, webrtc::SsrcStats>::iterator it = 1851 stats.substreams.begin(); 1852 it != stats.substreams.end(); 1853 ++it) { 1854 bwe_info->transmit_bitrate += it->second.total_bitrate_bps; 1855 bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps; 1856 } 1857 bwe_info->actual_enc_bitrate = stats.media_bitrate_bps; 1858} 1859 1860void WebRtcVideoChannel2::WebRtcVideoSendStream::OnCpuResolutionRequest( 1861 CoordinatedVideoAdapter::AdaptRequest adapt_request) { 1862 rtc::CritScope cs(&lock_); 1863 bool adapt_cpu; 1864 parameters_.options.cpu_overuse_detection.Get(&adapt_cpu); 1865 if (!adapt_cpu) { 1866 return; 1867 } 1868 if (capturer_ == NULL || capturer_->video_adapter() == NULL) { 1869 return; 1870 } 1871 1872 capturer_->video_adapter()->OnCpuResolutionRequest(adapt_request); 1873} 1874 1875void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() { 1876 if (stream_ != NULL) { 1877 call_->DestroyVideoSendStream(stream_); 1878 } 1879 1880 VideoCodecSettings codec_settings; 1881 parameters_.codec_settings.Get(&codec_settings); 1882 parameters_.encoder_config.encoder_specific_settings = 1883 encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec, 1884 parameters_.options); 1885 1886 stream_ = call_->CreateVideoSendStream(parameters_.config, 1887 parameters_.encoder_config); 1888 1889 encoder_factory_->DestroyVideoEncoderSettings( 1890 codec_settings.codec, 1891 parameters_.encoder_config.encoder_specific_settings); 1892 1893 parameters_.encoder_config.encoder_specific_settings = NULL; 1894 1895 if (sending_) { 1896 stream_->Start(); 1897 } 1898} 1899 1900WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( 1901 webrtc::Call* call, 1902 WebRtcVideoDecoderFactory* external_decoder_factory, 1903 const webrtc::VideoReceiveStream::Config& config, 1904 const std::vector<VideoCodecSettings>& recv_codecs) 1905 : call_(call), 1906 stream_(NULL), 1907 config_(config), 1908 external_decoder_factory_(external_decoder_factory), 1909 renderer_(NULL), 1910 last_width_(-1), 1911 last_height_(-1) { 1912 config_.renderer = this; 1913 // SetRecvCodecs will also reset (start) the VideoReceiveStream. 1914 SetRecvCodecs(recv_codecs); 1915} 1916 1917WebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() { 1918 call_->DestroyVideoReceiveStream(stream_); 1919 ClearDecoders(&allocated_decoders_); 1920} 1921 1922WebRtcVideoChannel2::WebRtcVideoReceiveStream::AllocatedDecoder 1923WebRtcVideoChannel2::WebRtcVideoReceiveStream::CreateOrReuseVideoDecoder( 1924 std::vector<AllocatedDecoder>* old_decoders, 1925 const VideoCodec& codec) { 1926 webrtc::VideoCodecType type = CodecTypeFromName(codec.name); 1927 1928 for (size_t i = 0; i < old_decoders->size(); ++i) { 1929 if ((*old_decoders)[i].type == type) { 1930 AllocatedDecoder decoder = (*old_decoders)[i]; 1931 (*old_decoders)[i] = old_decoders->back(); 1932 old_decoders->pop_back(); 1933 return decoder; 1934 } 1935 } 1936 1937 if (external_decoder_factory_ != NULL) { 1938 webrtc::VideoDecoder* decoder = 1939 external_decoder_factory_->CreateVideoDecoder(type); 1940 if (decoder != NULL) { 1941 return AllocatedDecoder(decoder, type, true); 1942 } 1943 } 1944 1945 if (type == webrtc::kVideoCodecVP8) { 1946 return AllocatedDecoder( 1947 webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kVp8), type, false); 1948 } 1949 1950 // This shouldn't happen, we should not be trying to create something we don't 1951 // support. 1952 assert(false); 1953 return AllocatedDecoder(NULL, webrtc::kVideoCodecUnknown, false); 1954} 1955 1956void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs( 1957 const std::vector<VideoCodecSettings>& recv_codecs) { 1958 std::vector<AllocatedDecoder> old_decoders = allocated_decoders_; 1959 allocated_decoders_.clear(); 1960 config_.decoders.clear(); 1961 for (size_t i = 0; i < recv_codecs.size(); ++i) { 1962 AllocatedDecoder allocated_decoder = 1963 CreateOrReuseVideoDecoder(&old_decoders, recv_codecs[i].codec); 1964 allocated_decoders_.push_back(allocated_decoder); 1965 1966 webrtc::VideoReceiveStream::Decoder decoder; 1967 decoder.decoder = allocated_decoder.decoder; 1968 decoder.payload_type = recv_codecs[i].codec.id; 1969 decoder.payload_name = recv_codecs[i].codec.name; 1970 config_.decoders.push_back(decoder); 1971 } 1972 1973 // TODO(pbos): Reconfigure RTX based on incoming recv_codecs. 1974 config_.rtp.fec = recv_codecs.front().fec; 1975 config_.rtp.nack.rtp_history_ms = 1976 IsNackEnabled(recv_codecs.begin()->codec) ? kNackHistoryMs : 0; 1977 config_.rtp.remb = IsRembEnabled(recv_codecs.begin()->codec); 1978 1979 ClearDecoders(&old_decoders); 1980 RecreateWebRtcStream(); 1981} 1982 1983void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions( 1984 const std::vector<webrtc::RtpExtension>& extensions) { 1985 config_.rtp.extensions = extensions; 1986 RecreateWebRtcStream(); 1987} 1988 1989void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() { 1990 if (stream_ != NULL) { 1991 call_->DestroyVideoReceiveStream(stream_); 1992 } 1993 stream_ = call_->CreateVideoReceiveStream(config_); 1994 stream_->Start(); 1995} 1996 1997void WebRtcVideoChannel2::WebRtcVideoReceiveStream::ClearDecoders( 1998 std::vector<AllocatedDecoder>* allocated_decoders) { 1999 for (size_t i = 0; i < allocated_decoders->size(); ++i) { 2000 if ((*allocated_decoders)[i].external) { 2001 external_decoder_factory_->DestroyVideoDecoder( 2002 (*allocated_decoders)[i].decoder); 2003 } else { 2004 delete (*allocated_decoders)[i].decoder; 2005 } 2006 } 2007 allocated_decoders->clear(); 2008} 2009 2010void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame( 2011 const webrtc::I420VideoFrame& frame, 2012 int time_to_render_ms) { 2013 rtc::CritScope crit(&renderer_lock_); 2014 if (renderer_ == NULL) { 2015 LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer."; 2016 return; 2017 } 2018 2019 if (frame.width() != last_width_ || frame.height() != last_height_) { 2020 SetSize(frame.width(), frame.height()); 2021 } 2022 2023 LOG(LS_VERBOSE) << "RenderFrame: (" << frame.width() << "x" << frame.height() 2024 << ")"; 2025 2026 const WebRtcVideoRenderFrame render_frame(&frame); 2027 renderer_->RenderFrame(&render_frame); 2028} 2029 2030void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRenderer( 2031 cricket::VideoRenderer* renderer) { 2032 rtc::CritScope crit(&renderer_lock_); 2033 renderer_ = renderer; 2034 if (renderer_ != NULL && last_width_ != -1) { 2035 SetSize(last_width_, last_height_); 2036 } 2037} 2038 2039VideoRenderer* WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetRenderer() { 2040 // TODO(pbos): Remove GetRenderer and all uses of it, it's thread-unsafe by 2041 // design. 2042 rtc::CritScope crit(&renderer_lock_); 2043 return renderer_; 2044} 2045 2046void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width, 2047 int height) { 2048 rtc::CritScope crit(&renderer_lock_); 2049 if (!renderer_->SetSize(width, height, 0)) { 2050 LOG(LS_ERROR) << "Could not set renderer size."; 2051 } 2052 last_width_ = width; 2053 last_height_ = height; 2054} 2055 2056VideoReceiverInfo 2057WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() { 2058 VideoReceiverInfo info; 2059 info.add_ssrc(config_.rtp.remote_ssrc); 2060 webrtc::VideoReceiveStream::Stats stats = stream_->GetStats(); 2061 info.bytes_rcvd = stats.rtp_stats.bytes + stats.rtp_stats.header_bytes + 2062 stats.rtp_stats.padding_bytes; 2063 info.packets_rcvd = stats.rtp_stats.packets; 2064 2065 info.framerate_rcvd = stats.network_frame_rate; 2066 info.framerate_decoded = stats.decode_frame_rate; 2067 info.framerate_output = stats.render_frame_rate; 2068 2069 rtc::CritScope frame_cs(&renderer_lock_); 2070 info.frame_width = last_width_; 2071 info.frame_height = last_height_; 2072 2073 // TODO(pbos): Support or remove the following stats. 2074 info.packets_concealed = -1; 2075 2076 return info; 2077} 2078 2079WebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings() 2080 : rtx_payload_type(-1) {} 2081 2082bool WebRtcVideoChannel2::VideoCodecSettings::operator==( 2083 const WebRtcVideoChannel2::VideoCodecSettings& other) const { 2084 return codec == other.codec && 2085 fec.ulpfec_payload_type == other.fec.ulpfec_payload_type && 2086 fec.red_payload_type == other.fec.red_payload_type && 2087 rtx_payload_type == other.rtx_payload_type; 2088} 2089 2090std::vector<WebRtcVideoChannel2::VideoCodecSettings> 2091WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) { 2092 assert(!codecs.empty()); 2093 2094 std::vector<VideoCodecSettings> video_codecs; 2095 std::map<int, bool> payload_used; 2096 std::map<int, VideoCodec::CodecType> payload_codec_type; 2097 std::map<int, int> rtx_mapping; // video payload type -> rtx payload type. 2098 2099 webrtc::FecConfig fec_settings; 2100 2101 for (size_t i = 0; i < codecs.size(); ++i) { 2102 const VideoCodec& in_codec = codecs[i]; 2103 int payload_type = in_codec.id; 2104 2105 if (payload_used[payload_type]) { 2106 LOG(LS_ERROR) << "Payload type already registered: " 2107 << in_codec.ToString(); 2108 return std::vector<VideoCodecSettings>(); 2109 } 2110 payload_used[payload_type] = true; 2111 payload_codec_type[payload_type] = in_codec.GetCodecType(); 2112 2113 switch (in_codec.GetCodecType()) { 2114 case VideoCodec::CODEC_RED: { 2115 // RED payload type, should not have duplicates. 2116 assert(fec_settings.red_payload_type == -1); 2117 fec_settings.red_payload_type = in_codec.id; 2118 continue; 2119 } 2120 2121 case VideoCodec::CODEC_ULPFEC: { 2122 // ULPFEC payload type, should not have duplicates. 2123 assert(fec_settings.ulpfec_payload_type == -1); 2124 fec_settings.ulpfec_payload_type = in_codec.id; 2125 continue; 2126 } 2127 2128 case VideoCodec::CODEC_RTX: { 2129 int associated_payload_type; 2130 if (!in_codec.GetParam(kCodecParamAssociatedPayloadType, 2131 &associated_payload_type)) { 2132 LOG(LS_ERROR) << "RTX codec without associated payload type: " 2133 << in_codec.ToString(); 2134 return std::vector<VideoCodecSettings>(); 2135 } 2136 rtx_mapping[associated_payload_type] = in_codec.id; 2137 continue; 2138 } 2139 2140 case VideoCodec::CODEC_VIDEO: 2141 break; 2142 } 2143 2144 video_codecs.push_back(VideoCodecSettings()); 2145 video_codecs.back().codec = in_codec; 2146 } 2147 2148 // One of these codecs should have been a video codec. Only having FEC 2149 // parameters into this code is a logic error. 2150 assert(!video_codecs.empty()); 2151 2152 for (std::map<int, int>::const_iterator it = rtx_mapping.begin(); 2153 it != rtx_mapping.end(); 2154 ++it) { 2155 if (!payload_used[it->first]) { 2156 LOG(LS_ERROR) << "RTX mapped to payload not in codec list."; 2157 return std::vector<VideoCodecSettings>(); 2158 } 2159 if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO) { 2160 LOG(LS_ERROR) << "RTX not mapped to regular video codec."; 2161 return std::vector<VideoCodecSettings>(); 2162 } 2163 } 2164 2165 // TODO(pbos): Write tests that figure out that I have not verified that RTX 2166 // codecs aren't mapped to bogus payloads. 2167 for (size_t i = 0; i < video_codecs.size(); ++i) { 2168 video_codecs[i].fec = fec_settings; 2169 if (rtx_mapping[video_codecs[i].codec.id] != 0) { 2170 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; 2171 } 2172 } 2173 2174 return video_codecs; 2175} 2176 2177} // namespace cricket 2178 2179#endif // HAVE_WEBRTC_VIDEO 2180