• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &current_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