1 /* 2 * libjingle 3 * Copyright 2004 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/webrtcvideoengine.h" 30 31 #ifdef HAVE_CONFIG_H 32 #include <config.h> 33 #endif 34 35 #include <math.h> 36 #include <set> 37 38 #include "talk/media/base/constants.h" 39 #include "talk/media/base/rtputils.h" 40 #include "talk/media/base/streamparams.h" 41 #include "talk/media/base/videoadapter.h" 42 #include "talk/media/base/videocapturer.h" 43 #include "talk/media/base/videorenderer.h" 44 #include "talk/media/devices/filevideocapturer.h" 45 #include "talk/media/webrtc/constants.h" 46 #include "talk/media/webrtc/webrtcpassthroughrender.h" 47 #include "talk/media/webrtc/webrtctexturevideoframe.h" 48 #include "talk/media/webrtc/webrtcvideocapturer.h" 49 #include "talk/media/webrtc/webrtcvideodecoderfactory.h" 50 #include "talk/media/webrtc/webrtcvideoencoderfactory.h" 51 #include "talk/media/webrtc/webrtcvideoframe.h" 52 #include "talk/media/webrtc/webrtcvie.h" 53 #include "talk/media/webrtc/webrtcvoe.h" 54 #include "talk/media/webrtc/webrtcvoiceengine.h" 55 #include "webrtc/base/basictypes.h" 56 #include "webrtc/base/buffer.h" 57 #include "webrtc/base/byteorder.h" 58 #include "webrtc/base/common.h" 59 #include "webrtc/base/cpumonitor.h" 60 #include "webrtc/base/logging.h" 61 #include "webrtc/base/stringutils.h" 62 #include "webrtc/base/thread.h" 63 #include "webrtc/base/timeutils.h" 64 #include "webrtc/experiments.h" 65 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" 66 67 namespace { 68 69 template <class T> 70 bool Changed(cricket::Settable<T> proposed, 71 cricket::Settable<T> original) { 72 return proposed.IsSet() && proposed != original; 73 } 74 75 template <class T> 76 bool Changed(cricket::Settable<T> proposed, 77 cricket::Settable<T> original, 78 T* value) { 79 return proposed.Get(value) && proposed != original; 80 } 81 82 } // namespace 83 84 namespace cricket { 85 86 // Constants defined in talk/media/webrtc/constants.h 87 // TODO(pbos): Move these to a separate constants.cc file. 88 const int kVideoMtu = 1200; 89 const int kVideoRtpBufferSize = 65536; 90 91 const char kVp8CodecName[] = "VP8"; 92 93 const int kDefaultFramerate = 30; 94 const int kMinVideoBitrate = 30; 95 const int kStartVideoBitrate = 300; 96 const int kMaxVideoBitrate = 2000; 97 98 const int kCpuMonitorPeriodMs = 2000; // 2 seconds. 99 100 // TODO(pthatcher): Figure out what the proper value here is, or if we 101 // can just remove this altogether. 102 static const int kDefaultRenderDelayMs = 100; 103 104 static const int kDefaultLogSeverity = rtc::LS_WARNING; 105 106 static const int kDefaultNumberOfTemporalLayers = 1; // 1:1 107 108 static const int kExternalVideoPayloadTypeBase = 120; 109 110 static const int kChannelIdUnset = -1; 111 static const uint32 kDefaultChannelSsrcKey = 0; 112 static const uint32 kSsrcUnset = 0; 113 114 static bool BitrateIsSet(int value) { 115 return value > kAutoBandwidth; 116 } 117 118 static int GetBitrate(int value, int deflt) { 119 return BitrateIsSet(value) ? value : deflt; 120 } 121 122 // Static allocation of payload type values for external video codec. 123 static int GetExternalVideoPayloadType(int index) { 124 #if ENABLE_DEBUG 125 static const int kMaxExternalVideoCodecs = 8; 126 ASSERT(index >= 0 && index < kMaxExternalVideoCodecs); 127 #endif 128 return kExternalVideoPayloadTypeBase + index; 129 } 130 131 static void LogMultiline(rtc::LoggingSeverity sev, char* text) { 132 const char* delim = "\r\n"; 133 // TODO(fbarchard): Fix strtok lint warning. 134 for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) { 135 LOG_V(sev) << tok; 136 } 137 } 138 139 // Severity is an integer because it comes is assumed to be from command line. 140 static int SeverityToFilter(int severity) { 141 int filter = webrtc::kTraceNone; 142 switch (severity) { 143 case rtc::LS_VERBOSE: 144 filter |= webrtc::kTraceAll; 145 case rtc::LS_INFO: 146 filter |= (webrtc::kTraceStateInfo | webrtc::kTraceInfo); 147 case rtc::LS_WARNING: 148 filter |= (webrtc::kTraceTerseInfo | webrtc::kTraceWarning); 149 case rtc::LS_ERROR: 150 filter |= (webrtc::kTraceError | webrtc::kTraceCritical); 151 } 152 return filter; 153 } 154 155 static const bool kNotSending = false; 156 157 // Default video dscp value. 158 // See http://tools.ietf.org/html/rfc2474 for details 159 // See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00 160 static const rtc::DiffServCodePoint kVideoDscpValue = 161 rtc::DSCP_AF41; 162 163 static bool IsNackEnabled(const VideoCodec& codec) { 164 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack, 165 kParamValueEmpty)); 166 } 167 168 // Returns true if Receiver Estimated Max Bitrate is enabled. 169 static bool IsRembEnabled(const VideoCodec& codec) { 170 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamRemb, 171 kParamValueEmpty)); 172 } 173 174 struct FlushBlackFrameData : public rtc::MessageData { 175 FlushBlackFrameData(uint32 s, int64 t) : ssrc(s), timestamp(t) { 176 } 177 uint32 ssrc; 178 int64 timestamp; 179 }; 180 181 class WebRtcRenderAdapter : public webrtc::ExternalRenderer { 182 public: 183 WebRtcRenderAdapter(VideoRenderer* renderer, int channel_id) 184 : renderer_(renderer), 185 channel_id_(channel_id), 186 width_(0), 187 height_(0), 188 capture_start_rtp_time_stamp_(-1), 189 capture_start_ntp_time_ms_(0) { 190 } 191 192 virtual ~WebRtcRenderAdapter() { 193 } 194 195 void SetRenderer(VideoRenderer* renderer) { 196 rtc::CritScope cs(&crit_); 197 renderer_ = renderer; 198 // FrameSizeChange may have already been called when renderer was not set. 199 // If so we should call SetSize here. 200 // TODO(ronghuawu): Add unit test for this case. Didn't do it now 201 // because the WebRtcRenderAdapter is currently hiding in cc file. No 202 // good way to get access to it from the unit test. 203 if (width_ > 0 && height_ > 0 && renderer_) { 204 if (!renderer_->SetSize(width_, height_, 0)) { 205 LOG(LS_ERROR) 206 << "WebRtcRenderAdapter (channel " << channel_id_ 207 << ") SetRenderer failed to SetSize to: " 208 << width_ << "x" << height_; 209 } 210 } 211 } 212 213 // Implementation of webrtc::ExternalRenderer. 214 virtual int FrameSizeChange(unsigned int width, unsigned int height, 215 unsigned int /*number_of_streams*/) { 216 rtc::CritScope cs(&crit_); 217 width_ = width; 218 height_ = height; 219 LOG(LS_INFO) << "WebRtcRenderAdapter (channel " << channel_id_ 220 << ") frame size changed to: " 221 << width << "x" << height; 222 if (!renderer_) { 223 LOG(LS_VERBOSE) << "WebRtcRenderAdapter (channel " << channel_id_ 224 << ") the renderer has not been set. " 225 << "SetSize will be called later in SetRenderer."; 226 return 0; 227 } 228 return renderer_->SetSize(width_, height_, 0) ? 0 : -1; 229 } 230 231 virtual int DeliverFrame(unsigned char* buffer, 232 int buffer_size, 233 uint32_t rtp_time_stamp, 234 int64_t ntp_time_ms, 235 int64_t render_time, 236 void* handle) { 237 rtc::CritScope cs(&crit_); 238 if (capture_start_rtp_time_stamp_ < 0) { 239 capture_start_rtp_time_stamp_ = rtp_time_stamp; 240 } 241 242 const int kVideoCodecClockratekHz = cricket::kVideoCodecClockrate / 1000; 243 244 int64 elapsed_time_ms = 245 (rtp_ts_wraparound_handler_.Unwrap(rtp_time_stamp) - 246 capture_start_rtp_time_stamp_) / kVideoCodecClockratekHz; 247 if (ntp_time_ms > 0) { 248 capture_start_ntp_time_ms_ = ntp_time_ms - elapsed_time_ms; 249 } 250 frame_rate_tracker_.Update(1); 251 if (!renderer_) { 252 return 0; 253 } 254 // Convert elapsed_time_ms to ns timestamp. 255 int64 elapsed_time_ns = 256 elapsed_time_ms * rtc::kNumNanosecsPerMillisec; 257 // Convert milisecond render time to ns timestamp. 258 int64 render_time_ns = render_time * 259 rtc::kNumNanosecsPerMillisec; 260 // Note that here we send the |elapsed_time_ns| to renderer as the 261 // cricket::VideoFrame's elapsed_time_ and the |render_time_ns| as the 262 // cricket::VideoFrame's time_stamp_. 263 if (!handle) { 264 return DeliverBufferFrame(buffer, buffer_size, render_time_ns, 265 elapsed_time_ns); 266 } else { 267 return DeliverTextureFrame(handle, render_time_ns, 268 elapsed_time_ns); 269 } 270 } 271 272 virtual bool IsTextureSupported() { return true; } 273 274 int DeliverBufferFrame(unsigned char* buffer, int buffer_size, 275 int64 time_stamp, int64 elapsed_time) { 276 WebRtcVideoFrame video_frame; 277 video_frame.Alias(buffer, buffer_size, width_, height_, 278 1, 1, elapsed_time, time_stamp, 0); 279 280 // Sanity check on decoded frame size. 281 if (buffer_size != static_cast<int>(VideoFrame::SizeOf(width_, height_))) { 282 LOG(LS_WARNING) << "WebRtcRenderAdapter (channel " << channel_id_ 283 << ") received a strange frame size: " 284 << buffer_size; 285 } 286 287 int ret = renderer_->RenderFrame(&video_frame) ? 0 : -1; 288 return ret; 289 } 290 291 int DeliverTextureFrame(void* handle, int64 time_stamp, int64 elapsed_time) { 292 WebRtcTextureVideoFrame video_frame( 293 static_cast<webrtc::NativeHandle*>(handle), width_, height_, 294 elapsed_time, time_stamp); 295 return renderer_->RenderFrame(&video_frame); 296 } 297 298 unsigned int width() { 299 rtc::CritScope cs(&crit_); 300 return width_; 301 } 302 303 unsigned int height() { 304 rtc::CritScope cs(&crit_); 305 return height_; 306 } 307 308 int framerate() { 309 rtc::CritScope cs(&crit_); 310 return static_cast<int>(frame_rate_tracker_.units_second()); 311 } 312 313 VideoRenderer* renderer() { 314 rtc::CritScope cs(&crit_); 315 return renderer_; 316 } 317 318 int64 capture_start_ntp_time_ms() { 319 rtc::CritScope cs(&crit_); 320 return capture_start_ntp_time_ms_; 321 } 322 323 private: 324 rtc::CriticalSection crit_; 325 VideoRenderer* renderer_; 326 int channel_id_; 327 unsigned int width_; 328 unsigned int height_; 329 rtc::RateTracker frame_rate_tracker_; 330 rtc::TimestampWrapAroundHandler rtp_ts_wraparound_handler_; 331 int64 capture_start_rtp_time_stamp_; 332 int64 capture_start_ntp_time_ms_; 333 }; 334 335 class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver { 336 public: 337 explicit WebRtcDecoderObserver(int video_channel_id) 338 : video_channel_id_(video_channel_id), 339 framerate_(0), 340 bitrate_(0), 341 decode_ms_(0), 342 max_decode_ms_(0), 343 current_delay_ms_(0), 344 target_delay_ms_(0), 345 jitter_buffer_ms_(0), 346 min_playout_delay_ms_(0), 347 render_delay_ms_(0) { 348 } 349 350 // virtual functions from VieDecoderObserver. 351 virtual void IncomingCodecChanged(const int video_channel_id, 352 const webrtc::VideoCodec& videoCodec) {} 353 virtual void IncomingRate(const int video_channel_id, 354 const unsigned int framerate, 355 const unsigned int bitrate) { 356 rtc::CritScope cs(&crit_); 357 ASSERT(video_channel_id_ == video_channel_id); 358 framerate_ = framerate; 359 bitrate_ = bitrate; 360 } 361 362 virtual void DecoderTiming(int decode_ms, 363 int max_decode_ms, 364 int current_delay_ms, 365 int target_delay_ms, 366 int jitter_buffer_ms, 367 int min_playout_delay_ms, 368 int render_delay_ms) { 369 rtc::CritScope cs(&crit_); 370 decode_ms_ = decode_ms; 371 max_decode_ms_ = max_decode_ms; 372 current_delay_ms_ = current_delay_ms; 373 target_delay_ms_ = target_delay_ms; 374 jitter_buffer_ms_ = jitter_buffer_ms; 375 min_playout_delay_ms_ = min_playout_delay_ms; 376 render_delay_ms_ = render_delay_ms; 377 } 378 379 virtual void RequestNewKeyFrame(const int video_channel_id) {} 380 381 // Populate |rinfo| based on previously-set data in |*this|. 382 void ExportTo(VideoReceiverInfo* rinfo) { 383 rtc::CritScope cs(&crit_); 384 rinfo->framerate_rcvd = framerate_; 385 rinfo->decode_ms = decode_ms_; 386 rinfo->max_decode_ms = max_decode_ms_; 387 rinfo->current_delay_ms = current_delay_ms_; 388 rinfo->target_delay_ms = target_delay_ms_; 389 rinfo->jitter_buffer_ms = jitter_buffer_ms_; 390 rinfo->min_playout_delay_ms = min_playout_delay_ms_; 391 rinfo->render_delay_ms = render_delay_ms_; 392 } 393 394 private: 395 mutable rtc::CriticalSection crit_; 396 int video_channel_id_; 397 int framerate_; 398 int bitrate_; 399 int decode_ms_; 400 int max_decode_ms_; 401 int current_delay_ms_; 402 int target_delay_ms_; 403 int jitter_buffer_ms_; 404 int min_playout_delay_ms_; 405 int render_delay_ms_; 406 }; 407 408 class WebRtcEncoderObserver : public webrtc::ViEEncoderObserver { 409 public: 410 explicit WebRtcEncoderObserver(int video_channel_id) 411 : video_channel_id_(video_channel_id), 412 framerate_(0), 413 bitrate_(0), 414 suspended_(false) { 415 } 416 417 // virtual functions from VieEncoderObserver. 418 virtual void OutgoingRate(const int video_channel_id, 419 const unsigned int framerate, 420 const unsigned int bitrate) { 421 rtc::CritScope cs(&crit_); 422 ASSERT(video_channel_id_ == video_channel_id); 423 framerate_ = framerate; 424 bitrate_ = bitrate; 425 } 426 427 virtual void SuspendChange(int video_channel_id, bool is_suspended) { 428 rtc::CritScope cs(&crit_); 429 ASSERT(video_channel_id_ == video_channel_id); 430 suspended_ = is_suspended; 431 } 432 433 int framerate() const { 434 rtc::CritScope cs(&crit_); 435 return framerate_; 436 } 437 int bitrate() const { 438 rtc::CritScope cs(&crit_); 439 return bitrate_; 440 } 441 bool suspended() const { 442 rtc::CritScope cs(&crit_); 443 return suspended_; 444 } 445 446 private: 447 mutable rtc::CriticalSection crit_; 448 int video_channel_id_; 449 int framerate_; 450 int bitrate_; 451 bool suspended_; 452 }; 453 454 class WebRtcLocalStreamInfo { 455 public: 456 WebRtcLocalStreamInfo() 457 : width_(0), height_(0), elapsed_time_(-1), time_stamp_(-1) {} 458 size_t width() const { 459 rtc::CritScope cs(&crit_); 460 return width_; 461 } 462 size_t height() const { 463 rtc::CritScope cs(&crit_); 464 return height_; 465 } 466 int64 elapsed_time() const { 467 rtc::CritScope cs(&crit_); 468 return elapsed_time_; 469 } 470 int64 time_stamp() const { 471 rtc::CritScope cs(&crit_); 472 return time_stamp_; 473 } 474 int framerate() { 475 rtc::CritScope cs(&crit_); 476 return static_cast<int>(rate_tracker_.units_second()); 477 } 478 void GetLastFrameInfo( 479 size_t* width, size_t* height, int64* elapsed_time) const { 480 rtc::CritScope cs(&crit_); 481 *width = width_; 482 *height = height_; 483 *elapsed_time = elapsed_time_; 484 } 485 486 void UpdateFrame(const VideoFrame* frame) { 487 rtc::CritScope cs(&crit_); 488 489 width_ = frame->GetWidth(); 490 height_ = frame->GetHeight(); 491 elapsed_time_ = frame->GetElapsedTime(); 492 time_stamp_ = frame->GetTimeStamp(); 493 494 rate_tracker_.Update(1); 495 } 496 497 private: 498 mutable rtc::CriticalSection crit_; 499 size_t width_; 500 size_t height_; 501 int64 elapsed_time_; 502 int64 time_stamp_; 503 rtc::RateTracker rate_tracker_; 504 505 DISALLOW_COPY_AND_ASSIGN(WebRtcLocalStreamInfo); 506 }; 507 508 // WebRtcVideoChannelRecvInfo is a container class with members such as renderer 509 // and a decoder observer that is used by receive channels. 510 // It must exist as long as the receive channel is connected to renderer or a 511 // decoder observer in this class and methods in the class should only be called 512 // from the worker thread. 513 class WebRtcVideoChannelRecvInfo { 514 public: 515 typedef std::map<int, webrtc::VideoDecoder*> DecoderMap; // key: payload type 516 explicit WebRtcVideoChannelRecvInfo(int channel_id) 517 : channel_id_(channel_id), 518 render_adapter_(NULL, channel_id), 519 decoder_observer_(channel_id) { 520 } 521 int channel_id() { return channel_id_; } 522 void SetRenderer(VideoRenderer* renderer) { 523 render_adapter_.SetRenderer(renderer); 524 } 525 WebRtcRenderAdapter* render_adapter() { return &render_adapter_; } 526 WebRtcDecoderObserver* decoder_observer() { return &decoder_observer_; } 527 void RegisterDecoder(int pl_type, webrtc::VideoDecoder* decoder) { 528 ASSERT(!IsDecoderRegistered(pl_type)); 529 registered_decoders_[pl_type] = decoder; 530 } 531 bool IsDecoderRegistered(int pl_type) { 532 return registered_decoders_.count(pl_type) != 0; 533 } 534 const DecoderMap& registered_decoders() { 535 return registered_decoders_; 536 } 537 void ClearRegisteredDecoders() { 538 registered_decoders_.clear(); 539 } 540 541 private: 542 int channel_id_; // Webrtc video channel number. 543 // Renderer for this channel. 544 WebRtcRenderAdapter render_adapter_; 545 WebRtcDecoderObserver decoder_observer_; 546 DecoderMap registered_decoders_; 547 }; 548 549 class WebRtcOveruseObserver : public webrtc::CpuOveruseObserver { 550 public: 551 explicit WebRtcOveruseObserver(CoordinatedVideoAdapter* video_adapter) 552 : video_adapter_(video_adapter), 553 enabled_(false) { 554 } 555 556 // TODO(mflodman): Consider sending resolution as part of event, to let 557 // adapter know what resolution the request is based on. Helps eliminate stale 558 // data, race conditions. 559 virtual void OveruseDetected() OVERRIDE { 560 rtc::CritScope cs(&crit_); 561 if (!enabled_) { 562 return; 563 } 564 565 video_adapter_->OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE); 566 } 567 568 virtual void NormalUsage() OVERRIDE { 569 rtc::CritScope cs(&crit_); 570 if (!enabled_) { 571 return; 572 } 573 574 video_adapter_->OnCpuResolutionRequest(CoordinatedVideoAdapter::UPGRADE); 575 } 576 577 void Enable(bool enable) { 578 LOG(LS_INFO) << "WebRtcOveruseObserver enable: " << enable; 579 rtc::CritScope cs(&crit_); 580 enabled_ = enable; 581 } 582 583 bool enabled() const { return enabled_; } 584 585 private: 586 CoordinatedVideoAdapter* video_adapter_; 587 bool enabled_; 588 rtc::CriticalSection crit_; 589 }; 590 591 592 class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> { 593 public: 594 typedef std::map<int, webrtc::VideoEncoder*> EncoderMap; // key: payload type 595 WebRtcVideoChannelSendInfo(int channel_id, int capture_id, 596 webrtc::ViEExternalCapture* external_capture, 597 rtc::CpuMonitor* cpu_monitor) 598 : channel_id_(channel_id), 599 capture_id_(capture_id), 600 sending_(false), 601 muted_(false), 602 video_capturer_(NULL), 603 encoder_observer_(channel_id), 604 external_capture_(external_capture), 605 interval_(0), 606 cpu_monitor_(cpu_monitor), 607 old_adaptation_changes_(0) { 608 } 609 610 int channel_id() const { return channel_id_; } 611 int capture_id() const { return capture_id_; } 612 void set_sending(bool sending) { sending_ = sending; } 613 bool sending() const { return sending_; } 614 void set_muted(bool on) { 615 // TODO(asapersson): add support. 616 // video_adapter_.SetBlackOutput(on); 617 muted_ = on; 618 } 619 bool muted() {return muted_; } 620 621 WebRtcEncoderObserver* encoder_observer() { return &encoder_observer_; } 622 webrtc::ViEExternalCapture* external_capture() { return external_capture_; } 623 const VideoFormat& video_format() const { 624 return video_format_; 625 } 626 void set_video_format(const VideoFormat& video_format) { 627 video_format_ = video_format; 628 if (video_format_ != cricket::VideoFormat()) { 629 interval_ = video_format_.interval; 630 } 631 CoordinatedVideoAdapter* adapter = video_adapter(); 632 if (adapter) { 633 adapter->OnOutputFormatRequest(video_format_); 634 } 635 } 636 void set_interval(int64 interval) { 637 if (video_format() == cricket::VideoFormat()) { 638 interval_ = interval; 639 } 640 } 641 int64 interval() { return interval_; } 642 643 int CurrentAdaptReason() const { 644 if (!video_adapter()) { 645 return CoordinatedVideoAdapter::ADAPTREASON_NONE; 646 } 647 return video_adapter()->adapt_reason(); 648 } 649 int AdaptChanges() const { 650 if (!video_adapter()) { 651 return old_adaptation_changes_; 652 } 653 return old_adaptation_changes_ + video_adapter()->adaptation_changes(); 654 } 655 656 StreamParams* stream_params() { return stream_params_.get(); } 657 void set_stream_params(const StreamParams& sp) { 658 stream_params_.reset(new StreamParams(sp)); 659 } 660 void ClearStreamParams() { stream_params_.reset(); } 661 bool has_ssrc(uint32 local_ssrc) const { 662 return !stream_params_ ? false : 663 stream_params_->has_ssrc(local_ssrc); 664 } 665 WebRtcLocalStreamInfo* local_stream_info() { 666 return &local_stream_info_; 667 } 668 VideoCapturer* video_capturer() { 669 return video_capturer_; 670 } 671 void set_video_capturer(VideoCapturer* video_capturer, 672 ViEWrapper* vie_wrapper) { 673 if (video_capturer == video_capturer_) { 674 return; 675 } 676 677 CoordinatedVideoAdapter* old_video_adapter = video_adapter(); 678 if (old_video_adapter) { 679 // Get adaptation changes from old video adapter. 680 old_adaptation_changes_ += old_video_adapter->adaptation_changes(); 681 // Disconnect signals from old video adapter. 682 SignalCpuAdaptationUnable.disconnect(old_video_adapter); 683 if (cpu_monitor_) { 684 cpu_monitor_->SignalUpdate.disconnect(old_video_adapter); 685 } 686 } 687 688 video_capturer_ = video_capturer; 689 690 vie_wrapper->base()->RegisterCpuOveruseObserver(channel_id_, NULL); 691 if (!video_capturer) { 692 overuse_observer_.reset(); 693 return; 694 } 695 696 CoordinatedVideoAdapter* adapter = video_adapter(); 697 ASSERT(adapter && "Video adapter should not be null here."); 698 699 UpdateAdapterCpuOptions(); 700 701 overuse_observer_.reset(new WebRtcOveruseObserver(adapter)); 702 vie_wrapper->base()->RegisterCpuOveruseObserver(channel_id_, 703 overuse_observer_.get()); 704 // (Dis)connect the video adapter from the cpu monitor as appropriate. 705 SetCpuOveruseDetection( 706 video_options_.cpu_overuse_detection.GetWithDefaultIfUnset(false)); 707 708 SignalCpuAdaptationUnable.repeat(adapter->SignalCpuAdaptationUnable); 709 } 710 711 CoordinatedVideoAdapter* video_adapter() { 712 if (!video_capturer_) { 713 return NULL; 714 } 715 return video_capturer_->video_adapter(); 716 } 717 const CoordinatedVideoAdapter* video_adapter() const { 718 if (!video_capturer_) { 719 return NULL; 720 } 721 return video_capturer_->video_adapter(); 722 } 723 724 void ApplyCpuOptions(const VideoOptions& video_options) { 725 bool cpu_overuse_detection_changed = 726 video_options.cpu_overuse_detection.IsSet() && 727 (video_options.cpu_overuse_detection.GetWithDefaultIfUnset(false) != 728 video_options_.cpu_overuse_detection.GetWithDefaultIfUnset(false)); 729 // Use video_options_.SetAll() instead of assignment so that unset value in 730 // video_options will not overwrite the previous option value. 731 video_options_.SetAll(video_options); 732 UpdateAdapterCpuOptions(); 733 if (cpu_overuse_detection_changed) { 734 SetCpuOveruseDetection( 735 video_options_.cpu_overuse_detection.GetWithDefaultIfUnset(false)); 736 } 737 } 738 739 void UpdateAdapterCpuOptions() { 740 if (!video_capturer_) { 741 return; 742 } 743 744 bool cpu_smoothing, adapt_third; 745 float low, med, high; 746 bool cpu_adapt = 747 video_options_.adapt_input_to_cpu_usage.GetWithDefaultIfUnset(false); 748 bool cpu_overuse_detection = 749 video_options_.cpu_overuse_detection.GetWithDefaultIfUnset(false); 750 751 // TODO(thorcarpenter): Have VideoAdapter be responsible for setting 752 // all these video options. 753 CoordinatedVideoAdapter* video_adapter = video_capturer_->video_adapter(); 754 if (video_options_.adapt_input_to_cpu_usage.IsSet() || 755 video_options_.cpu_overuse_detection.IsSet()) { 756 video_adapter->set_cpu_adaptation(cpu_adapt || cpu_overuse_detection); 757 } 758 if (video_options_.adapt_cpu_with_smoothing.Get(&cpu_smoothing)) { 759 video_adapter->set_cpu_smoothing(cpu_smoothing); 760 } 761 if (video_options_.process_adaptation_threshhold.Get(&med)) { 762 video_adapter->set_process_threshold(med); 763 } 764 if (video_options_.system_low_adaptation_threshhold.Get(&low)) { 765 video_adapter->set_low_system_threshold(low); 766 } 767 if (video_options_.system_high_adaptation_threshhold.Get(&high)) { 768 video_adapter->set_high_system_threshold(high); 769 } 770 if (video_options_.video_adapt_third.Get(&adapt_third)) { 771 video_adapter->set_scale_third(adapt_third); 772 } 773 } 774 775 void SetCpuOveruseDetection(bool enable) { 776 if (overuse_observer_) { 777 overuse_observer_->Enable(enable); 778 } 779 780 // The video adapter is signaled by overuse detection if enabled; otherwise 781 // it will be signaled by cpu monitor. 782 CoordinatedVideoAdapter* adapter = video_adapter(); 783 if (adapter) { 784 if (cpu_monitor_) { 785 if (enable) { 786 cpu_monitor_->SignalUpdate.disconnect(adapter); 787 } else { 788 cpu_monitor_->SignalUpdate.connect( 789 adapter, &CoordinatedVideoAdapter::OnCpuLoadUpdated); 790 } 791 } 792 } 793 } 794 795 void ProcessFrame(const VideoFrame& original_frame, bool mute, 796 VideoFrame** processed_frame) { 797 if (!mute) { 798 *processed_frame = original_frame.Copy(); 799 } else { 800 WebRtcVideoFrame* black_frame = new WebRtcVideoFrame(); 801 black_frame->InitToBlack(static_cast<int>(original_frame.GetWidth()), 802 static_cast<int>(original_frame.GetHeight()), 803 1, 1, 804 original_frame.GetElapsedTime(), 805 original_frame.GetTimeStamp()); 806 *processed_frame = black_frame; 807 } 808 local_stream_info_.UpdateFrame(*processed_frame); 809 } 810 void RegisterEncoder(int pl_type, webrtc::VideoEncoder* encoder) { 811 ASSERT(!IsEncoderRegistered(pl_type)); 812 registered_encoders_[pl_type] = encoder; 813 } 814 bool IsEncoderRegistered(int pl_type) { 815 return registered_encoders_.count(pl_type) != 0; 816 } 817 const EncoderMap& registered_encoders() { 818 return registered_encoders_; 819 } 820 void ClearRegisteredEncoders() { 821 registered_encoders_.clear(); 822 } 823 824 sigslot::repeater0<> SignalCpuAdaptationUnable; 825 826 private: 827 int channel_id_; 828 int capture_id_; 829 bool sending_; 830 bool muted_; 831 VideoCapturer* video_capturer_; 832 WebRtcEncoderObserver encoder_observer_; 833 webrtc::ViEExternalCapture* external_capture_; 834 EncoderMap registered_encoders_; 835 836 VideoFormat video_format_; 837 838 rtc::scoped_ptr<StreamParams> stream_params_; 839 840 WebRtcLocalStreamInfo local_stream_info_; 841 842 int64 interval_; 843 844 rtc::CpuMonitor* cpu_monitor_; 845 rtc::scoped_ptr<WebRtcOveruseObserver> overuse_observer_; 846 847 int old_adaptation_changes_; 848 849 VideoOptions video_options_; 850 }; 851 852 const WebRtcVideoEngine::VideoCodecPref 853 WebRtcVideoEngine::kVideoCodecPrefs[] = { 854 {kVp8CodecName, 100, -1, 0}, 855 {kRedCodecName, 116, -1, 1}, 856 {kUlpfecCodecName, 117, -1, 2}, 857 {kRtxCodecName, 96, 100, 3}, 858 }; 859 860 const VideoFormatPod WebRtcVideoEngine::kDefaultMaxVideoFormat = 861 {640, 400, FPS_TO_INTERVAL(30), FOURCC_ANY}; 862 // TODO(ronghuawu): Change to 640x360. 863 864 static void UpdateVideoCodec(const cricket::VideoFormat& video_format, 865 webrtc::VideoCodec* target_codec) { 866 if ((!target_codec) || (video_format == cricket::VideoFormat())) { 867 return; 868 } 869 target_codec->width = video_format.width; 870 target_codec->height = video_format.height; 871 target_codec->maxFramerate = cricket::VideoFormat::IntervalToFps( 872 video_format.interval); 873 } 874 875 static bool GetCpuOveruseOptions(const VideoOptions& options, 876 webrtc::CpuOveruseOptions* overuse_options) { 877 int underuse_threshold = 0; 878 int overuse_threshold = 0; 879 if (!options.cpu_underuse_threshold.Get(&underuse_threshold) || 880 !options.cpu_overuse_threshold.Get(&overuse_threshold)) { 881 return false; 882 } 883 if (underuse_threshold <= 0 || overuse_threshold <= 0) { 884 return false; 885 } 886 // Valid thresholds. 887 bool encode_usage = 888 options.cpu_overuse_encode_usage.GetWithDefaultIfUnset(false); 889 overuse_options->enable_capture_jitter_method = !encode_usage; 890 overuse_options->enable_encode_usage_method = encode_usage; 891 if (encode_usage) { 892 // Use method based on encode usage. 893 overuse_options->low_encode_usage_threshold_percent = underuse_threshold; 894 overuse_options->high_encode_usage_threshold_percent = overuse_threshold; 895 #ifdef USE_WEBRTC_DEV_BRANCH 896 // Set optional thresholds, if configured. 897 int underuse_rsd_threshold = 0; 898 if (options.cpu_underuse_encode_rsd_threshold.Get( 899 &underuse_rsd_threshold)) { 900 overuse_options->low_encode_time_rsd_threshold = underuse_rsd_threshold; 901 } 902 int overuse_rsd_threshold = 0; 903 if (options.cpu_overuse_encode_rsd_threshold.Get(&overuse_rsd_threshold)) { 904 overuse_options->high_encode_time_rsd_threshold = overuse_rsd_threshold; 905 } 906 #endif 907 } else { 908 // Use default method based on capture jitter. 909 overuse_options->low_capture_jitter_threshold_ms = 910 static_cast<float>(underuse_threshold); 911 overuse_options->high_capture_jitter_threshold_ms = 912 static_cast<float>(overuse_threshold); 913 } 914 return true; 915 } 916 917 WebRtcVideoEngine::WebRtcVideoEngine() { 918 Construct(new ViEWrapper(), new ViETraceWrapper(), NULL, 919 new rtc::CpuMonitor(NULL)); 920 } 921 922 WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine, 923 ViEWrapper* vie_wrapper, 924 rtc::CpuMonitor* cpu_monitor) { 925 Construct(vie_wrapper, new ViETraceWrapper(), voice_engine, cpu_monitor); 926 } 927 928 WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine, 929 ViEWrapper* vie_wrapper, 930 ViETraceWrapper* tracing, 931 rtc::CpuMonitor* cpu_monitor) { 932 Construct(vie_wrapper, tracing, voice_engine, cpu_monitor); 933 } 934 935 void WebRtcVideoEngine::Construct(ViEWrapper* vie_wrapper, 936 ViETraceWrapper* tracing, 937 WebRtcVoiceEngine* voice_engine, 938 rtc::CpuMonitor* cpu_monitor) { 939 LOG(LS_INFO) << "WebRtcVideoEngine::WebRtcVideoEngine"; 940 worker_thread_ = NULL; 941 vie_wrapper_.reset(vie_wrapper); 942 vie_wrapper_base_initialized_ = false; 943 tracing_.reset(tracing); 944 voice_engine_ = voice_engine; 945 initialized_ = false; 946 SetTraceFilter(SeverityToFilter(kDefaultLogSeverity)); 947 render_module_.reset(new WebRtcPassthroughRender()); 948 capture_started_ = false; 949 decoder_factory_ = NULL; 950 encoder_factory_ = NULL; 951 cpu_monitor_.reset(cpu_monitor); 952 953 SetTraceOptions(""); 954 if (tracing_->SetTraceCallback(this) != 0) { 955 LOG_RTCERR1(SetTraceCallback, this); 956 } 957 958 // Set default quality levels for our supported codecs. We override them here 959 // if we know your cpu performance is low, and they can be updated explicitly 960 // by calling SetDefaultCodec. For example by a flute preference setting, or 961 // by the server with a jec in response to our reported system info. 962 VideoCodec max_codec(kVideoCodecPrefs[0].payload_type, 963 kVideoCodecPrefs[0].name, 964 kDefaultMaxVideoFormat.width, 965 kDefaultMaxVideoFormat.height, 966 VideoFormat::IntervalToFps( 967 kDefaultMaxVideoFormat.interval), 968 0); 969 if (!SetDefaultCodec(max_codec)) { 970 LOG(LS_ERROR) << "Failed to initialize list of supported codec types"; 971 } 972 973 // Consider jitter, packet loss, etc when rendering. This will 974 // theoretically make rendering more smooth. 975 EnableTimedRender(); 976 977 // Load our RTP Header extensions. 978 rtp_header_extensions_.push_back( 979 RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, 980 kRtpTimestampOffsetHeaderExtensionDefaultId)); 981 rtp_header_extensions_.push_back( 982 RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, 983 kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); 984 } 985 986 WebRtcVideoEngine::~WebRtcVideoEngine() { 987 LOG(LS_INFO) << "WebRtcVideoEngine::~WebRtcVideoEngine"; 988 if (initialized_) { 989 Terminate(); 990 } 991 if (encoder_factory_) { 992 encoder_factory_->RemoveObserver(this); 993 } 994 tracing_->SetTraceCallback(NULL); 995 // Test to see if the media processor was deregistered properly. 996 ASSERT(SignalMediaFrame.is_empty()); 997 } 998 999 bool WebRtcVideoEngine::Init(rtc::Thread* worker_thread) { 1000 LOG(LS_INFO) << "WebRtcVideoEngine::Init"; 1001 worker_thread_ = worker_thread; 1002 ASSERT(worker_thread_ != NULL); 1003 1004 cpu_monitor_->set_thread(worker_thread_); 1005 if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) { 1006 LOG(LS_ERROR) << "Failed to start CPU monitor."; 1007 cpu_monitor_.reset(); 1008 } 1009 1010 bool result = InitVideoEngine(); 1011 if (result) { 1012 LOG(LS_INFO) << "VideoEngine Init done"; 1013 } else { 1014 LOG(LS_ERROR) << "VideoEngine Init failed, releasing"; 1015 Terminate(); 1016 } 1017 return result; 1018 } 1019 1020 bool WebRtcVideoEngine::InitVideoEngine() { 1021 LOG(LS_INFO) << "WebRtcVideoEngine::InitVideoEngine"; 1022 1023 // Init WebRTC VideoEngine. 1024 if (!vie_wrapper_base_initialized_) { 1025 if (vie_wrapper_->base()->Init() != 0) { 1026 LOG_RTCERR0(Init); 1027 return false; 1028 } 1029 vie_wrapper_base_initialized_ = true; 1030 } 1031 1032 // Log the VoiceEngine version info. 1033 char buffer[1024] = ""; 1034 if (vie_wrapper_->base()->GetVersion(buffer) != 0) { 1035 LOG_RTCERR0(GetVersion); 1036 return false; 1037 } 1038 1039 LOG(LS_INFO) << "WebRtc VideoEngine Version:"; 1040 LogMultiline(rtc::LS_INFO, buffer); 1041 1042 // Hook up to VoiceEngine for sync purposes, if supplied. 1043 if (!voice_engine_) { 1044 LOG(LS_WARNING) << "NULL voice engine"; 1045 } else if ((vie_wrapper_->base()->SetVoiceEngine( 1046 voice_engine_->voe()->engine())) != 0) { 1047 LOG_RTCERR0(SetVoiceEngine); 1048 return false; 1049 } 1050 1051 // Register our custom render module. 1052 if (vie_wrapper_->render()->RegisterVideoRenderModule( 1053 *render_module_.get()) != 0) { 1054 LOG_RTCERR0(RegisterVideoRenderModule); 1055 return false; 1056 } 1057 1058 initialized_ = true; 1059 return true; 1060 } 1061 1062 void WebRtcVideoEngine::Terminate() { 1063 LOG(LS_INFO) << "WebRtcVideoEngine::Terminate"; 1064 initialized_ = false; 1065 1066 if (vie_wrapper_->render()->DeRegisterVideoRenderModule( 1067 *render_module_.get()) != 0) { 1068 LOG_RTCERR0(DeRegisterVideoRenderModule); 1069 } 1070 1071 if (vie_wrapper_->base()->SetVoiceEngine(NULL) != 0) { 1072 LOG_RTCERR0(SetVoiceEngine); 1073 } 1074 1075 cpu_monitor_->Stop(); 1076 } 1077 1078 int WebRtcVideoEngine::GetCapabilities() { 1079 return VIDEO_RECV | VIDEO_SEND; 1080 } 1081 1082 bool WebRtcVideoEngine::SetDefaultEncoderConfig( 1083 const VideoEncoderConfig& config) { 1084 return SetDefaultCodec(config.max_codec); 1085 } 1086 1087 VideoEncoderConfig WebRtcVideoEngine::GetDefaultEncoderConfig() const { 1088 ASSERT(!video_codecs_.empty()); 1089 VideoCodec max_codec(kVideoCodecPrefs[0].payload_type, 1090 kVideoCodecPrefs[0].name, 1091 video_codecs_[0].width, 1092 video_codecs_[0].height, 1093 video_codecs_[0].framerate, 1094 0); 1095 return VideoEncoderConfig(max_codec); 1096 } 1097 1098 // SetDefaultCodec may be called while the capturer is running. For example, a 1099 // test call is started in a page with QVGA default codec, and then a real call 1100 // is started in another page with VGA default codec. This is the corner case 1101 // and happens only when a session is started. We ignore this case currently. 1102 bool WebRtcVideoEngine::SetDefaultCodec(const VideoCodec& codec) { 1103 if (!RebuildCodecList(codec)) { 1104 LOG(LS_WARNING) << "Failed to RebuildCodecList"; 1105 return false; 1106 } 1107 1108 ASSERT(!video_codecs_.empty()); 1109 default_codec_format_ = VideoFormat( 1110 video_codecs_[0].width, 1111 video_codecs_[0].height, 1112 VideoFormat::FpsToInterval(video_codecs_[0].framerate), 1113 FOURCC_ANY); 1114 return true; 1115 } 1116 1117 WebRtcVideoMediaChannel* WebRtcVideoEngine::CreateChannel( 1118 VoiceMediaChannel* voice_channel) { 1119 WebRtcVideoMediaChannel* channel = 1120 new WebRtcVideoMediaChannel(this, voice_channel); 1121 if (!channel->Init()) { 1122 delete channel; 1123 channel = NULL; 1124 } 1125 return channel; 1126 } 1127 1128 const std::vector<VideoCodec>& WebRtcVideoEngine::codecs() const { 1129 return video_codecs_; 1130 } 1131 1132 const std::vector<RtpHeaderExtension>& 1133 WebRtcVideoEngine::rtp_header_extensions() const { 1134 return rtp_header_extensions_; 1135 } 1136 1137 void WebRtcVideoEngine::SetLogging(int min_sev, const char* filter) { 1138 // if min_sev == -1, we keep the current log level. 1139 if (min_sev >= 0) { 1140 SetTraceFilter(SeverityToFilter(min_sev)); 1141 } 1142 SetTraceOptions(filter); 1143 } 1144 1145 int WebRtcVideoEngine::GetLastEngineError() { 1146 return vie_wrapper_->error(); 1147 } 1148 1149 // Checks to see whether we comprehend and could receive a particular codec 1150 bool WebRtcVideoEngine::FindCodec(const VideoCodec& in) { 1151 if (encoder_factory_) { 1152 const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs = 1153 encoder_factory_->codecs(); 1154 for (size_t j = 0; j < codecs.size(); ++j) { 1155 VideoCodec codec(GetExternalVideoPayloadType(static_cast<int>(j)), 1156 codecs[j].name, 0, 0, 0, 0); 1157 if (codec.Matches(in)) 1158 return true; 1159 } 1160 } 1161 for (size_t j = 0; j < ARRAY_SIZE(kVideoCodecPrefs); ++j) { 1162 VideoCodec codec(kVideoCodecPrefs[j].payload_type, 1163 kVideoCodecPrefs[j].name, 0, 0, 0, 0); 1164 if (codec.Matches(in)) { 1165 return true; 1166 } 1167 } 1168 return false; 1169 } 1170 1171 // Given the requested codec, returns true if we can send that codec type and 1172 // updates out with the best quality we could send for that codec. 1173 // TODO(ronghuawu): Remove |current| from the interface. 1174 bool WebRtcVideoEngine::CanSendCodec(const VideoCodec& requested, 1175 const VideoCodec& /* current */, 1176 VideoCodec* out) { 1177 if (!out) { 1178 return false; 1179 } 1180 1181 std::vector<VideoCodec>::const_iterator local_max; 1182 for (local_max = video_codecs_.begin(); 1183 local_max < video_codecs_.end(); 1184 ++local_max) { 1185 // First match codecs by payload type 1186 if (!requested.Matches(*local_max)) { 1187 continue; 1188 } 1189 1190 out->id = requested.id; 1191 out->name = requested.name; 1192 out->preference = requested.preference; 1193 out->params = requested.params; 1194 out->framerate = rtc::_min(requested.framerate, local_max->framerate); 1195 out->width = 0; 1196 out->height = 0; 1197 out->params = requested.params; 1198 out->feedback_params = requested.feedback_params; 1199 1200 if (0 == requested.width && 0 == requested.height) { 1201 // Special case with resolution 0. The channel should not send frames. 1202 return true; 1203 } else if (0 == requested.width || 0 == requested.height) { 1204 // 0xn and nx0 are invalid resolutions. 1205 return false; 1206 } 1207 1208 // Reduce the requested size by /= 2 until it's width under 1209 // |local_max->width|. 1210 out->width = requested.width; 1211 out->height = requested.height; 1212 while (out->width > local_max->width) { 1213 out->width /= 2; 1214 out->height /= 2; 1215 } 1216 1217 if (out->width > 0 && out->height > 0) { 1218 return true; 1219 } 1220 } 1221 return false; 1222 } 1223 1224 static void ConvertToCricketVideoCodec( 1225 const webrtc::VideoCodec& in_codec, VideoCodec* out_codec) { 1226 out_codec->id = in_codec.plType; 1227 out_codec->name = in_codec.plName; 1228 out_codec->width = in_codec.width; 1229 out_codec->height = in_codec.height; 1230 out_codec->framerate = in_codec.maxFramerate; 1231 if (BitrateIsSet(in_codec.minBitrate)) { 1232 out_codec->SetParam(kCodecParamMinBitrate, in_codec.minBitrate); 1233 } 1234 if (BitrateIsSet(in_codec.maxBitrate)) { 1235 out_codec->SetParam(kCodecParamMaxBitrate, in_codec.maxBitrate); 1236 } 1237 if (BitrateIsSet(in_codec.startBitrate)) { 1238 out_codec->SetParam(kCodecParamStartBitrate, in_codec.startBitrate); 1239 } 1240 if (in_codec.qpMax) { 1241 out_codec->SetParam(kCodecParamMaxQuantization, in_codec.qpMax); 1242 } 1243 } 1244 1245 bool WebRtcVideoEngine::ConvertFromCricketVideoCodec( 1246 const VideoCodec& in_codec, webrtc::VideoCodec* out_codec) { 1247 bool found = false; 1248 int ncodecs = vie_wrapper_->codec()->NumberOfCodecs(); 1249 for (int i = 0; i < ncodecs; ++i) { 1250 if (vie_wrapper_->codec()->GetCodec(i, *out_codec) == 0 && 1251 _stricmp(in_codec.name.c_str(), out_codec->plName) == 0) { 1252 found = true; 1253 break; 1254 } 1255 } 1256 1257 // If not found, check if this is supported by external encoder factory. 1258 if (!found && encoder_factory_) { 1259 const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs = 1260 encoder_factory_->codecs(); 1261 for (size_t i = 0; i < codecs.size(); ++i) { 1262 if (_stricmp(in_codec.name.c_str(), codecs[i].name.c_str()) == 0) { 1263 out_codec->codecType = codecs[i].type; 1264 out_codec->plType = GetExternalVideoPayloadType(static_cast<int>(i)); 1265 rtc::strcpyn(out_codec->plName, sizeof(out_codec->plName), 1266 codecs[i].name.c_str(), codecs[i].name.length()); 1267 found = true; 1268 break; 1269 } 1270 } 1271 } 1272 1273 // Is this an RTX codec? Handled separately here since webrtc doesn't handle 1274 // them as webrtc::VideoCodec internally. 1275 if (!found && _stricmp(in_codec.name.c_str(), kRtxCodecName) == 0) { 1276 rtc::strcpyn(out_codec->plName, sizeof(out_codec->plName), 1277 in_codec.name.c_str(), in_codec.name.length()); 1278 out_codec->plType = in_codec.id; 1279 found = true; 1280 } 1281 1282 if (!found) { 1283 LOG(LS_ERROR) << "invalid codec type"; 1284 return false; 1285 } 1286 1287 if (in_codec.id != 0) 1288 out_codec->plType = in_codec.id; 1289 1290 if (in_codec.width != 0) 1291 out_codec->width = in_codec.width; 1292 1293 if (in_codec.height != 0) 1294 out_codec->height = in_codec.height; 1295 1296 if (in_codec.framerate != 0) 1297 out_codec->maxFramerate = in_codec.framerate; 1298 1299 // Convert bitrate parameters. 1300 int max_bitrate = -1; 1301 int min_bitrate = -1; 1302 int start_bitrate = -1; 1303 1304 in_codec.GetParam(kCodecParamMinBitrate, &min_bitrate); 1305 in_codec.GetParam(kCodecParamMaxBitrate, &max_bitrate); 1306 in_codec.GetParam(kCodecParamStartBitrate, &start_bitrate); 1307 1308 1309 out_codec->minBitrate = min_bitrate; 1310 out_codec->startBitrate = start_bitrate; 1311 out_codec->maxBitrate = max_bitrate; 1312 1313 // Convert general codec parameters. 1314 int max_quantization = 0; 1315 if (in_codec.GetParam(kCodecParamMaxQuantization, &max_quantization)) { 1316 if (max_quantization < 0) { 1317 return false; 1318 } 1319 out_codec->qpMax = max_quantization; 1320 } 1321 return true; 1322 } 1323 1324 void WebRtcVideoEngine::RegisterChannel(WebRtcVideoMediaChannel *channel) { 1325 rtc::CritScope cs(&channels_crit_); 1326 channels_.push_back(channel); 1327 } 1328 1329 void WebRtcVideoEngine::UnregisterChannel(WebRtcVideoMediaChannel *channel) { 1330 rtc::CritScope cs(&channels_crit_); 1331 channels_.erase(std::remove(channels_.begin(), channels_.end(), channel), 1332 channels_.end()); 1333 } 1334 1335 bool WebRtcVideoEngine::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) { 1336 if (initialized_) { 1337 LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init"; 1338 return false; 1339 } 1340 voice_engine_ = voice_engine; 1341 return true; 1342 } 1343 1344 bool WebRtcVideoEngine::EnableTimedRender() { 1345 if (initialized_) { 1346 LOG(LS_WARNING) << "EnableTimedRender can not be called after Init"; 1347 return false; 1348 } 1349 render_module_.reset(webrtc::VideoRender::CreateVideoRender(0, NULL, 1350 false, webrtc::kRenderExternal)); 1351 return true; 1352 } 1353 1354 void WebRtcVideoEngine::SetTraceFilter(int filter) { 1355 tracing_->SetTraceFilter(filter); 1356 } 1357 1358 // See https://sites.google.com/a/google.com/wavelet/ 1359 // Home/Magic-Flute--RTC-Engine-/Magic-Flute-Command-Line-Parameters 1360 // for all supported command line setttings. 1361 void WebRtcVideoEngine::SetTraceOptions(const std::string& options) { 1362 // Set WebRTC trace file. 1363 std::vector<std::string> opts; 1364 rtc::tokenize(options, ' ', '"', '"', &opts); 1365 std::vector<std::string>::iterator tracefile = 1366 std::find(opts.begin(), opts.end(), "tracefile"); 1367 if (tracefile != opts.end() && ++tracefile != opts.end()) { 1368 // Write WebRTC debug output (at same loglevel) to file 1369 if (tracing_->SetTraceFile(tracefile->c_str()) == -1) { 1370 LOG_RTCERR1(SetTraceFile, *tracefile); 1371 } 1372 } 1373 } 1374 1375 static void AddDefaultFeedbackParams(VideoCodec* codec) { 1376 const FeedbackParam kFir(kRtcpFbParamCcm, kRtcpFbCcmParamFir); 1377 codec->AddFeedbackParam(kFir); 1378 const FeedbackParam kNack(kRtcpFbParamNack, kParamValueEmpty); 1379 codec->AddFeedbackParam(kNack); 1380 const FeedbackParam kPli(kRtcpFbParamNack, kRtcpFbNackParamPli); 1381 codec->AddFeedbackParam(kPli); 1382 const FeedbackParam kRemb(kRtcpFbParamRemb, kParamValueEmpty); 1383 codec->AddFeedbackParam(kRemb); 1384 } 1385 1386 // Rebuilds the codec list to be only those that are less intensive 1387 // than the specified codec. Prefers internal codec over external with 1388 // higher preference field. 1389 bool WebRtcVideoEngine::RebuildCodecList(const VideoCodec& in_codec) { 1390 if (!FindCodec(in_codec)) 1391 return false; 1392 1393 video_codecs_.clear(); 1394 1395 bool found = false; 1396 std::set<std::string> internal_codec_names; 1397 for (size_t i = 0; i < ARRAY_SIZE(kVideoCodecPrefs); ++i) { 1398 const VideoCodecPref& pref(kVideoCodecPrefs[i]); 1399 if (!found) 1400 found = (in_codec.name == pref.name); 1401 if (found) { 1402 VideoCodec codec(pref.payload_type, pref.name, 1403 in_codec.width, in_codec.height, in_codec.framerate, 1404 static_cast<int>(ARRAY_SIZE(kVideoCodecPrefs) - i)); 1405 if (_stricmp(kVp8CodecName, codec.name.c_str()) == 0) { 1406 AddDefaultFeedbackParams(&codec); 1407 } 1408 if (pref.associated_payload_type != -1) { 1409 codec.SetParam(kCodecParamAssociatedPayloadType, 1410 pref.associated_payload_type); 1411 } 1412 video_codecs_.push_back(codec); 1413 internal_codec_names.insert(codec.name); 1414 } 1415 } 1416 if (encoder_factory_) { 1417 const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs = 1418 encoder_factory_->codecs(); 1419 for (size_t i = 0; i < codecs.size(); ++i) { 1420 bool is_internal_codec = internal_codec_names.find(codecs[i].name) != 1421 internal_codec_names.end(); 1422 if (!is_internal_codec) { 1423 if (!found) 1424 found = (in_codec.name == codecs[i].name); 1425 VideoCodec codec( 1426 GetExternalVideoPayloadType(static_cast<int>(i)), 1427 codecs[i].name, 1428 codecs[i].max_width, 1429 codecs[i].max_height, 1430 codecs[i].max_fps, 1431 // Use negative preference on external codec to ensure the internal 1432 // codec is preferred. 1433 static_cast<int>(0 - i)); 1434 AddDefaultFeedbackParams(&codec); 1435 video_codecs_.push_back(codec); 1436 } 1437 } 1438 } 1439 ASSERT(found); 1440 return true; 1441 } 1442 1443 // Ignore spammy trace messages, mostly from the stats API when we haven't 1444 // gotten RTCP info yet from the remote side. 1445 bool WebRtcVideoEngine::ShouldIgnoreTrace(const std::string& trace) { 1446 static const char* const kTracesToIgnore[] = { 1447 NULL 1448 }; 1449 for (const char* const* p = kTracesToIgnore; *p; ++p) { 1450 if (trace.find(*p) == 0) { 1451 return true; 1452 } 1453 } 1454 return false; 1455 } 1456 1457 int WebRtcVideoEngine::GetNumOfChannels() { 1458 rtc::CritScope cs(&channels_crit_); 1459 return static_cast<int>(channels_.size()); 1460 } 1461 1462 void WebRtcVideoEngine::Print(webrtc::TraceLevel level, const char* trace, 1463 int length) { 1464 rtc::LoggingSeverity sev = rtc::LS_VERBOSE; 1465 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical) 1466 sev = rtc::LS_ERROR; 1467 else if (level == webrtc::kTraceWarning) 1468 sev = rtc::LS_WARNING; 1469 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo) 1470 sev = rtc::LS_INFO; 1471 else if (level == webrtc::kTraceTerseInfo) 1472 sev = rtc::LS_INFO; 1473 1474 // Skip past boilerplate prefix text 1475 if (length < 72) { 1476 std::string msg(trace, length); 1477 LOG(LS_ERROR) << "Malformed webrtc log message: "; 1478 LOG_V(sev) << msg; 1479 } else { 1480 std::string msg(trace + 71, length - 72); 1481 if (!ShouldIgnoreTrace(msg) && 1482 (!voice_engine_ || !voice_engine_->ShouldIgnoreTrace(msg))) { 1483 LOG_V(sev) << "webrtc: " << msg; 1484 } 1485 } 1486 } 1487 1488 webrtc::VideoDecoder* WebRtcVideoEngine::CreateExternalDecoder( 1489 webrtc::VideoCodecType type) { 1490 if (!decoder_factory_) { 1491 return NULL; 1492 } 1493 return decoder_factory_->CreateVideoDecoder(type); 1494 } 1495 1496 void WebRtcVideoEngine::DestroyExternalDecoder(webrtc::VideoDecoder* decoder) { 1497 ASSERT(decoder_factory_ != NULL); 1498 if (!decoder_factory_) 1499 return; 1500 decoder_factory_->DestroyVideoDecoder(decoder); 1501 } 1502 1503 webrtc::VideoEncoder* WebRtcVideoEngine::CreateExternalEncoder( 1504 webrtc::VideoCodecType type) { 1505 if (!encoder_factory_) { 1506 return NULL; 1507 } 1508 return encoder_factory_->CreateVideoEncoder(type); 1509 } 1510 1511 void WebRtcVideoEngine::DestroyExternalEncoder(webrtc::VideoEncoder* encoder) { 1512 ASSERT(encoder_factory_ != NULL); 1513 if (!encoder_factory_) 1514 return; 1515 encoder_factory_->DestroyVideoEncoder(encoder); 1516 } 1517 1518 bool WebRtcVideoEngine::IsExternalEncoderCodecType( 1519 webrtc::VideoCodecType type) const { 1520 if (!encoder_factory_) 1521 return false; 1522 const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs = 1523 encoder_factory_->codecs(); 1524 std::vector<WebRtcVideoEncoderFactory::VideoCodec>::const_iterator it; 1525 for (it = codecs.begin(); it != codecs.end(); ++it) { 1526 if (it->type == type) 1527 return true; 1528 } 1529 return false; 1530 } 1531 1532 void WebRtcVideoEngine::SetExternalDecoderFactory( 1533 WebRtcVideoDecoderFactory* decoder_factory) { 1534 decoder_factory_ = decoder_factory; 1535 } 1536 1537 void WebRtcVideoEngine::SetExternalEncoderFactory( 1538 WebRtcVideoEncoderFactory* encoder_factory) { 1539 if (encoder_factory_ == encoder_factory) 1540 return; 1541 1542 if (encoder_factory_) { 1543 encoder_factory_->RemoveObserver(this); 1544 } 1545 encoder_factory_ = encoder_factory; 1546 if (encoder_factory_) { 1547 encoder_factory_->AddObserver(this); 1548 } 1549 1550 // Invoke OnCodecAvailable() here in case the list of codecs is already 1551 // available when the encoder factory is installed. If not the encoder 1552 // factory will invoke the callback later when the codecs become available. 1553 OnCodecsAvailable(); 1554 } 1555 1556 void WebRtcVideoEngine::OnCodecsAvailable() { 1557 // Rebuild codec list while reapplying the current default codec format. 1558 VideoCodec max_codec(kVideoCodecPrefs[0].payload_type, 1559 kVideoCodecPrefs[0].name, 1560 video_codecs_[0].width, 1561 video_codecs_[0].height, 1562 video_codecs_[0].framerate, 1563 0); 1564 if (!RebuildCodecList(max_codec)) { 1565 LOG(LS_ERROR) << "Failed to initialize list of supported codec types"; 1566 } 1567 } 1568 1569 // WebRtcVideoMediaChannel 1570 1571 WebRtcVideoMediaChannel::WebRtcVideoMediaChannel( 1572 WebRtcVideoEngine* engine, 1573 VoiceMediaChannel* channel) 1574 : engine_(engine), 1575 voice_channel_(channel), 1576 default_channel_id_(kChannelIdUnset), 1577 nack_enabled_(true), 1578 remb_enabled_(false), 1579 render_started_(false), 1580 first_receive_ssrc_(kSsrcUnset), 1581 receiver_report_ssrc_(kSsrcUnset), 1582 num_unsignalled_recv_channels_(0), 1583 send_rtx_type_(-1), 1584 send_red_type_(-1), 1585 send_fec_type_(-1), 1586 sending_(false), 1587 ratio_w_(0), 1588 ratio_h_(0) { 1589 engine->RegisterChannel(this); 1590 } 1591 1592 bool WebRtcVideoMediaChannel::Init() { 1593 const uint32 ssrc_key = 0; 1594 bool result = CreateChannel(ssrc_key, MD_SENDRECV, &default_channel_id_); 1595 if (!result) { 1596 return false; 1597 } 1598 if (voice_channel_) { 1599 WebRtcVoiceMediaChannel* voice_channel = 1600 static_cast<WebRtcVoiceMediaChannel*>(voice_channel_); 1601 if (!voice_channel->SetupSharedBandwidthEstimation( 1602 engine()->vie()->engine(), default_channel_id_)) { 1603 return false; 1604 } 1605 } 1606 return true; 1607 } 1608 1609 WebRtcVideoMediaChannel::~WebRtcVideoMediaChannel() { 1610 const bool send = false; 1611 SetSend(send); 1612 const bool render = false; 1613 SetRender(render); 1614 1615 while (!send_channels_.empty()) { 1616 if (!DeleteSendChannel(send_channels_.begin()->first)) { 1617 LOG(LS_ERROR) << "Unable to delete channel with ssrc key " 1618 << send_channels_.begin()->first; 1619 ASSERT(false); 1620 break; 1621 } 1622 } 1623 1624 // Remove all receive streams and the default channel. 1625 while (!recv_channels_.empty()) { 1626 RemoveRecvStreamInternal(recv_channels_.begin()->first); 1627 } 1628 1629 // Unregister the channel from the engine. 1630 engine()->UnregisterChannel(this); 1631 if (worker_thread()) { 1632 worker_thread()->Clear(this); 1633 } 1634 } 1635 1636 bool WebRtcVideoMediaChannel::SetRecvCodecs( 1637 const std::vector<VideoCodec>& codecs) { 1638 receive_codecs_.clear(); 1639 associated_payload_types_.clear(); 1640 for (std::vector<VideoCodec>::const_iterator iter = codecs.begin(); 1641 iter != codecs.end(); ++iter) { 1642 if (engine()->FindCodec(*iter)) { 1643 webrtc::VideoCodec wcodec; 1644 if (engine()->ConvertFromCricketVideoCodec(*iter, &wcodec)) { 1645 receive_codecs_.push_back(wcodec); 1646 int apt; 1647 if (iter->GetParam(cricket::kCodecParamAssociatedPayloadType, &apt)) { 1648 associated_payload_types_[wcodec.plType] = apt; 1649 } 1650 } 1651 } else { 1652 LOG(LS_INFO) << "Unknown codec " << iter->name; 1653 return false; 1654 } 1655 } 1656 1657 for (RecvChannelMap::iterator it = recv_channels_.begin(); 1658 it != recv_channels_.end(); ++it) { 1659 if (!SetReceiveCodecs(it->second)) 1660 return false; 1661 } 1662 return true; 1663 } 1664 1665 bool WebRtcVideoMediaChannel::SetSendCodecs( 1666 const std::vector<VideoCodec>& codecs) { 1667 // Match with local video codec list. 1668 std::vector<webrtc::VideoCodec> send_codecs; 1669 VideoCodec checked_codec; 1670 VideoCodec dummy_current; // Will be ignored by CanSendCodec. 1671 std::map<int, int> primary_rtx_pt_mapping; 1672 bool nack_enabled = nack_enabled_; 1673 bool remb_enabled = remb_enabled_; 1674 for (std::vector<VideoCodec>::const_iterator iter = codecs.begin(); 1675 iter != codecs.end(); ++iter) { 1676 if (_stricmp(iter->name.c_str(), kRedCodecName) == 0) { 1677 send_red_type_ = iter->id; 1678 } else if (_stricmp(iter->name.c_str(), kUlpfecCodecName) == 0) { 1679 send_fec_type_ = iter->id; 1680 } else if (_stricmp(iter->name.c_str(), kRtxCodecName) == 0) { 1681 int rtx_type = iter->id; 1682 int rtx_primary_type = -1; 1683 if (iter->GetParam(kCodecParamAssociatedPayloadType, &rtx_primary_type)) { 1684 primary_rtx_pt_mapping[rtx_primary_type] = rtx_type; 1685 } 1686 } else if (engine()->CanSendCodec(*iter, dummy_current, &checked_codec)) { 1687 webrtc::VideoCodec wcodec; 1688 if (engine()->ConvertFromCricketVideoCodec(checked_codec, &wcodec)) { 1689 if (send_codecs.empty()) { 1690 nack_enabled = IsNackEnabled(checked_codec); 1691 remb_enabled = IsRembEnabled(checked_codec); 1692 } 1693 send_codecs.push_back(wcodec); 1694 } 1695 } else { 1696 LOG(LS_WARNING) << "Unknown codec " << iter->name; 1697 } 1698 } 1699 1700 // Fail if we don't have a match. 1701 if (send_codecs.empty()) { 1702 LOG(LS_WARNING) << "No matching codecs available"; 1703 return false; 1704 } 1705 1706 // Recv protection. 1707 // Do not update if the status is same as previously configured. 1708 if (nack_enabled_ != nack_enabled) { 1709 for (RecvChannelMap::iterator it = recv_channels_.begin(); 1710 it != recv_channels_.end(); ++it) { 1711 int channel_id = it->second->channel_id(); 1712 if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, 1713 nack_enabled)) { 1714 return false; 1715 } 1716 if (engine_->vie()->rtp()->SetRembStatus(channel_id, 1717 kNotSending, 1718 remb_enabled_) != 0) { 1719 LOG_RTCERR3(SetRembStatus, channel_id, kNotSending, remb_enabled_); 1720 return false; 1721 } 1722 } 1723 nack_enabled_ = nack_enabled; 1724 } 1725 1726 // Send settings. 1727 // Do not update if the status is same as previously configured. 1728 if (remb_enabled_ != remb_enabled) { 1729 for (SendChannelMap::iterator iter = send_channels_.begin(); 1730 iter != send_channels_.end(); ++iter) { 1731 int channel_id = iter->second->channel_id(); 1732 if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, 1733 nack_enabled_)) { 1734 return false; 1735 } 1736 if (engine_->vie()->rtp()->SetRembStatus(channel_id, 1737 remb_enabled, 1738 remb_enabled) != 0) { 1739 LOG_RTCERR3(SetRembStatus, channel_id, remb_enabled, remb_enabled); 1740 return false; 1741 } 1742 } 1743 remb_enabled_ = remb_enabled; 1744 } 1745 1746 // Select the first matched codec. 1747 webrtc::VideoCodec& codec(send_codecs[0]); 1748 1749 // Set RTX payload type if primary now active. This value will be used in 1750 // SetSendCodec. 1751 std::map<int, int>::const_iterator rtx_it = 1752 primary_rtx_pt_mapping.find(static_cast<int>(codec.plType)); 1753 if (rtx_it != primary_rtx_pt_mapping.end()) { 1754 send_rtx_type_ = rtx_it->second; 1755 } 1756 1757 if (BitrateIsSet(codec.minBitrate) && BitrateIsSet(codec.maxBitrate) && 1758 codec.minBitrate > codec.maxBitrate) { 1759 // TODO(pthatcher): This behavior contradicts other behavior in 1760 // this file which will cause min > max to push the min down to 1761 // the max. There are unit tests for both behaviors. We should 1762 // pick one and do that. 1763 LOG(LS_INFO) << "Rejecting codec with min bitrate (" 1764 << codec.minBitrate << ") larger than max (" 1765 << codec.maxBitrate << "). "; 1766 return false; 1767 } 1768 1769 if (!SetSendCodec(codec)) { 1770 return false; 1771 } 1772 1773 LogSendCodecChange("SetSendCodecs()"); 1774 1775 return true; 1776 } 1777 1778 bool WebRtcVideoMediaChannel::MaybeRegisterExternalEncoder( 1779 WebRtcVideoChannelSendInfo* send_channel, 1780 const webrtc::VideoCodec& codec) { 1781 // Codec type not supported or encoder already registered, so 1782 // nothing to do. 1783 if (!engine()->IsExternalEncoderCodecType(codec.codecType) 1784 || send_channel->IsEncoderRegistered(codec.plType)) { 1785 return true; 1786 } 1787 1788 webrtc::VideoEncoder* encoder = 1789 engine()->CreateExternalEncoder(codec.codecType); 1790 if (!encoder) { 1791 // No encoder factor, so nothing to do. 1792 return true; 1793 } 1794 1795 const int channel_id = send_channel->channel_id(); 1796 if (engine()->vie()->ext_codec()->RegisterExternalSendCodec( 1797 channel_id, codec.plType, encoder, false) != 0) { 1798 LOG_RTCERR2(RegisterExternalSendCodec, channel_id, codec.plName); 1799 engine()->DestroyExternalEncoder(encoder); 1800 return false; 1801 } 1802 1803 send_channel->RegisterEncoder(codec.plType, encoder); 1804 return true; 1805 } 1806 1807 bool WebRtcVideoMediaChannel::GetSendCodec(VideoCodec* send_codec) { 1808 if (!send_codec_) { 1809 return false; 1810 } 1811 ConvertToCricketVideoCodec(*send_codec_, send_codec); 1812 return true; 1813 } 1814 1815 bool WebRtcVideoMediaChannel::SetSendStreamFormat(uint32 ssrc, 1816 const VideoFormat& format) { 1817 WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); 1818 if (!send_channel) { 1819 LOG(LS_ERROR) << "The specified ssrc " << ssrc << " is not in use."; 1820 return false; 1821 } 1822 send_channel->set_video_format(format); 1823 return true; 1824 } 1825 1826 bool WebRtcVideoMediaChannel::SetRender(bool render) { 1827 if (render == render_started_) { 1828 return true; // no action required 1829 } 1830 1831 bool ret = true; 1832 for (RecvChannelMap::iterator it = recv_channels_.begin(); 1833 it != recv_channels_.end(); ++it) { 1834 if (render) { 1835 if (engine()->vie()->render()->StartRender( 1836 it->second->channel_id()) != 0) { 1837 LOG_RTCERR1(StartRender, it->second->channel_id()); 1838 ret = false; 1839 } 1840 } else { 1841 if (engine()->vie()->render()->StopRender( 1842 it->second->channel_id()) != 0) { 1843 LOG_RTCERR1(StopRender, it->second->channel_id()); 1844 ret = false; 1845 } 1846 } 1847 } 1848 if (ret) { 1849 render_started_ = render; 1850 } 1851 1852 return ret; 1853 } 1854 1855 bool WebRtcVideoMediaChannel::SetSend(bool send) { 1856 if (!HasReadySendChannels() && send) { 1857 LOG(LS_ERROR) << "No stream added"; 1858 return false; 1859 } 1860 if (send == sending()) { 1861 return true; // No action required. 1862 } 1863 1864 if (send) { 1865 // We've been asked to start sending. 1866 // SetSendCodecs must have been called already. 1867 if (!send_codec_) { 1868 return false; 1869 } 1870 // Start send now. 1871 if (!StartSend()) { 1872 return false; 1873 } 1874 } else { 1875 // We've been asked to stop sending. 1876 if (!StopSend()) { 1877 return false; 1878 } 1879 } 1880 sending_ = send; 1881 1882 return true; 1883 } 1884 1885 bool WebRtcVideoMediaChannel::AddSendStream(const StreamParams& sp) { 1886 if (sp.first_ssrc() == 0) { 1887 LOG(LS_ERROR) << "AddSendStream with 0 ssrc is not supported."; 1888 return false; 1889 } 1890 1891 LOG(LS_INFO) << "AddSendStream " << sp.ToString(); 1892 1893 if (!IsOneSsrcStream(sp) && !IsSimulcastStream(sp)) { 1894 LOG(LS_ERROR) << "AddSendStream: bad local stream parameters"; 1895 return false; 1896 } 1897 1898 uint32 ssrc_key; 1899 if (!CreateSendChannelSsrcKey(sp.first_ssrc(), &ssrc_key)) { 1900 LOG(LS_ERROR) << "Trying to register duplicate ssrc: " << sp.first_ssrc(); 1901 return false; 1902 } 1903 // If the default channel is already used for sending create a new channel 1904 // otherwise use the default channel for sending. 1905 int channel_id = kChannelIdUnset; 1906 if (!DefaultSendChannelInUse()) { 1907 channel_id = default_channel_id_; 1908 } else { 1909 if (!CreateChannel(ssrc_key, MD_SEND, &channel_id)) { 1910 LOG(LS_ERROR) << "AddSendStream: unable to create channel"; 1911 return false; 1912 } 1913 } 1914 1915 WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrcKey(ssrc_key); 1916 // If there are multiple send SSRCs, we can only set the first one here, and 1917 // the rest of the SSRC(s) need to be set after SetSendCodec has been called 1918 if (!SetLimitedNumberOfSendSsrcs(channel_id, sp, 1)) { 1919 return false; 1920 } 1921 1922 // Set RTCP CName. 1923 if (engine()->vie()->rtp()->SetRTCPCName(channel_id, 1924 sp.cname.c_str()) != 0) { 1925 LOG_RTCERR2(SetRTCPCName, channel_id, sp.cname.c_str()); 1926 return false; 1927 } 1928 1929 // Use the SSRC of the default channel in the RTCP receiver reports. 1930 if (IsDefaultChannelId(channel_id)) { 1931 SetReceiverReportSsrc(sp.first_ssrc()); 1932 } 1933 1934 send_channel->set_stream_params(sp); 1935 1936 // Reset send codec after stream parameters changed. 1937 if (send_codec_) { 1938 if (!SetSendCodec(send_channel, *send_codec_)) { 1939 return false; 1940 } 1941 LogSendCodecChange("SetSendStreamFormat()"); 1942 } 1943 1944 if (sending_) { 1945 return StartSend(send_channel); 1946 } 1947 return true; 1948 } 1949 1950 bool WebRtcVideoMediaChannel::RemoveSendStream(uint32 ssrc) { 1951 if (ssrc == 0) { 1952 LOG(LS_ERROR) << "RemoveSendStream with 0 ssrc is not supported."; 1953 return false; 1954 } 1955 1956 uint32 ssrc_key; 1957 if (!GetSendChannelSsrcKey(ssrc, &ssrc_key)) { 1958 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc 1959 << " which doesn't exist."; 1960 return false; 1961 } 1962 WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrcKey(ssrc_key); 1963 int channel_id = send_channel->channel_id(); 1964 if (IsDefaultChannelId(channel_id) && !send_channel->stream_params()) { 1965 // Default channel will still exist. However, if stream_params() is NULL 1966 // there is no stream to remove. 1967 return false; 1968 } 1969 if (sending_) { 1970 StopSend(send_channel); 1971 } 1972 1973 const WebRtcVideoChannelSendInfo::EncoderMap& encoder_map = 1974 send_channel->registered_encoders(); 1975 for (WebRtcVideoChannelSendInfo::EncoderMap::const_iterator it = 1976 encoder_map.begin(); it != encoder_map.end(); ++it) { 1977 if (engine()->vie()->ext_codec()->DeRegisterExternalSendCodec( 1978 channel_id, it->first) != 0) { 1979 LOG_RTCERR1(DeregisterEncoderObserver, channel_id); 1980 } 1981 engine()->DestroyExternalEncoder(it->second); 1982 } 1983 send_channel->ClearRegisteredEncoders(); 1984 1985 // The receive channels depend on the default channel, recycle it instead. 1986 if (IsDefaultChannelId(channel_id)) { 1987 SetCapturer(GetDefaultSendChannelSsrc(), NULL); 1988 send_channel->ClearStreamParams(); 1989 } else { 1990 return DeleteSendChannel(ssrc_key); 1991 } 1992 return true; 1993 } 1994 1995 bool WebRtcVideoMediaChannel::AddRecvStream(const StreamParams& sp) { 1996 if (sp.first_ssrc() == 0) { 1997 LOG(LS_ERROR) << "AddRecvStream with 0 ssrc is not supported."; 1998 return false; 1999 } 2000 2001 // TODO(zhurunz) Remove this once BWE works properly across different send 2002 // and receive channels. 2003 // Reuse default channel for recv stream in 1:1 call. 2004 if (!InConferenceMode() && first_receive_ssrc_ == kSsrcUnset) { 2005 LOG(LS_INFO) << "Recv stream " << sp.first_ssrc() 2006 << " reuse default channel #" 2007 << default_channel_id_; 2008 first_receive_ssrc_ = sp.first_ssrc(); 2009 if (!MaybeSetRtxSsrc(sp, default_channel_id_)) { 2010 return false; 2011 } 2012 if (render_started_) { 2013 if (engine()->vie()->render()->StartRender(default_channel_id_) !=0) { 2014 LOG_RTCERR1(StartRender, default_channel_id_); 2015 } 2016 } 2017 return true; 2018 } 2019 2020 int channel_id = kChannelIdUnset; 2021 uint32 ssrc = sp.first_ssrc(); 2022 WebRtcVideoChannelRecvInfo* recv_channel = GetRecvChannelBySsrc(ssrc); 2023 if (!recv_channel && first_receive_ssrc_ != ssrc) { 2024 // TODO(perkj): Implement recv media from multiple media SSRCs per stream. 2025 // NOTE: We have two SSRCs per stream when RTX is enabled. 2026 if (!IsOneSsrcStream(sp)) { 2027 LOG(LS_ERROR) << "WebRtcVideoMediaChannel supports one primary SSRC per" 2028 << " stream and one FID SSRC per primary SSRC."; 2029 return false; 2030 } 2031 2032 // Create a new channel for receiving video data. 2033 // In order to get the bandwidth estimation work fine for 2034 // receive only channels, we connect all receiving channels 2035 // to our master send channel. 2036 if (!CreateChannel(sp.first_ssrc(), MD_RECV, &channel_id)) { 2037 return false; 2038 } 2039 } else { 2040 // Already exists. 2041 if (first_receive_ssrc_ == ssrc) { 2042 return false; 2043 } 2044 // Early receive added channel. 2045 channel_id = recv_channel->channel_id(); 2046 } 2047 2048 if (!MaybeSetRtxSsrc(sp, channel_id)) { 2049 return false; 2050 } 2051 2052 LOG(LS_INFO) << "New video stream " << sp.first_ssrc() 2053 << " registered to VideoEngine channel #" 2054 << channel_id << " and connected to channel #" 2055 << default_channel_id_; 2056 return true; 2057 } 2058 2059 bool WebRtcVideoMediaChannel::MaybeSetRtxSsrc(const StreamParams& sp, 2060 int channel_id) { 2061 uint32 rtx_ssrc; 2062 bool has_rtx = sp.GetFidSsrc(sp.first_ssrc(), &rtx_ssrc); 2063 if (has_rtx) { 2064 LOG(LS_INFO) << "Setting rtx ssrc " << rtx_ssrc << " for stream " 2065 << sp.first_ssrc(); 2066 if (engine()->vie()->rtp()->SetRemoteSSRCType( 2067 channel_id, webrtc::kViEStreamTypeRtx, rtx_ssrc) != 0) { 2068 LOG_RTCERR3(SetRemoteSSRCType, channel_id, webrtc::kViEStreamTypeRtx, 2069 rtx_ssrc); 2070 return false; 2071 } 2072 rtx_to_primary_ssrc_[rtx_ssrc] = sp.first_ssrc(); 2073 } 2074 return true; 2075 } 2076 2077 bool WebRtcVideoMediaChannel::RemoveRecvStream(uint32 ssrc) { 2078 if (ssrc == 0) { 2079 LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported."; 2080 return false; 2081 } 2082 return RemoveRecvStreamInternal(ssrc); 2083 } 2084 2085 bool WebRtcVideoMediaChannel::RemoveRecvStreamInternal(uint32 ssrc) { 2086 WebRtcVideoChannelRecvInfo* recv_channel = GetRecvChannelBySsrc(ssrc); 2087 if (!recv_channel) { 2088 // TODO(perkj): Remove this once BWE works properly across different send 2089 // and receive channels. 2090 // The default channel is reused for recv stream in 1:1 call. 2091 if (first_receive_ssrc_ == ssrc) { 2092 first_receive_ssrc_ = kSsrcUnset; 2093 // Need to stop the renderer and remove it since the render window can be 2094 // deleted after this. 2095 if (render_started_) { 2096 if (engine()->vie()->render()->StopRender(default_channel_id_) !=0) { 2097 LOG_RTCERR1(StopRender, recv_channel->channel_id()); 2098 } 2099 } 2100 GetDefaultRecvChannel()->SetRenderer(NULL); 2101 return true; 2102 } 2103 return false; 2104 } 2105 2106 // Remove any RTX SSRC mappings to this stream. 2107 SsrcMap::iterator rtx_it = rtx_to_primary_ssrc_.begin(); 2108 while (rtx_it != rtx_to_primary_ssrc_.end()) { 2109 if (rtx_it->second == ssrc) { 2110 rtx_to_primary_ssrc_.erase(rtx_it++); 2111 } else { 2112 ++rtx_it; 2113 } 2114 } 2115 2116 int channel_id = recv_channel->channel_id(); 2117 if (engine()->vie()->render()->RemoveRenderer(channel_id) != 0) { 2118 LOG_RTCERR1(RemoveRenderer, channel_id); 2119 } 2120 2121 if (engine()->vie()->network()->DeregisterSendTransport(channel_id) !=0) { 2122 LOG_RTCERR1(DeRegisterSendTransport, channel_id); 2123 } 2124 2125 if (engine()->vie()->codec()->DeregisterDecoderObserver( 2126 channel_id) != 0) { 2127 LOG_RTCERR1(DeregisterDecoderObserver, channel_id); 2128 } 2129 2130 const WebRtcVideoChannelRecvInfo::DecoderMap& decoder_map = 2131 recv_channel->registered_decoders(); 2132 for (WebRtcVideoChannelRecvInfo::DecoderMap::const_iterator it = 2133 decoder_map.begin(); it != decoder_map.end(); ++it) { 2134 if (engine()->vie()->ext_codec()->DeRegisterExternalReceiveCodec( 2135 channel_id, it->first) != 0) { 2136 LOG_RTCERR1(DeregisterDecoderObserver, channel_id); 2137 } 2138 engine()->DestroyExternalDecoder(it->second); 2139 } 2140 recv_channel->ClearRegisteredDecoders(); 2141 2142 LOG(LS_INFO) << "Removing video stream " << ssrc 2143 << " with VideoEngine channel #" 2144 << channel_id; 2145 bool ret = true; 2146 if (engine()->vie()->base()->DeleteChannel(channel_id) == -1) { 2147 LOG_RTCERR1(DeleteChannel, channel_id); 2148 ret = false; 2149 } 2150 // Delete the WebRtcVideoChannelRecvInfo pointed to by it->second. 2151 delete recv_channel; 2152 recv_channels_.erase(ssrc); 2153 return ret; 2154 } 2155 2156 bool WebRtcVideoMediaChannel::StartSend() { 2157 bool success = true; 2158 for (SendChannelMap::iterator iter = send_channels_.begin(); 2159 iter != send_channels_.end(); ++iter) { 2160 WebRtcVideoChannelSendInfo* send_channel = iter->second; 2161 if (!StartSend(send_channel)) { 2162 success = false; 2163 } 2164 } 2165 return success; 2166 } 2167 2168 bool WebRtcVideoMediaChannel::StartSend( 2169 WebRtcVideoChannelSendInfo* send_channel) { 2170 const int channel_id = send_channel->channel_id(); 2171 if (engine()->vie()->base()->StartSend(channel_id) != 0) { 2172 LOG_RTCERR1(StartSend, channel_id); 2173 return false; 2174 } 2175 2176 send_channel->set_sending(true); 2177 return true; 2178 } 2179 2180 bool WebRtcVideoMediaChannel::StopSend() { 2181 bool success = true; 2182 for (SendChannelMap::iterator iter = send_channels_.begin(); 2183 iter != send_channels_.end(); ++iter) { 2184 WebRtcVideoChannelSendInfo* send_channel = iter->second; 2185 if (!StopSend(send_channel)) { 2186 success = false; 2187 } 2188 } 2189 return success; 2190 } 2191 2192 bool WebRtcVideoMediaChannel::StopSend( 2193 WebRtcVideoChannelSendInfo* send_channel) { 2194 const int channel_id = send_channel->channel_id(); 2195 if (engine()->vie()->base()->StopSend(channel_id) != 0) { 2196 LOG_RTCERR1(StopSend, channel_id); 2197 return false; 2198 } 2199 send_channel->set_sending(false); 2200 return true; 2201 } 2202 2203 bool WebRtcVideoMediaChannel::SendIntraFrame() { 2204 bool success = true; 2205 for (SendChannelMap::iterator iter = send_channels_.begin(); 2206 iter != send_channels_.end(); 2207 ++iter) { 2208 WebRtcVideoChannelSendInfo* send_channel = iter->second; 2209 const int channel_id = send_channel->channel_id(); 2210 if (engine()->vie()->codec()->SendKeyFrame(channel_id) != 0) { 2211 LOG_RTCERR1(SendKeyFrame, channel_id); 2212 success = false; 2213 } 2214 } 2215 return success; 2216 } 2217 2218 bool WebRtcVideoMediaChannel::HasReadySendChannels() { 2219 return !send_channels_.empty() && 2220 ((send_channels_.size() > 1) || DefaultSendChannelInUse()); 2221 } 2222 2223 bool WebRtcVideoMediaChannel::DefaultSendChannelInUse() { 2224 return GetDefaultSendChannel() && GetDefaultSendChannel()->stream_params(); 2225 } 2226 2227 bool WebRtcVideoMediaChannel::GetSendChannelSsrcKey(uint32 local_ssrc, 2228 uint32* ssrc_key) { 2229 *ssrc_key = kDefaultChannelSsrcKey; 2230 // If a send channel is not ready to send it will not have local_ssrc 2231 // registered to it. 2232 if (!HasReadySendChannels()) { 2233 return false; 2234 } 2235 // The default channel is stored with ssrc key 2236 // kDefaultChannelSsrcKey. The ssrc key therefore does not match the 2237 // SSRC associated with the default channel. Check if the SSRC 2238 // provided corresponds to the default channel's SSRC. 2239 if (local_ssrc == GetDefaultSendChannelSsrc()) { 2240 return true; 2241 } 2242 if (!GetSendChannelBySsrcKey(local_ssrc)) { 2243 // If a stream has multiple ssrcs, the local_ssrc could be any of 2244 // them, but we use the first one (StreamParams::first_ssrc()) as 2245 // the key. 2246 for (SendChannelMap::iterator iter = send_channels_.begin(); 2247 iter != send_channels_.end(); ++iter) { 2248 WebRtcVideoChannelSendInfo* send_channel = iter->second; 2249 if (send_channel->has_ssrc(local_ssrc)) { 2250 *ssrc_key = iter->first; 2251 return true; 2252 } 2253 } 2254 return false; 2255 } 2256 // The ssrc key was found in the above std::map::find call. This 2257 // means that the ssrc is the ssrc key. 2258 *ssrc_key = local_ssrc; 2259 return true; 2260 } 2261 2262 WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetDefaultSendChannel() { 2263 return GetSendChannelBySsrcKey(kDefaultChannelSsrcKey); 2264 } 2265 2266 WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannelBySsrcKey( 2267 uint32 ssrc_key) { 2268 std::map<uint32, WebRtcVideoChannelSendInfo *>::iterator iter = 2269 send_channels_.find(ssrc_key); 2270 if (iter == send_channels_.end()) { 2271 return NULL; 2272 } 2273 return iter->second; 2274 } 2275 2276 WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannelBySsrc( 2277 uint32 local_ssrc) { 2278 uint32 ssrc_key; 2279 if (!GetSendChannelSsrcKey(local_ssrc, &ssrc_key)) { 2280 return NULL; 2281 } 2282 return send_channels_[ssrc_key]; 2283 } 2284 2285 bool WebRtcVideoMediaChannel::CreateSendChannelSsrcKey(uint32 local_ssrc, 2286 uint32* ssrc_key) { 2287 if (GetSendChannelSsrcKey(local_ssrc, ssrc_key)) { 2288 // If there is an ssrc key corresponding to |local_ssrc|, the SSRC 2289 // is already in use. SSRCs need to be unique in a session and at 2290 // this point a duplicate SSRC has been detected. 2291 return false; 2292 } 2293 if (!DefaultSendChannelInUse()) { 2294 // |ssrc_key| should be kDefaultChannelSsrcKey here as the default 2295 // channel should be re-used whenever it is not used. 2296 *ssrc_key = kDefaultChannelSsrcKey; 2297 return true; 2298 } 2299 // SSRC is currently not in use and the default channel is already 2300 // in use. Use the SSRC as ssrc_key since it is supposed to be 2301 // unique in a session. 2302 *ssrc_key = local_ssrc; 2303 return true; 2304 } 2305 2306 int WebRtcVideoMediaChannel::GetSendChannelNum(VideoCapturer* capturer) { 2307 int num = 0; 2308 for (SendChannelMap::iterator iter = send_channels_.begin(); 2309 iter != send_channels_.end(); ++iter) { 2310 WebRtcVideoChannelSendInfo* send_channel = iter->second; 2311 if (send_channel->video_capturer() == capturer) { 2312 ++num; 2313 } 2314 } 2315 return num; 2316 } 2317 2318 uint32 WebRtcVideoMediaChannel::GetDefaultSendChannelSsrc() { 2319 if (!DefaultSendChannelInUse()) { 2320 return 0; 2321 } 2322 return GetDefaultSendChannel()->stream_params()->first_ssrc(); 2323 } 2324 2325 bool WebRtcVideoMediaChannel::DeleteSendChannel(uint32 ssrc_key) { 2326 WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrcKey(ssrc_key); 2327 if (!send_channel) { 2328 return false; 2329 } 2330 MaybeDisconnectCapturer(send_channel->video_capturer()); 2331 send_channel->set_video_capturer(NULL, engine()->vie()); 2332 2333 int channel_id = send_channel->channel_id(); 2334 int capture_id = send_channel->capture_id(); 2335 if (engine()->vie()->codec()->DeregisterEncoderObserver( 2336 channel_id) != 0) { 2337 LOG_RTCERR1(DeregisterEncoderObserver, channel_id); 2338 } 2339 2340 // Destroy the external capture interface. 2341 if (engine()->vie()->capture()->DisconnectCaptureDevice( 2342 channel_id) != 0) { 2343 LOG_RTCERR1(DisconnectCaptureDevice, channel_id); 2344 } 2345 if (engine()->vie()->capture()->ReleaseCaptureDevice( 2346 capture_id) != 0) { 2347 LOG_RTCERR1(ReleaseCaptureDevice, capture_id); 2348 } 2349 2350 // The default channel is stored in both |send_channels_| and 2351 // |recv_channels_|. To make sure it is only deleted once from vie let the 2352 // delete call happen when tearing down |recv_channels_| and not here. 2353 if (!IsDefaultChannelId(channel_id)) { 2354 engine_->vie()->base()->DeleteChannel(channel_id); 2355 } 2356 delete send_channel; 2357 send_channels_.erase(ssrc_key); 2358 return true; 2359 } 2360 2361 WebRtcVideoChannelRecvInfo* WebRtcVideoMediaChannel::GetDefaultRecvChannel() { 2362 return GetRecvChannelBySsrc(kDefaultChannelSsrcKey); 2363 } 2364 2365 WebRtcVideoChannelRecvInfo* WebRtcVideoMediaChannel::GetRecvChannelBySsrc( 2366 uint32 ssrc) { 2367 if (recv_channels_.find(ssrc) == recv_channels_.end()) { 2368 return NULL; 2369 } 2370 return recv_channels_[ssrc]; 2371 } 2372 2373 bool WebRtcVideoMediaChannel::RemoveCapturer(uint32 ssrc) { 2374 WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); 2375 if (!send_channel) { 2376 return false; 2377 } 2378 VideoCapturer* capturer = send_channel->video_capturer(); 2379 if (!capturer) { 2380 return false; 2381 } 2382 MaybeDisconnectCapturer(capturer); 2383 send_channel->set_video_capturer(NULL, engine()->vie()); 2384 const int64 timestamp = send_channel->local_stream_info()->time_stamp(); 2385 if (send_codec_) { 2386 QueueBlackFrame(ssrc, timestamp, send_codec_->maxFramerate); 2387 } 2388 return true; 2389 } 2390 2391 bool WebRtcVideoMediaChannel::SetRenderer(uint32 ssrc, 2392 VideoRenderer* renderer) { 2393 WebRtcVideoChannelRecvInfo* recv_channel = GetRecvChannelBySsrc(ssrc); 2394 if (!recv_channel) { 2395 // TODO(perkj): Remove this once BWE works properly across different send 2396 // and receive channels. 2397 // The default channel is reused for recv stream in 1:1 call. 2398 if (first_receive_ssrc_ == ssrc && GetDefaultRecvChannel()) { 2399 LOG(LS_INFO) << "SetRenderer " << ssrc 2400 << " reuse default channel #" 2401 << default_channel_id_; 2402 GetDefaultRecvChannel()->SetRenderer(renderer); 2403 return true; 2404 } 2405 return false; 2406 } 2407 2408 recv_channel->SetRenderer(renderer); 2409 return true; 2410 } 2411 2412 bool WebRtcVideoMediaChannel::GetStats(const StatsOptions& options, 2413 VideoMediaInfo* info) { 2414 // Get sender statistics and build VideoSenderInfo. 2415 unsigned int total_bitrate_sent = 0; 2416 unsigned int video_bitrate_sent = 0; 2417 unsigned int fec_bitrate_sent = 0; 2418 unsigned int nack_bitrate_sent = 0; 2419 unsigned int estimated_send_bandwidth = 0; 2420 unsigned int target_enc_bitrate = 0; 2421 if (send_codec_) { 2422 for (SendChannelMap::const_iterator iter = send_channels_.begin(); 2423 iter != send_channels_.end(); ++iter) { 2424 WebRtcVideoChannelSendInfo* send_channel = iter->second; 2425 const int channel_id = send_channel->channel_id(); 2426 VideoSenderInfo sinfo; 2427 const StreamParams* send_params = send_channel->stream_params(); 2428 if (!send_params) { 2429 // This should only happen if the default vie channel is not in use. 2430 // This can happen if no streams have ever been added or the stream 2431 // corresponding to the default channel has been removed. Note that 2432 // there may be non-default vie channels in use when this happen so 2433 // asserting send_channels_.size() == 1 is not correct and neither is 2434 // breaking out of the loop. 2435 ASSERT(channel_id == default_channel_id_); 2436 continue; 2437 } 2438 unsigned int bytes_sent, packets_sent, bytes_recv, packets_recv; 2439 if (engine_->vie()->rtp()->GetRTPStatistics(channel_id, bytes_sent, 2440 packets_sent, bytes_recv, 2441 packets_recv) != 0) { 2442 LOG_RTCERR1(GetRTPStatistics, default_channel_id_); 2443 continue; 2444 } 2445 WebRtcLocalStreamInfo* channel_stream_info = 2446 send_channel->local_stream_info(); 2447 2448 for (size_t i = 0; i < send_params->ssrcs.size(); ++i) { 2449 sinfo.add_ssrc(send_params->ssrcs[i]); 2450 } 2451 sinfo.codec_name = send_codec_->plName; 2452 sinfo.bytes_sent = bytes_sent; 2453 sinfo.packets_sent = packets_sent; 2454 sinfo.packets_cached = -1; 2455 sinfo.packets_lost = -1; 2456 sinfo.fraction_lost = -1; 2457 sinfo.rtt_ms = -1; 2458 2459 VideoCapturer* video_capturer = send_channel->video_capturer(); 2460 if (video_capturer) { 2461 VideoFormat last_captured_frame_format; 2462 video_capturer->GetStats(&sinfo.adapt_frame_drops, 2463 &sinfo.effects_frame_drops, 2464 &sinfo.capturer_frame_time, 2465 &last_captured_frame_format); 2466 sinfo.input_frame_width = last_captured_frame_format.width; 2467 sinfo.input_frame_height = last_captured_frame_format.height; 2468 } else { 2469 sinfo.input_frame_width = 0; 2470 sinfo.input_frame_height = 0; 2471 } 2472 2473 webrtc::VideoCodec vie_codec; 2474 if (!video_capturer || video_capturer->IsMuted()) { 2475 sinfo.send_frame_width = 0; 2476 sinfo.send_frame_height = 0; 2477 } else if (engine()->vie()->codec()->GetSendCodec(channel_id, 2478 vie_codec) == 0) { 2479 sinfo.send_frame_width = vie_codec.width; 2480 sinfo.send_frame_height = vie_codec.height; 2481 } else { 2482 sinfo.send_frame_width = -1; 2483 sinfo.send_frame_height = -1; 2484 LOG_RTCERR1(GetSendCodec, channel_id); 2485 } 2486 sinfo.framerate_input = channel_stream_info->framerate(); 2487 sinfo.framerate_sent = send_channel->encoder_observer()->framerate(); 2488 sinfo.nominal_bitrate = send_channel->encoder_observer()->bitrate(); 2489 if (send_codec_) { 2490 sinfo.preferred_bitrate = GetBitrate( 2491 send_codec_->maxBitrate, kMaxVideoBitrate); 2492 } 2493 sinfo.adapt_reason = send_channel->CurrentAdaptReason(); 2494 sinfo.adapt_changes = send_channel->AdaptChanges(); 2495 2496 #ifdef USE_WEBRTC_DEV_BRANCH 2497 webrtc::CpuOveruseMetrics metrics; 2498 engine()->vie()->base()->GetCpuOveruseMetrics(channel_id, &metrics); 2499 sinfo.capture_jitter_ms = metrics.capture_jitter_ms; 2500 sinfo.avg_encode_ms = metrics.avg_encode_time_ms; 2501 sinfo.encode_usage_percent = metrics.encode_usage_percent; 2502 sinfo.encode_rsd = metrics.encode_rsd; 2503 sinfo.capture_queue_delay_ms_per_s = metrics.capture_queue_delay_ms_per_s; 2504 #else 2505 sinfo.capture_jitter_ms = -1; 2506 sinfo.avg_encode_ms = -1; 2507 sinfo.encode_usage_percent = -1; 2508 sinfo.capture_queue_delay_ms_per_s = -1; 2509 2510 int capture_jitter_ms = 0; 2511 int avg_encode_time_ms = 0; 2512 int encode_usage_percent = 0; 2513 int capture_queue_delay_ms_per_s = 0; 2514 if (engine()->vie()->base()->CpuOveruseMeasures( 2515 channel_id, 2516 &capture_jitter_ms, 2517 &avg_encode_time_ms, 2518 &encode_usage_percent, 2519 &capture_queue_delay_ms_per_s) == 0) { 2520 sinfo.capture_jitter_ms = capture_jitter_ms; 2521 sinfo.avg_encode_ms = avg_encode_time_ms; 2522 sinfo.encode_usage_percent = encode_usage_percent; 2523 sinfo.capture_queue_delay_ms_per_s = capture_queue_delay_ms_per_s; 2524 } 2525 #endif 2526 2527 webrtc::RtcpPacketTypeCounter rtcp_sent; 2528 webrtc::RtcpPacketTypeCounter rtcp_received; 2529 if (engine()->vie()->rtp()->GetRtcpPacketTypeCounters( 2530 channel_id, &rtcp_sent, &rtcp_received) == 0) { 2531 sinfo.firs_rcvd = rtcp_received.fir_packets; 2532 sinfo.plis_rcvd = rtcp_received.pli_packets; 2533 sinfo.nacks_rcvd = rtcp_received.nack_packets; 2534 } else { 2535 sinfo.firs_rcvd = -1; 2536 sinfo.plis_rcvd = -1; 2537 sinfo.nacks_rcvd = -1; 2538 LOG_RTCERR1(GetRtcpPacketTypeCounters, channel_id); 2539 } 2540 2541 // Get received RTCP statistics for the sender (reported by the remote 2542 // client in a RTCP packet), if available. 2543 // It's not a fatal error if we can't, since RTCP may not have arrived 2544 // yet. 2545 webrtc::RtcpStatistics outgoing_stream_rtcp_stats; 2546 int outgoing_stream_rtt_ms; 2547 2548 if (engine_->vie()->rtp()->GetSendChannelRtcpStatistics( 2549 channel_id, 2550 outgoing_stream_rtcp_stats, 2551 outgoing_stream_rtt_ms) == 0) { 2552 // Convert Q8 to float. 2553 sinfo.packets_lost = outgoing_stream_rtcp_stats.cumulative_lost; 2554 sinfo.fraction_lost = static_cast<float>( 2555 outgoing_stream_rtcp_stats.fraction_lost) / (1 << 8); 2556 sinfo.rtt_ms = outgoing_stream_rtt_ms; 2557 } 2558 info->senders.push_back(sinfo); 2559 2560 unsigned int channel_total_bitrate_sent = 0; 2561 unsigned int channel_video_bitrate_sent = 0; 2562 unsigned int channel_fec_bitrate_sent = 0; 2563 unsigned int channel_nack_bitrate_sent = 0; 2564 if (engine_->vie()->rtp()->GetBandwidthUsage( 2565 channel_id, channel_total_bitrate_sent, channel_video_bitrate_sent, 2566 channel_fec_bitrate_sent, channel_nack_bitrate_sent) == 0) { 2567 total_bitrate_sent += channel_total_bitrate_sent; 2568 video_bitrate_sent += channel_video_bitrate_sent; 2569 fec_bitrate_sent += channel_fec_bitrate_sent; 2570 nack_bitrate_sent += channel_nack_bitrate_sent; 2571 } else { 2572 LOG_RTCERR1(GetBandwidthUsage, channel_id); 2573 } 2574 2575 unsigned int target_enc_stream_bitrate = 0; 2576 if (engine_->vie()->codec()->GetCodecTargetBitrate( 2577 channel_id, &target_enc_stream_bitrate) == 0) { 2578 target_enc_bitrate += target_enc_stream_bitrate; 2579 } else { 2580 LOG_RTCERR1(GetCodecTargetBitrate, channel_id); 2581 } 2582 } 2583 if (!send_channels_.empty()) { 2584 // GetEstimatedSendBandwidth returns the estimated bandwidth for all video 2585 // engine channels in a channel group. Any valid channel id will do as it 2586 // is only used to access the right group of channels. 2587 const int channel_id = send_channels_.begin()->second->channel_id(); 2588 // Get the send bandwidth available for this MediaChannel. 2589 if (engine_->vie()->rtp()->GetEstimatedSendBandwidth( 2590 channel_id, &estimated_send_bandwidth) != 0) { 2591 LOG_RTCERR1(GetEstimatedSendBandwidth, channel_id); 2592 } 2593 } 2594 } else { 2595 LOG(LS_WARNING) << "GetStats: sender information not ready."; 2596 } 2597 2598 // Get the SSRC and stats for each receiver, based on our own calculations. 2599 for (RecvChannelMap::const_iterator it = recv_channels_.begin(); 2600 it != recv_channels_.end(); ++it) { 2601 WebRtcVideoChannelRecvInfo* channel = it->second; 2602 2603 unsigned int ssrc = 0; 2604 // Get receiver statistics and build VideoReceiverInfo, if we have data. 2605 // Skip the default channel (ssrc == 0). 2606 if (engine_->vie()->rtp()->GetRemoteSSRC( 2607 channel->channel_id(), ssrc) != 0 || 2608 ssrc == 0) 2609 continue; 2610 2611 webrtc::StreamDataCounters sent; 2612 webrtc::StreamDataCounters received; 2613 if (engine_->vie()->rtp()->GetRtpStatistics(channel->channel_id(), 2614 sent, received) != 0) { 2615 LOG_RTCERR1(GetRTPStatistics, channel->channel_id()); 2616 return false; 2617 } 2618 VideoReceiverInfo rinfo; 2619 rinfo.add_ssrc(ssrc); 2620 rinfo.bytes_rcvd = received.bytes; 2621 rinfo.packets_rcvd = received.packets; 2622 rinfo.packets_lost = -1; 2623 rinfo.packets_concealed = -1; 2624 rinfo.fraction_lost = -1; // from SentRTCP 2625 rinfo.frame_width = channel->render_adapter()->width(); 2626 rinfo.frame_height = channel->render_adapter()->height(); 2627 int fps = channel->render_adapter()->framerate(); 2628 rinfo.framerate_decoded = fps; 2629 rinfo.framerate_output = fps; 2630 rinfo.capture_start_ntp_time_ms = 2631 channel->render_adapter()->capture_start_ntp_time_ms(); 2632 channel->decoder_observer()->ExportTo(&rinfo); 2633 2634 webrtc::RtcpPacketTypeCounter rtcp_sent; 2635 webrtc::RtcpPacketTypeCounter rtcp_received; 2636 if (engine()->vie()->rtp()->GetRtcpPacketTypeCounters( 2637 channel->channel_id(), &rtcp_sent, &rtcp_received) == 0) { 2638 rinfo.firs_sent = rtcp_sent.fir_packets; 2639 rinfo.plis_sent = rtcp_sent.pli_packets; 2640 rinfo.nacks_sent = rtcp_sent.nack_packets; 2641 } else { 2642 rinfo.firs_sent = -1; 2643 rinfo.plis_sent = -1; 2644 rinfo.nacks_sent = -1; 2645 LOG_RTCERR1(GetRtcpPacketTypeCounters, channel->channel_id()); 2646 } 2647 2648 // Get our locally created statistics of the received RTP stream. 2649 webrtc::RtcpStatistics incoming_stream_rtcp_stats; 2650 int incoming_stream_rtt_ms; 2651 if (engine_->vie()->rtp()->GetReceiveChannelRtcpStatistics( 2652 channel->channel_id(), 2653 incoming_stream_rtcp_stats, 2654 incoming_stream_rtt_ms) == 0) { 2655 // Convert Q8 to float. 2656 rinfo.packets_lost = incoming_stream_rtcp_stats.cumulative_lost; 2657 rinfo.fraction_lost = static_cast<float>( 2658 incoming_stream_rtcp_stats.fraction_lost) / (1 << 8); 2659 } 2660 info->receivers.push_back(rinfo); 2661 } 2662 unsigned int estimated_recv_bandwidth = 0; 2663 if (!recv_channels_.empty()) { 2664 // GetEstimatedReceiveBandwidth returns the estimated bandwidth for all 2665 // video engine channels in a channel group. Any valid channel id will do as 2666 // it is only used to access the right group of channels. 2667 const int channel_id = recv_channels_.begin()->second->channel_id(); 2668 // Gets the estimated receive bandwidth for the MediaChannel. 2669 if (engine_->vie()->rtp()->GetEstimatedReceiveBandwidth( 2670 channel_id, &estimated_recv_bandwidth) != 0) { 2671 LOG_RTCERR1(GetEstimatedReceiveBandwidth, channel_id); 2672 } 2673 } 2674 2675 // Build BandwidthEstimationInfo. 2676 // TODO(zhurunz): Add real unittest for this. 2677 BandwidthEstimationInfo bwe; 2678 2679 // TODO(jiayl): remove the condition when the necessary changes are available 2680 // outside the dev branch. 2681 if (options.include_received_propagation_stats) { 2682 webrtc::ReceiveBandwidthEstimatorStats additional_stats; 2683 // Only call for the default channel because the returned stats are 2684 // collected for all the channels using the same estimator. 2685 if (engine_->vie()->rtp()->GetReceiveBandwidthEstimatorStats( 2686 GetDefaultRecvChannel()->channel_id(), &additional_stats) == 0) { 2687 bwe.total_received_propagation_delta_ms = 2688 additional_stats.total_propagation_time_delta_ms; 2689 bwe.recent_received_propagation_delta_ms.swap( 2690 additional_stats.recent_propagation_time_delta_ms); 2691 bwe.recent_received_packet_group_arrival_time_ms.swap( 2692 additional_stats.recent_arrival_time_ms); 2693 } 2694 } 2695 2696 engine_->vie()->rtp()->GetPacerQueuingDelayMs( 2697 GetDefaultRecvChannel()->channel_id(), &bwe.bucket_delay); 2698 2699 // Calculations done above per send/receive stream. 2700 bwe.actual_enc_bitrate = video_bitrate_sent; 2701 bwe.transmit_bitrate = total_bitrate_sent; 2702 bwe.retransmit_bitrate = nack_bitrate_sent; 2703 bwe.available_send_bandwidth = estimated_send_bandwidth; 2704 bwe.available_recv_bandwidth = estimated_recv_bandwidth; 2705 bwe.target_enc_bitrate = target_enc_bitrate; 2706 2707 info->bw_estimations.push_back(bwe); 2708 2709 return true; 2710 } 2711 2712 bool WebRtcVideoMediaChannel::SetCapturer(uint32 ssrc, 2713 VideoCapturer* capturer) { 2714 ASSERT(ssrc != 0); 2715 if (!capturer) { 2716 return RemoveCapturer(ssrc); 2717 } 2718 WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); 2719 if (!send_channel) { 2720 return false; 2721 } 2722 VideoCapturer* old_capturer = send_channel->video_capturer(); 2723 MaybeDisconnectCapturer(old_capturer); 2724 2725 send_channel->set_video_capturer(capturer, engine()->vie()); 2726 MaybeConnectCapturer(capturer); 2727 if (!capturer->IsScreencast() && ratio_w_ != 0 && ratio_h_ != 0) { 2728 capturer->UpdateAspectRatio(ratio_w_, ratio_h_); 2729 } 2730 const int64 timestamp = send_channel->local_stream_info()->time_stamp(); 2731 if (send_codec_) { 2732 QueueBlackFrame(ssrc, timestamp, send_codec_->maxFramerate); 2733 } 2734 return true; 2735 } 2736 2737 bool WebRtcVideoMediaChannel::RequestIntraFrame() { 2738 // There is no API exposed to application to request a key frame 2739 // ViE does this internally when there are errors from decoder 2740 return false; 2741 } 2742 2743 void WebRtcVideoMediaChannel::OnPacketReceived( 2744 rtc::Buffer* packet, const rtc::PacketTime& packet_time) { 2745 // Pick which channel to send this packet to. If this packet doesn't match 2746 // any multiplexed streams, just send it to the default channel. Otherwise, 2747 // send it to the specific decoder instance for that stream. 2748 uint32 ssrc = 0; 2749 if (!GetRtpSsrc(packet->data(), packet->length(), &ssrc)) 2750 return; 2751 int processing_channel_id = GetRecvChannelId(ssrc); 2752 if (processing_channel_id == kChannelIdUnset) { 2753 // Allocate an unsignalled recv channel for processing in conference mode. 2754 if (!InConferenceMode()) { 2755 // If we can't find or allocate one, use the default. 2756 processing_channel_id = default_channel_id_; 2757 } else if (!CreateUnsignalledRecvChannel(ssrc, &processing_channel_id)) { 2758 // If we can't create an unsignalled recv channel, drop the packet in 2759 // conference mode. 2760 return; 2761 } 2762 } 2763 2764 engine()->vie()->network()->ReceivedRTPPacket( 2765 processing_channel_id, 2766 packet->data(), 2767 static_cast<int>(packet->length()), 2768 webrtc::PacketTime(packet_time.timestamp, packet_time.not_before)); 2769 } 2770 2771 void WebRtcVideoMediaChannel::OnRtcpReceived( 2772 rtc::Buffer* packet, const rtc::PacketTime& packet_time) { 2773 // Sending channels need all RTCP packets with feedback information. 2774 // Even sender reports can contain attached report blocks. 2775 // Receiving channels need sender reports in order to create 2776 // correct receiver reports. 2777 2778 uint32 ssrc = 0; 2779 if (!GetRtcpSsrc(packet->data(), packet->length(), &ssrc)) { 2780 LOG(LS_WARNING) << "Failed to parse SSRC from received RTCP packet"; 2781 return; 2782 } 2783 int type = 0; 2784 if (!GetRtcpType(packet->data(), packet->length(), &type)) { 2785 LOG(LS_WARNING) << "Failed to parse type from received RTCP packet"; 2786 return; 2787 } 2788 2789 // If it is a sender report, find the channel that is listening. 2790 if (type == kRtcpTypeSR) { 2791 int recv_channel_id = GetRecvChannelId(ssrc); 2792 if (recv_channel_id != kChannelIdUnset && !IsDefaultChannelId(recv_channel_id)) { 2793 engine_->vie()->network()->ReceivedRTCPPacket( 2794 recv_channel_id, 2795 packet->data(), 2796 static_cast<int>(packet->length())); 2797 } 2798 } 2799 // SR may continue RR and any RR entry may correspond to any one of the send 2800 // channels. So all RTCP packets must be forwarded all send channels. ViE 2801 // will filter out RR internally. 2802 for (SendChannelMap::iterator iter = send_channels_.begin(); 2803 iter != send_channels_.end(); ++iter) { 2804 WebRtcVideoChannelSendInfo* send_channel = iter->second; 2805 int channel_id = send_channel->channel_id(); 2806 engine_->vie()->network()->ReceivedRTCPPacket( 2807 channel_id, 2808 packet->data(), 2809 static_cast<int>(packet->length())); 2810 } 2811 } 2812 2813 void WebRtcVideoMediaChannel::OnReadyToSend(bool ready) { 2814 SetNetworkTransmissionState(ready); 2815 } 2816 2817 bool WebRtcVideoMediaChannel::MuteStream(uint32 ssrc, bool muted) { 2818 WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); 2819 if (!send_channel) { 2820 LOG(LS_ERROR) << "The specified ssrc " << ssrc << " is not in use."; 2821 return false; 2822 } 2823 send_channel->set_muted(muted); 2824 return true; 2825 } 2826 2827 bool WebRtcVideoMediaChannel::SetRecvRtpHeaderExtensions( 2828 const std::vector<RtpHeaderExtension>& extensions) { 2829 if (receive_extensions_ == extensions) { 2830 return true; 2831 } 2832 2833 const RtpHeaderExtension* offset_extension = 2834 FindHeaderExtension(extensions, kRtpTimestampOffsetHeaderExtension); 2835 const RtpHeaderExtension* send_time_extension = 2836 FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension); 2837 2838 // Loop through all receive channels and enable/disable the extensions. 2839 for (RecvChannelMap::iterator channel_it = recv_channels_.begin(); 2840 channel_it != recv_channels_.end(); ++channel_it) { 2841 int channel_id = channel_it->second->channel_id(); 2842 if (!SetHeaderExtension( 2843 &webrtc::ViERTP_RTCP::SetReceiveTimestampOffsetStatus, channel_id, 2844 offset_extension)) { 2845 return false; 2846 } 2847 if (!SetHeaderExtension( 2848 &webrtc::ViERTP_RTCP::SetReceiveAbsoluteSendTimeStatus, channel_id, 2849 send_time_extension)) { 2850 return false; 2851 } 2852 } 2853 2854 receive_extensions_ = extensions; 2855 return true; 2856 } 2857 2858 bool WebRtcVideoMediaChannel::SetSendRtpHeaderExtensions( 2859 const std::vector<RtpHeaderExtension>& extensions) { 2860 if (send_extensions_ == extensions) { 2861 return true; 2862 } 2863 2864 const RtpHeaderExtension* offset_extension = 2865 FindHeaderExtension(extensions, kRtpTimestampOffsetHeaderExtension); 2866 const RtpHeaderExtension* send_time_extension = 2867 FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension); 2868 2869 // Loop through all send channels and enable/disable the extensions. 2870 for (SendChannelMap::iterator channel_it = send_channels_.begin(); 2871 channel_it != send_channels_.end(); ++channel_it) { 2872 int channel_id = channel_it->second->channel_id(); 2873 if (!SetHeaderExtension( 2874 &webrtc::ViERTP_RTCP::SetSendTimestampOffsetStatus, channel_id, 2875 offset_extension)) { 2876 return false; 2877 } 2878 if (!SetHeaderExtension( 2879 &webrtc::ViERTP_RTCP::SetSendAbsoluteSendTimeStatus, channel_id, 2880 send_time_extension)) { 2881 return false; 2882 } 2883 } 2884 2885 if (send_time_extension) { 2886 // For video RTP packets, we would like to update AbsoluteSendTimeHeader 2887 // Extension closer to the network, @ socket level before sending. 2888 // Pushing the extension id to socket layer. 2889 MediaChannel::SetOption(NetworkInterface::ST_RTP, 2890 rtc::Socket::OPT_RTP_SENDTIME_EXTN_ID, 2891 send_time_extension->id); 2892 } 2893 2894 send_extensions_ = extensions; 2895 return true; 2896 } 2897 2898 int WebRtcVideoMediaChannel::GetRtpSendTimeExtnId() const { 2899 const RtpHeaderExtension* send_time_extension = FindHeaderExtension( 2900 send_extensions_, kRtpAbsoluteSenderTimeHeaderExtension); 2901 if (send_time_extension) { 2902 return send_time_extension->id; 2903 } 2904 return -1; 2905 } 2906 2907 bool WebRtcVideoMediaChannel::SetStartSendBandwidth(int bps) { 2908 LOG(LS_INFO) << "WebRtcVideoMediaChannel::SetStartSendBandwidth"; 2909 2910 if (!send_codec_) { 2911 LOG(LS_INFO) << "The send codec has not been set up yet"; 2912 return true; 2913 } 2914 2915 // On success, SetSendCodec() will reset |send_start_bitrate_| to |bps/1000|, 2916 // by calling SanitizeBitrates. That method will also clamp the 2917 // start bitrate between min and max, consistent with the override behavior 2918 // in SetMaxSendBandwidth. 2919 webrtc::VideoCodec new_codec = *send_codec_; 2920 if (BitrateIsSet(bps)) { 2921 new_codec.startBitrate = bps / 1000; 2922 } 2923 return SetSendCodec(new_codec); 2924 } 2925 2926 bool WebRtcVideoMediaChannel::SetMaxSendBandwidth(int bps) { 2927 LOG(LS_INFO) << "WebRtcVideoMediaChannel::SetMaxSendBandwidth"; 2928 2929 if (!send_codec_) { 2930 LOG(LS_INFO) << "The send codec has not been set up yet"; 2931 return true; 2932 } 2933 2934 webrtc::VideoCodec new_codec = *send_codec_; 2935 if (BitrateIsSet(bps)) { 2936 new_codec.maxBitrate = bps / 1000; 2937 } 2938 if (!SetSendCodec(new_codec)) { 2939 return false; 2940 } 2941 LogSendCodecChange("SetMaxSendBandwidth()"); 2942 2943 return true; 2944 } 2945 2946 bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) { 2947 // Always accept options that are unchanged. 2948 if (options_ == options) { 2949 return true; 2950 } 2951 2952 // Save the options, to be interpreted where appropriate. 2953 // Use options_.SetAll() instead of assignment so that unset value in options 2954 // will not overwrite the previous option value. 2955 VideoOptions original = options_; 2956 options_.SetAll(options); 2957 2958 // Set CPU options for all send channels. 2959 for (SendChannelMap::iterator iter = send_channels_.begin(); 2960 iter != send_channels_.end(); ++iter) { 2961 WebRtcVideoChannelSendInfo* send_channel = iter->second; 2962 send_channel->ApplyCpuOptions(options_); 2963 } 2964 2965 if (send_codec_) { 2966 webrtc::VideoCodec new_codec = *send_codec_; 2967 2968 bool conference_mode_turned_off = ( 2969 original.conference_mode.IsSet() && 2970 options.conference_mode.IsSet() && 2971 original.conference_mode.GetWithDefaultIfUnset(false) && 2972 !options.conference_mode.GetWithDefaultIfUnset(false)); 2973 if (conference_mode_turned_off) { 2974 // This is a special case for turning conference mode off. 2975 // Max bitrate should go back to the default maximum value instead 2976 // of the current maximum. 2977 new_codec.maxBitrate = kAutoBandwidth; 2978 } 2979 2980 // TODO(pthatcher): Remove this. We don't need 4 ways to set bitrates. 2981 int new_start_bitrate; 2982 if (options.video_start_bitrate.Get(&new_start_bitrate)) { 2983 new_codec.startBitrate = new_start_bitrate; 2984 } 2985 2986 if (!SetSendCodec(new_codec)) { 2987 return false; 2988 } 2989 LogSendCodecChange("SetOptions()"); 2990 } 2991 2992 bool enable_leaky_bucket; 2993 if (Changed(options.video_leaky_bucket, 2994 original.video_leaky_bucket, 2995 &enable_leaky_bucket)) { 2996 LOG(LS_INFO) << "Leaky bucket is enabled? " << enable_leaky_bucket; 2997 for (SendChannelMap::iterator it = send_channels_.begin(); 2998 it != send_channels_.end(); ++it) { 2999 // TODO(holmer): This API will be removed as we move to the new 3000 // webrtc::Call API. We should clean up this experiment when that is 3001 // happening. 3002 if (engine()->vie()->rtp()->SetTransmissionSmoothingStatus( 3003 it->second->channel_id(), enable_leaky_bucket) != 0) { 3004 LOG_RTCERR2(SetTransmissionSmoothingStatus, it->second->channel_id(), 3005 enable_leaky_bucket); 3006 } 3007 } 3008 } 3009 3010 int buffer_latency; 3011 if (Changed(options.buffered_mode_latency, 3012 original.buffered_mode_latency, 3013 &buffer_latency)) { 3014 LOG(LS_INFO) << "Buffer latency is " << buffer_latency; 3015 for (SendChannelMap::iterator it = send_channels_.begin(); 3016 it != send_channels_.end(); ++it) { 3017 if (engine()->vie()->rtp()->SetSenderBufferingMode( 3018 it->second->channel_id(), buffer_latency) != 0) { 3019 LOG_RTCERR2(SetSenderBufferingMode, it->second->channel_id(), 3020 buffer_latency); 3021 } 3022 } 3023 for (RecvChannelMap::iterator it = recv_channels_.begin(); 3024 it != recv_channels_.end(); ++it) { 3025 if (engine()->vie()->rtp()->SetReceiverBufferingMode( 3026 it->second->channel_id(), buffer_latency) != 0) { 3027 LOG_RTCERR2(SetReceiverBufferingMode, it->second->channel_id(), 3028 buffer_latency); 3029 } 3030 } 3031 } 3032 3033 bool dscp_enabled; 3034 if (Changed(options.dscp, original.dscp, &dscp_enabled)) { 3035 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; 3036 if (dscp_enabled) { 3037 dscp = kVideoDscpValue; 3038 } 3039 LOG(LS_INFO) << "DSCP is " << dscp; 3040 if (MediaChannel::SetDscp(dscp) != 0) { 3041 LOG(LS_WARNING) << "Failed to set DSCP settings for video channel"; 3042 } 3043 } 3044 3045 bool suspend_below_min_bitrate; 3046 if (Changed(options.suspend_below_min_bitrate, 3047 original.suspend_below_min_bitrate, 3048 &suspend_below_min_bitrate)) { 3049 if (suspend_below_min_bitrate) { 3050 LOG(LS_INFO) << "Suspend below min bitrate enabled."; 3051 for (SendChannelMap::iterator it = send_channels_.begin(); 3052 it != send_channels_.end(); ++it) { 3053 engine()->vie()->codec()->SuspendBelowMinBitrate( 3054 it->second->channel_id()); 3055 } 3056 } else { 3057 LOG(LS_WARNING) << "Cannot disable video suspension once it is enabled"; 3058 } 3059 } 3060 3061 #ifdef USE_WEBRTC_DEV_BRANCH 3062 bool use_payload_padding; 3063 if (Changed(options.use_payload_padding, 3064 original.use_payload_padding, 3065 &use_payload_padding)) { 3066 LOG(LS_INFO) << "Payload-based padding called."; 3067 for (SendChannelMap::iterator it = send_channels_.begin(); 3068 it != send_channels_.end(); ++it) { 3069 engine()->vie()->rtp()->SetPadWithRedundantPayloads( 3070 it->second->channel_id(), use_payload_padding); 3071 } 3072 } 3073 #endif 3074 webrtc::CpuOveruseOptions overuse_options; 3075 if (GetCpuOveruseOptions(options_, &overuse_options)) { 3076 for (SendChannelMap::iterator it = send_channels_.begin(); 3077 it != send_channels_.end(); ++it) { 3078 if (engine()->vie()->base()->SetCpuOveruseOptions( 3079 it->second->channel_id(), overuse_options) != 0) { 3080 LOG_RTCERR1(SetCpuOveruseOptions, it->second->channel_id()); 3081 } 3082 } 3083 } 3084 return true; 3085 } 3086 3087 void WebRtcVideoMediaChannel::SetInterface(NetworkInterface* iface) { 3088 MediaChannel::SetInterface(iface); 3089 // Set the RTP recv/send buffer to a bigger size 3090 MediaChannel::SetOption(NetworkInterface::ST_RTP, 3091 rtc::Socket::OPT_RCVBUF, 3092 kVideoRtpBufferSize); 3093 3094 // TODO(sriniv): Remove or re-enable this. 3095 // As part of b/8030474, send-buffer is size now controlled through 3096 // portallocator flags. 3097 // network_interface_->SetOption(NetworkInterface::ST_RTP, 3098 // rtc::Socket::OPT_SNDBUF, 3099 // kVideoRtpBufferSize); 3100 } 3101 3102 void WebRtcVideoMediaChannel::UpdateAspectRatio(int ratio_w, int ratio_h) { 3103 ASSERT(ratio_w != 0); 3104 ASSERT(ratio_h != 0); 3105 ratio_w_ = ratio_w; 3106 ratio_h_ = ratio_h; 3107 // For now assume that all streams want the same aspect ratio. 3108 // TODO(hellner): remove the need for this assumption. 3109 for (SendChannelMap::iterator iter = send_channels_.begin(); 3110 iter != send_channels_.end(); ++iter) { 3111 WebRtcVideoChannelSendInfo* send_channel = iter->second; 3112 VideoCapturer* capturer = send_channel->video_capturer(); 3113 if (capturer) { 3114 capturer->UpdateAspectRatio(ratio_w, ratio_h); 3115 } 3116 } 3117 } 3118 3119 bool WebRtcVideoMediaChannel::GetRenderer(uint32 ssrc, 3120 VideoRenderer** renderer) { 3121 WebRtcVideoChannelRecvInfo* recv_channel = GetRecvChannelBySsrc(ssrc); 3122 if (!recv_channel) { 3123 if (first_receive_ssrc_ == ssrc && GetDefaultRecvChannel()) { 3124 LOG(LS_INFO) << " GetRenderer " << ssrc 3125 << " reuse default renderer #" 3126 << default_channel_id_; 3127 *renderer = GetDefaultRecvChannel()->render_adapter()->renderer(); 3128 return true; 3129 } 3130 return false; 3131 } 3132 3133 *renderer = recv_channel->render_adapter()->renderer(); 3134 return true; 3135 } 3136 3137 bool WebRtcVideoMediaChannel::GetVideoAdapter( 3138 uint32 ssrc, CoordinatedVideoAdapter** video_adapter) { 3139 WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); 3140 if (!send_channel) { 3141 return false; 3142 } 3143 *video_adapter = send_channel->video_adapter(); 3144 return true; 3145 } 3146 3147 void WebRtcVideoMediaChannel::SendFrame(VideoCapturer* capturer, 3148 const VideoFrame* frame) { 3149 // If the |capturer| is registered to any send channel, then send the frame 3150 // to those send channels. 3151 bool capturer_is_channel_owned = false; 3152 for (SendChannelMap::iterator iter = send_channels_.begin(); 3153 iter != send_channels_.end(); ++iter) { 3154 WebRtcVideoChannelSendInfo* send_channel = iter->second; 3155 if (send_channel->video_capturer() == capturer) { 3156 SendFrame(send_channel, frame, capturer->IsScreencast()); 3157 capturer_is_channel_owned = true; 3158 } 3159 } 3160 if (capturer_is_channel_owned) { 3161 return; 3162 } 3163 3164 // TODO(hellner): Remove below for loop once the captured frame no longer 3165 // come from the engine, i.e. the engine no longer owns a capturer. 3166 for (SendChannelMap::iterator iter = send_channels_.begin(); 3167 iter != send_channels_.end(); ++iter) { 3168 WebRtcVideoChannelSendInfo* send_channel = iter->second; 3169 if (!send_channel->video_capturer()) { 3170 SendFrame(send_channel, frame, capturer->IsScreencast()); 3171 } 3172 } 3173 } 3174 3175 bool WebRtcVideoMediaChannel::SendFrame( 3176 WebRtcVideoChannelSendInfo* send_channel, 3177 const VideoFrame* frame, 3178 bool is_screencast) { 3179 if (!send_channel) { 3180 return false; 3181 } 3182 if (!send_codec_) { 3183 // Send codec has not been set. No reason to process the frame any further. 3184 return false; 3185 } 3186 const VideoFormat& video_format = send_channel->video_format(); 3187 // If the frame should be dropped. 3188 const bool video_format_set = video_format != cricket::VideoFormat(); 3189 if (video_format_set && 3190 (video_format.width == 0 && video_format.height == 0)) { 3191 return true; 3192 } 3193 3194 // Checks if we need to reset vie send codec. 3195 if (!MaybeResetVieSendCodec(send_channel, 3196 static_cast<int>(frame->GetWidth()), 3197 static_cast<int>(frame->GetHeight()), 3198 is_screencast, NULL)) { 3199 LOG(LS_ERROR) << "MaybeResetVieSendCodec failed with " 3200 << frame->GetWidth() << "x" << frame->GetHeight(); 3201 return false; 3202 } 3203 const VideoFrame* frame_out = frame; 3204 rtc::scoped_ptr<VideoFrame> processed_frame; 3205 // TODO(hellner): Remove the need for disabling mute when screencasting. 3206 const bool mute = (send_channel->muted() && !is_screencast); 3207 send_channel->ProcessFrame(*frame_out, mute, processed_frame.use()); 3208 if (processed_frame) { 3209 frame_out = processed_frame.get(); 3210 } 3211 3212 webrtc::ViEVideoFrameI420 frame_i420; 3213 // TODO(ronghuawu): Update the webrtc::ViEVideoFrameI420 3214 // to use const unsigned char* 3215 frame_i420.y_plane = const_cast<unsigned char*>(frame_out->GetYPlane()); 3216 frame_i420.u_plane = const_cast<unsigned char*>(frame_out->GetUPlane()); 3217 frame_i420.v_plane = const_cast<unsigned char*>(frame_out->GetVPlane()); 3218 frame_i420.y_pitch = frame_out->GetYPitch(); 3219 frame_i420.u_pitch = frame_out->GetUPitch(); 3220 frame_i420.v_pitch = frame_out->GetVPitch(); 3221 frame_i420.width = static_cast<uint16>(frame_out->GetWidth()); 3222 frame_i420.height = static_cast<uint16>(frame_out->GetHeight()); 3223 3224 int64 timestamp_ntp_ms = 0; 3225 // TODO(justinlin): Reenable after Windows issues with clock drift are fixed. 3226 // Currently reverted to old behavior of discarding capture timestamp. 3227 #if 0 3228 static const int kTimestampDeltaInSecondsForWarning = 2; 3229 3230 // If the frame timestamp is 0, we will use the deliver time. 3231 const int64 frame_timestamp = frame->GetTimeStamp(); 3232 if (frame_timestamp != 0) { 3233 if (abs(time(NULL) - frame_timestamp / rtc::kNumNanosecsPerSec) > 3234 kTimestampDeltaInSecondsForWarning) { 3235 LOG(LS_WARNING) << "Frame timestamp differs by more than " 3236 << kTimestampDeltaInSecondsForWarning << " seconds from " 3237 << "current Unix timestamp."; 3238 } 3239 3240 timestamp_ntp_ms = 3241 rtc::UnixTimestampNanosecsToNtpMillisecs(frame_timestamp); 3242 } 3243 #endif 3244 3245 return send_channel->external_capture()->IncomingFrameI420( 3246 frame_i420, timestamp_ntp_ms) == 0; 3247 } 3248 3249 bool WebRtcVideoMediaChannel::CreateChannel(uint32 ssrc_key, 3250 MediaDirection direction, 3251 int* channel_id) { 3252 // There are 3 types of channels. Sending only, receiving only and 3253 // sending and receiving. The sending and receiving channel is the 3254 // default channel and there is only one. All other channels that 3255 // are created are associated with the default channel which must 3256 // exist. The default channel id is stored in 3257 // |default_channel_id_|. All channels need to know about the 3258 // default channel to properly handle remb which is why there are 3259 // different ViE create channel calls. For this channel the local 3260 // and remote ssrc_key is kDefaultChannelSsrcKey. However, it may 3261 // have a non-zero local and/or remote ssrc depending on if it is 3262 // currently sending and/or receiving. 3263 if ((default_channel_id_ == kChannelIdUnset || direction == MD_SENDRECV) && 3264 (!send_channels_.empty() || !recv_channels_.empty())) { 3265 ASSERT(false); 3266 return false; 3267 } 3268 3269 *channel_id = kChannelIdUnset; 3270 if (direction == MD_RECV) { 3271 // All rec channels are associated with default_channel_id_. 3272 if (engine_->vie()->base()->CreateReceiveChannel(*channel_id, 3273 default_channel_id_) != 0) { 3274 LOG_RTCERR2(CreateReceiveChannel, *channel_id, default_channel_id_); 3275 return false; 3276 } 3277 } else if (direction == MD_SEND) { 3278 if (engine_->vie()->base()->CreateChannel(*channel_id, 3279 default_channel_id_) != 0) { 3280 LOG_RTCERR2(CreateChannel, *channel_id, default_channel_id_); 3281 return false; 3282 } 3283 } else { 3284 ASSERT(direction == MD_SENDRECV); 3285 if (engine_->vie()->base()->CreateChannel(*channel_id) != 0) { 3286 LOG_RTCERR1(CreateChannel, *channel_id); 3287 return false; 3288 } 3289 } 3290 if (!ConfigureChannel(*channel_id, direction, ssrc_key)) { 3291 engine_->vie()->base()->DeleteChannel(*channel_id); 3292 *channel_id = kChannelIdUnset; 3293 return false; 3294 } 3295 3296 return true; 3297 } 3298 3299 bool WebRtcVideoMediaChannel::CreateUnsignalledRecvChannel( 3300 uint32 ssrc_key, int* out_channel_id) { 3301 int unsignalled_recv_channel_limit = 3302 options_.unsignalled_recv_stream_limit.GetWithDefaultIfUnset( 3303 kNumDefaultUnsignalledVideoRecvStreams); 3304 if (num_unsignalled_recv_channels_ >= unsignalled_recv_channel_limit) { 3305 return false; 3306 } 3307 if (!CreateChannel(ssrc_key, MD_RECV, out_channel_id)) { 3308 return false; 3309 } 3310 // TODO(tvsriram): Support dynamic sizing of unsignalled recv channels. 3311 num_unsignalled_recv_channels_++; 3312 return true; 3313 } 3314 3315 bool WebRtcVideoMediaChannel::ConfigureChannel(int channel_id, 3316 MediaDirection direction, 3317 uint32 ssrc_key) { 3318 const bool receiving = (direction == MD_RECV) || (direction == MD_SENDRECV); 3319 const bool sending = (direction == MD_SEND) || (direction == MD_SENDRECV); 3320 // Register external transport. 3321 if (engine_->vie()->network()->RegisterSendTransport( 3322 channel_id, *this) != 0) { 3323 LOG_RTCERR1(RegisterSendTransport, channel_id); 3324 return false; 3325 } 3326 3327 // Set MTU. 3328 if (engine_->vie()->network()->SetMTU(channel_id, kVideoMtu) != 0) { 3329 LOG_RTCERR2(SetMTU, channel_id, kVideoMtu); 3330 return false; 3331 } 3332 // Turn on RTCP and loss feedback reporting. 3333 if (engine()->vie()->rtp()->SetRTCPStatus( 3334 channel_id, webrtc::kRtcpCompound_RFC4585) != 0) { 3335 LOG_RTCERR2(SetRTCPStatus, channel_id, webrtc::kRtcpCompound_RFC4585); 3336 return false; 3337 } 3338 // Enable pli as key frame request method. 3339 if (engine_->vie()->rtp()->SetKeyFrameRequestMethod( 3340 channel_id, webrtc::kViEKeyFrameRequestPliRtcp) != 0) { 3341 LOG_RTCERR2(SetKeyFrameRequestMethod, 3342 channel_id, webrtc::kViEKeyFrameRequestPliRtcp); 3343 return false; 3344 } 3345 if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, nack_enabled_)) { 3346 // Logged in SetNackFec. Don't spam the logs. 3347 return false; 3348 } 3349 // Note that receiving must always be configured before sending to ensure 3350 // that send and receive channel is configured correctly (ConfigureReceiving 3351 // assumes no sending). 3352 if (receiving) { 3353 if (!ConfigureReceiving(channel_id, ssrc_key)) { 3354 return false; 3355 } 3356 } 3357 if (sending) { 3358 if (!ConfigureSending(channel_id, ssrc_key)) { 3359 return false; 3360 } 3361 } 3362 3363 // Start receiving for both receive and send channels so that we get incoming 3364 // RTP (if receiving) as well as RTCP feedback (if sending). 3365 if (engine()->vie()->base()->StartReceive(channel_id) != 0) { 3366 LOG_RTCERR1(StartReceive, channel_id); 3367 return false; 3368 } 3369 3370 return true; 3371 } 3372 3373 bool WebRtcVideoMediaChannel::ConfigureReceiving(int channel_id, 3374 uint32 remote_ssrc) { 3375 // Make sure that an SSRC isn't registered more than once. 3376 if (GetRecvChannelBySsrc(remote_ssrc)) { 3377 return false; 3378 } 3379 // Connect the voice channel, if there is one. 3380 // TODO(perkj): The A/V is synched by the receiving channel. So we need to 3381 // know the SSRC of the remote audio channel in order to fetch the correct 3382 // webrtc VoiceEngine channel. For now- only sync the default channel used 3383 // in 1-1 calls. 3384 if (remote_ssrc == kDefaultChannelSsrcKey && voice_channel_) { 3385 WebRtcVoiceMediaChannel* voice_channel = 3386 static_cast<WebRtcVoiceMediaChannel*>(voice_channel_); 3387 if (engine_->vie()->base()->ConnectAudioChannel( 3388 default_channel_id_, voice_channel->voe_channel()) != 0) { 3389 LOG_RTCERR2(ConnectAudioChannel, channel_id, 3390 voice_channel->voe_channel()); 3391 LOG(LS_WARNING) << "A/V not synchronized"; 3392 // Not a fatal error. 3393 } 3394 } 3395 3396 rtc::scoped_ptr<WebRtcVideoChannelRecvInfo> channel_info( 3397 new WebRtcVideoChannelRecvInfo(channel_id)); 3398 3399 // Install a render adapter. 3400 if (engine_->vie()->render()->AddRenderer(channel_id, 3401 webrtc::kVideoI420, channel_info->render_adapter()) != 0) { 3402 LOG_RTCERR3(AddRenderer, channel_id, webrtc::kVideoI420, 3403 channel_info->render_adapter()); 3404 return false; 3405 } 3406 3407 if (engine()->vie()->render()->SetExpectedRenderDelay( 3408 channel_id, kDefaultRenderDelayMs)) { 3409 LOG_RTCERR2(SetExpectedRenderDelay, 3410 channel_id, kDefaultRenderDelayMs); 3411 } 3412 3413 if (engine_->vie()->rtp()->SetRembStatus(channel_id, 3414 kNotSending, 3415 remb_enabled_) != 0) { 3416 LOG_RTCERR3(SetRembStatus, channel_id, kNotSending, remb_enabled_); 3417 return false; 3418 } 3419 3420 if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetReceiveTimestampOffsetStatus, 3421 channel_id, receive_extensions_, kRtpTimestampOffsetHeaderExtension)) { 3422 return false; 3423 } 3424 if (!SetHeaderExtension( 3425 &webrtc::ViERTP_RTCP::SetReceiveAbsoluteSendTimeStatus, channel_id, 3426 receive_extensions_, kRtpAbsoluteSenderTimeHeaderExtension)) { 3427 return false; 3428 } 3429 3430 if (receiver_report_ssrc_ != kSsrcUnset) { 3431 if (engine()->vie()->rtp()->SetLocalSSRC( 3432 channel_id, receiver_report_ssrc_) == -1) { 3433 LOG_RTCERR2(SetLocalSSRC, channel_id, receiver_report_ssrc_); 3434 return false; 3435 } 3436 } 3437 3438 // Disable color enhancement since it is a bit too aggressive. 3439 if (engine()->vie()->image()->EnableColorEnhancement(channel_id, 3440 false) != 0) { 3441 LOG_RTCERR1(EnableColorEnhancement, channel_id); 3442 return false; 3443 } 3444 3445 if (!SetReceiveCodecs(channel_info.get())) { 3446 return false; 3447 } 3448 3449 int buffer_latency = 3450 options_.buffered_mode_latency.GetWithDefaultIfUnset( 3451 cricket::kBufferedModeDisabled); 3452 if (buffer_latency != cricket::kBufferedModeDisabled) { 3453 if (engine()->vie()->rtp()->SetReceiverBufferingMode( 3454 channel_id, buffer_latency) != 0) { 3455 LOG_RTCERR2(SetReceiverBufferingMode, channel_id, buffer_latency); 3456 } 3457 } 3458 3459 if (render_started_) { 3460 if (engine_->vie()->render()->StartRender(channel_id) != 0) { 3461 LOG_RTCERR1(StartRender, channel_id); 3462 return false; 3463 } 3464 } 3465 3466 // Register decoder observer for incoming framerate and bitrate. 3467 if (engine()->vie()->codec()->RegisterDecoderObserver( 3468 channel_id, *channel_info->decoder_observer()) != 0) { 3469 LOG_RTCERR1(RegisterDecoderObserver, channel_info->decoder_observer()); 3470 return false; 3471 } 3472 3473 recv_channels_[remote_ssrc] = channel_info.release(); 3474 return true; 3475 } 3476 3477 bool WebRtcVideoMediaChannel::ConfigureSending(int channel_id, 3478 uint32 local_ssrc_key) { 3479 // The ssrc key can be zero or correspond to an SSRC. 3480 // Make sure the default channel isn't configured more than once. 3481 if (local_ssrc_key == kDefaultChannelSsrcKey && GetDefaultSendChannel()) { 3482 return false; 3483 } 3484 // Make sure that the SSRC is not already in use. 3485 uint32 dummy_key; 3486 if (GetSendChannelSsrcKey(local_ssrc_key, &dummy_key)) { 3487 return false; 3488 } 3489 int vie_capture = 0; 3490 webrtc::ViEExternalCapture* external_capture = NULL; 3491 // Register external capture. 3492 if (engine()->vie()->capture()->AllocateExternalCaptureDevice( 3493 vie_capture, external_capture) != 0) { 3494 LOG_RTCERR0(AllocateExternalCaptureDevice); 3495 return false; 3496 } 3497 3498 // Connect external capture. 3499 if (engine()->vie()->capture()->ConnectCaptureDevice( 3500 vie_capture, channel_id) != 0) { 3501 LOG_RTCERR2(ConnectCaptureDevice, vie_capture, channel_id); 3502 return false; 3503 } 3504 rtc::scoped_ptr<WebRtcVideoChannelSendInfo> send_channel( 3505 new WebRtcVideoChannelSendInfo(channel_id, vie_capture, 3506 external_capture, 3507 engine()->cpu_monitor())); 3508 send_channel->ApplyCpuOptions(options_); 3509 send_channel->SignalCpuAdaptationUnable.connect(this, 3510 &WebRtcVideoMediaChannel::OnCpuAdaptationUnable); 3511 3512 webrtc::CpuOveruseOptions overuse_options; 3513 if (GetCpuOveruseOptions(options_, &overuse_options)) { 3514 if (engine()->vie()->base()->SetCpuOveruseOptions(channel_id, 3515 overuse_options) != 0) { 3516 LOG_RTCERR1(SetCpuOveruseOptions, channel_id); 3517 } 3518 } 3519 3520 // Register encoder observer for outgoing framerate and bitrate. 3521 if (engine()->vie()->codec()->RegisterEncoderObserver( 3522 channel_id, *send_channel->encoder_observer()) != 0) { 3523 LOG_RTCERR1(RegisterEncoderObserver, send_channel->encoder_observer()); 3524 return false; 3525 } 3526 3527 if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetSendTimestampOffsetStatus, 3528 channel_id, send_extensions_, kRtpTimestampOffsetHeaderExtension)) { 3529 return false; 3530 } 3531 3532 if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetSendAbsoluteSendTimeStatus, 3533 channel_id, send_extensions_, kRtpAbsoluteSenderTimeHeaderExtension)) { 3534 return false; 3535 } 3536 3537 if (options_.video_leaky_bucket.GetWithDefaultIfUnset(true)) { 3538 if (engine()->vie()->rtp()->SetTransmissionSmoothingStatus(channel_id, 3539 true) != 0) { 3540 LOG_RTCERR2(SetTransmissionSmoothingStatus, channel_id, true); 3541 return false; 3542 } 3543 } 3544 3545 int buffer_latency = 3546 options_.buffered_mode_latency.GetWithDefaultIfUnset( 3547 cricket::kBufferedModeDisabled); 3548 if (buffer_latency != cricket::kBufferedModeDisabled) { 3549 if (engine()->vie()->rtp()->SetSenderBufferingMode( 3550 channel_id, buffer_latency) != 0) { 3551 LOG_RTCERR2(SetSenderBufferingMode, channel_id, buffer_latency); 3552 } 3553 } 3554 3555 if (options_.suspend_below_min_bitrate.GetWithDefaultIfUnset(false)) { 3556 engine()->vie()->codec()->SuspendBelowMinBitrate(channel_id); 3557 } 3558 3559 // The remb status direction correspond to the RTP stream (and not the RTCP 3560 // stream). I.e. if send remb is enabled it means it is receiving remote 3561 // rembs and should use them to estimate bandwidth. Receive remb mean that 3562 // remb packets will be generated and that the channel should be included in 3563 // it. If remb is enabled all channels are allowed to contribute to the remb 3564 // but only receive channels will ever end up actually contributing. This 3565 // keeps the logic simple. 3566 if (engine_->vie()->rtp()->SetRembStatus(channel_id, 3567 remb_enabled_, 3568 remb_enabled_) != 0) { 3569 LOG_RTCERR3(SetRembStatus, channel_id, remb_enabled_, remb_enabled_); 3570 return false; 3571 } 3572 if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, nack_enabled_)) { 3573 // Logged in SetNackFec. Don't spam the logs. 3574 return false; 3575 } 3576 3577 // Enable improved WiFi Bandwidth Estimation 3578 { 3579 webrtc::Config config; 3580 config.Set(new webrtc::AimdRemoteRateControl(true)); 3581 if (!engine()->vie()->network()->SetBandwidthEstimationConfig(channel_id, 3582 config)) { 3583 return false; 3584 } 3585 } 3586 3587 send_channels_[local_ssrc_key] = send_channel.release(); 3588 3589 return true; 3590 } 3591 3592 bool WebRtcVideoMediaChannel::SetNackFec(int channel_id, 3593 int red_payload_type, 3594 int fec_payload_type, 3595 bool nack_enabled) { 3596 bool enable = (red_payload_type != -1 && fec_payload_type != -1 && 3597 !InConferenceMode()); 3598 if (enable) { 3599 if (engine_->vie()->rtp()->SetHybridNACKFECStatus( 3600 channel_id, nack_enabled, red_payload_type, fec_payload_type) != 0) { 3601 LOG_RTCERR4(SetHybridNACKFECStatus, 3602 channel_id, nack_enabled, red_payload_type, fec_payload_type); 3603 return false; 3604 } 3605 LOG(LS_INFO) << "Hybrid NACK/FEC enabled for channel " << channel_id; 3606 } else { 3607 if (engine_->vie()->rtp()->SetNACKStatus(channel_id, nack_enabled) != 0) { 3608 LOG_RTCERR1(SetNACKStatus, channel_id); 3609 return false; 3610 } 3611 std::string enabled = nack_enabled ? "enabled" : "disabled"; 3612 LOG(LS_INFO) << "NACK " << enabled << " for channel " << channel_id; 3613 } 3614 return true; 3615 } 3616 3617 bool WebRtcVideoMediaChannel::SetSendCodec(const webrtc::VideoCodec& codec) { 3618 bool ret_val = true; 3619 for (SendChannelMap::iterator iter = send_channels_.begin(); 3620 iter != send_channels_.end(); ++iter) { 3621 WebRtcVideoChannelSendInfo* send_channel = iter->second; 3622 ret_val = SetSendCodec(send_channel, codec) && ret_val; 3623 } 3624 if (ret_val) { 3625 // All SetSendCodec calls were successful. Update the global state 3626 // accordingly. 3627 send_codec_.reset(new webrtc::VideoCodec(codec)); 3628 } else { 3629 // At least one SetSendCodec call failed, rollback. 3630 for (SendChannelMap::iterator iter = send_channels_.begin(); 3631 iter != send_channels_.end(); ++iter) { 3632 WebRtcVideoChannelSendInfo* send_channel = iter->second; 3633 if (send_codec_) { 3634 SetSendCodec(send_channel, *send_codec_); 3635 } 3636 } 3637 } 3638 return ret_val; 3639 } 3640 3641 bool WebRtcVideoMediaChannel::SetSendCodec( 3642 WebRtcVideoChannelSendInfo* send_channel, 3643 const webrtc::VideoCodec& codec) { 3644 if (!send_channel) { 3645 return false; 3646 } 3647 3648 const int channel_id = send_channel->channel_id(); 3649 // Make a copy of the codec 3650 webrtc::VideoCodec target_codec = codec; 3651 3652 // Set the default number of temporal layers for VP8. 3653 if (webrtc::kVideoCodecVP8 == codec.codecType) { 3654 target_codec.codecSpecific.VP8.numberOfTemporalLayers = 3655 kDefaultNumberOfTemporalLayers; 3656 3657 // Turn off the VP8 error resilience 3658 target_codec.codecSpecific.VP8.resilience = webrtc::kResilienceOff; 3659 3660 bool enable_denoising = 3661 options_.video_noise_reduction.GetWithDefaultIfUnset(true); 3662 target_codec.codecSpecific.VP8.denoisingOn = enable_denoising; 3663 } 3664 3665 MaybeRegisterExternalEncoder(send_channel, target_codec); 3666 3667 // Resolution and framerate may vary for different send channels. 3668 const VideoFormat& video_format = send_channel->video_format(); 3669 UpdateVideoCodec(video_format, &target_codec); 3670 3671 if (target_codec.width == 0 && target_codec.height == 0) { 3672 const uint32 ssrc = send_channel->stream_params()->first_ssrc(); 3673 LOG(LS_INFO) << "0x0 resolution selected. Captured frames will be dropped " 3674 << "for ssrc: " << ssrc << "."; 3675 } else { 3676 StreamParams* send_params = send_channel->stream_params(); 3677 SanitizeBitrates(channel_id, &target_codec); 3678 webrtc::VideoCodec current_codec; 3679 if (!engine()->vie()->codec()->GetSendCodec(channel_id, current_codec)) { 3680 // Compare against existing configured send codec. 3681 if (current_codec == target_codec) { 3682 // Codec is already configured on channel. no need to apply. 3683 return true; 3684 } 3685 } 3686 3687 if (0 != engine()->vie()->codec()->SetSendCodec(channel_id, target_codec)) { 3688 LOG_RTCERR2(SetSendCodec, channel_id, target_codec.plName); 3689 return false; 3690 } 3691 3692 if (send_params) { 3693 if (!SetSendSsrcs(channel_id, *send_params, target_codec)) { 3694 return false; 3695 } 3696 } 3697 // NOTE: SetRtxSendPayloadType must be called after all simulcast SSRCs 3698 // are configured. Otherwise ssrc's configured after this point will use 3699 // the primary PT for RTX. 3700 if (send_rtx_type_ != -1 && 3701 engine()->vie()->rtp()->SetRtxSendPayloadType(channel_id, 3702 send_rtx_type_) != 0) { 3703 LOG_RTCERR2(SetRtxSendPayloadType, channel_id, send_rtx_type_); 3704 return false; 3705 } 3706 } 3707 send_channel->set_interval( 3708 cricket::VideoFormat::FpsToInterval(target_codec.maxFramerate)); 3709 return true; 3710 } 3711 3712 static std::string ToString(webrtc::VideoCodecComplexity complexity) { 3713 switch (complexity) { 3714 case webrtc::kComplexityNormal: 3715 return "normal"; 3716 case webrtc::kComplexityHigh: 3717 return "high"; 3718 case webrtc::kComplexityHigher: 3719 return "higher"; 3720 case webrtc::kComplexityMax: 3721 return "max"; 3722 default: 3723 return "unknown"; 3724 } 3725 } 3726 3727 static std::string ToString(webrtc::VP8ResilienceMode resilience) { 3728 switch (resilience) { 3729 case webrtc::kResilienceOff: 3730 return "off"; 3731 case webrtc::kResilientStream: 3732 return "stream"; 3733 case webrtc::kResilientFrames: 3734 return "frames"; 3735 default: 3736 return "unknown"; 3737 } 3738 } 3739 3740 void WebRtcVideoMediaChannel::LogSendCodecChange(const std::string& reason) { 3741 webrtc::VideoCodec vie_codec; 3742 if (engine()->vie()->codec()->GetSendCodec(default_channel_id_, vie_codec) != 0) { 3743 LOG_RTCERR1(GetSendCodec, default_channel_id_); 3744 return; 3745 } 3746 3747 LOG(LS_INFO) << reason << " : selected video codec " 3748 << vie_codec.plName << "/" 3749 << vie_codec.width << "x" << vie_codec.height << "x" 3750 << static_cast<int>(vie_codec.maxFramerate) << "fps" 3751 << "@" << vie_codec.maxBitrate << "kbps" 3752 << " (min=" << vie_codec.minBitrate << "kbps," 3753 << " start=" << vie_codec.startBitrate << "kbps)"; 3754 LOG(LS_INFO) << "Video max quantization: " << vie_codec.qpMax; 3755 if (webrtc::kVideoCodecVP8 == vie_codec.codecType) { 3756 LOG(LS_INFO) << "VP8 number of temporal layers: " 3757 << static_cast<int>( 3758 vie_codec.codecSpecific.VP8.numberOfTemporalLayers); 3759 LOG(LS_INFO) << "VP8 options : " 3760 << "picture loss indication = " 3761 << vie_codec.codecSpecific.VP8.pictureLossIndicationOn 3762 << ", feedback mode = " 3763 << vie_codec.codecSpecific.VP8.feedbackModeOn 3764 << ", complexity = " 3765 << ToString(vie_codec.codecSpecific.VP8.complexity) 3766 << ", resilience = " 3767 << ToString(vie_codec.codecSpecific.VP8.resilience) 3768 << ", denoising = " 3769 << vie_codec.codecSpecific.VP8.denoisingOn 3770 << ", error concealment = " 3771 << vie_codec.codecSpecific.VP8.errorConcealmentOn 3772 << ", automatic resize = " 3773 << vie_codec.codecSpecific.VP8.automaticResizeOn 3774 << ", frame dropping = " 3775 << vie_codec.codecSpecific.VP8.frameDroppingOn 3776 << ", key frame interval = " 3777 << vie_codec.codecSpecific.VP8.keyFrameInterval; 3778 } 3779 3780 if (send_rtx_type_ != -1) { 3781 LOG(LS_INFO) << "RTX payload type: " << send_rtx_type_; 3782 } 3783 } 3784 3785 bool WebRtcVideoMediaChannel::SetReceiveCodecs( 3786 WebRtcVideoChannelRecvInfo* info) { 3787 int red_type = -1; 3788 int fec_type = -1; 3789 int channel_id = info->channel_id(); 3790 // Build a map from payload types to video codecs so that we easily can find 3791 // out if associated payload types are referring to valid codecs. 3792 std::map<int, webrtc::VideoCodec*> pt_to_codec; 3793 for (std::vector<webrtc::VideoCodec>::iterator it = receive_codecs_.begin(); 3794 it != receive_codecs_.end(); ++it) { 3795 pt_to_codec[it->plType] = &(*it); 3796 } 3797 bool rtx_registered = false; 3798 for (std::vector<webrtc::VideoCodec>::iterator it = receive_codecs_.begin(); 3799 it != receive_codecs_.end(); ++it) { 3800 if (it->codecType == webrtc::kVideoCodecRED) { 3801 red_type = it->plType; 3802 } else if (it->codecType == webrtc::kVideoCodecULPFEC) { 3803 fec_type = it->plType; 3804 } 3805 // If this is an RTX codec we have to verify that it is associated with 3806 // a valid video codec which we have RTX support for. 3807 if (_stricmp(it->plName, kRtxCodecName) == 0) { 3808 // WebRTC only supports one RTX codec at a time. 3809 if (rtx_registered) { 3810 LOG(LS_ERROR) << "Only one RTX codec at a time is supported."; 3811 return false; 3812 } 3813 std::map<int, int>::iterator apt_it = associated_payload_types_.find( 3814 it->plType); 3815 bool valid_apt = false; 3816 if (apt_it != associated_payload_types_.end()) { 3817 std::map<int, webrtc::VideoCodec*>::iterator codec_it = 3818 pt_to_codec.find(apt_it->second); 3819 valid_apt = codec_it != pt_to_codec.end(); 3820 } 3821 if (!valid_apt) { 3822 LOG(LS_ERROR) << "The RTX codec isn't associated with a known and " 3823 "supported payload type"; 3824 return false; 3825 } 3826 if (engine()->vie()->rtp()->SetRtxReceivePayloadType( 3827 channel_id, it->plType) != 0) { 3828 LOG_RTCERR2(SetRtxReceivePayloadType, channel_id, it->plType); 3829 return false; 3830 } 3831 rtx_registered = true; 3832 continue; 3833 } 3834 if (engine()->vie()->codec()->SetReceiveCodec(channel_id, *it) != 0) { 3835 LOG_RTCERR2(SetReceiveCodec, channel_id, it->plName); 3836 return false; 3837 } 3838 if (!info->IsDecoderRegistered(it->plType) && 3839 it->codecType != webrtc::kVideoCodecRED && 3840 it->codecType != webrtc::kVideoCodecULPFEC) { 3841 webrtc::VideoDecoder* decoder = 3842 engine()->CreateExternalDecoder(it->codecType); 3843 if (decoder) { 3844 if (engine()->vie()->ext_codec()->RegisterExternalReceiveCodec( 3845 channel_id, it->plType, decoder) == 0) { 3846 info->RegisterDecoder(it->plType, decoder); 3847 } else { 3848 LOG_RTCERR2(RegisterExternalReceiveCodec, channel_id, it->plName); 3849 engine()->DestroyExternalDecoder(decoder); 3850 } 3851 } 3852 } 3853 } 3854 return true; 3855 } 3856 3857 int WebRtcVideoMediaChannel::GetRecvChannelId(uint32 ssrc) { 3858 if (ssrc == first_receive_ssrc_) { 3859 return default_channel_id_; 3860 } 3861 int recv_channel_id = kChannelIdUnset; 3862 WebRtcVideoChannelRecvInfo* recv_channel = GetRecvChannelBySsrc(ssrc); 3863 if (!recv_channel) { 3864 // Check if we have an RTX stream registered on this SSRC. 3865 SsrcMap::iterator rtx_it = rtx_to_primary_ssrc_.find(ssrc); 3866 if (rtx_it != rtx_to_primary_ssrc_.end()) { 3867 if (rtx_it->second == first_receive_ssrc_) { 3868 recv_channel_id = default_channel_id_; 3869 } else { 3870 recv_channel = GetRecvChannelBySsrc(rtx_it->second); 3871 ASSERT(recv_channel != NULL); 3872 recv_channel_id = recv_channel->channel_id(); 3873 } 3874 } 3875 } else { 3876 recv_channel_id = recv_channel->channel_id(); 3877 } 3878 return recv_channel_id; 3879 } 3880 3881 // If the new frame size is different from the send codec size we set on vie, 3882 // we need to reset the send codec on vie. 3883 // The new send codec size should not exceed send_codec_ which is controlled 3884 // only by the 'jec' logic. 3885 // TODO(pthatcher): Get rid of this function, so we only ever set up 3886 // codecs in a single place. 3887 bool WebRtcVideoMediaChannel::MaybeResetVieSendCodec( 3888 WebRtcVideoChannelSendInfo* send_channel, 3889 int new_width, 3890 int new_height, 3891 bool is_screencast, 3892 bool* reset) { 3893 if (reset) { 3894 *reset = false; 3895 } 3896 ASSERT(send_codec_.get() != NULL); 3897 3898 webrtc::VideoCodec target_codec = *send_codec_; 3899 const VideoFormat& video_format = send_channel->video_format(); 3900 UpdateVideoCodec(video_format, &target_codec); 3901 3902 // Vie send codec size should not exceed target_codec. 3903 int target_width = new_width; 3904 int target_height = new_height; 3905 if (!is_screencast && 3906 (new_width > target_codec.width || new_height > target_codec.height)) { 3907 target_width = target_codec.width; 3908 target_height = target_codec.height; 3909 } 3910 3911 // Get current vie codec. 3912 webrtc::VideoCodec vie_codec; 3913 const int channel_id = send_channel->channel_id(); 3914 if (engine()->vie()->codec()->GetSendCodec(channel_id, vie_codec) != 0) { 3915 LOG_RTCERR1(GetSendCodec, channel_id); 3916 return false; 3917 } 3918 const int cur_width = vie_codec.width; 3919 const int cur_height = vie_codec.height; 3920 3921 // Only reset send codec when there is a size change. Additionally, 3922 // automatic resize needs to be turned off when screencasting and on when 3923 // not screencasting. 3924 // Don't allow automatic resizing for screencasting. 3925 bool automatic_resize = !is_screencast; 3926 // Turn off VP8 frame dropping when screensharing as the current model does 3927 // not work well at low fps. 3928 bool vp8_frame_dropping = !is_screencast; 3929 // TODO(pbos): Remove |video_noise_reduction| and enable it for all 3930 // non-screencast. 3931 bool enable_denoising = 3932 options_.video_noise_reduction.GetWithDefaultIfUnset(true); 3933 // Disable denoising for screencasting. 3934 if (is_screencast) { 3935 enable_denoising = false; 3936 } 3937 int screencast_min_bitrate = 3938 options_.screencast_min_bitrate.GetWithDefaultIfUnset(0); 3939 bool leaky_bucket = options_.video_leaky_bucket.GetWithDefaultIfUnset(true); 3940 StreamParams* send_params = send_channel->stream_params(); 3941 bool reset_send_codec = 3942 target_width != cur_width || target_height != cur_height; 3943 if (vie_codec.codecType == webrtc::kVideoCodecVP8) { 3944 reset_send_codec = reset_send_codec || 3945 automatic_resize != vie_codec.codecSpecific.VP8.automaticResizeOn || 3946 enable_denoising != vie_codec.codecSpecific.VP8.denoisingOn || 3947 vp8_frame_dropping != vie_codec.codecSpecific.VP8.frameDroppingOn; 3948 } 3949 3950 if (reset_send_codec) { 3951 // Set the new codec on vie. 3952 vie_codec.width = target_width; 3953 vie_codec.height = target_height; 3954 vie_codec.maxFramerate = target_codec.maxFramerate; 3955 vie_codec.startBitrate = target_codec.startBitrate; 3956 vie_codec.minBitrate = target_codec.minBitrate; 3957 vie_codec.maxBitrate = target_codec.maxBitrate; 3958 vie_codec.targetBitrate = 0; 3959 if (vie_codec.codecType == webrtc::kVideoCodecVP8) { 3960 vie_codec.codecSpecific.VP8.automaticResizeOn = automatic_resize; 3961 vie_codec.codecSpecific.VP8.denoisingOn = enable_denoising; 3962 vie_codec.codecSpecific.VP8.frameDroppingOn = vp8_frame_dropping; 3963 } 3964 SanitizeBitrates(channel_id, &vie_codec); 3965 3966 if (engine()->vie()->codec()->SetSendCodec(channel_id, vie_codec) != 0) { 3967 LOG_RTCERR1(SetSendCodec, channel_id); 3968 return false; 3969 } 3970 3971 if (is_screencast) { 3972 engine()->vie()->rtp()->SetMinTransmitBitrate(channel_id, 3973 screencast_min_bitrate); 3974 // If screencast and min bitrate set, force enable pacer. 3975 if (screencast_min_bitrate > 0) { 3976 engine()->vie()->rtp()->SetTransmissionSmoothingStatus(channel_id, 3977 true); 3978 } 3979 } else { 3980 // In case of switching from screencast to regular capture, set 3981 // min bitrate padding and pacer back to defaults. 3982 engine()->vie()->rtp()->SetMinTransmitBitrate(channel_id, 0); 3983 engine()->vie()->rtp()->SetTransmissionSmoothingStatus(channel_id, 3984 leaky_bucket); 3985 } 3986 // TODO(sriniv): SetSendCodec already sets ssrc's like below. 3987 // Consider removing. 3988 if (send_params) { 3989 if (!SetSendSsrcs(channel_id, *send_params, target_codec)) { 3990 return false; 3991 } 3992 } 3993 if (reset) { 3994 *reset = true; 3995 } 3996 LogSendCodecChange("Capture size changed"); 3997 } 3998 3999 return true; 4000 } 4001 4002 void WebRtcVideoMediaChannel::SanitizeBitrates( 4003 int channel_id, webrtc::VideoCodec* codec) { 4004 codec->minBitrate = GetBitrate(codec->minBitrate, kMinVideoBitrate); 4005 codec->startBitrate = GetBitrate(codec->startBitrate, kStartVideoBitrate); 4006 codec->maxBitrate = GetBitrate(codec->maxBitrate, kMaxVideoBitrate); 4007 4008 if (codec->minBitrate > codec->maxBitrate) { 4009 LOG(LS_INFO) << "Decreasing codec min bitrate to the max (" 4010 << codec->maxBitrate << ") because the min (" 4011 << codec->minBitrate << ") exceeds the max."; 4012 codec->minBitrate = codec->maxBitrate; 4013 } 4014 if (codec->startBitrate < codec->minBitrate) { 4015 LOG(LS_INFO) << "Increasing codec start bitrate to the min (" 4016 << codec->minBitrate << ") because the start (" 4017 << codec->startBitrate << ") is less than the min."; 4018 codec->startBitrate = codec->minBitrate; 4019 } else if (codec->startBitrate > codec->maxBitrate) { 4020 LOG(LS_INFO) << "Decreasing codec start bitrate to the max (" 4021 << codec->maxBitrate << ") because the start (" 4022 << codec->startBitrate << ") exceeds the max."; 4023 codec->startBitrate = codec->maxBitrate; 4024 } 4025 4026 // Use a previous target bitrate, if there is one. 4027 unsigned int current_target_bitrate = 0; 4028 if (engine()->vie()->codec()->GetCodecTargetBitrate( 4029 channel_id, ¤t_target_bitrate) == 0) { 4030 // Convert to kbps. 4031 current_target_bitrate /= 1000; 4032 if (current_target_bitrate > codec->maxBitrate) { 4033 current_target_bitrate = codec->maxBitrate; 4034 } 4035 if (current_target_bitrate > codec->startBitrate) { 4036 codec->startBitrate = current_target_bitrate; 4037 } 4038 } 4039 } 4040 4041 void WebRtcVideoMediaChannel::OnMessage(rtc::Message* msg) { 4042 FlushBlackFrameData* black_frame_data = 4043 static_cast<FlushBlackFrameData*>(msg->pdata); 4044 FlushBlackFrame(black_frame_data->ssrc, black_frame_data->timestamp); 4045 delete black_frame_data; 4046 } 4047 4048 int WebRtcVideoMediaChannel::SendPacket(int channel, const void* data, 4049 int len) { 4050 rtc::Buffer packet(data, len, kMaxRtpPacketLen); 4051 return MediaChannel::SendPacket(&packet) ? len : -1; 4052 } 4053 4054 int WebRtcVideoMediaChannel::SendRTCPPacket(int channel, 4055 const void* data, 4056 int len) { 4057 rtc::Buffer packet(data, len, kMaxRtpPacketLen); 4058 return MediaChannel::SendRtcp(&packet) ? len : -1; 4059 } 4060 4061 void WebRtcVideoMediaChannel::QueueBlackFrame(uint32 ssrc, int64 timestamp, 4062 int framerate) { 4063 if (timestamp) { 4064 FlushBlackFrameData* black_frame_data = new FlushBlackFrameData( 4065 ssrc, 4066 timestamp); 4067 const int delay_ms = static_cast<int>( 4068 2 * cricket::VideoFormat::FpsToInterval(framerate) * 4069 rtc::kNumMillisecsPerSec / rtc::kNumNanosecsPerSec); 4070 worker_thread()->PostDelayed(delay_ms, this, 0, black_frame_data); 4071 } 4072 } 4073 4074 void WebRtcVideoMediaChannel::FlushBlackFrame(uint32 ssrc, int64 timestamp) { 4075 WebRtcVideoChannelSendInfo* send_channel = GetSendChannelBySsrc(ssrc); 4076 if (!send_channel) { 4077 return; 4078 } 4079 rtc::scoped_ptr<const VideoFrame> black_frame_ptr; 4080 4081 const WebRtcLocalStreamInfo* channel_stream_info = 4082 send_channel->local_stream_info(); 4083 int64 last_frame_time_stamp = channel_stream_info->time_stamp(); 4084 if (last_frame_time_stamp == timestamp) { 4085 size_t last_frame_width = 0; 4086 size_t last_frame_height = 0; 4087 int64 last_frame_elapsed_time = 0; 4088 channel_stream_info->GetLastFrameInfo(&last_frame_width, &last_frame_height, 4089 &last_frame_elapsed_time); 4090 if (!last_frame_width || !last_frame_height) { 4091 return; 4092 } 4093 WebRtcVideoFrame black_frame; 4094 // Black frame is not screencast. 4095 const bool screencasting = false; 4096 const int64 timestamp_delta = send_channel->interval(); 4097 if (!black_frame.InitToBlack(send_codec_->width, send_codec_->height, 1, 1, 4098 last_frame_elapsed_time + timestamp_delta, 4099 last_frame_time_stamp + timestamp_delta) || 4100 !SendFrame(send_channel, &black_frame, screencasting)) { 4101 LOG(LS_ERROR) << "Failed to send black frame."; 4102 } 4103 } 4104 } 4105 4106 void WebRtcVideoMediaChannel::OnCpuAdaptationUnable() { 4107 // ssrc is hardcoded to 0. This message is based on a system wide issue, 4108 // so finding which ssrc caused it doesn't matter. 4109 SignalMediaError(0, VideoMediaChannel::ERROR_REC_CPU_MAX_CANT_DOWNGRADE); 4110 } 4111 4112 void WebRtcVideoMediaChannel::SetNetworkTransmissionState( 4113 bool is_transmitting) { 4114 LOG(LS_INFO) << "SetNetworkTransmissionState: " << is_transmitting; 4115 for (SendChannelMap::iterator iter = send_channels_.begin(); 4116 iter != send_channels_.end(); ++iter) { 4117 WebRtcVideoChannelSendInfo* send_channel = iter->second; 4118 int channel_id = send_channel->channel_id(); 4119 engine_->vie()->network()->SetNetworkTransmissionState(channel_id, 4120 is_transmitting); 4121 } 4122 } 4123 4124 bool WebRtcVideoMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter, 4125 int channel_id, const RtpHeaderExtension* extension) { 4126 bool enable = false; 4127 int id = 0; 4128 if (extension) { 4129 enable = true; 4130 id = extension->id; 4131 } 4132 if ((engine_->vie()->rtp()->*setter)(channel_id, enable, id) != 0) { 4133 LOG_RTCERR4(*setter, extension->uri, channel_id, enable, id); 4134 return false; 4135 } 4136 return true; 4137 } 4138 4139 bool WebRtcVideoMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter, 4140 int channel_id, const std::vector<RtpHeaderExtension>& extensions, 4141 const char header_extension_uri[]) { 4142 const RtpHeaderExtension* extension = FindHeaderExtension(extensions, 4143 header_extension_uri); 4144 return SetHeaderExtension(setter, channel_id, extension); 4145 } 4146 4147 bool WebRtcVideoMediaChannel::SetPrimaryAndRtxSsrcs( 4148 int channel_id, int idx, uint32 primary_ssrc, 4149 const StreamParams& send_params) { 4150 LOG(LS_INFO) << "Set primary ssrc " << primary_ssrc 4151 << " on channel " << channel_id << " idx " << idx; 4152 if (engine()->vie()->rtp()->SetLocalSSRC( 4153 channel_id, primary_ssrc, webrtc::kViEStreamTypeNormal, idx) != 0) { 4154 LOG_RTCERR4(SetLocalSSRC, 4155 channel_id, primary_ssrc, webrtc::kViEStreamTypeNormal, idx); 4156 return false; 4157 } 4158 4159 uint32 rtx_ssrc = 0; 4160 if (send_params.GetFidSsrc(primary_ssrc, &rtx_ssrc)) { 4161 LOG(LS_INFO) << "Set rtx ssrc " << rtx_ssrc 4162 << " on channel " << channel_id << " idx " << idx; 4163 if (engine()->vie()->rtp()->SetLocalSSRC( 4164 channel_id, rtx_ssrc, webrtc::kViEStreamTypeRtx, idx) != 0) { 4165 LOG_RTCERR4(SetLocalSSRC, 4166 channel_id, rtx_ssrc, webrtc::kViEStreamTypeRtx, idx); 4167 return false; 4168 } 4169 } 4170 return true; 4171 } 4172 4173 bool WebRtcVideoMediaChannel::SetLimitedNumberOfSendSsrcs( 4174 int channel_id, const StreamParams& sp, size_t limit) { 4175 const SsrcGroup* sim_group = sp.get_ssrc_group(kSimSsrcGroupSemantics); 4176 if (!sim_group || limit == 1) { 4177 return SetPrimaryAndRtxSsrcs(channel_id, 0, sp.first_ssrc(), sp); 4178 } 4179 4180 std::vector<uint32> ssrcs = sim_group->ssrcs; 4181 for (size_t i = 0; i < ssrcs.size() && i < limit; ++i) { 4182 if (!SetPrimaryAndRtxSsrcs(channel_id, static_cast<int>(i), ssrcs[i], sp)) { 4183 return false; 4184 } 4185 } 4186 return true; 4187 } 4188 4189 bool WebRtcVideoMediaChannel::SetSendSsrcs( 4190 int channel_id, const StreamParams& sp, 4191 const webrtc::VideoCodec& codec) { 4192 // TODO(pthatcher): Support more than one primary SSRC per stream. 4193 return SetLimitedNumberOfSendSsrcs(channel_id, sp, 1); 4194 } 4195 4196 void WebRtcVideoMediaChannel::MaybeConnectCapturer(VideoCapturer* capturer) { 4197 if (capturer && GetSendChannelNum(capturer) == 1) { 4198 capturer->SignalVideoFrame.connect(this, 4199 &WebRtcVideoMediaChannel::SendFrame); 4200 } 4201 } 4202 4203 void WebRtcVideoMediaChannel::MaybeDisconnectCapturer(VideoCapturer* capturer) { 4204 if (capturer && GetSendChannelNum(capturer) == 1) { 4205 capturer->SignalVideoFrame.disconnect(this); 4206 } 4207 } 4208 4209 void WebRtcVideoMediaChannel::SetReceiverReportSsrc(uint32 ssrc) { 4210 for (RecvChannelMap::const_iterator it = recv_channels_.begin(); 4211 it != recv_channels_.end(); ++it) { 4212 int channel_id = it->second->channel_id(); 4213 if (engine()->vie()->rtp()->SetLocalSSRC(channel_id, ssrc) != 0) { 4214 LOG_RTCERR2(SetLocalSSRC, channel_id, ssrc); 4215 ASSERT(false); 4216 } 4217 } 4218 receiver_report_ssrc_ = ssrc; 4219 } 4220 4221 } // namespace cricket 4222 4223 #endif // HAVE_WEBRTC_VIDEO 4224