webrtcvideoengine2.cc revision 1ecbe45c7e4c9142896cb2810d699558518f4f28
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 <set> 32#include <string> 33 34#include "libyuv/convert_from.h" 35#include "talk/media/base/videocapturer.h" 36#include "talk/media/base/videorenderer.h" 37#include "talk/media/webrtc/constants.h" 38#include "talk/media/webrtc/webrtcvideocapturer.h" 39#include "talk/media/webrtc/webrtcvideoframe.h" 40#include "talk/media/webrtc/webrtcvoiceengine.h" 41#include "webrtc/base/buffer.h" 42#include "webrtc/base/logging.h" 43#include "webrtc/base/stringutils.h" 44#include "webrtc/call.h" 45#include "webrtc/video_encoder.h" 46 47#define UNIMPLEMENTED \ 48 LOG(LS_ERROR) << "Call to unimplemented function " << __FUNCTION__; \ 49 ASSERT(false) 50 51namespace cricket { 52namespace { 53 54static bool CodecNameMatches(const std::string& name1, 55 const std::string& name2) { 56 return _stricmp(name1.c_str(), name2.c_str()) == 0; 57} 58 59// True if codec is supported by a software implementation that's always 60// available. 61static bool CodecIsInternallySupported(const std::string& codec_name) { 62 return CodecNameMatches(codec_name, kVp8CodecName); 63} 64 65static std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) { 66 std::stringstream out; 67 out << '{'; 68 for (size_t i = 0; i < codecs.size(); ++i) { 69 out << codecs[i].ToString(); 70 if (i != codecs.size() - 1) { 71 out << ", "; 72 } 73 } 74 out << '}'; 75 return out.str(); 76} 77 78static bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) { 79 bool has_video = false; 80 for (size_t i = 0; i < codecs.size(); ++i) { 81 if (!codecs[i].ValidateCodecFormat()) { 82 return false; 83 } 84 if (codecs[i].GetCodecType() == VideoCodec::CODEC_VIDEO) { 85 has_video = true; 86 } 87 } 88 if (!has_video) { 89 LOG(LS_ERROR) << "Setting codecs without a video codec is invalid: " 90 << CodecVectorToString(codecs); 91 return false; 92 } 93 return true; 94} 95 96static std::string RtpExtensionsToString( 97 const std::vector<RtpHeaderExtension>& extensions) { 98 std::stringstream out; 99 out << '{'; 100 for (size_t i = 0; i < extensions.size(); ++i) { 101 out << "{" << extensions[i].uri << ": " << extensions[i].id << "}"; 102 if (i != extensions.size() - 1) { 103 out << ", "; 104 } 105 } 106 out << '}'; 107 return out.str(); 108} 109 110} // namespace 111 112// This constant is really an on/off, lower-level configurable NACK history 113// duration hasn't been implemented. 114static const int kNackHistoryMs = 1000; 115 116static const int kDefaultQpMax = 56; 117 118static const int kDefaultRtcpReceiverReportSsrc = 1; 119 120// External video encoders are given payloads 120-127. This also means that we 121// only support up to 8 external payload types. 122static const int kExternalVideoPayloadTypeBase = 120; 123#ifndef NDEBUG 124static const size_t kMaxExternalVideoCodecs = 8; 125#endif 126 127struct VideoCodecPref { 128 int payload_type; 129 int width; 130 int height; 131 const char* name; 132 int rtx_payload_type; 133} kDefaultVideoCodecPref = {100, 640, 400, kVp8CodecName, 96}; 134 135const char kH264CodecName[] = "H264"; 136 137VideoCodecPref kRedPref = {116, -1, -1, kRedCodecName, -1}; 138VideoCodecPref kUlpfecPref = {117, -1, -1, kUlpfecCodecName, -1}; 139 140static bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs, 141 const VideoCodec& requested_codec, 142 VideoCodec* matching_codec) { 143 for (size_t i = 0; i < codecs.size(); ++i) { 144 if (requested_codec.Matches(codecs[i])) { 145 *matching_codec = codecs[i]; 146 return true; 147 } 148 } 149 return false; 150} 151 152static void AddDefaultFeedbackParams(VideoCodec* codec) { 153 const FeedbackParam kFir(kRtcpFbParamCcm, kRtcpFbCcmParamFir); 154 codec->AddFeedbackParam(kFir); 155 const FeedbackParam kNack(kRtcpFbParamNack, kParamValueEmpty); 156 codec->AddFeedbackParam(kNack); 157 const FeedbackParam kPli(kRtcpFbParamNack, kRtcpFbNackParamPli); 158 codec->AddFeedbackParam(kPli); 159 const FeedbackParam kRemb(kRtcpFbParamRemb, kParamValueEmpty); 160 codec->AddFeedbackParam(kRemb); 161} 162 163static bool IsNackEnabled(const VideoCodec& codec) { 164 return codec.HasFeedbackParam( 165 FeedbackParam(kRtcpFbParamNack, kParamValueEmpty)); 166} 167 168static bool IsRembEnabled(const VideoCodec& codec) { 169 return codec.HasFeedbackParam( 170 FeedbackParam(kRtcpFbParamRemb, kParamValueEmpty)); 171} 172 173static VideoCodec DefaultVideoCodec() { 174 VideoCodec default_codec(kDefaultVideoCodecPref.payload_type, 175 kDefaultVideoCodecPref.name, 176 kDefaultVideoCodecPref.width, 177 kDefaultVideoCodecPref.height, 178 kDefaultFramerate, 179 0); 180 AddDefaultFeedbackParams(&default_codec); 181 return default_codec; 182} 183 184static VideoCodec DefaultRedCodec() { 185 return VideoCodec(kRedPref.payload_type, kRedPref.name, 0, 0, 0, 0); 186} 187 188static VideoCodec DefaultUlpfecCodec() { 189 return VideoCodec(kUlpfecPref.payload_type, kUlpfecPref.name, 0, 0, 0, 0); 190} 191 192static std::vector<VideoCodec> DefaultVideoCodecs() { 193 std::vector<VideoCodec> codecs; 194 codecs.push_back(DefaultVideoCodec()); 195 codecs.push_back(DefaultRedCodec()); 196 codecs.push_back(DefaultUlpfecCodec()); 197 if (kDefaultVideoCodecPref.rtx_payload_type != -1) { 198 codecs.push_back( 199 VideoCodec::CreateRtxCodec(kDefaultVideoCodecPref.rtx_payload_type, 200 kDefaultVideoCodecPref.payload_type)); 201 } 202 return codecs; 203} 204 205static bool ValidateRtpHeaderExtensionIds( 206 const std::vector<RtpHeaderExtension>& extensions) { 207 std::set<int> extensions_used; 208 for (size_t i = 0; i < extensions.size(); ++i) { 209 if (extensions[i].id < 0 || extensions[i].id >= 15 || 210 !extensions_used.insert(extensions[i].id).second) { 211 LOG(LS_ERROR) << "RTP extensions are with incorrect or duplicate ids."; 212 return false; 213 } 214 } 215 return true; 216} 217 218static std::vector<webrtc::RtpExtension> FilterRtpExtensions( 219 const std::vector<RtpHeaderExtension>& extensions) { 220 std::vector<webrtc::RtpExtension> webrtc_extensions; 221 for (size_t i = 0; i < extensions.size(); ++i) { 222 // Unsupported extensions will be ignored. 223 if (webrtc::RtpExtension::IsSupported(extensions[i].uri)) { 224 webrtc_extensions.push_back(webrtc::RtpExtension( 225 extensions[i].uri, extensions[i].id)); 226 } else { 227 LOG(LS_WARNING) << "Unsupported RTP extension: " << extensions[i].uri; 228 } 229 } 230 return webrtc_extensions; 231} 232 233WebRtcVideoEncoderFactory2::~WebRtcVideoEncoderFactory2() { 234} 235 236std::vector<webrtc::VideoStream> WebRtcVideoEncoderFactory2::CreateVideoStreams( 237 const VideoCodec& codec, 238 const VideoOptions& options, 239 size_t num_streams) { 240 if (num_streams != 1) { 241 LOG(LS_ERROR) << "Unsupported number of streams: " << num_streams; 242 return std::vector<webrtc::VideoStream>(); 243 } 244 245 webrtc::VideoStream stream; 246 stream.width = codec.width; 247 stream.height = codec.height; 248 stream.max_framerate = 249 codec.framerate != 0 ? codec.framerate : kDefaultFramerate; 250 251 int min_bitrate = kMinVideoBitrate; 252 codec.GetParam(kCodecParamMinBitrate, &min_bitrate); 253 int max_bitrate = kMaxVideoBitrate; 254 codec.GetParam(kCodecParamMaxBitrate, &max_bitrate); 255 stream.min_bitrate_bps = min_bitrate * 1000; 256 stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate * 1000; 257 258 int max_qp = kDefaultQpMax; 259 codec.GetParam(kCodecParamMaxQuantization, &max_qp); 260 stream.max_qp = max_qp; 261 std::vector<webrtc::VideoStream> streams; 262 streams.push_back(stream); 263 return streams; 264} 265 266void* WebRtcVideoEncoderFactory2::CreateVideoEncoderSettings( 267 const VideoCodec& codec, 268 const VideoOptions& options) { 269 if (CodecNameMatches(codec.name, kVp8CodecName)) { 270 webrtc::VideoCodecVP8* settings = new webrtc::VideoCodecVP8( 271 webrtc::VideoEncoder::GetDefaultVp8Settings()); 272 options.video_noise_reduction.Get(&settings->denoisingOn); 273 return settings; 274 } 275 return NULL; 276} 277 278void WebRtcVideoEncoderFactory2::DestroyVideoEncoderSettings( 279 const VideoCodec& codec, 280 void* encoder_settings) { 281 if (encoder_settings == NULL) { 282 return; 283 } 284 if (CodecNameMatches(codec.name, kVp8CodecName)) { 285 delete reinterpret_cast<webrtc::VideoCodecVP8*>(encoder_settings); 286 } 287} 288 289DefaultUnsignalledSsrcHandler::DefaultUnsignalledSsrcHandler() 290 : default_recv_ssrc_(0), default_renderer_(NULL) {} 291 292UnsignalledSsrcHandler::Action DefaultUnsignalledSsrcHandler::OnUnsignalledSsrc( 293 VideoMediaChannel* channel, 294 uint32_t ssrc) { 295 if (default_recv_ssrc_ != 0) { // Already one default stream. 296 LOG(LS_WARNING) << "Unknown SSRC, but default receive stream already set."; 297 return kDropPacket; 298 } 299 300 StreamParams sp; 301 sp.ssrcs.push_back(ssrc); 302 LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << "."; 303 if (!channel->AddRecvStream(sp)) { 304 LOG(LS_WARNING) << "Could not create default receive stream."; 305 } 306 307 channel->SetRenderer(ssrc, default_renderer_); 308 default_recv_ssrc_ = ssrc; 309 return kDeliverPacket; 310} 311 312WebRtcCallFactory::~WebRtcCallFactory() { 313} 314webrtc::Call* WebRtcCallFactory::CreateCall( 315 const webrtc::Call::Config& config) { 316 return webrtc::Call::Create(config); 317} 318 319VideoRenderer* DefaultUnsignalledSsrcHandler::GetDefaultRenderer() const { 320 return default_renderer_; 321} 322 323void DefaultUnsignalledSsrcHandler::SetDefaultRenderer( 324 VideoMediaChannel* channel, 325 VideoRenderer* renderer) { 326 default_renderer_ = renderer; 327 if (default_recv_ssrc_ != 0) { 328 channel->SetRenderer(default_recv_ssrc_, default_renderer_); 329 } 330} 331 332WebRtcVideoEngine2::WebRtcVideoEngine2() 333 : worker_thread_(NULL), 334 voice_engine_(NULL), 335 default_codec_format_(kDefaultVideoCodecPref.width, 336 kDefaultVideoCodecPref.height, 337 FPS_TO_INTERVAL(kDefaultFramerate), 338 FOURCC_ANY), 339 initialized_(false), 340 cpu_monitor_(new rtc::CpuMonitor(NULL)), 341 call_factory_(&default_call_factory_), 342 external_decoder_factory_(NULL), 343 external_encoder_factory_(NULL) { 344 LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()"; 345 video_codecs_ = GetSupportedCodecs(); 346 rtp_header_extensions_.push_back( 347 RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 348 kRtpTimestampOffsetHeaderExtensionDefaultId)); 349 rtp_header_extensions_.push_back( 350 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 351 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); 352} 353 354WebRtcVideoEngine2::~WebRtcVideoEngine2() { 355 LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2"; 356 357 if (initialized_) { 358 Terminate(); 359 } 360} 361 362void WebRtcVideoEngine2::SetCallFactory(WebRtcCallFactory* call_factory) { 363 assert(!initialized_); 364 call_factory_ = call_factory; 365} 366 367bool WebRtcVideoEngine2::Init(rtc::Thread* worker_thread) { 368 LOG(LS_INFO) << "WebRtcVideoEngine2::Init"; 369 worker_thread_ = worker_thread; 370 ASSERT(worker_thread_ != NULL); 371 372 cpu_monitor_->set_thread(worker_thread_); 373 if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) { 374 LOG(LS_ERROR) << "Failed to start CPU monitor."; 375 cpu_monitor_.reset(); 376 } 377 378 initialized_ = true; 379 return true; 380} 381 382void WebRtcVideoEngine2::Terminate() { 383 LOG(LS_INFO) << "WebRtcVideoEngine2::Terminate"; 384 385 cpu_monitor_->Stop(); 386 387 initialized_ = false; 388} 389 390int WebRtcVideoEngine2::GetCapabilities() { return VIDEO_RECV | VIDEO_SEND; } 391 392bool WebRtcVideoEngine2::SetDefaultEncoderConfig( 393 const VideoEncoderConfig& config) { 394 const VideoCodec& codec = config.max_codec; 395 // TODO(pbos): Make use of external encoder factory. 396 if (!CodecIsInternallySupported(codec.name)) { 397 LOG(LS_ERROR) << "SetDefaultEncoderConfig, codec not supported:" 398 << codec.ToString(); 399 return false; 400 } 401 402 default_codec_format_ = 403 VideoFormat(codec.width, 404 codec.height, 405 VideoFormat::FpsToInterval(codec.framerate), 406 FOURCC_ANY); 407 video_codecs_.clear(); 408 video_codecs_.push_back(codec); 409 return true; 410} 411 412VideoEncoderConfig WebRtcVideoEngine2::GetDefaultEncoderConfig() const { 413 return VideoEncoderConfig(DefaultVideoCodec()); 414} 415 416WebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel( 417 const VideoOptions& options, 418 VoiceMediaChannel* voice_channel) { 419 assert(initialized_); 420 LOG(LS_INFO) << "CreateChannel: " 421 << (voice_channel != NULL ? "With" : "Without") 422 << " voice channel."; 423 WebRtcVideoChannel2* channel = 424 new WebRtcVideoChannel2(call_factory_, 425 voice_channel, 426 external_encoder_factory_, 427 external_decoder_factory_, 428 GetVideoEncoderFactory()); 429 if (!channel->Init()) { 430 delete channel; 431 return NULL; 432 } 433 channel->SetOptions(options); 434 channel->SetRecvCodecs(video_codecs_); 435 return channel; 436} 437 438const std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const { 439 return video_codecs_; 440} 441 442const std::vector<RtpHeaderExtension>& 443WebRtcVideoEngine2::rtp_header_extensions() const { 444 return rtp_header_extensions_; 445} 446 447void WebRtcVideoEngine2::SetLogging(int min_sev, const char* filter) { 448 // TODO(pbos): Set up logging. 449 LOG(LS_VERBOSE) << "SetLogging: " << min_sev << '"' << filter << '"'; 450 // if min_sev == -1, we keep the current log level. 451 if (min_sev < 0) { 452 assert(min_sev == -1); 453 return; 454 } 455} 456 457void WebRtcVideoEngine2::SetExternalDecoderFactory( 458 WebRtcVideoDecoderFactory* decoder_factory) { 459 assert(!initialized_); 460 external_decoder_factory_ = decoder_factory; 461} 462 463void WebRtcVideoEngine2::SetExternalEncoderFactory( 464 WebRtcVideoEncoderFactory* encoder_factory) { 465 assert(!initialized_); 466 external_encoder_factory_ = encoder_factory; 467 468 video_codecs_ = GetSupportedCodecs(); 469} 470 471bool WebRtcVideoEngine2::EnableTimedRender() { 472 // TODO(pbos): Figure out whether this can be removed. 473 return true; 474} 475 476// Checks to see whether we comprehend and could receive a particular codec 477bool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) { 478 // TODO(pbos): Probe encoder factory to figure out that the codec is supported 479 // if supported by the encoder factory. Add a corresponding test that fails 480 // with this code (that doesn't ask the factory). 481 for (size_t j = 0; j < video_codecs_.size(); ++j) { 482 VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0); 483 if (codec.Matches(in)) { 484 return true; 485 } 486 } 487 return false; 488} 489 490// Tells whether the |requested| codec can be transmitted or not. If it can be 491// transmitted |out| is set with the best settings supported. Aspect ratio will 492// be set as close to |current|'s as possible. If not set |requested|'s 493// dimensions will be used for aspect ratio matching. 494bool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested, 495 const VideoCodec& current, 496 VideoCodec* out) { 497 assert(out != NULL); 498 499 if (requested.width != requested.height && 500 (requested.height == 0 || requested.width == 0)) { 501 // 0xn and nx0 are invalid resolutions. 502 return false; 503 } 504 505 VideoCodec matching_codec; 506 if (!FindFirstMatchingCodec(video_codecs_, requested, &matching_codec)) { 507 // Codec not supported. 508 return false; 509 } 510 511 out->id = requested.id; 512 out->name = requested.name; 513 out->preference = requested.preference; 514 out->params = requested.params; 515 out->framerate = 516 rtc::_min(requested.framerate, matching_codec.framerate); 517 out->params = requested.params; 518 out->feedback_params = requested.feedback_params; 519 out->width = requested.width; 520 out->height = requested.height; 521 if (requested.width == 0 && requested.height == 0) { 522 return true; 523 } 524 525 while (out->width > matching_codec.width) { 526 out->width /= 2; 527 out->height /= 2; 528 } 529 530 return out->width > 0 && out->height > 0; 531} 532 533bool WebRtcVideoEngine2::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) { 534 if (initialized_) { 535 LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init"; 536 return false; 537 } 538 voice_engine_ = voice_engine; 539 return true; 540} 541 542// Ignore spammy trace messages, mostly from the stats API when we haven't 543// gotten RTCP info yet from the remote side. 544bool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) { 545 static const char* const kTracesToIgnore[] = {NULL}; 546 for (const char* const* p = kTracesToIgnore; *p; ++p) { 547 if (trace.find(*p) == 0) { 548 return true; 549 } 550 } 551 return false; 552} 553 554WebRtcVideoEncoderFactory2* WebRtcVideoEngine2::GetVideoEncoderFactory() { 555 return &default_video_encoder_factory_; 556} 557 558std::vector<VideoCodec> WebRtcVideoEngine2::GetSupportedCodecs() const { 559 std::vector<VideoCodec> supported_codecs = DefaultVideoCodecs(); 560 561 if (external_encoder_factory_ == NULL) { 562 return supported_codecs; 563 } 564 565 assert(external_encoder_factory_->codecs().size() <= kMaxExternalVideoCodecs); 566 const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs = 567 external_encoder_factory_->codecs(); 568 for (size_t i = 0; i < codecs.size(); ++i) { 569 // Don't add internally-supported codecs twice. 570 if (CodecIsInternallySupported(codecs[i].name)) { 571 continue; 572 } 573 574 VideoCodec codec(kExternalVideoPayloadTypeBase + static_cast<int>(i), 575 codecs[i].name, 576 codecs[i].max_width, 577 codecs[i].max_height, 578 codecs[i].max_fps, 579 0); 580 581 AddDefaultFeedbackParams(&codec); 582 supported_codecs.push_back(codec); 583 } 584 return supported_codecs; 585} 586 587// Thin map between VideoFrame and an existing webrtc::I420VideoFrame 588// to avoid having to copy the rendered VideoFrame prematurely. 589// This implementation is only safe to use in a const context and should never 590// be written to. 591class WebRtcVideoRenderFrame : public VideoFrame { 592 public: 593 explicit WebRtcVideoRenderFrame(const webrtc::I420VideoFrame* frame) 594 : frame_(frame) {} 595 596 virtual bool InitToBlack(int w, 597 int h, 598 size_t pixel_width, 599 size_t pixel_height, 600 int64 elapsed_time, 601 int64 time_stamp) OVERRIDE { 602 UNIMPLEMENTED; 603 return false; 604 } 605 606 virtual bool Reset(uint32 fourcc, 607 int w, 608 int h, 609 int dw, 610 int dh, 611 uint8* sample, 612 size_t sample_size, 613 size_t pixel_width, 614 size_t pixel_height, 615 int64 elapsed_time, 616 int64 time_stamp, 617 int rotation) OVERRIDE { 618 UNIMPLEMENTED; 619 return false; 620 } 621 622 virtual size_t GetWidth() const OVERRIDE { 623 return static_cast<size_t>(frame_->width()); 624 } 625 virtual size_t GetHeight() const OVERRIDE { 626 return static_cast<size_t>(frame_->height()); 627 } 628 629 virtual const uint8* GetYPlane() const OVERRIDE { 630 return frame_->buffer(webrtc::kYPlane); 631 } 632 virtual const uint8* GetUPlane() const OVERRIDE { 633 return frame_->buffer(webrtc::kUPlane); 634 } 635 virtual const uint8* GetVPlane() const OVERRIDE { 636 return frame_->buffer(webrtc::kVPlane); 637 } 638 639 virtual uint8* GetYPlane() OVERRIDE { 640 UNIMPLEMENTED; 641 return NULL; 642 } 643 virtual uint8* GetUPlane() OVERRIDE { 644 UNIMPLEMENTED; 645 return NULL; 646 } 647 virtual uint8* GetVPlane() OVERRIDE { 648 UNIMPLEMENTED; 649 return NULL; 650 } 651 652 virtual int32 GetYPitch() const OVERRIDE { 653 return frame_->stride(webrtc::kYPlane); 654 } 655 virtual int32 GetUPitch() const OVERRIDE { 656 return frame_->stride(webrtc::kUPlane); 657 } 658 virtual int32 GetVPitch() const OVERRIDE { 659 return frame_->stride(webrtc::kVPlane); 660 } 661 662 virtual void* GetNativeHandle() const OVERRIDE { return NULL; } 663 664 virtual size_t GetPixelWidth() const OVERRIDE { return 1; } 665 virtual size_t GetPixelHeight() const OVERRIDE { return 1; } 666 667 virtual int64 GetElapsedTime() const OVERRIDE { 668 // Convert millisecond render time to ns timestamp. 669 return frame_->render_time_ms() * rtc::kNumNanosecsPerMillisec; 670 } 671 virtual int64 GetTimeStamp() const OVERRIDE { 672 // Convert 90K rtp timestamp to ns timestamp. 673 return (frame_->timestamp() / 90) * rtc::kNumNanosecsPerMillisec; 674 } 675 virtual void SetElapsedTime(int64 elapsed_time) OVERRIDE { UNIMPLEMENTED; } 676 virtual void SetTimeStamp(int64 time_stamp) OVERRIDE { UNIMPLEMENTED; } 677 678 virtual int GetRotation() const OVERRIDE { 679 UNIMPLEMENTED; 680 return ROTATION_0; 681 } 682 683 virtual VideoFrame* Copy() const OVERRIDE { 684 UNIMPLEMENTED; 685 return NULL; 686 } 687 688 virtual bool MakeExclusive() OVERRIDE { 689 UNIMPLEMENTED; 690 return false; 691 } 692 693 virtual size_t CopyToBuffer(uint8* buffer, size_t size) const { 694 UNIMPLEMENTED; 695 return 0; 696 } 697 698 // TODO(fbarchard): Refactor into base class and share with LMI 699 virtual size_t ConvertToRgbBuffer(uint32 to_fourcc, 700 uint8* buffer, 701 size_t size, 702 int stride_rgb) const OVERRIDE { 703 size_t width = GetWidth(); 704 size_t height = GetHeight(); 705 size_t needed = (stride_rgb >= 0 ? stride_rgb : -stride_rgb) * height; 706 if (size < needed) { 707 LOG(LS_WARNING) << "RGB buffer is not large enough"; 708 return needed; 709 } 710 711 if (libyuv::ConvertFromI420(GetYPlane(), 712 GetYPitch(), 713 GetUPlane(), 714 GetUPitch(), 715 GetVPlane(), 716 GetVPitch(), 717 buffer, 718 stride_rgb, 719 static_cast<int>(width), 720 static_cast<int>(height), 721 to_fourcc)) { 722 LOG(LS_ERROR) << "RGB type not supported: " << to_fourcc; 723 return 0; // 0 indicates error 724 } 725 return needed; 726 } 727 728 protected: 729 virtual VideoFrame* CreateEmptyFrame(int w, 730 int h, 731 size_t pixel_width, 732 size_t pixel_height, 733 int64 elapsed_time, 734 int64 time_stamp) const OVERRIDE { 735 WebRtcVideoFrame* frame = new WebRtcVideoFrame(); 736 frame->InitToBlack( 737 w, h, pixel_width, pixel_height, elapsed_time, time_stamp); 738 return frame; 739 } 740 741 private: 742 const webrtc::I420VideoFrame* const frame_; 743}; 744 745WebRtcVideoChannel2::WebRtcVideoChannel2( 746 WebRtcCallFactory* call_factory, 747 VoiceMediaChannel* voice_channel, 748 WebRtcVideoEncoderFactory* external_encoder_factory, 749 WebRtcVideoDecoderFactory* external_decoder_factory, 750 WebRtcVideoEncoderFactory2* encoder_factory) 751 : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_), 752 external_encoder_factory_(external_encoder_factory), 753 external_decoder_factory_(external_decoder_factory), 754 encoder_factory_(encoder_factory) { 755 // TODO(pbos): Connect the video and audio with |voice_channel|. 756 webrtc::Call::Config config(this); 757 config.overuse_callback = this; 758 call_.reset(call_factory->CreateCall(config)); 759 760 rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc; 761 sending_ = false; 762 default_send_ssrc_ = 0; 763 764 SetDefaultOptions(); 765} 766 767void WebRtcVideoChannel2::SetDefaultOptions() { 768 options_.cpu_overuse_detection.Set(false); 769 options_.suspend_below_min_bitrate.Set(false); 770 options_.use_payload_padding.Set(false); 771 options_.video_noise_reduction.Set(true); 772} 773 774WebRtcVideoChannel2::~WebRtcVideoChannel2() { 775 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 776 send_streams_.begin(); 777 it != send_streams_.end(); 778 ++it) { 779 delete it->second; 780 } 781 782 for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 783 receive_streams_.begin(); 784 it != receive_streams_.end(); 785 ++it) { 786 delete it->second; 787 } 788} 789 790bool WebRtcVideoChannel2::Init() { return true; } 791 792bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) { 793 LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs); 794 if (!ValidateCodecFormats(codecs)) { 795 return false; 796 } 797 798 const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs); 799 if (mapped_codecs.empty()) { 800 LOG(LS_ERROR) << "SetRecvCodecs called without video codec payloads."; 801 return false; 802 } 803 804 // TODO(pbos): Add a decoder factory which controls supported codecs. 805 // Blocked on webrtc:2854. 806 for (size_t i = 0; i < mapped_codecs.size(); ++i) { 807 if (!CodecNameMatches(mapped_codecs[i].codec.name, kVp8CodecName)) { 808 LOG(LS_ERROR) << "SetRecvCodecs called with unsupported codec: '" 809 << mapped_codecs[i].codec.name << "'"; 810 return false; 811 } 812 } 813 814 recv_codecs_ = mapped_codecs; 815 816 rtc::CritScope stream_lock(&stream_crit_); 817 for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 818 receive_streams_.begin(); 819 it != receive_streams_.end(); 820 ++it) { 821 it->second->SetRecvCodecs(recv_codecs_); 822 } 823 824 return true; 825} 826 827bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) { 828 LOG(LS_INFO) << "SetSendCodecs: " << CodecVectorToString(codecs); 829 if (!ValidateCodecFormats(codecs)) { 830 return false; 831 } 832 833 const std::vector<VideoCodecSettings> supported_codecs = 834 FilterSupportedCodecs(MapCodecs(codecs)); 835 836 if (supported_codecs.empty()) { 837 LOG(LS_ERROR) << "No video codecs supported by encoder factory."; 838 return false; 839 } 840 841 send_codec_.Set(supported_codecs.front()); 842 LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString(); 843 844 rtc::CritScope stream_lock(&stream_crit_); 845 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 846 send_streams_.begin(); 847 it != send_streams_.end(); 848 ++it) { 849 assert(it->second != NULL); 850 it->second->SetCodec(supported_codecs.front()); 851 } 852 853 return true; 854} 855 856bool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) { 857 VideoCodecSettings codec_settings; 858 if (!send_codec_.Get(&codec_settings)) { 859 LOG(LS_VERBOSE) << "GetSendCodec: No send codec set."; 860 return false; 861 } 862 *codec = codec_settings.codec; 863 return true; 864} 865 866bool WebRtcVideoChannel2::SetSendStreamFormat(uint32 ssrc, 867 const VideoFormat& format) { 868 LOG(LS_VERBOSE) << "SetSendStreamFormat:" << ssrc << " -> " 869 << format.ToString(); 870 rtc::CritScope stream_lock(&stream_crit_); 871 if (send_streams_.find(ssrc) == send_streams_.end()) { 872 return false; 873 } 874 return send_streams_[ssrc]->SetVideoFormat(format); 875} 876 877bool WebRtcVideoChannel2::SetRender(bool render) { 878 // TODO(pbos): Implement. Or refactor away as it shouldn't be needed. 879 LOG(LS_VERBOSE) << "SetRender: " << (render ? "true" : "false"); 880 return true; 881} 882 883bool WebRtcVideoChannel2::SetSend(bool send) { 884 LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false"); 885 if (send && !send_codec_.IsSet()) { 886 LOG(LS_ERROR) << "SetSend(true) called before setting codec."; 887 return false; 888 } 889 if (send) { 890 StartAllSendStreams(); 891 } else { 892 StopAllSendStreams(); 893 } 894 sending_ = send; 895 return true; 896} 897 898bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) { 899 LOG(LS_INFO) << "AddSendStream: " << sp.ToString(); 900 if (sp.ssrcs.empty()) { 901 LOG(LS_ERROR) << "No SSRCs in stream parameters."; 902 return false; 903 } 904 905 uint32 ssrc = sp.first_ssrc(); 906 assert(ssrc != 0); 907 // TODO(pbos): Make sure none of sp.ssrcs are used, not just the identifying 908 // ssrc. 909 rtc::CritScope stream_lock(&stream_crit_); 910 if (send_streams_.find(ssrc) != send_streams_.end()) { 911 LOG(LS_ERROR) << "Send stream with ssrc '" << ssrc << "' already exists."; 912 return false; 913 } 914 915 std::vector<uint32> primary_ssrcs; 916 sp.GetPrimarySsrcs(&primary_ssrcs); 917 std::vector<uint32> rtx_ssrcs; 918 sp.GetFidSsrcs(primary_ssrcs, &rtx_ssrcs); 919 if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) { 920 LOG(LS_ERROR) 921 << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): " 922 << sp.ToString(); 923 return false; 924 } 925 926 WebRtcVideoSendStream* stream = 927 new WebRtcVideoSendStream(call_.get(), 928 external_encoder_factory_, 929 encoder_factory_, 930 options_, 931 send_codec_, 932 sp, 933 send_rtp_extensions_); 934 935 send_streams_[ssrc] = stream; 936 937 if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) { 938 rtcp_receiver_report_ssrc_ = ssrc; 939 } 940 if (default_send_ssrc_ == 0) { 941 default_send_ssrc_ = ssrc; 942 } 943 if (sending_) { 944 stream->Start(); 945 } 946 947 return true; 948} 949 950bool WebRtcVideoChannel2::RemoveSendStream(uint32 ssrc) { 951 LOG(LS_INFO) << "RemoveSendStream: " << ssrc; 952 953 if (ssrc == 0) { 954 if (default_send_ssrc_ == 0) { 955 LOG(LS_ERROR) << "No default send stream active."; 956 return false; 957 } 958 959 LOG(LS_VERBOSE) << "Removing default stream: " << default_send_ssrc_; 960 ssrc = default_send_ssrc_; 961 } 962 963 WebRtcVideoSendStream* removed_stream; 964 { 965 rtc::CritScope stream_lock(&stream_crit_); 966 std::map<uint32, WebRtcVideoSendStream*>::iterator it = 967 send_streams_.find(ssrc); 968 if (it == send_streams_.end()) { 969 return false; 970 } 971 972 removed_stream = it->second; 973 send_streams_.erase(it); 974 } 975 976 delete removed_stream; 977 978 if (ssrc == default_send_ssrc_) { 979 default_send_ssrc_ = 0; 980 } 981 982 return true; 983} 984 985bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) { 986 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString(); 987 assert(sp.ssrcs.size() > 0); 988 989 uint32 ssrc = sp.first_ssrc(); 990 assert(ssrc != 0); // TODO(pbos): Is this ever valid? 991 992 // TODO(pbos): Check if any of the SSRCs overlap. 993 rtc::CritScope stream_lock(&stream_crit_); 994 if (receive_streams_.find(ssrc) != receive_streams_.end()) { 995 LOG(LS_ERROR) << "Receive stream for SSRC " << ssrc << "already exists."; 996 return false; 997 } 998 999 webrtc::VideoReceiveStream::Config config; 1000 ConfigureReceiverRtp(&config, sp); 1001 receive_streams_[ssrc] = 1002 new WebRtcVideoReceiveStream(call_.get(), config, recv_codecs_); 1003 1004 return true; 1005} 1006 1007void WebRtcVideoChannel2::ConfigureReceiverRtp( 1008 webrtc::VideoReceiveStream::Config* config, 1009 const StreamParams& sp) const { 1010 uint32 ssrc = sp.first_ssrc(); 1011 1012 config->rtp.remote_ssrc = ssrc; 1013 config->rtp.local_ssrc = rtcp_receiver_report_ssrc_; 1014 1015 config->rtp.extensions = recv_rtp_extensions_; 1016 1017 // TODO(pbos): This protection is against setting the same local ssrc as 1018 // remote which is not permitted by the lower-level API. RTCP requires a 1019 // corresponding sender SSRC. Figure out what to do when we don't have 1020 // (receive-only) or know a good local SSRC. 1021 if (config->rtp.remote_ssrc == config->rtp.local_ssrc) { 1022 if (config->rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) { 1023 config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc; 1024 } else { 1025 config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1; 1026 } 1027 } 1028 1029 for (size_t i = 0; i < recv_codecs_.size(); ++i) { 1030 if (recv_codecs_[i].codec.id == kDefaultVideoCodecPref.payload_type) { 1031 config->rtp.fec = recv_codecs_[i].fec; 1032 uint32 rtx_ssrc; 1033 if (recv_codecs_[i].rtx_payload_type != -1 && 1034 sp.GetFidSsrc(ssrc, &rtx_ssrc)) { 1035 config->rtp.rtx[kDefaultVideoCodecPref.payload_type].ssrc = rtx_ssrc; 1036 config->rtp.rtx[kDefaultVideoCodecPref.payload_type].payload_type = 1037 recv_codecs_[i].rtx_payload_type; 1038 } 1039 break; 1040 } 1041 } 1042 1043} 1044 1045bool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) { 1046 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; 1047 if (ssrc == 0) { 1048 LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported."; 1049 return false; 1050 } 1051 1052 rtc::CritScope stream_lock(&stream_crit_); 1053 std::map<uint32, WebRtcVideoReceiveStream*>::iterator stream = 1054 receive_streams_.find(ssrc); 1055 if (stream == receive_streams_.end()) { 1056 LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc; 1057 return false; 1058 } 1059 delete stream->second; 1060 receive_streams_.erase(stream); 1061 1062 return true; 1063} 1064 1065bool WebRtcVideoChannel2::SetRenderer(uint32 ssrc, VideoRenderer* renderer) { 1066 LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " " 1067 << (renderer ? "(ptr)" : "NULL"); 1068 if (ssrc == 0) { 1069 default_unsignalled_ssrc_handler_.SetDefaultRenderer(this, renderer); 1070 return true; 1071 } 1072 1073 rtc::CritScope stream_lock(&stream_crit_); 1074 std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 1075 receive_streams_.find(ssrc); 1076 if (it == receive_streams_.end()) { 1077 return false; 1078 } 1079 1080 it->second->SetRenderer(renderer); 1081 return true; 1082} 1083 1084bool WebRtcVideoChannel2::GetRenderer(uint32 ssrc, VideoRenderer** renderer) { 1085 if (ssrc == 0) { 1086 *renderer = default_unsignalled_ssrc_handler_.GetDefaultRenderer(); 1087 return *renderer != NULL; 1088 } 1089 1090 rtc::CritScope stream_lock(&stream_crit_); 1091 std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 1092 receive_streams_.find(ssrc); 1093 if (it == receive_streams_.end()) { 1094 return false; 1095 } 1096 *renderer = it->second->GetRenderer(); 1097 return true; 1098} 1099 1100bool WebRtcVideoChannel2::GetStats(const StatsOptions& options, 1101 VideoMediaInfo* info) { 1102 info->Clear(); 1103 FillSenderStats(info); 1104 FillReceiverStats(info); 1105 FillBandwidthEstimationStats(info); 1106 return true; 1107} 1108 1109void WebRtcVideoChannel2::FillSenderStats(VideoMediaInfo* video_media_info) { 1110 rtc::CritScope stream_lock(&stream_crit_); 1111 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 1112 send_streams_.begin(); 1113 it != send_streams_.end(); 1114 ++it) { 1115 video_media_info->senders.push_back(it->second->GetVideoSenderInfo()); 1116 } 1117} 1118 1119void WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) { 1120 rtc::CritScope stream_lock(&stream_crit_); 1121 for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 1122 receive_streams_.begin(); 1123 it != receive_streams_.end(); 1124 ++it) { 1125 video_media_info->receivers.push_back(it->second->GetVideoReceiverInfo()); 1126 } 1127} 1128 1129void WebRtcVideoChannel2::FillBandwidthEstimationStats( 1130 VideoMediaInfo* video_media_info) { 1131 // TODO(pbos): Implement. 1132} 1133 1134bool WebRtcVideoChannel2::SetCapturer(uint32 ssrc, VideoCapturer* capturer) { 1135 LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> " 1136 << (capturer != NULL ? "(capturer)" : "NULL"); 1137 assert(ssrc != 0); 1138 rtc::CritScope stream_lock(&stream_crit_); 1139 if (send_streams_.find(ssrc) == send_streams_.end()) { 1140 LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc; 1141 return false; 1142 } 1143 return send_streams_[ssrc]->SetCapturer(capturer); 1144} 1145 1146bool WebRtcVideoChannel2::SendIntraFrame() { 1147 // TODO(pbos): Implement. 1148 LOG(LS_VERBOSE) << "SendIntraFrame()."; 1149 return true; 1150} 1151 1152bool WebRtcVideoChannel2::RequestIntraFrame() { 1153 // TODO(pbos): Implement. 1154 LOG(LS_VERBOSE) << "SendIntraFrame()."; 1155 return true; 1156} 1157 1158void WebRtcVideoChannel2::OnPacketReceived( 1159 rtc::Buffer* packet, 1160 const rtc::PacketTime& packet_time) { 1161 const webrtc::PacketReceiver::DeliveryStatus delivery_result = 1162 call_->Receiver()->DeliverPacket( 1163 reinterpret_cast<const uint8_t*>(packet->data()), packet->length()); 1164 switch (delivery_result) { 1165 case webrtc::PacketReceiver::DELIVERY_OK: 1166 return; 1167 case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR: 1168 return; 1169 case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC: 1170 break; 1171 } 1172 1173 uint32 ssrc = 0; 1174 if (!GetRtpSsrc(packet->data(), packet->length(), &ssrc)) { 1175 return; 1176 } 1177 1178 // TODO(pbos): Make sure that the unsignalled SSRC uses the video payload. 1179 // Also figure out whether RTX needs to be handled. 1180 switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) { 1181 case UnsignalledSsrcHandler::kDropPacket: 1182 return; 1183 case UnsignalledSsrcHandler::kDeliverPacket: 1184 break; 1185 } 1186 1187 if (call_->Receiver()->DeliverPacket( 1188 reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) != 1189 webrtc::PacketReceiver::DELIVERY_OK) { 1190 LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery."; 1191 return; 1192 } 1193} 1194 1195void WebRtcVideoChannel2::OnRtcpReceived( 1196 rtc::Buffer* packet, 1197 const rtc::PacketTime& packet_time) { 1198 if (call_->Receiver()->DeliverPacket( 1199 reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) != 1200 webrtc::PacketReceiver::DELIVERY_OK) { 1201 LOG(LS_WARNING) << "Failed to deliver RTCP packet."; 1202 } 1203} 1204 1205void WebRtcVideoChannel2::OnReadyToSend(bool ready) { 1206 LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready."); 1207 call_->SignalNetworkState(ready ? webrtc::Call::kNetworkUp 1208 : webrtc::Call::kNetworkDown); 1209} 1210 1211bool WebRtcVideoChannel2::MuteStream(uint32 ssrc, bool mute) { 1212 LOG(LS_VERBOSE) << "MuteStream: " << ssrc << " -> " 1213 << (mute ? "mute" : "unmute"); 1214 assert(ssrc != 0); 1215 rtc::CritScope stream_lock(&stream_crit_); 1216 if (send_streams_.find(ssrc) == send_streams_.end()) { 1217 LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc; 1218 return false; 1219 } 1220 1221 send_streams_[ssrc]->MuteStream(mute); 1222 return true; 1223} 1224 1225bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions( 1226 const std::vector<RtpHeaderExtension>& extensions) { 1227 LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: " 1228 << RtpExtensionsToString(extensions); 1229 if (!ValidateRtpHeaderExtensionIds(extensions)) 1230 return false; 1231 1232 recv_rtp_extensions_ = FilterRtpExtensions(extensions); 1233 rtc::CritScope stream_lock(&stream_crit_); 1234 for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it = 1235 receive_streams_.begin(); 1236 it != receive_streams_.end(); 1237 ++it) { 1238 it->second->SetRtpExtensions(recv_rtp_extensions_); 1239 } 1240 return true; 1241} 1242 1243bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions( 1244 const std::vector<RtpHeaderExtension>& extensions) { 1245 LOG(LS_INFO) << "SetSendRtpHeaderExtensions: " 1246 << RtpExtensionsToString(extensions); 1247 if (!ValidateRtpHeaderExtensionIds(extensions)) 1248 return false; 1249 1250 send_rtp_extensions_ = FilterRtpExtensions(extensions); 1251 rtc::CritScope stream_lock(&stream_crit_); 1252 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 1253 send_streams_.begin(); 1254 it != send_streams_.end(); 1255 ++it) { 1256 it->second->SetRtpExtensions(send_rtp_extensions_); 1257 } 1258 return true; 1259} 1260 1261bool WebRtcVideoChannel2::SetMaxSendBandwidth(int bps) { 1262 // TODO(pbos): Implement. 1263 LOG(LS_VERBOSE) << "SetMaxSendBandwidth: " << bps; 1264 return true; 1265} 1266 1267bool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) { 1268 LOG(LS_VERBOSE) << "SetOptions: " << options.ToString(); 1269 options_.SetAll(options); 1270 rtc::CritScope stream_lock(&stream_crit_); 1271 for (std::map<uint32, WebRtcVideoSendStream*>::iterator it = 1272 send_streams_.begin(); 1273 it != send_streams_.end(); 1274 ++it) { 1275 it->second->SetOptions(options_); 1276 } 1277 return true; 1278} 1279 1280void WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) { 1281 MediaChannel::SetInterface(iface); 1282 // Set the RTP recv/send buffer to a bigger size 1283 MediaChannel::SetOption(NetworkInterface::ST_RTP, 1284 rtc::Socket::OPT_RCVBUF, 1285 kVideoRtpBufferSize); 1286 1287 // TODO(sriniv): Remove or re-enable this. 1288 // As part of b/8030474, send-buffer is size now controlled through 1289 // portallocator flags. 1290 // network_interface_->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 int width = format_.width; 1481 int height = format_.height; 1482 int half_width = (width + 1) / 2; 1483 black_frame.CreateEmptyFrame( 1484 width, height, width, half_width, half_width); 1485 SetWebRtcFrameToBlack(&black_frame); 1486 SetDimensions(width, height, false); 1487 stream_->Input()->SwapFrame(&black_frame); 1488 } 1489 1490 capturer_ = NULL; 1491 return true; 1492 } 1493 1494 capturer_ = capturer; 1495 } 1496 // Lock cannot be held while connecting the capturer to prevent lock-order 1497 // violations. 1498 capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame); 1499 return true; 1500} 1501 1502bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat( 1503 const VideoFormat& format) { 1504 if ((format.width == 0 || format.height == 0) && 1505 format.width != format.height) { 1506 LOG(LS_ERROR) << "Can't set VideoFormat, width or height is zero (but not " 1507 "both, 0x0 drops frames)."; 1508 return false; 1509 } 1510 1511 rtc::CritScope cs(&lock_); 1512 if (format.width == 0 && format.height == 0) { 1513 LOG(LS_INFO) 1514 << "0x0 resolution selected. Captured frames will be dropped for ssrc: " 1515 << parameters_.config.rtp.ssrcs[0] << "."; 1516 } else { 1517 // TODO(pbos): Fix me, this only affects the last stream! 1518 parameters_.encoder_config.streams.back().max_framerate = 1519 VideoFormat::IntervalToFps(format.interval); 1520 SetDimensions(format.width, format.height, false); 1521 } 1522 1523 format_ = format; 1524 return true; 1525} 1526 1527void WebRtcVideoChannel2::WebRtcVideoSendStream::MuteStream(bool mute) { 1528 rtc::CritScope cs(&lock_); 1529 muted_ = mute; 1530} 1531 1532bool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() { 1533 cricket::VideoCapturer* capturer; 1534 { 1535 rtc::CritScope cs(&lock_); 1536 if (capturer_ == NULL) { 1537 return false; 1538 } 1539 capturer = capturer_; 1540 capturer_ = NULL; 1541 } 1542 capturer->SignalVideoFrame.disconnect(this); 1543 return true; 1544} 1545 1546void WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions( 1547 const VideoOptions& options) { 1548 rtc::CritScope cs(&lock_); 1549 VideoCodecSettings codec_settings; 1550 if (parameters_.codec_settings.Get(&codec_settings)) { 1551 SetCodecAndOptions(codec_settings, options); 1552 } else { 1553 parameters_.options = options; 1554 } 1555} 1556 1557void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec( 1558 const VideoCodecSettings& codec_settings) { 1559 rtc::CritScope cs(&lock_); 1560 SetCodecAndOptions(codec_settings, parameters_.options); 1561} 1562 1563webrtc::VideoCodecType CodecTypeFromName(const std::string& name) { 1564 if (CodecNameMatches(name, kVp8CodecName)) { 1565 return webrtc::kVideoCodecVP8; 1566 } else if (CodecNameMatches(name, kH264CodecName)) { 1567 return webrtc::kVideoCodecH264; 1568 } 1569 return webrtc::kVideoCodecUnknown; 1570} 1571 1572WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder 1573WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder( 1574 const VideoCodec& codec) { 1575 webrtc::VideoCodecType type = CodecTypeFromName(codec.name); 1576 1577 // Do not re-create encoders of the same type. 1578 if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) { 1579 return allocated_encoder_; 1580 } 1581 1582 if (external_encoder_factory_ != NULL) { 1583 webrtc::VideoEncoder* encoder = 1584 external_encoder_factory_->CreateVideoEncoder(type); 1585 if (encoder != NULL) { 1586 return AllocatedEncoder(encoder, type, true); 1587 } 1588 } 1589 1590 if (type == webrtc::kVideoCodecVP8) { 1591 return AllocatedEncoder( 1592 webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp8), type, false); 1593 } 1594 1595 // This shouldn't happen, we should not be trying to create something we don't 1596 // support. 1597 assert(false); 1598 return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false); 1599} 1600 1601void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder( 1602 AllocatedEncoder* encoder) { 1603 if (encoder->external) { 1604 external_encoder_factory_->DestroyVideoEncoder(encoder->encoder); 1605 } else { 1606 delete encoder->encoder; 1607 } 1608} 1609 1610void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions( 1611 const VideoCodecSettings& codec_settings, 1612 const VideoOptions& options) { 1613 std::vector<webrtc::VideoStream> video_streams = 1614 encoder_factory_->CreateVideoStreams( 1615 codec_settings.codec, options, parameters_.config.rtp.ssrcs.size()); 1616 if (video_streams.empty()) { 1617 return; 1618 } 1619 parameters_.encoder_config.streams = video_streams; 1620 format_ = VideoFormat(codec_settings.codec.width, 1621 codec_settings.codec.height, 1622 VideoFormat::FpsToInterval(30), 1623 FOURCC_I420); 1624 1625 AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec); 1626 parameters_.config.encoder_settings.encoder = new_encoder.encoder; 1627 parameters_.config.encoder_settings.payload_name = codec_settings.codec.name; 1628 parameters_.config.encoder_settings.payload_type = codec_settings.codec.id; 1629 parameters_.config.rtp.fec = codec_settings.fec; 1630 1631 // Set RTX payload type if RTX is enabled. 1632 if (!parameters_.config.rtp.rtx.ssrcs.empty()) { 1633 parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type; 1634 1635 options.use_payload_padding.Get( 1636 ¶meters_.config.rtp.rtx.pad_with_redundant_payloads); 1637 } 1638 1639 if (IsNackEnabled(codec_settings.codec)) { 1640 parameters_.config.rtp.nack.rtp_history_ms = kNackHistoryMs; 1641 } 1642 1643 options.suspend_below_min_bitrate.Get( 1644 ¶meters_.config.suspend_below_min_bitrate); 1645 1646 parameters_.codec_settings.Set(codec_settings); 1647 parameters_.options = options; 1648 1649 RecreateWebRtcStream(); 1650 if (allocated_encoder_.encoder != new_encoder.encoder) { 1651 DestroyVideoEncoder(&allocated_encoder_); 1652 allocated_encoder_ = new_encoder; 1653 } 1654} 1655 1656void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions( 1657 const std::vector<webrtc::RtpExtension>& rtp_extensions) { 1658 rtc::CritScope cs(&lock_); 1659 parameters_.config.rtp.extensions = rtp_extensions; 1660 RecreateWebRtcStream(); 1661} 1662 1663void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions( 1664 int width, 1665 int height, 1666 bool override_max) { 1667 assert(!parameters_.encoder_config.streams.empty()); 1668 LOG(LS_VERBOSE) << "SetDimensions: " << width << "x" << height; 1669 1670 VideoCodecSettings codec_settings; 1671 parameters_.codec_settings.Get(&codec_settings); 1672 // Restrict dimensions according to codec max. 1673 if (!override_max) { 1674 if (codec_settings.codec.width < width) 1675 width = codec_settings.codec.width; 1676 if (codec_settings.codec.height < height) 1677 height = codec_settings.codec.height; 1678 } 1679 1680 if (parameters_.encoder_config.streams.back().width == width && 1681 parameters_.encoder_config.streams.back().height == height) { 1682 return; 1683 } 1684 1685 webrtc::VideoEncoderConfig encoder_config = parameters_.encoder_config; 1686 encoder_config.encoder_specific_settings = 1687 encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec, 1688 parameters_.options); 1689 1690 VideoCodec codec = codec_settings.codec; 1691 codec.width = width; 1692 codec.height = height; 1693 1694 encoder_config.streams = encoder_factory_->CreateVideoStreams( 1695 codec, parameters_.options, parameters_.config.rtp.ssrcs.size()); 1696 1697 bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config); 1698 1699 encoder_factory_->DestroyVideoEncoderSettings( 1700 codec_settings.codec, 1701 encoder_config.encoder_specific_settings); 1702 1703 encoder_config.encoder_specific_settings = NULL; 1704 1705 if (!stream_reconfigured) { 1706 LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: " 1707 << width << "x" << height; 1708 return; 1709 } 1710 1711 parameters_.encoder_config = encoder_config; 1712} 1713 1714void WebRtcVideoChannel2::WebRtcVideoSendStream::Start() { 1715 rtc::CritScope cs(&lock_); 1716 assert(stream_ != NULL); 1717 stream_->Start(); 1718 sending_ = true; 1719} 1720 1721void WebRtcVideoChannel2::WebRtcVideoSendStream::Stop() { 1722 rtc::CritScope cs(&lock_); 1723 if (stream_ != NULL) { 1724 stream_->Stop(); 1725 } 1726 sending_ = false; 1727} 1728 1729VideoSenderInfo 1730WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() { 1731 VideoSenderInfo info; 1732 rtc::CritScope cs(&lock_); 1733 for (size_t i = 0; i < parameters_.config.rtp.ssrcs.size(); ++i) { 1734 info.add_ssrc(parameters_.config.rtp.ssrcs[i]); 1735 } 1736 1737 if (stream_ == NULL) { 1738 return info; 1739 } 1740 1741 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); 1742 info.framerate_input = stats.input_frame_rate; 1743 info.framerate_sent = stats.encode_frame_rate; 1744 1745 for (std::map<uint32_t, webrtc::StreamStats>::iterator it = 1746 stats.substreams.begin(); 1747 it != stats.substreams.end(); 1748 ++it) { 1749 // TODO(pbos): Wire up additional stats, such as padding bytes. 1750 webrtc::StreamStats stream_stats = it->second; 1751 info.bytes_sent += stream_stats.rtp_stats.bytes + 1752 stream_stats.rtp_stats.header_bytes + 1753 stream_stats.rtp_stats.padding_bytes; 1754 info.packets_sent += stream_stats.rtp_stats.packets; 1755 info.packets_lost += stream_stats.rtcp_stats.cumulative_lost; 1756 } 1757 1758 if (!stats.substreams.empty()) { 1759 // TODO(pbos): Report fraction lost per SSRC. 1760 webrtc::StreamStats first_stream_stats = stats.substreams.begin()->second; 1761 info.fraction_lost = 1762 static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) / 1763 (1 << 8); 1764 } 1765 1766 if (capturer_ != NULL && !capturer_->IsMuted()) { 1767 VideoFormat last_captured_frame_format; 1768 capturer_->GetStats(&info.adapt_frame_drops, 1769 &info.effects_frame_drops, 1770 &info.capturer_frame_time, 1771 &last_captured_frame_format); 1772 info.input_frame_width = last_captured_frame_format.width; 1773 info.input_frame_height = last_captured_frame_format.height; 1774 info.send_frame_width = 1775 static_cast<int>(parameters_.encoder_config.streams.front().width); 1776 info.send_frame_height = 1777 static_cast<int>(parameters_.encoder_config.streams.front().height); 1778 } 1779 1780 // TODO(pbos): Support or remove the following stats. 1781 info.packets_cached = -1; 1782 info.rtt_ms = -1; 1783 1784 return info; 1785} 1786 1787void WebRtcVideoChannel2::WebRtcVideoSendStream::OnCpuResolutionRequest( 1788 CoordinatedVideoAdapter::AdaptRequest adapt_request) { 1789 rtc::CritScope cs(&lock_); 1790 bool adapt_cpu; 1791 parameters_.options.cpu_overuse_detection.Get(&adapt_cpu); 1792 if (!adapt_cpu) { 1793 return; 1794 } 1795 if (capturer_ == NULL || capturer_->video_adapter() == NULL) { 1796 return; 1797 } 1798 1799 capturer_->video_adapter()->OnCpuResolutionRequest(adapt_request); 1800} 1801 1802void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() { 1803 if (stream_ != NULL) { 1804 call_->DestroyVideoSendStream(stream_); 1805 } 1806 1807 VideoCodecSettings codec_settings; 1808 parameters_.codec_settings.Get(&codec_settings); 1809 parameters_.encoder_config.encoder_specific_settings = 1810 encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec, 1811 parameters_.options); 1812 1813 stream_ = call_->CreateVideoSendStream(parameters_.config, 1814 parameters_.encoder_config); 1815 1816 encoder_factory_->DestroyVideoEncoderSettings( 1817 codec_settings.codec, 1818 parameters_.encoder_config.encoder_specific_settings); 1819 1820 parameters_.encoder_config.encoder_specific_settings = NULL; 1821 1822 if (sending_) { 1823 stream_->Start(); 1824 } 1825} 1826 1827WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( 1828 webrtc::Call* call, 1829 const webrtc::VideoReceiveStream::Config& config, 1830 const std::vector<VideoCodecSettings>& recv_codecs) 1831 : call_(call), 1832 stream_(NULL), 1833 config_(config), 1834 renderer_(NULL), 1835 last_width_(-1), 1836 last_height_(-1) { 1837 config_.renderer = this; 1838 // SetRecvCodecs will also reset (start) the VideoReceiveStream. 1839 SetRecvCodecs(recv_codecs); 1840} 1841 1842WebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() { 1843 call_->DestroyVideoReceiveStream(stream_); 1844} 1845 1846void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs( 1847 const std::vector<VideoCodecSettings>& recv_codecs) { 1848 // TODO(pbos): Reconfigure RTX based on incoming recv_codecs. 1849 // TODO(pbos): Base receive codecs off recv_codecs_ and set up using a 1850 // DecoderFactory similar to send side. Pending webrtc:2854. 1851 // Also set up default codecs if there's nothing in recv_codecs_. 1852 webrtc::VideoCodec codec; 1853 memset(&codec, 0, sizeof(codec)); 1854 1855 codec.plType = kDefaultVideoCodecPref.payload_type; 1856 strcpy(codec.plName, kDefaultVideoCodecPref.name); 1857 codec.codecType = webrtc::kVideoCodecVP8; 1858 codec.codecSpecific.VP8.resilience = webrtc::kResilientStream; 1859 codec.codecSpecific.VP8.numberOfTemporalLayers = 1; 1860 codec.codecSpecific.VP8.denoisingOn = true; 1861 codec.codecSpecific.VP8.errorConcealmentOn = false; 1862 codec.codecSpecific.VP8.automaticResizeOn = false; 1863 codec.codecSpecific.VP8.frameDroppingOn = true; 1864 codec.codecSpecific.VP8.keyFrameInterval = 3000; 1865 // Bitrates don't matter and are ignored for the receiver. This is put in to 1866 // have the current underlying implementation accept the VideoCodec. 1867 codec.minBitrate = codec.startBitrate = codec.maxBitrate = 300; 1868 config_.codecs.clear(); 1869 config_.codecs.push_back(codec); 1870 1871 config_.rtp.fec = recv_codecs.front().fec; 1872 1873 config_.rtp.nack.rtp_history_ms = 1874 IsNackEnabled(recv_codecs.begin()->codec) ? kNackHistoryMs : 0; 1875 config_.rtp.remb = IsRembEnabled(recv_codecs.begin()->codec); 1876 1877 RecreateWebRtcStream(); 1878} 1879 1880void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions( 1881 const std::vector<webrtc::RtpExtension>& extensions) { 1882 config_.rtp.extensions = extensions; 1883 RecreateWebRtcStream(); 1884} 1885 1886void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() { 1887 if (stream_ != NULL) { 1888 call_->DestroyVideoReceiveStream(stream_); 1889 } 1890 stream_ = call_->CreateVideoReceiveStream(config_); 1891 stream_->Start(); 1892} 1893 1894void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame( 1895 const webrtc::I420VideoFrame& frame, 1896 int time_to_render_ms) { 1897 rtc::CritScope crit(&renderer_lock_); 1898 if (renderer_ == NULL) { 1899 LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer."; 1900 return; 1901 } 1902 1903 if (frame.width() != last_width_ || frame.height() != last_height_) { 1904 SetSize(frame.width(), frame.height()); 1905 } 1906 1907 LOG(LS_VERBOSE) << "RenderFrame: (" << frame.width() << "x" << frame.height() 1908 << ")"; 1909 1910 const WebRtcVideoRenderFrame render_frame(&frame); 1911 renderer_->RenderFrame(&render_frame); 1912} 1913 1914void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRenderer( 1915 cricket::VideoRenderer* renderer) { 1916 rtc::CritScope crit(&renderer_lock_); 1917 renderer_ = renderer; 1918 if (renderer_ != NULL && last_width_ != -1) { 1919 SetSize(last_width_, last_height_); 1920 } 1921} 1922 1923VideoRenderer* WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetRenderer() { 1924 // TODO(pbos): Remove GetRenderer and all uses of it, it's thread-unsafe by 1925 // design. 1926 rtc::CritScope crit(&renderer_lock_); 1927 return renderer_; 1928} 1929 1930void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width, 1931 int height) { 1932 rtc::CritScope crit(&renderer_lock_); 1933 if (!renderer_->SetSize(width, height, 0)) { 1934 LOG(LS_ERROR) << "Could not set renderer size."; 1935 } 1936 last_width_ = width; 1937 last_height_ = height; 1938} 1939 1940VideoReceiverInfo 1941WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() { 1942 VideoReceiverInfo info; 1943 info.add_ssrc(config_.rtp.remote_ssrc); 1944 webrtc::VideoReceiveStream::Stats stats = stream_->GetStats(); 1945 info.bytes_rcvd = stats.rtp_stats.bytes + stats.rtp_stats.header_bytes + 1946 stats.rtp_stats.padding_bytes; 1947 info.packets_rcvd = stats.rtp_stats.packets; 1948 1949 info.framerate_rcvd = stats.network_frame_rate; 1950 info.framerate_decoded = stats.decode_frame_rate; 1951 info.framerate_output = stats.render_frame_rate; 1952 1953 rtc::CritScope frame_cs(&renderer_lock_); 1954 info.frame_width = last_width_; 1955 info.frame_height = last_height_; 1956 1957 // TODO(pbos): Support or remove the following stats. 1958 info.packets_concealed = -1; 1959 1960 return info; 1961} 1962 1963WebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings() 1964 : rtx_payload_type(-1) {} 1965 1966std::vector<WebRtcVideoChannel2::VideoCodecSettings> 1967WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) { 1968 assert(!codecs.empty()); 1969 1970 std::vector<VideoCodecSettings> video_codecs; 1971 std::map<int, bool> payload_used; 1972 std::map<int, VideoCodec::CodecType> payload_codec_type; 1973 std::map<int, int> rtx_mapping; // video payload type -> rtx payload type. 1974 1975 webrtc::FecConfig fec_settings; 1976 1977 for (size_t i = 0; i < codecs.size(); ++i) { 1978 const VideoCodec& in_codec = codecs[i]; 1979 int payload_type = in_codec.id; 1980 1981 if (payload_used[payload_type]) { 1982 LOG(LS_ERROR) << "Payload type already registered: " 1983 << in_codec.ToString(); 1984 return std::vector<VideoCodecSettings>(); 1985 } 1986 payload_used[payload_type] = true; 1987 payload_codec_type[payload_type] = in_codec.GetCodecType(); 1988 1989 switch (in_codec.GetCodecType()) { 1990 case VideoCodec::CODEC_RED: { 1991 // RED payload type, should not have duplicates. 1992 assert(fec_settings.red_payload_type == -1); 1993 fec_settings.red_payload_type = in_codec.id; 1994 continue; 1995 } 1996 1997 case VideoCodec::CODEC_ULPFEC: { 1998 // ULPFEC payload type, should not have duplicates. 1999 assert(fec_settings.ulpfec_payload_type == -1); 2000 fec_settings.ulpfec_payload_type = in_codec.id; 2001 continue; 2002 } 2003 2004 case VideoCodec::CODEC_RTX: { 2005 int associated_payload_type; 2006 if (!in_codec.GetParam(kCodecParamAssociatedPayloadType, 2007 &associated_payload_type)) { 2008 LOG(LS_ERROR) << "RTX codec without associated payload type: " 2009 << in_codec.ToString(); 2010 return std::vector<VideoCodecSettings>(); 2011 } 2012 rtx_mapping[associated_payload_type] = in_codec.id; 2013 continue; 2014 } 2015 2016 case VideoCodec::CODEC_VIDEO: 2017 break; 2018 } 2019 2020 video_codecs.push_back(VideoCodecSettings()); 2021 video_codecs.back().codec = in_codec; 2022 } 2023 2024 // One of these codecs should have been a video codec. Only having FEC 2025 // parameters into this code is a logic error. 2026 assert(!video_codecs.empty()); 2027 2028 for (std::map<int, int>::const_iterator it = rtx_mapping.begin(); 2029 it != rtx_mapping.end(); 2030 ++it) { 2031 if (!payload_used[it->first]) { 2032 LOG(LS_ERROR) << "RTX mapped to payload not in codec list."; 2033 return std::vector<VideoCodecSettings>(); 2034 } 2035 if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO) { 2036 LOG(LS_ERROR) << "RTX not mapped to regular video codec."; 2037 return std::vector<VideoCodecSettings>(); 2038 } 2039 } 2040 2041 // TODO(pbos): Write tests that figure out that I have not verified that RTX 2042 // codecs aren't mapped to bogus payloads. 2043 for (size_t i = 0; i < video_codecs.size(); ++i) { 2044 video_codecs[i].fec = fec_settings; 2045 if (rtx_mapping[video_codecs[i].codec.id] != 0) { 2046 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; 2047 } 2048 } 2049 2050 return video_codecs; 2051} 2052 2053std::vector<WebRtcVideoChannel2::VideoCodecSettings> 2054WebRtcVideoChannel2::FilterSupportedCodecs( 2055 const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs) { 2056 std::vector<VideoCodecSettings> supported_codecs; 2057 for (size_t i = 0; i < mapped_codecs.size(); ++i) { 2058 const VideoCodecSettings& codec = mapped_codecs[i]; 2059 if (CodecIsInternallySupported(codec.codec.name)) { 2060 supported_codecs.push_back(codec); 2061 } 2062 2063 if (external_encoder_factory_ == NULL) { 2064 continue; 2065 } 2066 const std::vector<WebRtcVideoEncoderFactory::VideoCodec> external_codecs = 2067 external_encoder_factory_->codecs(); 2068 for (size_t c = 0; c < external_codecs.size(); ++c) { 2069 if (CodecNameMatches(codec.codec.name, external_codecs[c].name)) { 2070 supported_codecs.push_back(codec); 2071 break; 2072 } 2073 } 2074 } 2075 return supported_codecs; 2076} 2077 2078} // namespace cricket 2079 2080#endif // HAVE_WEBRTC_VIDEO 2081