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>
Changed(cricket::Settable<T> proposed,cricket::Settable<T> original)70 bool Changed(cricket::Settable<T> proposed,
71 cricket::Settable<T> original) {
72 return proposed.IsSet() && proposed != original;
73 }
74
75 template <class T>
Changed(cricket::Settable<T> proposed,cricket::Settable<T> original,T * value)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
BitrateIsSet(int value)114 static bool BitrateIsSet(int value) {
115 return value > kAutoBandwidth;
116 }
117
GetBitrate(int value,int deflt)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.
GetExternalVideoPayloadType(int index)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
LogMultiline(rtc::LoggingSeverity sev,char * text)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.
SeverityToFilter(int severity)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
IsNackEnabled(const VideoCodec & codec)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.
IsRembEnabled(const VideoCodec & codec)169 static bool IsRembEnabled(const VideoCodec& codec) {
170 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamRemb,
171 kParamValueEmpty));
172 }
173
174 struct FlushBlackFrameData : public rtc::MessageData {
FlushBlackFrameDatacricket::FlushBlackFrameData175 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:
WebRtcRenderAdapter(VideoRenderer * renderer,int channel_id)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
~WebRtcRenderAdapter()192 virtual ~WebRtcRenderAdapter() {
193 }
194
SetRenderer(VideoRenderer * renderer)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.
FrameSizeChange(unsigned int width,unsigned int height,unsigned int)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
DeliverFrame(unsigned char * buffer,int buffer_size,uint32_t rtp_time_stamp,int64_t ntp_time_ms,int64_t render_time,void * handle)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
IsTextureSupported()272 virtual bool IsTextureSupported() { return true; }
273
DeliverBufferFrame(unsigned char * buffer,int buffer_size,int64 time_stamp,int64 elapsed_time)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
DeliverTextureFrame(void * handle,int64 time_stamp,int64 elapsed_time)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
width()298 unsigned int width() {
299 rtc::CritScope cs(&crit_);
300 return width_;
301 }
302
height()303 unsigned int height() {
304 rtc::CritScope cs(&crit_);
305 return height_;
306 }
307
framerate()308 int framerate() {
309 rtc::CritScope cs(&crit_);
310 return static_cast<int>(frame_rate_tracker_.units_second());
311 }
312
renderer()313 VideoRenderer* renderer() {
314 rtc::CritScope cs(&crit_);
315 return renderer_;
316 }
317
capture_start_ntp_time_ms()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:
WebRtcDecoderObserver(int video_channel_id)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.
IncomingCodecChanged(const int video_channel_id,const webrtc::VideoCodec & videoCodec)351 virtual void IncomingCodecChanged(const int video_channel_id,
352 const webrtc::VideoCodec& videoCodec) {}
IncomingRate(const int video_channel_id,const unsigned int framerate,const unsigned int bitrate)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
DecoderTiming(int decode_ms,int max_decode_ms,int current_delay_ms,int target_delay_ms,int jitter_buffer_ms,int min_playout_delay_ms,int render_delay_ms)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
RequestNewKeyFrame(const int video_channel_id)379 virtual void RequestNewKeyFrame(const int video_channel_id) {}
380
381 // Populate |rinfo| based on previously-set data in |*this|.
ExportTo(VideoReceiverInfo * rinfo)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:
WebRtcEncoderObserver(int video_channel_id)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.
OutgoingRate(const int video_channel_id,const unsigned int framerate,const unsigned int bitrate)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
SuspendChange(int video_channel_id,bool is_suspended)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
framerate() const433 int framerate() const {
434 rtc::CritScope cs(&crit_);
435 return framerate_;
436 }
bitrate() const437 int bitrate() const {
438 rtc::CritScope cs(&crit_);
439 return bitrate_;
440 }
suspended() const441 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:
WebRtcLocalStreamInfo()456 WebRtcLocalStreamInfo()
457 : width_(0), height_(0), elapsed_time_(-1), time_stamp_(-1) {}
width() const458 size_t width() const {
459 rtc::CritScope cs(&crit_);
460 return width_;
461 }
height() const462 size_t height() const {
463 rtc::CritScope cs(&crit_);
464 return height_;
465 }
elapsed_time() const466 int64 elapsed_time() const {
467 rtc::CritScope cs(&crit_);
468 return elapsed_time_;
469 }
time_stamp() const470 int64 time_stamp() const {
471 rtc::CritScope cs(&crit_);
472 return time_stamp_;
473 }
framerate()474 int framerate() {
475 rtc::CritScope cs(&crit_);
476 return static_cast<int>(rate_tracker_.units_second());
477 }
GetLastFrameInfo(size_t * width,size_t * height,int64 * elapsed_time) const478 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
UpdateFrame(const VideoFrame * frame)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
WebRtcVideoChannelRecvInfo(int channel_id)516 explicit WebRtcVideoChannelRecvInfo(int channel_id)
517 : channel_id_(channel_id),
518 render_adapter_(NULL, channel_id),
519 decoder_observer_(channel_id) {
520 }
channel_id()521 int channel_id() { return channel_id_; }
SetRenderer(VideoRenderer * renderer)522 void SetRenderer(VideoRenderer* renderer) {
523 render_adapter_.SetRenderer(renderer);
524 }
render_adapter()525 WebRtcRenderAdapter* render_adapter() { return &render_adapter_; }
decoder_observer()526 WebRtcDecoderObserver* decoder_observer() { return &decoder_observer_; }
RegisterDecoder(int pl_type,webrtc::VideoDecoder * decoder)527 void RegisterDecoder(int pl_type, webrtc::VideoDecoder* decoder) {
528 ASSERT(!IsDecoderRegistered(pl_type));
529 registered_decoders_[pl_type] = decoder;
530 }
IsDecoderRegistered(int pl_type)531 bool IsDecoderRegistered(int pl_type) {
532 return registered_decoders_.count(pl_type) != 0;
533 }
registered_decoders()534 const DecoderMap& registered_decoders() {
535 return registered_decoders_;
536 }
ClearRegisteredDecoders()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:
WebRtcOveruseObserver(CoordinatedVideoAdapter * video_adapter)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.
OveruseDetected()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
NormalUsage()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
Enable(bool enable)577 void Enable(bool enable) {
578 LOG(LS_INFO) << "WebRtcOveruseObserver enable: " << enable;
579 rtc::CritScope cs(&crit_);
580 enabled_ = enable;
581 }
582
enabled() const583 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
WebRtcVideoChannelSendInfo(int channel_id,int capture_id,webrtc::ViEExternalCapture * external_capture,rtc::CpuMonitor * cpu_monitor)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
channel_id() const610 int channel_id() const { return channel_id_; }
capture_id() const611 int capture_id() const { return capture_id_; }
set_sending(bool sending)612 void set_sending(bool sending) { sending_ = sending; }
sending() const613 bool sending() const { return sending_; }
set_muted(bool on)614 void set_muted(bool on) {
615 // TODO(asapersson): add support.
616 // video_adapter_.SetBlackOutput(on);
617 muted_ = on;
618 }
muted()619 bool muted() {return muted_; }
620
encoder_observer()621 WebRtcEncoderObserver* encoder_observer() { return &encoder_observer_; }
external_capture()622 webrtc::ViEExternalCapture* external_capture() { return external_capture_; }
video_format() const623 const VideoFormat& video_format() const {
624 return video_format_;
625 }
set_video_format(const VideoFormat & video_format)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 }
set_interval(int64 interval)636 void set_interval(int64 interval) {
637 if (video_format() == cricket::VideoFormat()) {
638 interval_ = interval;
639 }
640 }
interval()641 int64 interval() { return interval_; }
642
CurrentAdaptReason() const643 int CurrentAdaptReason() const {
644 if (!video_adapter()) {
645 return CoordinatedVideoAdapter::ADAPTREASON_NONE;
646 }
647 return video_adapter()->adapt_reason();
648 }
AdaptChanges() const649 int AdaptChanges() const {
650 if (!video_adapter()) {
651 return old_adaptation_changes_;
652 }
653 return old_adaptation_changes_ + video_adapter()->adaptation_changes();
654 }
655
stream_params()656 StreamParams* stream_params() { return stream_params_.get(); }
set_stream_params(const StreamParams & sp)657 void set_stream_params(const StreamParams& sp) {
658 stream_params_.reset(new StreamParams(sp));
659 }
ClearStreamParams()660 void ClearStreamParams() { stream_params_.reset(); }
has_ssrc(uint32 local_ssrc) const661 bool has_ssrc(uint32 local_ssrc) const {
662 return !stream_params_ ? false :
663 stream_params_->has_ssrc(local_ssrc);
664 }
local_stream_info()665 WebRtcLocalStreamInfo* local_stream_info() {
666 return &local_stream_info_;
667 }
video_capturer()668 VideoCapturer* video_capturer() {
669 return video_capturer_;
670 }
set_video_capturer(VideoCapturer * video_capturer,ViEWrapper * vie_wrapper)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
video_adapter()711 CoordinatedVideoAdapter* video_adapter() {
712 if (!video_capturer_) {
713 return NULL;
714 }
715 return video_capturer_->video_adapter();
716 }
video_adapter() const717 const CoordinatedVideoAdapter* video_adapter() const {
718 if (!video_capturer_) {
719 return NULL;
720 }
721 return video_capturer_->video_adapter();
722 }
723
ApplyCpuOptions(const VideoOptions & video_options)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
UpdateAdapterCpuOptions()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
SetCpuOveruseDetection(bool enable)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
ProcessFrame(const VideoFrame & original_frame,bool mute,VideoFrame ** processed_frame)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 }
RegisterEncoder(int pl_type,webrtc::VideoEncoder * encoder)810 void RegisterEncoder(int pl_type, webrtc::VideoEncoder* encoder) {
811 ASSERT(!IsEncoderRegistered(pl_type));
812 registered_encoders_[pl_type] = encoder;
813 }
IsEncoderRegistered(int pl_type)814 bool IsEncoderRegistered(int pl_type) {
815 return registered_encoders_.count(pl_type) != 0;
816 }
registered_encoders()817 const EncoderMap& registered_encoders() {
818 return registered_encoders_;
819 }
ClearRegisteredEncoders()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
UpdateVideoCodec(const cricket::VideoFormat & video_format,webrtc::VideoCodec * target_codec)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
GetCpuOveruseOptions(const VideoOptions & options,webrtc::CpuOveruseOptions * overuse_options)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
WebRtcVideoEngine()917 WebRtcVideoEngine::WebRtcVideoEngine() {
918 Construct(new ViEWrapper(), new ViETraceWrapper(), NULL,
919 new rtc::CpuMonitor(NULL));
920 }
921
WebRtcVideoEngine(WebRtcVoiceEngine * voice_engine,ViEWrapper * vie_wrapper,rtc::CpuMonitor * cpu_monitor)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
WebRtcVideoEngine(WebRtcVoiceEngine * voice_engine,ViEWrapper * vie_wrapper,ViETraceWrapper * tracing,rtc::CpuMonitor * cpu_monitor)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
Construct(ViEWrapper * vie_wrapper,ViETraceWrapper * tracing,WebRtcVoiceEngine * voice_engine,rtc::CpuMonitor * cpu_monitor)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
~WebRtcVideoEngine()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
Init(rtc::Thread * worker_thread)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
InitVideoEngine()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
Terminate()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
GetCapabilities()1078 int WebRtcVideoEngine::GetCapabilities() {
1079 return VIDEO_RECV | VIDEO_SEND;
1080 }
1081
SetDefaultEncoderConfig(const VideoEncoderConfig & config)1082 bool WebRtcVideoEngine::SetDefaultEncoderConfig(
1083 const VideoEncoderConfig& config) {
1084 return SetDefaultCodec(config.max_codec);
1085 }
1086
GetDefaultEncoderConfig() const1087 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.
SetDefaultCodec(const VideoCodec & codec)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
CreateChannel(VoiceMediaChannel * voice_channel)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
codecs() const1128 const std::vector<VideoCodec>& WebRtcVideoEngine::codecs() const {
1129 return video_codecs_;
1130 }
1131
1132 const std::vector<RtpHeaderExtension>&
rtp_header_extensions() const1133 WebRtcVideoEngine::rtp_header_extensions() const {
1134 return rtp_header_extensions_;
1135 }
1136
SetLogging(int min_sev,const char * filter)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
GetLastEngineError()1145 int WebRtcVideoEngine::GetLastEngineError() {
1146 return vie_wrapper_->error();
1147 }
1148
1149 // Checks to see whether we comprehend and could receive a particular codec
FindCodec(const VideoCodec & in)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.
CanSendCodec(const VideoCodec & requested,const VideoCodec &,VideoCodec * out)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
ConvertToCricketVideoCodec(const webrtc::VideoCodec & in_codec,VideoCodec * out_codec)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
ConvertFromCricketVideoCodec(const VideoCodec & in_codec,webrtc::VideoCodec * out_codec)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
RegisterChannel(WebRtcVideoMediaChannel * channel)1324 void WebRtcVideoEngine::RegisterChannel(WebRtcVideoMediaChannel *channel) {
1325 rtc::CritScope cs(&channels_crit_);
1326 channels_.push_back(channel);
1327 }
1328
UnregisterChannel(WebRtcVideoMediaChannel * channel)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
SetVoiceEngine(WebRtcVoiceEngine * voice_engine)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
EnableTimedRender()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
SetTraceFilter(int filter)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.
SetTraceOptions(const std::string & options)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
AddDefaultFeedbackParams(VideoCodec * codec)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.
RebuildCodecList(const VideoCodec & in_codec)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.
ShouldIgnoreTrace(const std::string & trace)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
GetNumOfChannels()1457 int WebRtcVideoEngine::GetNumOfChannels() {
1458 rtc::CritScope cs(&channels_crit_);
1459 return static_cast<int>(channels_.size());
1460 }
1461
Print(webrtc::TraceLevel level,const char * trace,int length)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
CreateExternalDecoder(webrtc::VideoCodecType type)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
DestroyExternalDecoder(webrtc::VideoDecoder * decoder)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
CreateExternalEncoder(webrtc::VideoCodecType type)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
DestroyExternalEncoder(webrtc::VideoEncoder * encoder)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
IsExternalEncoderCodecType(webrtc::VideoCodecType type) const1518 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
SetExternalDecoderFactory(WebRtcVideoDecoderFactory * decoder_factory)1532 void WebRtcVideoEngine::SetExternalDecoderFactory(
1533 WebRtcVideoDecoderFactory* decoder_factory) {
1534 decoder_factory_ = decoder_factory;
1535 }
1536
SetExternalEncoderFactory(WebRtcVideoEncoderFactory * encoder_factory)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
OnCodecsAvailable()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
WebRtcVideoMediaChannel(WebRtcVideoEngine * engine,VoiceMediaChannel * channel)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
Init()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
~WebRtcVideoMediaChannel()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
SetRecvCodecs(const std::vector<VideoCodec> & codecs)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
SetSendCodecs(const std::vector<VideoCodec> & codecs)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
MaybeRegisterExternalEncoder(WebRtcVideoChannelSendInfo * send_channel,const webrtc::VideoCodec & codec)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
GetSendCodec(VideoCodec * send_codec)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
SetSendStreamFormat(uint32 ssrc,const VideoFormat & format)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
SetRender(bool render)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
SetSend(bool send)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
AddSendStream(const StreamParams & sp)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
RemoveSendStream(uint32 ssrc)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
AddRecvStream(const StreamParams & sp)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
MaybeSetRtxSsrc(const StreamParams & sp,int channel_id)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
RemoveRecvStream(uint32 ssrc)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
RemoveRecvStreamInternal(uint32 ssrc)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
StartSend()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
StartSend(WebRtcVideoChannelSendInfo * send_channel)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
StopSend()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
StopSend(WebRtcVideoChannelSendInfo * send_channel)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
SendIntraFrame()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
HasReadySendChannels()2218 bool WebRtcVideoMediaChannel::HasReadySendChannels() {
2219 return !send_channels_.empty() &&
2220 ((send_channels_.size() > 1) || DefaultSendChannelInUse());
2221 }
2222
DefaultSendChannelInUse()2223 bool WebRtcVideoMediaChannel::DefaultSendChannelInUse() {
2224 return GetDefaultSendChannel() && GetDefaultSendChannel()->stream_params();
2225 }
2226
GetSendChannelSsrcKey(uint32 local_ssrc,uint32 * ssrc_key)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
GetDefaultSendChannel()2262 WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetDefaultSendChannel() {
2263 return GetSendChannelBySsrcKey(kDefaultChannelSsrcKey);
2264 }
2265
GetSendChannelBySsrcKey(uint32 ssrc_key)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
GetSendChannelBySsrc(uint32 local_ssrc)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
CreateSendChannelSsrcKey(uint32 local_ssrc,uint32 * ssrc_key)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
GetSendChannelNum(VideoCapturer * capturer)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
GetDefaultSendChannelSsrc()2318 uint32 WebRtcVideoMediaChannel::GetDefaultSendChannelSsrc() {
2319 if (!DefaultSendChannelInUse()) {
2320 return 0;
2321 }
2322 return GetDefaultSendChannel()->stream_params()->first_ssrc();
2323 }
2324
DeleteSendChannel(uint32 ssrc_key)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
GetDefaultRecvChannel()2361 WebRtcVideoChannelRecvInfo* WebRtcVideoMediaChannel::GetDefaultRecvChannel() {
2362 return GetRecvChannelBySsrc(kDefaultChannelSsrcKey);
2363 }
2364
GetRecvChannelBySsrc(uint32 ssrc)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
RemoveCapturer(uint32 ssrc)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
SetRenderer(uint32 ssrc,VideoRenderer * renderer)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
GetStats(const StatsOptions & options,VideoMediaInfo * info)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
SetCapturer(uint32 ssrc,VideoCapturer * capturer)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
RequestIntraFrame()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
OnPacketReceived(rtc::Buffer * packet,const rtc::PacketTime & packet_time)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
OnRtcpReceived(rtc::Buffer * packet,const rtc::PacketTime & packet_time)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
OnReadyToSend(bool ready)2813 void WebRtcVideoMediaChannel::OnReadyToSend(bool ready) {
2814 SetNetworkTransmissionState(ready);
2815 }
2816
MuteStream(uint32 ssrc,bool muted)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
SetRecvRtpHeaderExtensions(const std::vector<RtpHeaderExtension> & extensions)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
SetSendRtpHeaderExtensions(const std::vector<RtpHeaderExtension> & extensions)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
GetRtpSendTimeExtnId() const2898 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
SetStartSendBandwidth(int bps)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
SetMaxSendBandwidth(int bps)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
SetOptions(const VideoOptions & options)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
SetInterface(NetworkInterface * iface)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
UpdateAspectRatio(int ratio_w,int ratio_h)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
GetRenderer(uint32 ssrc,VideoRenderer ** renderer)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
GetVideoAdapter(uint32 ssrc,CoordinatedVideoAdapter ** video_adapter)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
SendFrame(VideoCapturer * capturer,const VideoFrame * frame)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
SendFrame(WebRtcVideoChannelSendInfo * send_channel,const VideoFrame * frame,bool is_screencast)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
CreateChannel(uint32 ssrc_key,MediaDirection direction,int * channel_id)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
CreateUnsignalledRecvChannel(uint32 ssrc_key,int * out_channel_id)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
ConfigureChannel(int channel_id,MediaDirection direction,uint32 ssrc_key)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
ConfigureReceiving(int channel_id,uint32 remote_ssrc)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
ConfigureSending(int channel_id,uint32 local_ssrc_key)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
SetNackFec(int channel_id,int red_payload_type,int fec_payload_type,bool nack_enabled)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
SetSendCodec(const webrtc::VideoCodec & codec)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
SetSendCodec(WebRtcVideoChannelSendInfo * send_channel,const webrtc::VideoCodec & codec)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
ToString(webrtc::VideoCodecComplexity complexity)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
ToString(webrtc::VP8ResilienceMode resilience)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
LogSendCodecChange(const std::string & reason)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
SetReceiveCodecs(WebRtcVideoChannelRecvInfo * info)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
GetRecvChannelId(uint32 ssrc)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.
MaybeResetVieSendCodec(WebRtcVideoChannelSendInfo * send_channel,int new_width,int new_height,bool is_screencast,bool * reset)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
SanitizeBitrates(int channel_id,webrtc::VideoCodec * codec)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
OnMessage(rtc::Message * msg)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
SendPacket(int channel,const void * data,int len)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
SendRTCPPacket(int channel,const void * data,int len)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
QueueBlackFrame(uint32 ssrc,int64 timestamp,int framerate)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
FlushBlackFrame(uint32 ssrc,int64 timestamp)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
OnCpuAdaptationUnable()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
SetNetworkTransmissionState(bool is_transmitting)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
SetHeaderExtension(ExtensionSetterFunction setter,int channel_id,const RtpHeaderExtension * extension)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
SetHeaderExtension(ExtensionSetterFunction setter,int channel_id,const std::vector<RtpHeaderExtension> & extensions,const char header_extension_uri[])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
SetPrimaryAndRtxSsrcs(int channel_id,int idx,uint32 primary_ssrc,const StreamParams & send_params)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
SetLimitedNumberOfSendSsrcs(int channel_id,const StreamParams & sp,size_t limit)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
SetSendSsrcs(int channel_id,const StreamParams & sp,const webrtc::VideoCodec & codec)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
MaybeConnectCapturer(VideoCapturer * capturer)4196 void WebRtcVideoMediaChannel::MaybeConnectCapturer(VideoCapturer* capturer) {
4197 if (capturer && GetSendChannelNum(capturer) == 1) {
4198 capturer->SignalVideoFrame.connect(this,
4199 &WebRtcVideoMediaChannel::SendFrame);
4200 }
4201 }
4202
MaybeDisconnectCapturer(VideoCapturer * capturer)4203 void WebRtcVideoMediaChannel::MaybeDisconnectCapturer(VideoCapturer* capturer) {
4204 if (capturer && GetSendChannelNum(capturer) == 1) {
4205 capturer->SignalVideoFrame.disconnect(this);
4206 }
4207 }
4208
SetReceiverReportSsrc(uint32 ssrc)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