blob: 5e6ca9e349c1454539cd2a39e12260a6dddb9ca1 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
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/base/basictypes.h"
39#include "talk/base/buffer.h"
40#include "talk/base/byteorder.h"
41#include "talk/base/common.h"
42#include "talk/base/cpumonitor.h"
43#include "talk/base/logging.h"
44#include "talk/base/stringutils.h"
45#include "talk/base/thread.h"
46#include "talk/base/timeutils.h"
47#include "talk/media/base/constants.h"
48#include "talk/media/base/rtputils.h"
49#include "talk/media/base/streamparams.h"
50#include "talk/media/base/videoadapter.h"
51#include "talk/media/base/videocapturer.h"
52#include "talk/media/base/videorenderer.h"
53#include "talk/media/devices/filevideocapturer.h"
wu@webrtc.org9dba5252013-08-05 20:36:57 +000054#include "talk/media/webrtc/webrtcpassthroughrender.h"
55#include "talk/media/webrtc/webrtctexturevideoframe.h"
56#include "talk/media/webrtc/webrtcvideocapturer.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000057#include "talk/media/webrtc/webrtcvideodecoderfactory.h"
58#include "talk/media/webrtc/webrtcvideoencoderfactory.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000059#include "talk/media/webrtc/webrtcvideoframe.h"
60#include "talk/media/webrtc/webrtcvie.h"
61#include "talk/media/webrtc/webrtcvoe.h"
62#include "talk/media/webrtc/webrtcvoiceengine.h"
63
64#if !defined(LIBPEERCONNECTION_LIB)
65#ifndef HAVE_WEBRTC_VIDEO
66#error Need webrtc video
67#endif
68#include "talk/media/webrtc/webrtcmediaengine.h"
69
70WRME_EXPORT
71cricket::MediaEngineInterface* CreateWebRtcMediaEngine(
72 webrtc::AudioDeviceModule* adm, webrtc::AudioDeviceModule* adm_sc,
73 cricket::WebRtcVideoEncoderFactory* encoder_factory,
74 cricket::WebRtcVideoDecoderFactory* decoder_factory) {
75 return new cricket::WebRtcMediaEngine(adm, adm_sc, encoder_factory,
76 decoder_factory);
77}
78
79WRME_EXPORT
80void DestroyWebRtcMediaEngine(cricket::MediaEngineInterface* media_engine) {
81 delete static_cast<cricket::WebRtcMediaEngine*>(media_engine);
82}
83#endif
84
85
86namespace cricket {
87
88
89static const int kDefaultLogSeverity = talk_base::LS_WARNING;
90
91static const int kMinVideoBitrate = 50;
92static const int kStartVideoBitrate = 300;
93static const int kMaxVideoBitrate = 2000;
94static const int kDefaultConferenceModeMaxVideoBitrate = 500;
95
96static const int kVideoMtu = 1200;
97
98static const int kVideoRtpBufferSize = 65536;
99
100static const char kVp8PayloadName[] = "VP8";
101static const char kRedPayloadName[] = "red";
102static const char kFecPayloadName[] = "ulpfec";
103
104static const int kDefaultNumberOfTemporalLayers = 1; // 1:1
105
106static const int kTimestampDeltaInSecondsForWarning = 2;
107
108static const int kMaxExternalVideoCodecs = 8;
109static const int kExternalVideoPayloadTypeBase = 120;
110
111// Static allocation of payload type values for external video codec.
112static int GetExternalVideoPayloadType(int index) {
113 ASSERT(index >= 0 && index < kMaxExternalVideoCodecs);
114 return kExternalVideoPayloadTypeBase + index;
115}
116
117static void LogMultiline(talk_base::LoggingSeverity sev, char* text) {
118 const char* delim = "\r\n";
119 // TODO(fbarchard): Fix strtok lint warning.
120 for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) {
121 LOG_V(sev) << tok;
122 }
123}
124
125// Severity is an integer because it comes is assumed to be from command line.
126static int SeverityToFilter(int severity) {
127 int filter = webrtc::kTraceNone;
128 switch (severity) {
129 case talk_base::LS_VERBOSE:
130 filter |= webrtc::kTraceAll;
131 case talk_base::LS_INFO:
132 filter |= (webrtc::kTraceStateInfo | webrtc::kTraceInfo);
133 case talk_base::LS_WARNING:
134 filter |= (webrtc::kTraceTerseInfo | webrtc::kTraceWarning);
135 case talk_base::LS_ERROR:
136 filter |= (webrtc::kTraceError | webrtc::kTraceCritical);
137 }
138 return filter;
139}
140
141static const int kCpuMonitorPeriodMs = 2000; // 2 seconds.
142
143static const bool kNotSending = false;
144
145// Extension header for RTP timestamp offset, see RFC 5450 for details:
146// http://tools.ietf.org/html/rfc5450
147static const char kRtpTimestampOffsetHeaderExtension[] =
148 "urn:ietf:params:rtp-hdrext:toffset";
149static const int kRtpTimeOffsetExtensionId = 2;
150
151// Extension header for absolute send time, see url for details:
152// http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
153static const char kRtpAbsoluteSendTimeHeaderExtension[] =
154 "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
155static const int kRtpAbsoluteSendTimeExtensionId = 3;
156
157static bool IsNackEnabled(const VideoCodec& codec) {
158 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack,
159 kParamValueEmpty));
160}
161
162// Returns true if Receiver Estimated Max Bitrate is enabled.
163static bool IsRembEnabled(const VideoCodec& codec) {
164 return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamRemb,
165 kParamValueEmpty));
166}
167
168struct FlushBlackFrameData : public talk_base::MessageData {
169 FlushBlackFrameData(uint32 s, int64 t) : ssrc(s), timestamp(t) {
170 }
171 uint32 ssrc;
172 int64 timestamp;
173};
174
175class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
176 public:
177 explicit WebRtcRenderAdapter(VideoRenderer* renderer)
178 : renderer_(renderer), width_(0), height_(0), watermark_enabled_(false) {
179 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000180
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000181 virtual ~WebRtcRenderAdapter() {
182 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000183
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000184 void set_watermark_enabled(bool enable) {
185 talk_base::CritScope cs(&crit_);
186 watermark_enabled_ = enable;
187 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000188
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000189 void SetRenderer(VideoRenderer* renderer) {
190 talk_base::CritScope cs(&crit_);
191 renderer_ = renderer;
192 // FrameSizeChange may have already been called when renderer was not set.
193 // If so we should call SetSize here.
194 // TODO(ronghuawu): Add unit test for this case. Didn't do it now
195 // because the WebRtcRenderAdapter is currently hiding in cc file. No
196 // good way to get access to it from the unit test.
197 if (width_ > 0 && height_ > 0 && renderer_ != NULL) {
198 if (!renderer_->SetSize(width_, height_, 0)) {
199 LOG(LS_ERROR)
200 << "WebRtcRenderAdapter SetRenderer failed to SetSize to: "
201 << width_ << "x" << height_;
202 }
203 }
204 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000205
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000206 // Implementation of webrtc::ExternalRenderer.
207 virtual int FrameSizeChange(unsigned int width, unsigned int height,
208 unsigned int /*number_of_streams*/) {
209 talk_base::CritScope cs(&crit_);
210 width_ = width;
211 height_ = height;
212 LOG(LS_INFO) << "WebRtcRenderAdapter frame size changed to: "
213 << width << "x" << height;
214 if (renderer_ == NULL) {
215 LOG(LS_VERBOSE) << "WebRtcRenderAdapter the renderer has not been set. "
216 << "SetSize will be called later in SetRenderer.";
217 return 0;
218 }
219 return renderer_->SetSize(width_, height_, 0) ? 0 : -1;
220 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000221
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000222 virtual int DeliverFrame(unsigned char* buffer, int buffer_size,
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000223 uint32_t time_stamp, int64_t render_time
224#ifdef USE_WEBRTC_DEV_BRANCH
225 , void* handle
226#endif
227 ) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000228 talk_base::CritScope cs(&crit_);
229 frame_rate_tracker_.Update(1);
230 if (renderer_ == NULL) {
231 return 0;
232 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000233 // Convert 90K rtp timestamp to ns timestamp.
234 int64 rtp_time_stamp_in_ns = (time_stamp / 90) *
235 talk_base::kNumNanosecsPerMillisec;
236 // Convert milisecond render time to ns timestamp.
237 int64 render_time_stamp_in_ns = render_time *
238 talk_base::kNumNanosecsPerMillisec;
239 // Send the rtp timestamp to renderer as the VideoFrame timestamp.
240 // and the render timestamp as the VideoFrame elapsed_time.
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000241#ifdef USE_WEBRTC_DEV_BRANCH
242 if (handle == NULL) {
243#endif
244 return DeliverBufferFrame(buffer, buffer_size, render_time_stamp_in_ns,
245 rtp_time_stamp_in_ns);
246#ifdef USE_WEBRTC_DEV_BRANCH
247 } else {
248 return DeliverTextureFrame(handle, render_time_stamp_in_ns,
249 rtp_time_stamp_in_ns);
250 }
251#endif
252 }
253
254 virtual bool IsTextureSupported() { return true; }
255
256 int DeliverBufferFrame(unsigned char* buffer, int buffer_size,
257 int64 elapsed_time, int64 time_stamp) {
258 WebRtcVideoFrame video_frame;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000259 video_frame.Attach(buffer, buffer_size, width_, height_,
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000260 1, 1, elapsed_time, time_stamp, 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000261
262
263 // Sanity check on decoded frame size.
264 if (buffer_size != static_cast<int>(VideoFrame::SizeOf(width_, height_))) {
265 LOG(LS_WARNING) << "WebRtcRenderAdapter received a strange frame size: "
266 << buffer_size;
267 }
268
269 int ret = renderer_->RenderFrame(&video_frame) ? 0 : -1;
270 uint8* buffer_temp;
271 size_t buffer_size_temp;
272 video_frame.Detach(&buffer_temp, &buffer_size_temp);
273 return ret;
274 }
275
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000276 int DeliverTextureFrame(void* handle, int64 elapsed_time, int64 time_stamp) {
277 WebRtcTextureVideoFrame video_frame(
278 static_cast<webrtc::NativeHandle*>(handle), width_, height_,
279 elapsed_time, time_stamp);
280 return renderer_->RenderFrame(&video_frame);
281 }
282
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000283 unsigned int width() {
284 talk_base::CritScope cs(&crit_);
285 return width_;
286 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000287
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000288 unsigned int height() {
289 talk_base::CritScope cs(&crit_);
290 return height_;
291 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000292
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000293 int framerate() {
294 talk_base::CritScope cs(&crit_);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000295 return static_cast<int>(frame_rate_tracker_.units_second());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000296 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000297
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000298 VideoRenderer* renderer() {
299 talk_base::CritScope cs(&crit_);
300 return renderer_;
301 }
302
303 private:
304 talk_base::CriticalSection crit_;
305 VideoRenderer* renderer_;
306 unsigned int width_;
307 unsigned int height_;
308 talk_base::RateTracker frame_rate_tracker_;
309 bool watermark_enabled_;
310};
311
312class WebRtcDecoderObserver : public webrtc::ViEDecoderObserver {
313 public:
314 explicit WebRtcDecoderObserver(int video_channel)
315 : video_channel_(video_channel),
316 framerate_(0),
317 bitrate_(0),
318 firs_requested_(0) {
319 }
320
321 // virtual functions from VieDecoderObserver.
322 virtual void IncomingCodecChanged(const int videoChannel,
323 const webrtc::VideoCodec& videoCodec) {}
324 virtual void IncomingRate(const int videoChannel,
325 const unsigned int framerate,
326 const unsigned int bitrate) {
327 ASSERT(video_channel_ == videoChannel);
328 framerate_ = framerate;
329 bitrate_ = bitrate;
330 }
331 virtual void RequestNewKeyFrame(const int videoChannel) {
332 ASSERT(video_channel_ == videoChannel);
333 ++firs_requested_;
334 }
335
336 int framerate() const { return framerate_; }
337 int bitrate() const { return bitrate_; }
338 int firs_requested() const { return firs_requested_; }
339
340 private:
341 int video_channel_;
342 int framerate_;
343 int bitrate_;
344 int firs_requested_;
345};
346
347class WebRtcEncoderObserver : public webrtc::ViEEncoderObserver {
348 public:
349 explicit WebRtcEncoderObserver(int video_channel)
350 : video_channel_(video_channel),
351 framerate_(0),
352 bitrate_(0) {
353 }
354
355 // virtual functions from VieEncoderObserver.
356 virtual void OutgoingRate(const int videoChannel,
357 const unsigned int framerate,
358 const unsigned int bitrate) {
359 ASSERT(video_channel_ == videoChannel);
360 framerate_ = framerate;
361 bitrate_ = bitrate;
362 }
363
364 int framerate() const { return framerate_; }
365 int bitrate() const { return bitrate_; }
366
367 private:
368 int video_channel_;
369 int framerate_;
370 int bitrate_;
371};
372
373class WebRtcLocalStreamInfo {
374 public:
375 WebRtcLocalStreamInfo()
376 : width_(0), height_(0), elapsed_time_(-1), time_stamp_(-1) {}
377 size_t width() const {
378 talk_base::CritScope cs(&crit_);
379 return width_;
380 }
381 size_t height() const {
382 talk_base::CritScope cs(&crit_);
383 return height_;
384 }
385 int64 elapsed_time() const {
386 talk_base::CritScope cs(&crit_);
387 return elapsed_time_;
388 }
389 int64 time_stamp() const {
390 talk_base::CritScope cs(&crit_);
391 return time_stamp_;
392 }
393 int framerate() {
394 talk_base::CritScope cs(&crit_);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000395 return static_cast<int>(rate_tracker_.units_second());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000396 }
397 void GetLastFrameInfo(
398 size_t* width, size_t* height, int64* elapsed_time) const {
399 talk_base::CritScope cs(&crit_);
400 *width = width_;
401 *height = height_;
402 *elapsed_time = elapsed_time_;
403 }
404
405 void UpdateFrame(const VideoFrame* frame) {
406 talk_base::CritScope cs(&crit_);
407
408 width_ = frame->GetWidth();
409 height_ = frame->GetHeight();
410 elapsed_time_ = frame->GetElapsedTime();
411 time_stamp_ = frame->GetTimeStamp();
412
413 rate_tracker_.Update(1);
414 }
415
416 private:
417 mutable talk_base::CriticalSection crit_;
418 size_t width_;
419 size_t height_;
420 int64 elapsed_time_;
421 int64 time_stamp_;
422 talk_base::RateTracker rate_tracker_;
423
424 DISALLOW_COPY_AND_ASSIGN(WebRtcLocalStreamInfo);
425};
426
427// WebRtcVideoChannelRecvInfo is a container class with members such as renderer
428// and a decoder observer that is used by receive channels.
429// It must exist as long as the receive channel is connected to renderer or a
430// decoder observer in this class and methods in the class should only be called
431// from the worker thread.
432class WebRtcVideoChannelRecvInfo {
433 public:
434 typedef std::map<int, webrtc::VideoDecoder*> DecoderMap; // key: payload type
435 explicit WebRtcVideoChannelRecvInfo(int channel_id)
436 : channel_id_(channel_id),
437 render_adapter_(NULL),
438 decoder_observer_(channel_id) {
439 }
440 int channel_id() { return channel_id_; }
441 void SetRenderer(VideoRenderer* renderer) {
442 render_adapter_.SetRenderer(renderer);
443 }
444 WebRtcRenderAdapter* render_adapter() { return &render_adapter_; }
445 WebRtcDecoderObserver* decoder_observer() { return &decoder_observer_; }
446 void RegisterDecoder(int pl_type, webrtc::VideoDecoder* decoder) {
447 ASSERT(!IsDecoderRegistered(pl_type));
448 registered_decoders_[pl_type] = decoder;
449 }
450 bool IsDecoderRegistered(int pl_type) {
451 return registered_decoders_.count(pl_type) != 0;
452 }
453 const DecoderMap& registered_decoders() {
454 return registered_decoders_;
455 }
456 void ClearRegisteredDecoders() {
457 registered_decoders_.clear();
458 }
459
460 private:
461 int channel_id_; // Webrtc video channel number.
462 // Renderer for this channel.
463 WebRtcRenderAdapter render_adapter_;
464 WebRtcDecoderObserver decoder_observer_;
465 DecoderMap registered_decoders_;
466};
467
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000468#ifdef USE_WEBRTC_DEV_BRANCH
469class WebRtcOveruseObserver : public webrtc::CpuOveruseObserver {
470 public:
471 explicit WebRtcOveruseObserver(CoordinatedVideoAdapter* video_adapter)
472 : video_adapter_(video_adapter),
473 enabled_(false) {
474 }
475
476 // TODO(mflodman): Consider sending resolution as part of event, to let
477 // adapter know what resolution the request is based on. Helps eliminate stale
478 // data, race conditions.
479 virtual void OveruseDetected() OVERRIDE {
480 talk_base::CritScope cs(&crit_);
481 if (!enabled_) {
482 return;
483 }
484
485 video_adapter_->OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
486 }
487
488 virtual void NormalUsage() OVERRIDE {
489 talk_base::CritScope cs(&crit_);
490 if (!enabled_) {
491 return;
492 }
493
494 video_adapter_->OnCpuResolutionRequest(CoordinatedVideoAdapter::UPGRADE);
495 }
496
497 void Enable(bool enable) {
498 talk_base::CritScope cs(&crit_);
499 enabled_ = enable;
500 }
501
502 private:
503 CoordinatedVideoAdapter* video_adapter_;
504 bool enabled_;
505 talk_base::CriticalSection crit_;
506};
507
508#endif
509
wu@webrtc.orgd64719d2013-08-01 00:00:07 +0000510class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000511 public:
512 typedef std::map<int, webrtc::VideoEncoder*> EncoderMap; // key: payload type
513 WebRtcVideoChannelSendInfo(int channel_id, int capture_id,
514 webrtc::ViEExternalCapture* external_capture,
515 talk_base::CpuMonitor* cpu_monitor)
516 : channel_id_(channel_id),
517 capture_id_(capture_id),
518 sending_(false),
519 muted_(false),
520 video_capturer_(NULL),
521 encoder_observer_(channel_id),
522 external_capture_(external_capture),
523 capturer_updated_(false),
524 interval_(0),
525 video_adapter_(new CoordinatedVideoAdapter) {
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000526#ifdef USE_WEBRTC_DEV_BRANCH
527 overuse_observer_.reset(new WebRtcOveruseObserver(video_adapter_.get()));
528#endif
wu@webrtc.orgd64719d2013-08-01 00:00:07 +0000529 SignalCpuAdaptationUnable.repeat(video_adapter_->SignalCpuAdaptationUnable);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530 if (cpu_monitor) {
531 cpu_monitor->SignalUpdate.connect(
532 video_adapter_.get(), &CoordinatedVideoAdapter::OnCpuLoadUpdated);
533 }
534 }
535
536 int channel_id() const { return channel_id_; }
537 int capture_id() const { return capture_id_; }
538 void set_sending(bool sending) { sending_ = sending; }
539 bool sending() const { return sending_; }
540 void set_muted(bool on) {
541 // TODO(asapersson): add support.
542 // video_adapter_->SetBlackOutput(on);
543 muted_ = on;
544 }
545 bool muted() {return muted_; }
546
547 WebRtcEncoderObserver* encoder_observer() { return &encoder_observer_; }
548 webrtc::ViEExternalCapture* external_capture() { return external_capture_; }
549 const VideoFormat& video_format() const {
550 return video_format_;
551 }
552 void set_video_format(const VideoFormat& video_format) {
553 video_format_ = video_format;
554 if (video_format_ != cricket::VideoFormat()) {
555 interval_ = video_format_.interval;
556 }
557 video_adapter_->OnOutputFormatRequest(video_format_);
558 }
559 void set_interval(int64 interval) {
560 if (video_format() == cricket::VideoFormat()) {
561 interval_ = interval;
562 }
563 }
564 int64 interval() { return interval_; }
565
566 void InitializeAdapterOutputFormat(const webrtc::VideoCodec& codec) {
567 VideoFormat format(codec.width, codec.height,
568 VideoFormat::FpsToInterval(codec.maxFramerate),
569 FOURCC_I420);
570 if (video_adapter_->output_format().IsSize0x0()) {
571 video_adapter_->SetOutputFormat(format);
572 }
573 }
574
575 bool AdaptFrame(const VideoFrame* in_frame, const VideoFrame** out_frame) {
576 *out_frame = NULL;
577 return video_adapter_->AdaptFrame(in_frame, out_frame);
578 }
579 int CurrentAdaptReason() const {
580 return video_adapter_->adapt_reason();
581 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000582#ifdef USE_WEBRTC_DEV_BRANCH
583 webrtc::CpuOveruseObserver* overuse_observer() {
584 return overuse_observer_.get();
585 }
586#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000587
588 StreamParams* stream_params() { return stream_params_.get(); }
589 void set_stream_params(const StreamParams& sp) {
590 stream_params_.reset(new StreamParams(sp));
591 }
592 void ClearStreamParams() { stream_params_.reset(); }
593 bool has_ssrc(uint32 local_ssrc) const {
594 return !stream_params_ ? false :
595 stream_params_->has_ssrc(local_ssrc);
596 }
597 WebRtcLocalStreamInfo* local_stream_info() {
598 return &local_stream_info_;
599 }
600 VideoCapturer* video_capturer() {
601 return video_capturer_;
602 }
603 void set_video_capturer(VideoCapturer* video_capturer) {
604 if (video_capturer == video_capturer_) {
605 return;
606 }
607 capturer_updated_ = true;
608 video_capturer_ = video_capturer;
609 if (video_capturer && !video_capturer->IsScreencast()) {
610 const VideoFormat* capture_format = video_capturer->GetCaptureFormat();
611 if (capture_format) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000612 // TODO(thorcarpenter): This is broken. Video capturer doesn't have
613 // a capture format until the capturer is started. So, if
614 // the capturer is started immediately after calling set_video_capturer
615 // video adapter may not have the input format set, the interval may
616 // be zero, and all frames may be dropped.
617 // Consider fixing this by having video_adapter keep a pointer to the
618 // video capturer.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000619 video_adapter_->SetInputFormat(*capture_format);
620 }
621 }
622 }
623
624 void ApplyCpuOptions(const VideoOptions& options) {
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000625 bool cpu_adapt, cpu_smoothing, adapt_third;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000626 float low, med, high;
627 if (options.adapt_input_to_cpu_usage.Get(&cpu_adapt)) {
628 video_adapter_->set_cpu_adaptation(cpu_adapt);
629 }
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000630 if (options.adapt_cpu_with_smoothing.Get(&cpu_smoothing)) {
631 video_adapter_->set_cpu_smoothing(cpu_smoothing);
632 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000633 if (options.process_adaptation_threshhold.Get(&med)) {
634 video_adapter_->set_process_threshold(med);
635 }
636 if (options.system_low_adaptation_threshhold.Get(&low)) {
637 video_adapter_->set_low_system_threshold(low);
638 }
639 if (options.system_high_adaptation_threshhold.Get(&high)) {
640 video_adapter_->set_high_system_threshold(high);
641 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000642 if (options.video_adapt_third.Get(&adapt_third)) {
643 video_adapter_->set_scale_third(adapt_third);
644 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000645 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000646
647 void SetCpuOveruseDetection(bool enable) {
648#ifdef USE_WEBRTC_DEV_BRANCH
649 overuse_observer_->Enable(enable);
650 video_adapter_->set_cpu_adaptation(enable);
651#endif
652 }
653
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000654 void ProcessFrame(const VideoFrame& original_frame, bool mute,
655 VideoFrame** processed_frame) {
656 if (!mute) {
657 *processed_frame = original_frame.Copy();
658 } else {
659 WebRtcVideoFrame* black_frame = new WebRtcVideoFrame();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000660 black_frame->InitToBlack(static_cast<int>(original_frame.GetWidth()),
661 static_cast<int>(original_frame.GetHeight()),
662 1, 1,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000663 original_frame.GetElapsedTime(),
664 original_frame.GetTimeStamp());
665 *processed_frame = black_frame;
666 }
667 local_stream_info_.UpdateFrame(*processed_frame);
668 }
669 void RegisterEncoder(int pl_type, webrtc::VideoEncoder* encoder) {
670 ASSERT(!IsEncoderRegistered(pl_type));
671 registered_encoders_[pl_type] = encoder;
672 }
673 bool IsEncoderRegistered(int pl_type) {
674 return registered_encoders_.count(pl_type) != 0;
675 }
676 const EncoderMap& registered_encoders() {
677 return registered_encoders_;
678 }
679 void ClearRegisteredEncoders() {
680 registered_encoders_.clear();
681 }
682
wu@webrtc.orgd64719d2013-08-01 00:00:07 +0000683 sigslot::repeater0<> SignalCpuAdaptationUnable;
684
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000685 private:
686 int channel_id_;
687 int capture_id_;
688 bool sending_;
689 bool muted_;
690 VideoCapturer* video_capturer_;
691 WebRtcEncoderObserver encoder_observer_;
692 webrtc::ViEExternalCapture* external_capture_;
693 EncoderMap registered_encoders_;
694
695 VideoFormat video_format_;
696
697 talk_base::scoped_ptr<StreamParams> stream_params_;
698
699 WebRtcLocalStreamInfo local_stream_info_;
700
701 bool capturer_updated_;
702
703 int64 interval_;
704
705 talk_base::scoped_ptr<CoordinatedVideoAdapter> video_adapter_;
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000706#ifdef USE_WEBRTC_DEV_BRANCH
707 talk_base::scoped_ptr<WebRtcOveruseObserver> overuse_observer_;
708#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000709};
710
711const WebRtcVideoEngine::VideoCodecPref
712 WebRtcVideoEngine::kVideoCodecPrefs[] = {
713 {kVp8PayloadName, 100, 0},
714 {kRedPayloadName, 116, 1},
715 {kFecPayloadName, 117, 2},
716};
717
718// The formats are sorted by the descending order of width. We use the order to
719// find the next format for CPU and bandwidth adaptation.
720const VideoFormatPod WebRtcVideoEngine::kVideoFormats[] = {
721 {1280, 800, FPS_TO_INTERVAL(30), FOURCC_ANY},
722 {1280, 720, FPS_TO_INTERVAL(30), FOURCC_ANY},
723 {960, 600, FPS_TO_INTERVAL(30), FOURCC_ANY},
724 {960, 540, FPS_TO_INTERVAL(30), FOURCC_ANY},
725 {640, 400, FPS_TO_INTERVAL(30), FOURCC_ANY},
726 {640, 360, FPS_TO_INTERVAL(30), FOURCC_ANY},
727 {640, 480, FPS_TO_INTERVAL(30), FOURCC_ANY},
728 {480, 300, FPS_TO_INTERVAL(30), FOURCC_ANY},
729 {480, 270, FPS_TO_INTERVAL(30), FOURCC_ANY},
730 {480, 360, FPS_TO_INTERVAL(30), FOURCC_ANY},
731 {320, 200, FPS_TO_INTERVAL(30), FOURCC_ANY},
732 {320, 180, FPS_TO_INTERVAL(30), FOURCC_ANY},
733 {320, 240, FPS_TO_INTERVAL(30), FOURCC_ANY},
734 {240, 150, FPS_TO_INTERVAL(30), FOURCC_ANY},
735 {240, 135, FPS_TO_INTERVAL(30), FOURCC_ANY},
736 {240, 180, FPS_TO_INTERVAL(30), FOURCC_ANY},
737 {160, 100, FPS_TO_INTERVAL(30), FOURCC_ANY},
738 {160, 90, FPS_TO_INTERVAL(30), FOURCC_ANY},
739 {160, 120, FPS_TO_INTERVAL(30), FOURCC_ANY},
740};
741
742const VideoFormatPod WebRtcVideoEngine::kDefaultVideoFormat =
743 {640, 400, FPS_TO_INTERVAL(30), FOURCC_ANY};
744
745static void UpdateVideoCodec(const cricket::VideoFormat& video_format,
746 webrtc::VideoCodec* target_codec) {
747 if ((target_codec == NULL) || (video_format == cricket::VideoFormat())) {
748 return;
749 }
750 target_codec->width = video_format.width;
751 target_codec->height = video_format.height;
752 target_codec->maxFramerate = cricket::VideoFormat::IntervalToFps(
753 video_format.interval);
754}
755
756WebRtcVideoEngine::WebRtcVideoEngine() {
757 Construct(new ViEWrapper(), new ViETraceWrapper(), NULL,
758 new talk_base::CpuMonitor(NULL));
759}
760
761WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine,
762 ViEWrapper* vie_wrapper,
763 talk_base::CpuMonitor* cpu_monitor) {
764 Construct(vie_wrapper, new ViETraceWrapper(), voice_engine, cpu_monitor);
765}
766
767WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine,
768 ViEWrapper* vie_wrapper,
769 ViETraceWrapper* tracing,
770 talk_base::CpuMonitor* cpu_monitor) {
771 Construct(vie_wrapper, tracing, voice_engine, cpu_monitor);
772}
773
774void WebRtcVideoEngine::Construct(ViEWrapper* vie_wrapper,
775 ViETraceWrapper* tracing,
776 WebRtcVoiceEngine* voice_engine,
777 talk_base::CpuMonitor* cpu_monitor) {
778 LOG(LS_INFO) << "WebRtcVideoEngine::WebRtcVideoEngine";
779 worker_thread_ = NULL;
780 vie_wrapper_.reset(vie_wrapper);
781 vie_wrapper_base_initialized_ = false;
782 tracing_.reset(tracing);
783 voice_engine_ = voice_engine;
784 initialized_ = false;
785 SetTraceFilter(SeverityToFilter(kDefaultLogSeverity));
786 render_module_.reset(new WebRtcPassthroughRender());
787 local_renderer_w_ = local_renderer_h_ = 0;
788 local_renderer_ = NULL;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000789 capture_started_ = false;
790 decoder_factory_ = NULL;
791 encoder_factory_ = NULL;
792 cpu_monitor_.reset(cpu_monitor);
793
794 SetTraceOptions("");
795 if (tracing_->SetTraceCallback(this) != 0) {
796 LOG_RTCERR1(SetTraceCallback, this);
797 }
798
799 // Set default quality levels for our supported codecs. We override them here
800 // if we know your cpu performance is low, and they can be updated explicitly
801 // by calling SetDefaultCodec. For example by a flute preference setting, or
802 // by the server with a jec in response to our reported system info.
803 VideoCodec max_codec(kVideoCodecPrefs[0].payload_type,
804 kVideoCodecPrefs[0].name,
805 kDefaultVideoFormat.width,
806 kDefaultVideoFormat.height,
807 VideoFormat::IntervalToFps(kDefaultVideoFormat.interval),
808 0);
809 if (!SetDefaultCodec(max_codec)) {
810 LOG(LS_ERROR) << "Failed to initialize list of supported codec types";
811 }
812
813
814 // Load our RTP Header extensions.
815 rtp_header_extensions_.push_back(
816 RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
817 kRtpTimeOffsetExtensionId));
818 rtp_header_extensions_.push_back(
819 RtpHeaderExtension(kRtpAbsoluteSendTimeHeaderExtension,
820 kRtpAbsoluteSendTimeExtensionId));
821}
822
823WebRtcVideoEngine::~WebRtcVideoEngine() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000824 LOG(LS_INFO) << "WebRtcVideoEngine::~WebRtcVideoEngine";
825 if (initialized_) {
826 Terminate();
827 }
828 if (encoder_factory_) {
829 encoder_factory_->RemoveObserver(this);
830 }
831 tracing_->SetTraceCallback(NULL);
832 // Test to see if the media processor was deregistered properly.
833 ASSERT(SignalMediaFrame.is_empty());
834}
835
836bool WebRtcVideoEngine::Init(talk_base::Thread* worker_thread) {
837 LOG(LS_INFO) << "WebRtcVideoEngine::Init";
838 worker_thread_ = worker_thread;
839 ASSERT(worker_thread_ != NULL);
840
841 cpu_monitor_->set_thread(worker_thread_);
842 if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) {
843 LOG(LS_ERROR) << "Failed to start CPU monitor.";
844 cpu_monitor_.reset();
845 }
846
847 bool result = InitVideoEngine();
848 if (result) {
849 LOG(LS_INFO) << "VideoEngine Init done";
850 } else {
851 LOG(LS_ERROR) << "VideoEngine Init failed, releasing";
852 Terminate();
853 }
854 return result;
855}
856
857bool WebRtcVideoEngine::InitVideoEngine() {
858 LOG(LS_INFO) << "WebRtcVideoEngine::InitVideoEngine";
859
860 // Init WebRTC VideoEngine.
861 if (!vie_wrapper_base_initialized_) {
862 if (vie_wrapper_->base()->Init() != 0) {
863 LOG_RTCERR0(Init);
864 return false;
865 }
866 vie_wrapper_base_initialized_ = true;
867 }
868
869 // Log the VoiceEngine version info.
870 char buffer[1024] = "";
871 if (vie_wrapper_->base()->GetVersion(buffer) != 0) {
872 LOG_RTCERR0(GetVersion);
873 return false;
874 }
875
876 LOG(LS_INFO) << "WebRtc VideoEngine Version:";
877 LogMultiline(talk_base::LS_INFO, buffer);
878
879 // Hook up to VoiceEngine for sync purposes, if supplied.
880 if (!voice_engine_) {
881 LOG(LS_WARNING) << "NULL voice engine";
882 } else if ((vie_wrapper_->base()->SetVoiceEngine(
883 voice_engine_->voe()->engine())) != 0) {
884 LOG_RTCERR0(SetVoiceEngine);
885 return false;
886 }
887
888 // Register our custom render module.
889 if (vie_wrapper_->render()->RegisterVideoRenderModule(
890 *render_module_.get()) != 0) {
891 LOG_RTCERR0(RegisterVideoRenderModule);
892 return false;
893 }
894
895 initialized_ = true;
896 return true;
897}
898
899void WebRtcVideoEngine::Terminate() {
900 LOG(LS_INFO) << "WebRtcVideoEngine::Terminate";
901 initialized_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000902
903 if (vie_wrapper_->render()->DeRegisterVideoRenderModule(
904 *render_module_.get()) != 0) {
905 LOG_RTCERR0(DeRegisterVideoRenderModule);
906 }
907
908 if (vie_wrapper_->base()->SetVoiceEngine(NULL) != 0) {
909 LOG_RTCERR0(SetVoiceEngine);
910 }
911
912 cpu_monitor_->Stop();
913}
914
915int WebRtcVideoEngine::GetCapabilities() {
916 return VIDEO_RECV | VIDEO_SEND;
917}
918
919bool WebRtcVideoEngine::SetOptions(int options) {
920 return true;
921}
922
923bool WebRtcVideoEngine::SetDefaultEncoderConfig(
924 const VideoEncoderConfig& config) {
925 return SetDefaultCodec(config.max_codec);
926}
927
928// SetDefaultCodec may be called while the capturer is running. For example, a
929// test call is started in a page with QVGA default codec, and then a real call
930// is started in another page with VGA default codec. This is the corner case
931// and happens only when a session is started. We ignore this case currently.
932bool WebRtcVideoEngine::SetDefaultCodec(const VideoCodec& codec) {
933 if (!RebuildCodecList(codec)) {
934 LOG(LS_WARNING) << "Failed to RebuildCodecList";
935 return false;
936 }
937
938 default_codec_format_ = VideoFormat(
939 video_codecs_[0].width,
940 video_codecs_[0].height,
941 VideoFormat::FpsToInterval(video_codecs_[0].framerate),
942 FOURCC_ANY);
943 return true;
944}
945
946WebRtcVideoMediaChannel* WebRtcVideoEngine::CreateChannel(
947 VoiceMediaChannel* voice_channel) {
948 WebRtcVideoMediaChannel* channel =
949 new WebRtcVideoMediaChannel(this, voice_channel);
950 if (!channel->Init()) {
951 delete channel;
952 channel = NULL;
953 }
954 return channel;
955}
956
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000957bool WebRtcVideoEngine::SetLocalRenderer(VideoRenderer* renderer) {
958 local_renderer_w_ = local_renderer_h_ = 0;
959 local_renderer_ = renderer;
960 return true;
961}
962
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000963const std::vector<VideoCodec>& WebRtcVideoEngine::codecs() const {
964 return video_codecs_;
965}
966
967const std::vector<RtpHeaderExtension>&
968WebRtcVideoEngine::rtp_header_extensions() const {
969 return rtp_header_extensions_;
970}
971
972void WebRtcVideoEngine::SetLogging(int min_sev, const char* filter) {
973 // if min_sev == -1, we keep the current log level.
974 if (min_sev >= 0) {
975 SetTraceFilter(SeverityToFilter(min_sev));
976 }
977 SetTraceOptions(filter);
978}
979
980int WebRtcVideoEngine::GetLastEngineError() {
981 return vie_wrapper_->error();
982}
983
984// Checks to see whether we comprehend and could receive a particular codec
985bool WebRtcVideoEngine::FindCodec(const VideoCodec& in) {
986 for (int i = 0; i < ARRAY_SIZE(kVideoFormats); ++i) {
987 const VideoFormat fmt(kVideoFormats[i]);
988 if ((in.width == 0 && in.height == 0) ||
989 (fmt.width == in.width && fmt.height == in.height)) {
990 if (encoder_factory_) {
991 const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
992 encoder_factory_->codecs();
993 for (size_t j = 0; j < codecs.size(); ++j) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000994 VideoCodec codec(GetExternalVideoPayloadType(static_cast<int>(j)),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000995 codecs[j].name, 0, 0, 0, 0);
996 if (codec.Matches(in))
997 return true;
998 }
999 }
1000 for (size_t j = 0; j < ARRAY_SIZE(kVideoCodecPrefs); ++j) {
1001 VideoCodec codec(kVideoCodecPrefs[j].payload_type,
1002 kVideoCodecPrefs[j].name, 0, 0, 0, 0);
1003 if (codec.Matches(in)) {
1004 return true;
1005 }
1006 }
1007 }
1008 }
1009 return false;
1010}
1011
1012// Given the requested codec, returns true if we can send that codec type and
1013// updates out with the best quality we could send for that codec. If current is
1014// not empty, we constrain out so that its aspect ratio matches current's.
1015bool WebRtcVideoEngine::CanSendCodec(const VideoCodec& requested,
1016 const VideoCodec& current,
1017 VideoCodec* out) {
1018 if (!out) {
1019 return false;
1020 }
1021
1022 std::vector<VideoCodec>::const_iterator local_max;
1023 for (local_max = video_codecs_.begin();
1024 local_max < video_codecs_.end();
1025 ++local_max) {
1026 // First match codecs by payload type
1027 if (!requested.Matches(*local_max)) {
1028 continue;
1029 }
1030
1031 out->id = requested.id;
1032 out->name = requested.name;
1033 out->preference = requested.preference;
1034 out->params = requested.params;
1035 out->framerate = talk_base::_min(requested.framerate, local_max->framerate);
1036 out->width = 0;
1037 out->height = 0;
1038 out->params = requested.params;
1039 out->feedback_params = requested.feedback_params;
1040
1041 if (0 == requested.width && 0 == requested.height) {
1042 // Special case with resolution 0. The channel should not send frames.
1043 return true;
1044 } else if (0 == requested.width || 0 == requested.height) {
1045 // 0xn and nx0 are invalid resolutions.
1046 return false;
1047 }
1048
1049 // Pick the best quality that is within their and our bounds and has the
1050 // correct aspect ratio.
1051 for (int j = 0; j < ARRAY_SIZE(kVideoFormats); ++j) {
1052 const VideoFormat format(kVideoFormats[j]);
1053
1054 // Skip any format that is larger than the local or remote maximums, or
1055 // smaller than the current best match
1056 if (format.width > requested.width || format.height > requested.height ||
1057 format.width > local_max->width ||
1058 (format.width < out->width && format.height < out->height)) {
1059 continue;
1060 }
1061
1062 bool better = false;
1063
1064 // Check any further constraints on this prospective format
1065 if (!out->width || !out->height) {
1066 // If we don't have any matches yet, this is the best so far.
1067 better = true;
1068 } else if (current.width && current.height) {
1069 // current is set so format must match its ratio exactly.
1070 better =
1071 (format.width * current.height == format.height * current.width);
1072 } else {
1073 // Prefer closer aspect ratios i.e
1074 // format.aspect - requested.aspect < out.aspect - requested.aspect
1075 better = abs(format.width * requested.height * out->height -
1076 requested.width * format.height * out->height) <
1077 abs(out->width * format.height * requested.height -
1078 requested.width * format.height * out->height);
1079 }
1080
1081 if (better) {
1082 out->width = format.width;
1083 out->height = format.height;
1084 }
1085 }
1086 if (out->width > 0) {
1087 return true;
1088 }
1089 }
1090 return false;
1091}
1092
1093static void ConvertToCricketVideoCodec(
1094 const webrtc::VideoCodec& in_codec, VideoCodec* out_codec) {
1095 out_codec->id = in_codec.plType;
1096 out_codec->name = in_codec.plName;
1097 out_codec->width = in_codec.width;
1098 out_codec->height = in_codec.height;
1099 out_codec->framerate = in_codec.maxFramerate;
1100 out_codec->SetParam(kCodecParamMinBitrate, in_codec.minBitrate);
1101 out_codec->SetParam(kCodecParamMaxBitrate, in_codec.maxBitrate);
1102 if (in_codec.qpMax) {
1103 out_codec->SetParam(kCodecParamMaxQuantization, in_codec.qpMax);
1104 }
1105}
1106
1107bool WebRtcVideoEngine::ConvertFromCricketVideoCodec(
1108 const VideoCodec& in_codec, webrtc::VideoCodec* out_codec) {
1109 bool found = false;
1110 int ncodecs = vie_wrapper_->codec()->NumberOfCodecs();
1111 for (int i = 0; i < ncodecs; ++i) {
1112 if (vie_wrapper_->codec()->GetCodec(i, *out_codec) == 0 &&
1113 _stricmp(in_codec.name.c_str(), out_codec->plName) == 0) {
1114 found = true;
1115 break;
1116 }
1117 }
1118
1119 // If not found, check if this is supported by external encoder factory.
1120 if (!found && encoder_factory_) {
1121 const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
1122 encoder_factory_->codecs();
1123 for (size_t i = 0; i < codecs.size(); ++i) {
1124 if (_stricmp(in_codec.name.c_str(), codecs[i].name.c_str()) == 0) {
1125 out_codec->codecType = codecs[i].type;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001126 out_codec->plType = GetExternalVideoPayloadType(static_cast<int>(i));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001127 talk_base::strcpyn(out_codec->plName, sizeof(out_codec->plName),
1128 codecs[i].name.c_str(), codecs[i].name.length());
1129 found = true;
1130 break;
1131 }
1132 }
1133 }
1134
1135 if (!found) {
1136 LOG(LS_ERROR) << "invalid codec type";
1137 return false;
1138 }
1139
1140 if (in_codec.id != 0)
1141 out_codec->plType = in_codec.id;
1142
1143 if (in_codec.width != 0)
1144 out_codec->width = in_codec.width;
1145
1146 if (in_codec.height != 0)
1147 out_codec->height = in_codec.height;
1148
1149 if (in_codec.framerate != 0)
1150 out_codec->maxFramerate = in_codec.framerate;
1151
1152 // Convert bitrate parameters.
1153 int max_bitrate = kMaxVideoBitrate;
1154 int min_bitrate = kMinVideoBitrate;
1155 int start_bitrate = kStartVideoBitrate;
1156
1157 in_codec.GetParam(kCodecParamMinBitrate, &min_bitrate);
1158 in_codec.GetParam(kCodecParamMaxBitrate, &max_bitrate);
1159
1160 if (max_bitrate < min_bitrate) {
1161 return false;
1162 }
1163 start_bitrate = talk_base::_max(start_bitrate, min_bitrate);
1164 start_bitrate = talk_base::_min(start_bitrate, max_bitrate);
1165
1166 out_codec->minBitrate = min_bitrate;
1167 out_codec->startBitrate = start_bitrate;
1168 out_codec->maxBitrate = max_bitrate;
1169
1170 // Convert general codec parameters.
1171 int max_quantization = 0;
1172 if (in_codec.GetParam(kCodecParamMaxQuantization, &max_quantization)) {
1173 if (max_quantization < 0) {
1174 return false;
1175 }
1176 out_codec->qpMax = max_quantization;
1177 }
1178 return true;
1179}
1180
1181void WebRtcVideoEngine::RegisterChannel(WebRtcVideoMediaChannel *channel) {
1182 talk_base::CritScope cs(&channels_crit_);
1183 channels_.push_back(channel);
1184}
1185
1186void WebRtcVideoEngine::UnregisterChannel(WebRtcVideoMediaChannel *channel) {
1187 talk_base::CritScope cs(&channels_crit_);
1188 channels_.erase(std::remove(channels_.begin(), channels_.end(), channel),
1189 channels_.end());
1190}
1191
1192bool WebRtcVideoEngine::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) {
1193 if (initialized_) {
1194 LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init";
1195 return false;
1196 }
1197 voice_engine_ = voice_engine;
1198 return true;
1199}
1200
1201bool WebRtcVideoEngine::EnableTimedRender() {
1202 if (initialized_) {
1203 LOG(LS_WARNING) << "EnableTimedRender can not be called after Init";
1204 return false;
1205 }
1206 render_module_.reset(webrtc::VideoRender::CreateVideoRender(0, NULL,
1207 false, webrtc::kRenderExternal));
1208 return true;
1209}
1210
1211void WebRtcVideoEngine::SetTraceFilter(int filter) {
1212 tracing_->SetTraceFilter(filter);
1213}
1214
1215// See https://sites.google.com/a/google.com/wavelet/
1216// Home/Magic-Flute--RTC-Engine-/Magic-Flute-Command-Line-Parameters
1217// for all supported command line setttings.
1218void WebRtcVideoEngine::SetTraceOptions(const std::string& options) {
1219 // Set WebRTC trace file.
1220 std::vector<std::string> opts;
1221 talk_base::tokenize(options, ' ', '"', '"', &opts);
1222 std::vector<std::string>::iterator tracefile =
1223 std::find(opts.begin(), opts.end(), "tracefile");
1224 if (tracefile != opts.end() && ++tracefile != opts.end()) {
1225 // Write WebRTC debug output (at same loglevel) to file
1226 if (tracing_->SetTraceFile(tracefile->c_str()) == -1) {
1227 LOG_RTCERR1(SetTraceFile, *tracefile);
1228 }
1229 }
1230}
1231
1232static void AddDefaultFeedbackParams(VideoCodec* codec) {
1233 const FeedbackParam kFir(kRtcpFbParamCcm, kRtcpFbCcmParamFir);
1234 codec->AddFeedbackParam(kFir);
1235 const FeedbackParam kNack(kRtcpFbParamNack, kParamValueEmpty);
1236 codec->AddFeedbackParam(kNack);
1237 const FeedbackParam kRemb(kRtcpFbParamRemb, kParamValueEmpty);
1238 codec->AddFeedbackParam(kRemb);
1239}
1240
1241// Rebuilds the codec list to be only those that are less intensive
1242// than the specified codec.
1243bool WebRtcVideoEngine::RebuildCodecList(const VideoCodec& in_codec) {
1244 if (!FindCodec(in_codec))
1245 return false;
1246
1247 video_codecs_.clear();
1248
1249 bool found = false;
1250 std::set<std::string> external_codec_names;
1251 if (encoder_factory_) {
1252 const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
1253 encoder_factory_->codecs();
1254 for (size_t i = 0; i < codecs.size(); ++i) {
1255 if (!found)
1256 found = (in_codec.name == codecs[i].name);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001257 VideoCodec codec(
1258 GetExternalVideoPayloadType(static_cast<int>(i)),
1259 codecs[i].name,
1260 codecs[i].max_width,
1261 codecs[i].max_height,
1262 codecs[i].max_fps,
1263 static_cast<int>(codecs.size() + ARRAY_SIZE(kVideoCodecPrefs) - i));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001264 AddDefaultFeedbackParams(&codec);
1265 video_codecs_.push_back(codec);
1266 external_codec_names.insert(codecs[i].name);
1267 }
1268 }
1269 for (size_t i = 0; i < ARRAY_SIZE(kVideoCodecPrefs); ++i) {
1270 const VideoCodecPref& pref(kVideoCodecPrefs[i]);
1271 if (!found)
1272 found = (in_codec.name == pref.name);
1273 bool is_external_codec = external_codec_names.find(pref.name) !=
1274 external_codec_names.end();
1275 if (found && !is_external_codec) {
1276 VideoCodec codec(pref.payload_type, pref.name,
1277 in_codec.width, in_codec.height, in_codec.framerate,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001278 static_cast<int>(ARRAY_SIZE(kVideoCodecPrefs) - i));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001279 if (_stricmp(kVp8PayloadName, codec.name.c_str()) == 0) {
1280 AddDefaultFeedbackParams(&codec);
1281 }
1282 video_codecs_.push_back(codec);
1283 }
1284 }
1285 ASSERT(found);
1286 return true;
1287}
1288
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001289// Ignore spammy trace messages, mostly from the stats API when we haven't
1290// gotten RTCP info yet from the remote side.
1291bool WebRtcVideoEngine::ShouldIgnoreTrace(const std::string& trace) {
1292 static const char* const kTracesToIgnore[] = {
1293 NULL
1294 };
1295 for (const char* const* p = kTracesToIgnore; *p; ++p) {
1296 if (trace.find(*p) == 0) {
1297 return true;
1298 }
1299 }
1300 return false;
1301}
1302
1303int WebRtcVideoEngine::GetNumOfChannels() {
1304 talk_base::CritScope cs(&channels_crit_);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001305 return static_cast<int>(channels_.size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306}
1307
1308void WebRtcVideoEngine::Print(webrtc::TraceLevel level, const char* trace,
1309 int length) {
1310 talk_base::LoggingSeverity sev = talk_base::LS_VERBOSE;
1311 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
1312 sev = talk_base::LS_ERROR;
1313 else if (level == webrtc::kTraceWarning)
1314 sev = talk_base::LS_WARNING;
1315 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo)
1316 sev = talk_base::LS_INFO;
1317 else if (level == webrtc::kTraceTerseInfo)
1318 sev = talk_base::LS_INFO;
1319
1320 // Skip past boilerplate prefix text
1321 if (length < 72) {
1322 std::string msg(trace, length);
1323 LOG(LS_ERROR) << "Malformed webrtc log message: ";
1324 LOG_V(sev) << msg;
1325 } else {
1326 std::string msg(trace + 71, length - 72);
1327 if (!ShouldIgnoreTrace(msg) &&
1328 (!voice_engine_ || !voice_engine_->ShouldIgnoreTrace(msg))) {
1329 LOG_V(sev) << "webrtc: " << msg;
1330 }
1331 }
1332}
1333
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001334webrtc::VideoDecoder* WebRtcVideoEngine::CreateExternalDecoder(
1335 webrtc::VideoCodecType type) {
1336 if (decoder_factory_ == NULL) {
1337 return NULL;
1338 }
1339 return decoder_factory_->CreateVideoDecoder(type);
1340}
1341
1342void WebRtcVideoEngine::DestroyExternalDecoder(webrtc::VideoDecoder* decoder) {
1343 ASSERT(decoder_factory_ != NULL);
1344 if (decoder_factory_ == NULL)
1345 return;
1346 decoder_factory_->DestroyVideoDecoder(decoder);
1347}
1348
1349webrtc::VideoEncoder* WebRtcVideoEngine::CreateExternalEncoder(
1350 webrtc::VideoCodecType type) {
1351 if (encoder_factory_ == NULL) {
1352 return NULL;
1353 }
1354 return encoder_factory_->CreateVideoEncoder(type);
1355}
1356
1357void WebRtcVideoEngine::DestroyExternalEncoder(webrtc::VideoEncoder* encoder) {
1358 ASSERT(encoder_factory_ != NULL);
1359 if (encoder_factory_ == NULL)
1360 return;
1361 encoder_factory_->DestroyVideoEncoder(encoder);
1362}
1363
1364bool WebRtcVideoEngine::IsExternalEncoderCodecType(
1365 webrtc::VideoCodecType type) const {
1366 if (!encoder_factory_)
1367 return false;
1368 const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
1369 encoder_factory_->codecs();
1370 std::vector<WebRtcVideoEncoderFactory::VideoCodec>::const_iterator it;
1371 for (it = codecs.begin(); it != codecs.end(); ++it) {
1372 if (it->type == type)
1373 return true;
1374 }
1375 return false;
1376}
1377
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001378void WebRtcVideoEngine::SetExternalDecoderFactory(
1379 WebRtcVideoDecoderFactory* decoder_factory) {
1380 decoder_factory_ = decoder_factory;
1381}
1382
1383void WebRtcVideoEngine::SetExternalEncoderFactory(
1384 WebRtcVideoEncoderFactory* encoder_factory) {
1385 if (encoder_factory_ == encoder_factory)
1386 return;
1387
1388 if (encoder_factory_) {
1389 encoder_factory_->RemoveObserver(this);
1390 }
1391 encoder_factory_ = encoder_factory;
1392 if (encoder_factory_) {
1393 encoder_factory_->AddObserver(this);
1394 }
1395
1396 // Invoke OnCodecAvailable() here in case the list of codecs is already
1397 // available when the encoder factory is installed. If not the encoder
1398 // factory will invoke the callback later when the codecs become available.
1399 OnCodecsAvailable();
1400}
1401
1402void WebRtcVideoEngine::OnCodecsAvailable() {
1403 // Rebuild codec list while reapplying the current default codec format.
1404 VideoCodec max_codec(kVideoCodecPrefs[0].payload_type,
1405 kVideoCodecPrefs[0].name,
1406 video_codecs_[0].width,
1407 video_codecs_[0].height,
1408 video_codecs_[0].framerate,
1409 0);
1410 if (!RebuildCodecList(max_codec)) {
1411 LOG(LS_ERROR) << "Failed to initialize list of supported codec types";
1412 }
1413}
1414
1415// WebRtcVideoMediaChannel
1416
1417WebRtcVideoMediaChannel::WebRtcVideoMediaChannel(
1418 WebRtcVideoEngine* engine,
1419 VoiceMediaChannel* channel)
1420 : engine_(engine),
1421 voice_channel_(channel),
1422 vie_channel_(-1),
1423 nack_enabled_(true),
1424 remb_enabled_(false),
1425 render_started_(false),
1426 first_receive_ssrc_(0),
1427 send_red_type_(-1),
1428 send_fec_type_(-1),
1429 send_min_bitrate_(kMinVideoBitrate),
1430 send_start_bitrate_(kStartVideoBitrate),
1431 send_max_bitrate_(kMaxVideoBitrate),
1432 sending_(false),
1433 ratio_w_(0),
1434 ratio_h_(0) {
1435 engine->RegisterChannel(this);
1436}
1437
1438bool WebRtcVideoMediaChannel::Init() {
1439 const uint32 ssrc_key = 0;
1440 return CreateChannel(ssrc_key, MD_SENDRECV, &vie_channel_);
1441}
1442
1443WebRtcVideoMediaChannel::~WebRtcVideoMediaChannel() {
1444 const bool send = false;
1445 SetSend(send);
1446 const bool render = false;
1447 SetRender(render);
1448
1449 while (!send_channels_.empty()) {
1450 if (!DeleteSendChannel(send_channels_.begin()->first)) {
1451 LOG(LS_ERROR) << "Unable to delete channel with ssrc key "
1452 << send_channels_.begin()->first;
1453 ASSERT(false);
1454 break;
1455 }
1456 }
1457
1458 // Remove all receive streams and the default channel.
1459 while (!recv_channels_.empty()) {
1460 RemoveRecvStream(recv_channels_.begin()->first);
1461 }
1462
1463 // Unregister the channel from the engine.
1464 engine()->UnregisterChannel(this);
1465 if (worker_thread()) {
1466 worker_thread()->Clear(this);
1467 }
1468}
1469
1470bool WebRtcVideoMediaChannel::SetRecvCodecs(
1471 const std::vector<VideoCodec>& codecs) {
1472 receive_codecs_.clear();
1473 for (std::vector<VideoCodec>::const_iterator iter = codecs.begin();
1474 iter != codecs.end(); ++iter) {
1475 if (engine()->FindCodec(*iter)) {
1476 webrtc::VideoCodec wcodec;
1477 if (engine()->ConvertFromCricketVideoCodec(*iter, &wcodec)) {
1478 receive_codecs_.push_back(wcodec);
1479 }
1480 } else {
1481 LOG(LS_INFO) << "Unknown codec " << iter->name;
1482 return false;
1483 }
1484 }
1485
1486 for (RecvChannelMap::iterator it = recv_channels_.begin();
1487 it != recv_channels_.end(); ++it) {
1488 if (!SetReceiveCodecs(it->second))
1489 return false;
1490 }
1491 return true;
1492}
1493
1494bool WebRtcVideoMediaChannel::SetSendCodecs(
1495 const std::vector<VideoCodec>& codecs) {
1496 // Match with local video codec list.
1497 std::vector<webrtc::VideoCodec> send_codecs;
1498 VideoCodec checked_codec;
1499 VideoCodec current; // defaults to 0x0
1500 if (sending_) {
1501 ConvertToCricketVideoCodec(*send_codec_, &current);
1502 }
1503 for (std::vector<VideoCodec>::const_iterator iter = codecs.begin();
1504 iter != codecs.end(); ++iter) {
1505 if (_stricmp(iter->name.c_str(), kRedPayloadName) == 0) {
1506 send_red_type_ = iter->id;
1507 } else if (_stricmp(iter->name.c_str(), kFecPayloadName) == 0) {
1508 send_fec_type_ = iter->id;
1509 } else if (engine()->CanSendCodec(*iter, current, &checked_codec)) {
1510 webrtc::VideoCodec wcodec;
1511 if (engine()->ConvertFromCricketVideoCodec(checked_codec, &wcodec)) {
1512 if (send_codecs.empty()) {
1513 nack_enabled_ = IsNackEnabled(checked_codec);
1514 remb_enabled_ = IsRembEnabled(checked_codec);
1515 }
1516 send_codecs.push_back(wcodec);
1517 }
1518 } else {
1519 LOG(LS_WARNING) << "Unknown codec " << iter->name;
1520 }
1521 }
1522
1523 // Fail if we don't have a match.
1524 if (send_codecs.empty()) {
1525 LOG(LS_WARNING) << "No matching codecs available";
1526 return false;
1527 }
1528
1529 // Recv protection.
1530 for (RecvChannelMap::iterator it = recv_channels_.begin();
1531 it != recv_channels_.end(); ++it) {
1532 int channel_id = it->second->channel_id();
1533 if (!SetNackFec(channel_id, send_red_type_, send_fec_type_,
1534 nack_enabled_)) {
1535 return false;
1536 }
1537 if (engine_->vie()->rtp()->SetRembStatus(channel_id,
1538 kNotSending,
1539 remb_enabled_) != 0) {
1540 LOG_RTCERR3(SetRembStatus, channel_id, kNotSending, remb_enabled_);
1541 return false;
1542 }
1543 }
1544
1545 // Send settings.
1546 for (SendChannelMap::iterator iter = send_channels_.begin();
1547 iter != send_channels_.end(); ++iter) {
1548 int channel_id = iter->second->channel_id();
1549 if (!SetNackFec(channel_id, send_red_type_, send_fec_type_,
1550 nack_enabled_)) {
1551 return false;
1552 }
1553 if (engine_->vie()->rtp()->SetRembStatus(channel_id,
1554 remb_enabled_,
1555 remb_enabled_) != 0) {
1556 LOG_RTCERR3(SetRembStatus, channel_id, remb_enabled_, remb_enabled_);
1557 return false;
1558 }
1559 }
1560
1561 // Select the first matched codec.
1562 webrtc::VideoCodec& codec(send_codecs[0]);
1563
1564 if (!SetSendCodec(
1565 codec, codec.minBitrate, codec.startBitrate, codec.maxBitrate)) {
1566 return false;
1567 }
1568
1569 for (SendChannelMap::iterator iter = send_channels_.begin();
1570 iter != send_channels_.end(); ++iter) {
1571 WebRtcVideoChannelSendInfo* send_channel = iter->second;
1572 send_channel->InitializeAdapterOutputFormat(codec);
1573 }
1574
1575 LogSendCodecChange("SetSendCodecs()");
1576
1577 return true;
1578}
1579
1580bool WebRtcVideoMediaChannel::GetSendCodec(VideoCodec* send_codec) {
1581 if (!send_codec_) {
1582 return false;
1583 }
1584 ConvertToCricketVideoCodec(*send_codec_, send_codec);
1585 return true;
1586}
1587
1588bool WebRtcVideoMediaChannel::SetSendStreamFormat(uint32 ssrc,
1589 const VideoFormat& format) {
1590 if (!send_codec_) {
1591 LOG(LS_ERROR) << "The send codec has not been set yet.";
1592 return false;
1593 }
1594 WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(ssrc);
1595 if (!send_channel) {
1596 LOG(LS_ERROR) << "The specified ssrc " << ssrc << " is not in use.";
1597 return false;
1598 }
1599 send_channel->set_video_format(format);
1600 return true;
1601}
1602
1603bool WebRtcVideoMediaChannel::SetRender(bool render) {
1604 if (render == render_started_) {
1605 return true; // no action required
1606 }
1607
1608 bool ret = true;
1609 for (RecvChannelMap::iterator it = recv_channels_.begin();
1610 it != recv_channels_.end(); ++it) {
1611 if (render) {
1612 if (engine()->vie()->render()->StartRender(
1613 it->second->channel_id()) != 0) {
1614 LOG_RTCERR1(StartRender, it->second->channel_id());
1615 ret = false;
1616 }
1617 } else {
1618 if (engine()->vie()->render()->StopRender(
1619 it->second->channel_id()) != 0) {
1620 LOG_RTCERR1(StopRender, it->second->channel_id());
1621 ret = false;
1622 }
1623 }
1624 }
1625 if (ret) {
1626 render_started_ = render;
1627 }
1628
1629 return ret;
1630}
1631
1632bool WebRtcVideoMediaChannel::SetSend(bool send) {
1633 if (!HasReadySendChannels() && send) {
1634 LOG(LS_ERROR) << "No stream added";
1635 return false;
1636 }
1637 if (send == sending()) {
1638 return true; // No action required.
1639 }
1640
1641 if (send) {
1642 // We've been asked to start sending.
1643 // SetSendCodecs must have been called already.
1644 if (!send_codec_) {
1645 return false;
1646 }
1647 // Start send now.
1648 if (!StartSend()) {
1649 return false;
1650 }
1651 } else {
1652 // We've been asked to stop sending.
1653 if (!StopSend()) {
1654 return false;
1655 }
1656 }
1657 sending_ = send;
1658
1659 return true;
1660}
1661
1662bool WebRtcVideoMediaChannel::AddSendStream(const StreamParams& sp) {
1663 LOG(LS_INFO) << "AddSendStream " << sp.ToString();
1664
1665 if (!IsOneSsrcStream(sp)) {
1666 LOG(LS_ERROR) << "AddSendStream: bad local stream parameters";
1667 return false;
1668 }
1669
1670 uint32 ssrc_key;
1671 if (!CreateSendChannelKey(sp.first_ssrc(), &ssrc_key)) {
1672 LOG(LS_ERROR) << "Trying to register duplicate ssrc: " << sp.first_ssrc();
1673 return false;
1674 }
1675 // If the default channel is already used for sending create a new channel
1676 // otherwise use the default channel for sending.
1677 int channel_id = -1;
1678 if (send_channels_[0]->stream_params() == NULL) {
1679 channel_id = vie_channel_;
1680 } else {
1681 if (!CreateChannel(ssrc_key, MD_SEND, &channel_id)) {
1682 LOG(LS_ERROR) << "AddSendStream: unable to create channel";
1683 return false;
1684 }
1685 }
1686 WebRtcVideoChannelSendInfo* send_channel = send_channels_[ssrc_key];
1687 // Set the send (local) SSRC.
1688 // If there are multiple send SSRCs, we can only set the first one here, and
1689 // the rest of the SSRC(s) need to be set after SetSendCodec has been called
1690 // (with a codec requires multiple SSRC(s)).
1691 if (engine()->vie()->rtp()->SetLocalSSRC(channel_id,
1692 sp.first_ssrc()) != 0) {
1693 LOG_RTCERR2(SetLocalSSRC, channel_id, sp.first_ssrc());
1694 return false;
1695 }
1696
1697 // Set RTCP CName.
1698 if (engine()->vie()->rtp()->SetRTCPCName(channel_id,
1699 sp.cname.c_str()) != 0) {
1700 LOG_RTCERR2(SetRTCPCName, channel_id, sp.cname.c_str());
1701 return false;
1702 }
1703
1704 // At this point the channel's local SSRC has been updated. If the channel is
1705 // the default channel make sure that all the receive channels are updated as
1706 // well. Receive channels have to have the same SSRC as the default channel in
1707 // order to send receiver reports with this SSRC.
1708 if (IsDefaultChannel(channel_id)) {
1709 for (RecvChannelMap::const_iterator it = recv_channels_.begin();
1710 it != recv_channels_.end(); ++it) {
1711 WebRtcVideoChannelRecvInfo* info = it->second;
1712 int channel_id = info->channel_id();
1713 if (engine()->vie()->rtp()->SetLocalSSRC(channel_id,
1714 sp.first_ssrc()) != 0) {
1715 LOG_RTCERR1(SetLocalSSRC, it->first);
1716 return false;
1717 }
1718 }
1719 }
1720
1721 send_channel->set_stream_params(sp);
1722
1723 // Reset send codec after stream parameters changed.
1724 if (send_codec_) {
1725 if (!SetSendCodec(send_channel, *send_codec_, send_min_bitrate_,
1726 send_start_bitrate_, send_max_bitrate_)) {
1727 return false;
1728 }
1729 LogSendCodecChange("SetSendStreamFormat()");
1730 }
1731
1732 if (sending_) {
1733 return StartSend(send_channel);
1734 }
1735 return true;
1736}
1737
1738bool WebRtcVideoMediaChannel::RemoveSendStream(uint32 ssrc) {
1739 uint32 ssrc_key;
1740 if (!GetSendChannelKey(ssrc, &ssrc_key)) {
1741 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1742 << " which doesn't exist.";
1743 return false;
1744 }
1745 WebRtcVideoChannelSendInfo* send_channel = send_channels_[ssrc_key];
1746 int channel_id = send_channel->channel_id();
1747 if (IsDefaultChannel(channel_id) && (send_channel->stream_params() == NULL)) {
1748 // Default channel will still exist. However, if stream_params() is NULL
1749 // there is no stream to remove.
1750 return false;
1751 }
1752 if (sending_) {
1753 StopSend(send_channel);
1754 }
1755
1756 const WebRtcVideoChannelSendInfo::EncoderMap& encoder_map =
1757 send_channel->registered_encoders();
1758 for (WebRtcVideoChannelSendInfo::EncoderMap::const_iterator it =
1759 encoder_map.begin(); it != encoder_map.end(); ++it) {
1760 if (engine()->vie()->ext_codec()->DeRegisterExternalSendCodec(
1761 channel_id, it->first) != 0) {
1762 LOG_RTCERR1(DeregisterEncoderObserver, channel_id);
1763 }
1764 engine()->DestroyExternalEncoder(it->second);
1765 }
1766 send_channel->ClearRegisteredEncoders();
1767
1768 // The receive channels depend on the default channel, recycle it instead.
1769 if (IsDefaultChannel(channel_id)) {
1770 SetCapturer(GetDefaultChannelSsrc(), NULL);
1771 send_channel->ClearStreamParams();
1772 } else {
1773 return DeleteSendChannel(ssrc_key);
1774 }
1775 return true;
1776}
1777
1778bool WebRtcVideoMediaChannel::AddRecvStream(const StreamParams& sp) {
1779 // TODO(zhurunz) Remove this once BWE works properly across different send
1780 // and receive channels.
1781 // Reuse default channel for recv stream in 1:1 call.
1782 if (!InConferenceMode() && first_receive_ssrc_ == 0) {
1783 LOG(LS_INFO) << "Recv stream " << sp.first_ssrc()
1784 << " reuse default channel #"
1785 << vie_channel_;
1786 first_receive_ssrc_ = sp.first_ssrc();
1787 if (render_started_) {
1788 if (engine()->vie()->render()->StartRender(vie_channel_) !=0) {
1789 LOG_RTCERR1(StartRender, vie_channel_);
1790 }
1791 }
1792 return true;
1793 }
1794
1795 if (recv_channels_.find(sp.first_ssrc()) != recv_channels_.end() ||
1796 first_receive_ssrc_ == sp.first_ssrc()) {
1797 LOG(LS_ERROR) << "Stream already exists";
1798 return false;
1799 }
1800
1801 // TODO(perkj): Implement recv media from multiple SSRCs per stream.
1802 if (sp.ssrcs.size() != 1) {
1803 LOG(LS_ERROR) << "WebRtcVideoMediaChannel supports one receiving SSRC per"
1804 << " stream";
1805 return false;
1806 }
1807
1808 // Create a new channel for receiving video data.
1809 // In order to get the bandwidth estimation work fine for
1810 // receive only channels, we connect all receiving channels
1811 // to our master send channel.
1812 int channel_id = -1;
1813 if (!CreateChannel(sp.first_ssrc(), MD_RECV, &channel_id)) {
1814 return false;
1815 }
1816
1817 // Get the default renderer.
1818 VideoRenderer* default_renderer = NULL;
1819 if (InConferenceMode()) {
1820 // The recv_channels_ size start out being 1, so if it is two here this
1821 // is the first receive channel created (vie_channel_ is not used for
1822 // receiving in a conference call). This means that the renderer stored
1823 // inside vie_channel_ should be used for the just created channel.
1824 if (recv_channels_.size() == 2 &&
1825 recv_channels_.find(0) != recv_channels_.end()) {
1826 GetRenderer(0, &default_renderer);
1827 }
1828 }
1829
1830 // The first recv stream reuses the default renderer (if a default renderer
1831 // has been set).
1832 if (default_renderer) {
1833 SetRenderer(sp.first_ssrc(), default_renderer);
1834 }
1835
1836 LOG(LS_INFO) << "New video stream " << sp.first_ssrc()
1837 << " registered to VideoEngine channel #"
1838 << channel_id << " and connected to channel #" << vie_channel_;
1839
1840 return true;
1841}
1842
1843bool WebRtcVideoMediaChannel::RemoveRecvStream(uint32 ssrc) {
1844 RecvChannelMap::iterator it = recv_channels_.find(ssrc);
1845
1846 if (it == recv_channels_.end()) {
1847 // TODO(perkj): Remove this once BWE works properly across different send
1848 // and receive channels.
1849 // The default channel is reused for recv stream in 1:1 call.
1850 if (first_receive_ssrc_ == ssrc) {
1851 first_receive_ssrc_ = 0;
1852 // Need to stop the renderer and remove it since the render window can be
1853 // deleted after this.
1854 if (render_started_) {
1855 if (engine()->vie()->render()->StopRender(vie_channel_) !=0) {
1856 LOG_RTCERR1(StopRender, it->second->channel_id());
1857 }
1858 }
1859 recv_channels_[0]->SetRenderer(NULL);
1860 return true;
1861 }
1862 return false;
1863 }
1864 WebRtcVideoChannelRecvInfo* info = it->second;
1865 int channel_id = info->channel_id();
1866 if (engine()->vie()->render()->RemoveRenderer(channel_id) != 0) {
1867 LOG_RTCERR1(RemoveRenderer, channel_id);
1868 }
1869
1870 if (engine()->vie()->network()->DeregisterSendTransport(channel_id) !=0) {
1871 LOG_RTCERR1(DeRegisterSendTransport, channel_id);
1872 }
1873
1874 if (engine()->vie()->codec()->DeregisterDecoderObserver(
1875 channel_id) != 0) {
1876 LOG_RTCERR1(DeregisterDecoderObserver, channel_id);
1877 }
1878
1879 const WebRtcVideoChannelRecvInfo::DecoderMap& decoder_map =
1880 info->registered_decoders();
1881 for (WebRtcVideoChannelRecvInfo::DecoderMap::const_iterator it =
1882 decoder_map.begin(); it != decoder_map.end(); ++it) {
1883 if (engine()->vie()->ext_codec()->DeRegisterExternalReceiveCodec(
1884 channel_id, it->first) != 0) {
1885 LOG_RTCERR1(DeregisterDecoderObserver, channel_id);
1886 }
1887 engine()->DestroyExternalDecoder(it->second);
1888 }
1889 info->ClearRegisteredDecoders();
1890
1891 LOG(LS_INFO) << "Removing video stream " << ssrc
1892 << " with VideoEngine channel #"
1893 << channel_id;
1894 if (engine()->vie()->base()->DeleteChannel(channel_id) == -1) {
1895 LOG_RTCERR1(DeleteChannel, channel_id);
1896 // Leak the WebRtcVideoChannelRecvInfo owned by |it| but remove the channel
1897 // from recv_channels_.
1898 recv_channels_.erase(it);
1899 return false;
1900 }
1901 // Delete the WebRtcVideoChannelRecvInfo pointed to by it->second.
1902 delete info;
1903 recv_channels_.erase(it);
1904 return true;
1905}
1906
1907bool WebRtcVideoMediaChannel::StartSend() {
1908 bool success = true;
1909 for (SendChannelMap::iterator iter = send_channels_.begin();
1910 iter != send_channels_.end(); ++iter) {
1911 WebRtcVideoChannelSendInfo* send_channel = iter->second;
1912 if (!StartSend(send_channel)) {
1913 success = false;
1914 }
1915 }
1916 return success;
1917}
1918
1919bool WebRtcVideoMediaChannel::StartSend(
1920 WebRtcVideoChannelSendInfo* send_channel) {
1921 const int channel_id = send_channel->channel_id();
1922 if (engine()->vie()->base()->StartSend(channel_id) != 0) {
1923 LOG_RTCERR1(StartSend, channel_id);
1924 return false;
1925 }
1926
1927 send_channel->set_sending(true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001928 return true;
1929}
1930
1931bool WebRtcVideoMediaChannel::StopSend() {
1932 bool success = true;
1933 for (SendChannelMap::iterator iter = send_channels_.begin();
1934 iter != send_channels_.end(); ++iter) {
1935 WebRtcVideoChannelSendInfo* send_channel = iter->second;
1936 if (!StopSend(send_channel)) {
1937 success = false;
1938 }
1939 }
1940 return success;
1941}
1942
1943bool WebRtcVideoMediaChannel::StopSend(
1944 WebRtcVideoChannelSendInfo* send_channel) {
1945 const int channel_id = send_channel->channel_id();
1946 if (engine()->vie()->base()->StopSend(channel_id) != 0) {
1947 LOG_RTCERR1(StopSend, channel_id);
1948 return false;
1949 }
1950 send_channel->set_sending(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001951 return true;
1952}
1953
1954bool WebRtcVideoMediaChannel::SendIntraFrame() {
1955 bool success = true;
1956 for (SendChannelMap::iterator iter = send_channels_.begin();
1957 iter != send_channels_.end();
1958 ++iter) {
1959 WebRtcVideoChannelSendInfo* send_channel = iter->second;
1960 const int channel_id = send_channel->channel_id();
1961 if (engine()->vie()->codec()->SendKeyFrame(channel_id) != 0) {
1962 LOG_RTCERR1(SendKeyFrame, channel_id);
1963 success = false;
1964 }
1965 }
1966 return success;
1967}
1968
1969bool WebRtcVideoMediaChannel::IsOneSsrcStream(const StreamParams& sp) {
1970 return (sp.ssrcs.size() == 1 && sp.ssrc_groups.size() == 0);
1971}
1972
1973bool WebRtcVideoMediaChannel::HasReadySendChannels() {
1974 return !send_channels_.empty() &&
1975 ((send_channels_.size() > 1) ||
1976 (send_channels_[0]->stream_params() != NULL));
1977}
1978
1979bool WebRtcVideoMediaChannel::GetSendChannelKey(uint32 local_ssrc,
1980 uint32* key) {
1981 *key = 0;
1982 // If a send channel is not ready to send it will not have local_ssrc
1983 // registered to it.
1984 if (!HasReadySendChannels()) {
1985 return false;
1986 }
1987 // The default channel is stored with key 0. The key therefore does not match
1988 // the SSRC associated with the default channel. Check if the SSRC provided
1989 // corresponds to the default channel's SSRC.
1990 if (local_ssrc == GetDefaultChannelSsrc()) {
1991 return true;
1992 }
1993 if (send_channels_.find(local_ssrc) == send_channels_.end()) {
1994 for (SendChannelMap::iterator iter = send_channels_.begin();
1995 iter != send_channels_.end(); ++iter) {
1996 WebRtcVideoChannelSendInfo* send_channel = iter->second;
1997 if (send_channel->has_ssrc(local_ssrc)) {
1998 *key = iter->first;
1999 return true;
2000 }
2001 }
2002 return false;
2003 }
2004 // The key was found in the above std::map::find call. This means that the
2005 // ssrc is the key.
2006 *key = local_ssrc;
2007 return true;
2008}
2009
2010WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannel(
2011 VideoCapturer* video_capturer) {
2012 for (SendChannelMap::iterator iter = send_channels_.begin();
2013 iter != send_channels_.end(); ++iter) {
2014 WebRtcVideoChannelSendInfo* send_channel = iter->second;
2015 if (send_channel->video_capturer() == video_capturer) {
2016 return send_channel;
2017 }
2018 }
2019 return NULL;
2020}
2021
2022WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannel(
2023 uint32 local_ssrc) {
2024 uint32 key;
2025 if (!GetSendChannelKey(local_ssrc, &key)) {
2026 return NULL;
2027 }
2028 return send_channels_[key];
2029}
2030
2031bool WebRtcVideoMediaChannel::CreateSendChannelKey(uint32 local_ssrc,
2032 uint32* key) {
2033 if (GetSendChannelKey(local_ssrc, key)) {
2034 // If there is a key corresponding to |local_ssrc|, the SSRC is already in
2035 // use. SSRCs need to be unique in a session and at this point a duplicate
2036 // SSRC has been detected.
2037 return false;
2038 }
2039 if (send_channels_[0]->stream_params() == NULL) {
2040 // key should be 0 here as the default channel should be re-used whenever it
2041 // is not used.
2042 *key = 0;
2043 return true;
2044 }
2045 // SSRC is currently not in use and the default channel is already in use. Use
2046 // the SSRC as key since it is supposed to be unique in a session.
2047 *key = local_ssrc;
2048 return true;
2049}
2050
2051uint32 WebRtcVideoMediaChannel::GetDefaultChannelSsrc() {
2052 WebRtcVideoChannelSendInfo* send_channel = send_channels_[0];
2053 const StreamParams* sp = send_channel->stream_params();
2054 if (sp == NULL) {
2055 // This happens if no send stream is currently registered.
2056 return 0;
2057 }
2058 return sp->first_ssrc();
2059}
2060
2061bool WebRtcVideoMediaChannel::DeleteSendChannel(uint32 ssrc_key) {
2062 if (send_channels_.find(ssrc_key) == send_channels_.end()) {
2063 return false;
2064 }
2065 WebRtcVideoChannelSendInfo* send_channel = send_channels_[ssrc_key];
2066 VideoCapturer* capturer = send_channel->video_capturer();
2067 if (capturer != NULL) {
2068 capturer->SignalVideoFrame.disconnect(this);
2069 send_channel->set_video_capturer(NULL);
2070 }
2071
2072 int channel_id = send_channel->channel_id();
2073 int capture_id = send_channel->capture_id();
2074 if (engine()->vie()->codec()->DeregisterEncoderObserver(
2075 channel_id) != 0) {
2076 LOG_RTCERR1(DeregisterEncoderObserver, channel_id);
2077 }
2078
2079 // Destroy the external capture interface.
2080 if (engine()->vie()->capture()->DisconnectCaptureDevice(
2081 channel_id) != 0) {
2082 LOG_RTCERR1(DisconnectCaptureDevice, channel_id);
2083 }
2084 if (engine()->vie()->capture()->ReleaseCaptureDevice(
2085 capture_id) != 0) {
2086 LOG_RTCERR1(ReleaseCaptureDevice, capture_id);
2087 }
2088
2089 // The default channel is stored in both |send_channels_| and
2090 // |recv_channels_|. To make sure it is only deleted once from vie let the
2091 // delete call happen when tearing down |recv_channels_| and not here.
2092 if (!IsDefaultChannel(channel_id)) {
2093 engine_->vie()->base()->DeleteChannel(channel_id);
2094 }
2095 delete send_channel;
2096 send_channels_.erase(ssrc_key);
2097 return true;
2098}
2099
2100bool WebRtcVideoMediaChannel::RemoveCapturer(uint32 ssrc) {
2101 WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(ssrc);
2102 if (!send_channel) {
2103 return false;
2104 }
2105 VideoCapturer* capturer = send_channel->video_capturer();
2106 if (capturer == NULL) {
2107 return false;
2108 }
2109 capturer->SignalVideoFrame.disconnect(this);
2110 send_channel->set_video_capturer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002111 const int64 timestamp = send_channel->local_stream_info()->time_stamp();
2112 if (send_codec_) {
2113 QueueBlackFrame(ssrc, timestamp, send_codec_->maxFramerate);
2114 }
2115 return true;
2116}
2117
2118bool WebRtcVideoMediaChannel::SetRenderer(uint32 ssrc,
2119 VideoRenderer* renderer) {
2120 if (recv_channels_.find(ssrc) == recv_channels_.end()) {
2121 // TODO(perkj): Remove this once BWE works properly across different send
2122 // and receive channels.
2123 // The default channel is reused for recv stream in 1:1 call.
2124 if (first_receive_ssrc_ == ssrc &&
2125 recv_channels_.find(0) != recv_channels_.end()) {
2126 LOG(LS_INFO) << "SetRenderer " << ssrc
2127 << " reuse default channel #"
2128 << vie_channel_;
2129 recv_channels_[0]->SetRenderer(renderer);
2130 return true;
2131 }
2132 return false;
2133 }
2134
2135 recv_channels_[ssrc]->SetRenderer(renderer);
2136 return true;
2137}
2138
2139bool WebRtcVideoMediaChannel::GetStats(VideoMediaInfo* info) {
2140 // Get sender statistics and build VideoSenderInfo.
2141 unsigned int total_bitrate_sent = 0;
2142 unsigned int video_bitrate_sent = 0;
2143 unsigned int fec_bitrate_sent = 0;
2144 unsigned int nack_bitrate_sent = 0;
2145 unsigned int estimated_send_bandwidth = 0;
2146 unsigned int target_enc_bitrate = 0;
2147 if (send_codec_) {
2148 for (SendChannelMap::const_iterator iter = send_channels_.begin();
2149 iter != send_channels_.end(); ++iter) {
2150 WebRtcVideoChannelSendInfo* send_channel = iter->second;
2151 const int channel_id = send_channel->channel_id();
2152 VideoSenderInfo sinfo;
2153 const StreamParams* send_params = send_channel->stream_params();
2154 if (send_params == NULL) {
2155 // This should only happen if the default vie channel is not in use.
2156 // This can happen if no streams have ever been added or the stream
2157 // corresponding to the default channel has been removed. Note that
2158 // there may be non-default vie channels in use when this happen so
2159 // asserting send_channels_.size() == 1 is not correct and neither is
2160 // breaking out of the loop.
2161 ASSERT(channel_id == vie_channel_);
2162 continue;
2163 }
2164 unsigned int bytes_sent, packets_sent, bytes_recv, packets_recv;
2165 if (engine_->vie()->rtp()->GetRTPStatistics(channel_id, bytes_sent,
2166 packets_sent, bytes_recv,
2167 packets_recv) != 0) {
2168 LOG_RTCERR1(GetRTPStatistics, vie_channel_);
2169 continue;
2170 }
2171 WebRtcLocalStreamInfo* channel_stream_info =
2172 send_channel->local_stream_info();
2173
2174 sinfo.ssrcs = send_params->ssrcs;
2175 sinfo.codec_name = send_codec_->plName;
2176 sinfo.bytes_sent = bytes_sent;
2177 sinfo.packets_sent = packets_sent;
2178 sinfo.packets_cached = -1;
2179 sinfo.packets_lost = -1;
2180 sinfo.fraction_lost = -1;
2181 sinfo.firs_rcvd = -1;
2182 sinfo.nacks_rcvd = -1;
2183 sinfo.rtt_ms = -1;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002184 sinfo.frame_width = static_cast<int>(channel_stream_info->width());
2185 sinfo.frame_height = static_cast<int>(channel_stream_info->height());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002186 sinfo.framerate_input = channel_stream_info->framerate();
2187 sinfo.framerate_sent = send_channel->encoder_observer()->framerate();
2188 sinfo.nominal_bitrate = send_channel->encoder_observer()->bitrate();
2189 sinfo.preferred_bitrate = send_max_bitrate_;
2190 sinfo.adapt_reason = send_channel->CurrentAdaptReason();
2191
2192 // Get received RTCP statistics for the sender, if available.
2193 // It's not a fatal error if we can't, since RTCP may not have arrived
2194 // yet.
2195 uint16 r_fraction_lost;
2196 unsigned int r_cumulative_lost;
2197 unsigned int r_extended_max;
2198 unsigned int r_jitter;
2199 int r_rtt_ms;
2200
2201 if (engine_->vie()->rtp()->GetSentRTCPStatistics(
2202 channel_id,
2203 r_fraction_lost,
2204 r_cumulative_lost,
2205 r_extended_max,
2206 r_jitter, r_rtt_ms) == 0) {
2207 // Convert Q8 to float.
2208 sinfo.packets_lost = r_cumulative_lost;
2209 sinfo.fraction_lost = static_cast<float>(r_fraction_lost) / (1 << 8);
2210 sinfo.rtt_ms = r_rtt_ms;
2211 }
2212 info->senders.push_back(sinfo);
2213
2214 unsigned int channel_total_bitrate_sent = 0;
2215 unsigned int channel_video_bitrate_sent = 0;
2216 unsigned int channel_fec_bitrate_sent = 0;
2217 unsigned int channel_nack_bitrate_sent = 0;
2218 if (engine_->vie()->rtp()->GetBandwidthUsage(
2219 channel_id, channel_total_bitrate_sent, channel_video_bitrate_sent,
2220 channel_fec_bitrate_sent, channel_nack_bitrate_sent) == 0) {
2221 total_bitrate_sent += channel_total_bitrate_sent;
2222 video_bitrate_sent += channel_video_bitrate_sent;
2223 fec_bitrate_sent += channel_fec_bitrate_sent;
2224 nack_bitrate_sent += channel_nack_bitrate_sent;
2225 } else {
2226 LOG_RTCERR1(GetBandwidthUsage, channel_id);
2227 }
2228
2229 unsigned int estimated_stream_send_bandwidth = 0;
2230 if (engine_->vie()->rtp()->GetEstimatedSendBandwidth(
2231 channel_id, &estimated_stream_send_bandwidth) == 0) {
2232 estimated_send_bandwidth += estimated_stream_send_bandwidth;
2233 } else {
2234 LOG_RTCERR1(GetEstimatedSendBandwidth, channel_id);
2235 }
2236 unsigned int target_enc_stream_bitrate = 0;
2237 if (engine_->vie()->codec()->GetCodecTargetBitrate(
2238 channel_id, &target_enc_stream_bitrate) == 0) {
2239 target_enc_bitrate += target_enc_stream_bitrate;
2240 } else {
2241 LOG_RTCERR1(GetCodecTargetBitrate, channel_id);
2242 }
2243 }
2244 } else {
2245 LOG(LS_WARNING) << "GetStats: sender information not ready.";
2246 }
2247
2248 // Get the SSRC and stats for each receiver, based on our own calculations.
2249 unsigned int estimated_recv_bandwidth = 0;
2250 for (RecvChannelMap::const_iterator it = recv_channels_.begin();
2251 it != recv_channels_.end(); ++it) {
2252 // Don't report receive statistics from the default channel if we have
2253 // specified receive channels.
2254 if (it->first == 0 && recv_channels_.size() > 1)
2255 continue;
2256 WebRtcVideoChannelRecvInfo* channel = it->second;
2257
2258 unsigned int ssrc;
2259 // Get receiver statistics and build VideoReceiverInfo, if we have data.
2260 if (engine_->vie()->rtp()->GetRemoteSSRC(channel->channel_id(), ssrc) != 0)
2261 continue;
2262
2263 unsigned int bytes_sent, packets_sent, bytes_recv, packets_recv;
2264 if (engine_->vie()->rtp()->GetRTPStatistics(
2265 channel->channel_id(), bytes_sent, packets_sent, bytes_recv,
2266 packets_recv) != 0) {
2267 LOG_RTCERR1(GetRTPStatistics, channel->channel_id());
2268 return false;
2269 }
2270 VideoReceiverInfo rinfo;
2271 rinfo.ssrcs.push_back(ssrc);
2272 rinfo.bytes_rcvd = bytes_recv;
2273 rinfo.packets_rcvd = packets_recv;
2274 rinfo.packets_lost = -1;
2275 rinfo.packets_concealed = -1;
2276 rinfo.fraction_lost = -1; // from SentRTCP
2277 rinfo.firs_sent = channel->decoder_observer()->firs_requested();
2278 rinfo.nacks_sent = -1;
2279 rinfo.frame_width = channel->render_adapter()->width();
2280 rinfo.frame_height = channel->render_adapter()->height();
2281 rinfo.framerate_rcvd = channel->decoder_observer()->framerate();
2282 int fps = channel->render_adapter()->framerate();
2283 rinfo.framerate_decoded = fps;
2284 rinfo.framerate_output = fps;
2285
2286 // Get sent RTCP statistics.
2287 uint16 s_fraction_lost;
2288 unsigned int s_cumulative_lost;
2289 unsigned int s_extended_max;
2290 unsigned int s_jitter;
2291 int s_rtt_ms;
2292 if (engine_->vie()->rtp()->GetReceivedRTCPStatistics(channel->channel_id(),
2293 s_fraction_lost, s_cumulative_lost, s_extended_max,
2294 s_jitter, s_rtt_ms) == 0) {
2295 // Convert Q8 to float.
2296 rinfo.packets_lost = s_cumulative_lost;
2297 rinfo.fraction_lost = static_cast<float>(s_fraction_lost) / (1 << 8);
2298 }
2299 info->receivers.push_back(rinfo);
2300
2301 unsigned int estimated_recv_stream_bandwidth = 0;
2302 if (engine_->vie()->rtp()->GetEstimatedReceiveBandwidth(
2303 channel->channel_id(), &estimated_recv_stream_bandwidth) == 0) {
2304 estimated_recv_bandwidth += estimated_recv_stream_bandwidth;
2305 } else {
2306 LOG_RTCERR1(GetEstimatedReceiveBandwidth, channel->channel_id());
2307 }
2308 }
2309
2310 // Build BandwidthEstimationInfo.
2311 // TODO(zhurunz): Add real unittest for this.
2312 BandwidthEstimationInfo bwe;
2313
2314 // Calculations done above per send/receive stream.
2315 bwe.actual_enc_bitrate = video_bitrate_sent;
2316 bwe.transmit_bitrate = total_bitrate_sent;
2317 bwe.retransmit_bitrate = nack_bitrate_sent;
2318 bwe.available_send_bandwidth = estimated_send_bandwidth;
2319 bwe.available_recv_bandwidth = estimated_recv_bandwidth;
2320 bwe.target_enc_bitrate = target_enc_bitrate;
2321
2322 info->bw_estimations.push_back(bwe);
2323
2324 return true;
2325}
2326
2327bool WebRtcVideoMediaChannel::SetCapturer(uint32 ssrc,
2328 VideoCapturer* capturer) {
2329 ASSERT(ssrc != 0);
2330 if (!capturer) {
2331 return RemoveCapturer(ssrc);
2332 }
2333 WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(ssrc);
2334 if (!send_channel) {
2335 return false;
2336 }
2337 VideoCapturer* old_capturer = send_channel->video_capturer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002338 if (old_capturer) {
2339 old_capturer->SignalVideoFrame.disconnect(this);
2340 }
2341
2342 send_channel->set_video_capturer(capturer);
2343 capturer->SignalVideoFrame.connect(
2344 this,
2345 &WebRtcVideoMediaChannel::AdaptAndSendFrame);
2346 if (!capturer->IsScreencast() && ratio_w_ != 0 && ratio_h_ != 0) {
2347 capturer->UpdateAspectRatio(ratio_w_, ratio_h_);
2348 }
2349 const int64 timestamp = send_channel->local_stream_info()->time_stamp();
2350 if (send_codec_) {
2351 QueueBlackFrame(ssrc, timestamp, send_codec_->maxFramerate);
2352 }
2353 return true;
2354}
2355
2356bool WebRtcVideoMediaChannel::RequestIntraFrame() {
2357 // There is no API exposed to application to request a key frame
2358 // ViE does this internally when there are errors from decoder
2359 return false;
2360}
2361
2362void WebRtcVideoMediaChannel::OnPacketReceived(talk_base::Buffer* packet) {
2363 // Pick which channel to send this packet to. If this packet doesn't match
2364 // any multiplexed streams, just send it to the default channel. Otherwise,
2365 // send it to the specific decoder instance for that stream.
2366 uint32 ssrc = 0;
2367 if (!GetRtpSsrc(packet->data(), packet->length(), &ssrc))
2368 return;
2369 int which_channel = GetRecvChannelNum(ssrc);
2370 if (which_channel == -1) {
2371 which_channel = video_channel();
2372 }
2373
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002374 engine()->vie()->network()->ReceivedRTPPacket(
2375 which_channel,
2376 packet->data(),
2377 static_cast<int>(packet->length()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002378}
2379
2380void WebRtcVideoMediaChannel::OnRtcpReceived(talk_base::Buffer* packet) {
2381// Sending channels need all RTCP packets with feedback information.
2382// Even sender reports can contain attached report blocks.
2383// Receiving channels need sender reports in order to create
2384// correct receiver reports.
2385
2386 uint32 ssrc = 0;
2387 if (!GetRtcpSsrc(packet->data(), packet->length(), &ssrc)) {
2388 LOG(LS_WARNING) << "Failed to parse SSRC from received RTCP packet";
2389 return;
2390 }
2391 int type = 0;
2392 if (!GetRtcpType(packet->data(), packet->length(), &type)) {
2393 LOG(LS_WARNING) << "Failed to parse type from received RTCP packet";
2394 return;
2395 }
2396
2397 // If it is a sender report, find the channel that is listening.
2398 if (type == kRtcpTypeSR) {
2399 int which_channel = GetRecvChannelNum(ssrc);
2400 if (which_channel != -1 && !IsDefaultChannel(which_channel)) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002401 engine_->vie()->network()->ReceivedRTCPPacket(
2402 which_channel,
2403 packet->data(),
2404 static_cast<int>(packet->length()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002405 }
2406 }
2407 // SR may continue RR and any RR entry may correspond to any one of the send
2408 // channels. So all RTCP packets must be forwarded all send channels. ViE
2409 // will filter out RR internally.
2410 for (SendChannelMap::iterator iter = send_channels_.begin();
2411 iter != send_channels_.end(); ++iter) {
2412 WebRtcVideoChannelSendInfo* send_channel = iter->second;
2413 int channel_id = send_channel->channel_id();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002414 engine_->vie()->network()->ReceivedRTCPPacket(
2415 channel_id,
2416 packet->data(),
2417 static_cast<int>(packet->length()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002418 }
2419}
2420
2421void WebRtcVideoMediaChannel::OnReadyToSend(bool ready) {
2422 SetNetworkTransmissionState(ready);
2423}
2424
2425bool WebRtcVideoMediaChannel::MuteStream(uint32 ssrc, bool muted) {
2426 WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(ssrc);
2427 if (!send_channel) {
2428 LOG(LS_ERROR) << "The specified ssrc " << ssrc << " is not in use.";
2429 return false;
2430 }
2431 send_channel->set_muted(muted);
2432 return true;
2433}
2434
2435bool WebRtcVideoMediaChannel::SetRecvRtpHeaderExtensions(
2436 const std::vector<RtpHeaderExtension>& extensions) {
2437 if (receive_extensions_ == extensions) {
2438 return true;
2439 }
2440 receive_extensions_ = extensions;
2441
2442 const RtpHeaderExtension* offset_extension =
2443 FindHeaderExtension(extensions, kRtpTimestampOffsetHeaderExtension);
2444 const RtpHeaderExtension* send_time_extension =
2445 FindHeaderExtension(extensions, kRtpAbsoluteSendTimeHeaderExtension);
2446
2447 // Loop through all receive channels and enable/disable the extensions.
2448 for (RecvChannelMap::iterator channel_it = recv_channels_.begin();
2449 channel_it != recv_channels_.end(); ++channel_it) {
2450 int channel_id = channel_it->second->channel_id();
2451 if (!SetHeaderExtension(
2452 &webrtc::ViERTP_RTCP::SetReceiveTimestampOffsetStatus, channel_id,
2453 offset_extension)) {
2454 return false;
2455 }
2456 if (!SetHeaderExtension(
2457 &webrtc::ViERTP_RTCP::SetReceiveAbsoluteSendTimeStatus, channel_id,
2458 send_time_extension)) {
2459 return false;
2460 }
2461 }
2462 return true;
2463}
2464
2465bool WebRtcVideoMediaChannel::SetSendRtpHeaderExtensions(
2466 const std::vector<RtpHeaderExtension>& extensions) {
2467 send_extensions_ = extensions;
2468
2469 const RtpHeaderExtension* offset_extension =
2470 FindHeaderExtension(extensions, kRtpTimestampOffsetHeaderExtension);
2471 const RtpHeaderExtension* send_time_extension =
2472 FindHeaderExtension(extensions, kRtpAbsoluteSendTimeHeaderExtension);
2473
2474 // Loop through all send channels and enable/disable the extensions.
2475 for (SendChannelMap::iterator channel_it = send_channels_.begin();
2476 channel_it != send_channels_.end(); ++channel_it) {
2477 int channel_id = channel_it->second->channel_id();
2478 if (!SetHeaderExtension(
2479 &webrtc::ViERTP_RTCP::SetSendTimestampOffsetStatus, channel_id,
2480 offset_extension)) {
2481 return false;
2482 }
2483 if (!SetHeaderExtension(
2484 &webrtc::ViERTP_RTCP::SetSendAbsoluteSendTimeStatus, channel_id,
2485 send_time_extension)) {
2486 return false;
2487 }
2488 }
2489 return true;
2490}
2491
2492bool WebRtcVideoMediaChannel::SetSendBandwidth(bool autobw, int bps) {
2493 LOG(LS_INFO) << "WebRtcVideoMediaChanne::SetSendBandwidth";
2494
2495 if (InConferenceMode()) {
2496 LOG(LS_INFO) << "Conference mode ignores SetSendBandWidth";
2497 return true;
2498 }
2499
2500 if (!send_codec_) {
2501 LOG(LS_INFO) << "The send codec has not been set up yet";
2502 return true;
2503 }
2504
2505 int min_bitrate;
2506 int start_bitrate;
2507 int max_bitrate;
2508 if (autobw) {
2509 // Use the default values for min bitrate.
2510 min_bitrate = kMinVideoBitrate;
2511 // Use the default value or the bps for the max
2512 max_bitrate = (bps <= 0) ? send_max_bitrate_ : (bps / 1000);
2513 // Maximum start bitrate can be kStartVideoBitrate.
2514 start_bitrate = talk_base::_min(kStartVideoBitrate, max_bitrate);
2515 } else {
2516 // Use the default start or the bps as the target bitrate.
2517 int target_bitrate = (bps <= 0) ? kStartVideoBitrate : (bps / 1000);
2518 min_bitrate = target_bitrate;
2519 start_bitrate = target_bitrate;
2520 max_bitrate = target_bitrate;
2521 }
2522
2523 if (!SetSendCodec(*send_codec_, min_bitrate, start_bitrate, max_bitrate)) {
2524 return false;
2525 }
2526 LogSendCodecChange("SetSendBandwidth()");
2527
2528 return true;
2529}
2530
2531bool WebRtcVideoMediaChannel::SetOptions(const VideoOptions &options) {
2532 // Always accept options that are unchanged.
2533 if (options_ == options) {
2534 return true;
2535 }
2536
2537 // Trigger SetSendCodec to set correct noise reduction state if the option has
2538 // changed.
2539 bool denoiser_changed = options.video_noise_reduction.IsSet() &&
2540 (options_.video_noise_reduction != options.video_noise_reduction);
2541
2542 bool leaky_bucket_changed = options.video_leaky_bucket.IsSet() &&
2543 (options_.video_leaky_bucket != options.video_leaky_bucket);
2544
2545 bool buffer_latency_changed = options.buffered_mode_latency.IsSet() &&
2546 (options_.buffered_mode_latency != options.buffered_mode_latency);
2547
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00002548 bool cpu_overuse_detection_changed = options.cpu_overuse_detection.IsSet() &&
2549 (options_.cpu_overuse_detection != options.cpu_overuse_detection);
2550
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002551 bool conference_mode_turned_off = false;
2552 if (options_.conference_mode.IsSet() && options.conference_mode.IsSet() &&
2553 options_.conference_mode.GetWithDefaultIfUnset(false) &&
2554 !options.conference_mode.GetWithDefaultIfUnset(false)) {
2555 conference_mode_turned_off = true;
2556 }
2557
2558 // Save the options, to be interpreted where appropriate.
2559 // Use options_.SetAll() instead of assignment so that unset value in options
2560 // will not overwrite the previous option value.
2561 options_.SetAll(options);
2562
2563 // Set CPU options for all send channels.
2564 for (SendChannelMap::iterator iter = send_channels_.begin();
2565 iter != send_channels_.end(); ++iter) {
2566 WebRtcVideoChannelSendInfo* send_channel = iter->second;
2567 send_channel->ApplyCpuOptions(options_);
2568 }
2569
2570 // Adjust send codec bitrate if needed.
2571 int conf_max_bitrate = kDefaultConferenceModeMaxVideoBitrate;
2572
2573 int expected_bitrate = send_max_bitrate_;
2574 if (InConferenceMode()) {
2575 expected_bitrate = conf_max_bitrate;
2576 } else if (conference_mode_turned_off) {
2577 // This is a special case for turning conference mode off.
2578 // Max bitrate should go back to the default maximum value instead
2579 // of the current maximum.
2580 expected_bitrate = kMaxVideoBitrate;
2581 }
2582
2583 if (send_codec_ &&
2584 (send_max_bitrate_ != expected_bitrate || denoiser_changed)) {
2585 // On success, SetSendCodec() will reset send_max_bitrate_ to
2586 // expected_bitrate.
2587 if (!SetSendCodec(*send_codec_,
2588 send_min_bitrate_,
2589 send_start_bitrate_,
2590 expected_bitrate)) {
2591 return false;
2592 }
2593 LogSendCodecChange("SetOptions()");
2594 }
2595 if (leaky_bucket_changed) {
2596 bool enable_leaky_bucket =
2597 options_.video_leaky_bucket.GetWithDefaultIfUnset(false);
2598 for (SendChannelMap::iterator it = send_channels_.begin();
2599 it != send_channels_.end(); ++it) {
2600 if (engine()->vie()->rtp()->SetTransmissionSmoothingStatus(
2601 it->second->channel_id(), enable_leaky_bucket) != 0) {
2602 LOG_RTCERR2(SetTransmissionSmoothingStatus, it->second->channel_id(),
2603 enable_leaky_bucket);
2604 }
2605 }
2606 }
2607 if (buffer_latency_changed) {
2608 int buffer_latency =
2609 options_.buffered_mode_latency.GetWithDefaultIfUnset(
2610 cricket::kBufferedModeDisabled);
2611 for (SendChannelMap::iterator it = send_channels_.begin();
2612 it != send_channels_.end(); ++it) {
2613 if (engine()->vie()->rtp()->SetSenderBufferingMode(
2614 it->second->channel_id(), buffer_latency) != 0) {
2615 LOG_RTCERR2(SetSenderBufferingMode, it->second->channel_id(),
2616 buffer_latency);
2617 }
2618 }
2619 for (RecvChannelMap::iterator it = recv_channels_.begin();
2620 it != recv_channels_.end(); ++it) {
2621 if (engine()->vie()->rtp()->SetReceiverBufferingMode(
2622 it->second->channel_id(), buffer_latency) != 0) {
2623 LOG_RTCERR2(SetReceiverBufferingMode, it->second->channel_id(),
2624 buffer_latency);
2625 }
2626 }
2627 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00002628 if (cpu_overuse_detection_changed) {
2629 bool cpu_overuse_detection =
2630 options_.cpu_overuse_detection.GetWithDefaultIfUnset(false);
2631 for (SendChannelMap::iterator iter = send_channels_.begin();
2632 iter != send_channels_.end(); ++iter) {
2633 WebRtcVideoChannelSendInfo* send_channel = iter->second;
2634 send_channel->SetCpuOveruseDetection(cpu_overuse_detection);
2635 }
2636 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002637 return true;
2638}
2639
2640void WebRtcVideoMediaChannel::SetInterface(NetworkInterface* iface) {
2641 MediaChannel::SetInterface(iface);
2642 // Set the RTP recv/send buffer to a bigger size
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002643 MediaChannel::SetOption(NetworkInterface::ST_RTP,
2644 talk_base::Socket::OPT_RCVBUF,
2645 kVideoRtpBufferSize);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002646
2647 // TODO(sriniv): Remove or re-enable this.
2648 // As part of b/8030474, send-buffer is size now controlled through
2649 // portallocator flags.
2650 // network_interface_->SetOption(NetworkInterface::ST_RTP,
2651 // talk_base::Socket::OPT_SNDBUF,
2652 // kVideoRtpBufferSize);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002653}
2654
2655void WebRtcVideoMediaChannel::UpdateAspectRatio(int ratio_w, int ratio_h) {
2656 ASSERT(ratio_w != 0);
2657 ASSERT(ratio_h != 0);
2658 ratio_w_ = ratio_w;
2659 ratio_h_ = ratio_h;
2660 // For now assume that all streams want the same aspect ratio.
2661 // TODO(hellner): remove the need for this assumption.
2662 for (SendChannelMap::iterator iter = send_channels_.begin();
2663 iter != send_channels_.end(); ++iter) {
2664 WebRtcVideoChannelSendInfo* send_channel = iter->second;
2665 VideoCapturer* capturer = send_channel->video_capturer();
2666 if (capturer) {
2667 capturer->UpdateAspectRatio(ratio_w, ratio_h);
2668 }
2669 }
2670}
2671
2672bool WebRtcVideoMediaChannel::GetRenderer(uint32 ssrc,
2673 VideoRenderer** renderer) {
2674 RecvChannelMap::const_iterator it = recv_channels_.find(ssrc);
2675 if (it == recv_channels_.end()) {
2676 if (first_receive_ssrc_ == ssrc &&
2677 recv_channels_.find(0) != recv_channels_.end()) {
2678 LOG(LS_INFO) << " GetRenderer " << ssrc
2679 << " reuse default renderer #"
2680 << vie_channel_;
2681 *renderer = recv_channels_[0]->render_adapter()->renderer();
2682 return true;
2683 }
2684 return false;
2685 }
2686
2687 *renderer = it->second->render_adapter()->renderer();
2688 return true;
2689}
2690
2691void WebRtcVideoMediaChannel::AdaptAndSendFrame(VideoCapturer* capturer,
2692 const VideoFrame* frame) {
2693 if (capturer->IsScreencast()) {
2694 // Do not adapt frames that are screencast.
2695 SendFrame(capturer, frame);
2696 return;
2697 }
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002698 // TODO(thorcarpenter): This is broken. One capturer registered on two ssrc
2699 // will not send any video to the second ssrc send channel. We should remove
2700 // GetSendChannel(capturer) and pass in an ssrc here.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002701 WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(capturer);
2702 if (!send_channel) {
2703 SendFrame(capturer, frame);
2704 return;
2705 }
2706 const VideoFrame* output_frame = NULL;
2707 send_channel->AdaptFrame(frame, &output_frame);
2708 if (output_frame) {
2709 SendFrame(send_channel, output_frame, capturer->IsScreencast());
2710 }
2711}
2712
2713// TODO(zhurunz): Add unittests to test this function.
2714void WebRtcVideoMediaChannel::SendFrame(VideoCapturer* capturer,
2715 const VideoFrame* frame) {
2716 // If there's send channel registers to the |capturer|, then only send the
2717 // frame to that channel and return. Otherwise send the frame to the default
2718 // channel, which currently taking frames from the engine.
2719 WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(capturer);
2720 if (send_channel) {
2721 SendFrame(send_channel, frame, capturer->IsScreencast());
2722 return;
2723 }
2724 // TODO(hellner): Remove below for loop once the captured frame no longer
2725 // come from the engine, i.e. the engine no longer owns a capturer.
2726 for (SendChannelMap::iterator iter = send_channels_.begin();
2727 iter != send_channels_.end(); ++iter) {
2728 WebRtcVideoChannelSendInfo* send_channel = iter->second;
2729 if (send_channel->video_capturer() == NULL) {
2730 SendFrame(send_channel, frame, capturer->IsScreencast());
2731 }
2732 }
2733}
2734
2735bool WebRtcVideoMediaChannel::SendFrame(
2736 WebRtcVideoChannelSendInfo* send_channel,
2737 const VideoFrame* frame,
2738 bool is_screencast) {
2739 if (!send_channel) {
2740 return false;
2741 }
2742 if (!send_codec_) {
2743 // Send codec has not been set. No reason to process the frame any further.
2744 return false;
2745 }
2746 const VideoFormat& video_format = send_channel->video_format();
2747 // If the frame should be dropped.
2748 const bool video_format_set = video_format != cricket::VideoFormat();
2749 if (video_format_set &&
2750 (video_format.width == 0 && video_format.height == 0)) {
2751 return true;
2752 }
2753
2754 // Checks if we need to reset vie send codec.
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002755 if (!MaybeResetVieSendCodec(send_channel,
2756 static_cast<int>(frame->GetWidth()),
2757 static_cast<int>(frame->GetHeight()),
2758 is_screencast, NULL)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002759 LOG(LS_ERROR) << "MaybeResetVieSendCodec failed with "
2760 << frame->GetWidth() << "x" << frame->GetHeight();
2761 return false;
2762 }
2763 const VideoFrame* frame_out = frame;
2764 talk_base::scoped_ptr<VideoFrame> processed_frame;
2765 // Disable muting for screencast.
2766 const bool mute = (send_channel->muted() && !is_screencast);
2767 send_channel->ProcessFrame(*frame_out, mute, processed_frame.use());
2768 if (processed_frame) {
2769 frame_out = processed_frame.get();
2770 }
2771
2772 webrtc::ViEVideoFrameI420 frame_i420;
2773 // TODO(ronghuawu): Update the webrtc::ViEVideoFrameI420
2774 // to use const unsigned char*
2775 frame_i420.y_plane = const_cast<unsigned char*>(frame_out->GetYPlane());
2776 frame_i420.u_plane = const_cast<unsigned char*>(frame_out->GetUPlane());
2777 frame_i420.v_plane = const_cast<unsigned char*>(frame_out->GetVPlane());
2778 frame_i420.y_pitch = frame_out->GetYPitch();
2779 frame_i420.u_pitch = frame_out->GetUPitch();
2780 frame_i420.v_pitch = frame_out->GetVPitch();
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00002781 frame_i420.width = static_cast<uint16>(frame_out->GetWidth());
2782 frame_i420.height = static_cast<uint16>(frame_out->GetHeight());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002783
2784 int64 timestamp_ntp_ms = 0;
2785 // TODO(justinlin): Reenable after Windows issues with clock drift are fixed.
2786 // Currently reverted to old behavior of discarding capture timestamp.
2787#if 0
2788 // If the frame timestamp is 0, we will use the deliver time.
2789 const int64 frame_timestamp = frame->GetTimeStamp();
2790 if (frame_timestamp != 0) {
2791 if (abs(time(NULL) - frame_timestamp / talk_base::kNumNanosecsPerSec) >
2792 kTimestampDeltaInSecondsForWarning) {
2793 LOG(LS_WARNING) << "Frame timestamp differs by more than "
2794 << kTimestampDeltaInSecondsForWarning << " seconds from "
2795 << "current Unix timestamp.";
2796 }
2797
2798 timestamp_ntp_ms =
2799 talk_base::UnixTimestampNanosecsToNtpMillisecs(frame_timestamp);
2800 }
2801#endif
2802
2803 return send_channel->external_capture()->IncomingFrameI420(
2804 frame_i420, timestamp_ntp_ms) == 0;
2805}
2806
2807bool WebRtcVideoMediaChannel::CreateChannel(uint32 ssrc_key,
2808 MediaDirection direction,
2809 int* channel_id) {
2810 // There are 3 types of channels. Sending only, receiving only and
2811 // sending and receiving. The sending and receiving channel is the
2812 // default channel and there is only one. All other channels that are created
2813 // are associated with the default channel which must exist. The default
2814 // channel id is stored in |vie_channel_|. All channels need to know about
2815 // the default channel to properly handle remb which is why there are
2816 // different ViE create channel calls.
2817 // For this channel the local and remote ssrc key is 0. However, it may
2818 // have a non-zero local and/or remote ssrc depending on if it is currently
2819 // sending and/or receiving.
2820 if ((vie_channel_ == -1 || direction == MD_SENDRECV) &&
2821 (!send_channels_.empty() || !recv_channels_.empty())) {
2822 ASSERT(false);
2823 return false;
2824 }
2825
2826 *channel_id = -1;
2827 if (direction == MD_RECV) {
2828 // All rec channels are associated with the default channel |vie_channel_|
2829 if (engine_->vie()->base()->CreateReceiveChannel(*channel_id,
2830 vie_channel_) != 0) {
2831 LOG_RTCERR2(CreateReceiveChannel, *channel_id, vie_channel_);
2832 return false;
2833 }
2834 } else if (direction == MD_SEND) {
2835 if (engine_->vie()->base()->CreateChannel(*channel_id,
2836 vie_channel_) != 0) {
2837 LOG_RTCERR2(CreateChannel, *channel_id, vie_channel_);
2838 return false;
2839 }
2840 } else {
2841 ASSERT(direction == MD_SENDRECV);
2842 if (engine_->vie()->base()->CreateChannel(*channel_id) != 0) {
2843 LOG_RTCERR1(CreateChannel, *channel_id);
2844 return false;
2845 }
2846 }
2847 if (!ConfigureChannel(*channel_id, direction, ssrc_key)) {
2848 engine_->vie()->base()->DeleteChannel(*channel_id);
2849 *channel_id = -1;
2850 return false;
2851 }
2852
2853 return true;
2854}
2855
2856bool WebRtcVideoMediaChannel::ConfigureChannel(int channel_id,
2857 MediaDirection direction,
2858 uint32 ssrc_key) {
2859 const bool receiving = (direction == MD_RECV) || (direction == MD_SENDRECV);
2860 const bool sending = (direction == MD_SEND) || (direction == MD_SENDRECV);
2861 // Register external transport.
2862 if (engine_->vie()->network()->RegisterSendTransport(
2863 channel_id, *this) != 0) {
2864 LOG_RTCERR1(RegisterSendTransport, channel_id);
2865 return false;
2866 }
2867
2868 // Set MTU.
2869 if (engine_->vie()->network()->SetMTU(channel_id, kVideoMtu) != 0) {
2870 LOG_RTCERR2(SetMTU, channel_id, kVideoMtu);
2871 return false;
2872 }
2873 // Turn on RTCP and loss feedback reporting.
2874 if (engine()->vie()->rtp()->SetRTCPStatus(
2875 channel_id, webrtc::kRtcpCompound_RFC4585) != 0) {
2876 LOG_RTCERR2(SetRTCPStatus, channel_id, webrtc::kRtcpCompound_RFC4585);
2877 return false;
2878 }
2879 // Enable pli as key frame request method.
2880 if (engine_->vie()->rtp()->SetKeyFrameRequestMethod(
2881 channel_id, webrtc::kViEKeyFrameRequestPliRtcp) != 0) {
2882 LOG_RTCERR2(SetKeyFrameRequestMethod,
2883 channel_id, webrtc::kViEKeyFrameRequestPliRtcp);
2884 return false;
2885 }
2886 if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, nack_enabled_)) {
2887 // Logged in SetNackFec. Don't spam the logs.
2888 return false;
2889 }
2890 // Note that receiving must always be configured before sending to ensure
2891 // that send and receive channel is configured correctly (ConfigureReceiving
2892 // assumes no sending).
2893 if (receiving) {
2894 if (!ConfigureReceiving(channel_id, ssrc_key)) {
2895 return false;
2896 }
2897 }
2898 if (sending) {
2899 if (!ConfigureSending(channel_id, ssrc_key)) {
2900 return false;
2901 }
2902 }
2903
2904 return true;
2905}
2906
2907bool WebRtcVideoMediaChannel::ConfigureReceiving(int channel_id,
2908 uint32 remote_ssrc_key) {
2909 // Make sure that an SSRC/key isn't registered more than once.
2910 if (recv_channels_.find(remote_ssrc_key) != recv_channels_.end()) {
2911 return false;
2912 }
2913 // Connect the voice channel, if there is one.
2914 // TODO(perkj): The A/V is synched by the receiving channel. So we need to
2915 // know the SSRC of the remote audio channel in order to fetch the correct
2916 // webrtc VoiceEngine channel. For now- only sync the default channel used
2917 // in 1-1 calls.
2918 if (remote_ssrc_key == 0 && voice_channel_) {
2919 WebRtcVoiceMediaChannel* voice_channel =
2920 static_cast<WebRtcVoiceMediaChannel*>(voice_channel_);
2921 if (engine_->vie()->base()->ConnectAudioChannel(
2922 vie_channel_, voice_channel->voe_channel()) != 0) {
2923 LOG_RTCERR2(ConnectAudioChannel, channel_id,
2924 voice_channel->voe_channel());
2925 LOG(LS_WARNING) << "A/V not synchronized";
2926 // Not a fatal error.
2927 }
2928 }
2929
2930 talk_base::scoped_ptr<WebRtcVideoChannelRecvInfo> channel_info(
2931 new WebRtcVideoChannelRecvInfo(channel_id));
2932
2933 // Install a render adapter.
2934 if (engine_->vie()->render()->AddRenderer(channel_id,
2935 webrtc::kVideoI420, channel_info->render_adapter()) != 0) {
2936 LOG_RTCERR3(AddRenderer, channel_id, webrtc::kVideoI420,
2937 channel_info->render_adapter());
2938 return false;
2939 }
2940
2941
2942 if (engine_->vie()->rtp()->SetRembStatus(channel_id,
2943 kNotSending,
2944 remb_enabled_) != 0) {
2945 LOG_RTCERR3(SetRembStatus, channel_id, kNotSending, remb_enabled_);
2946 return false;
2947 }
2948
2949 if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetReceiveTimestampOffsetStatus,
2950 channel_id, receive_extensions_, kRtpTimestampOffsetHeaderExtension)) {
2951 return false;
2952 }
2953
2954 if (!SetHeaderExtension(
2955 &webrtc::ViERTP_RTCP::SetReceiveAbsoluteSendTimeStatus, channel_id,
2956 receive_extensions_, kRtpAbsoluteSendTimeHeaderExtension)) {
2957 return false;
2958 }
2959
2960 if (remote_ssrc_key != 0) {
2961 // Use the same SSRC as our default channel
2962 // (so the RTCP reports are correct).
2963 unsigned int send_ssrc = 0;
2964 webrtc::ViERTP_RTCP* rtp = engine()->vie()->rtp();
2965 if (rtp->GetLocalSSRC(vie_channel_, send_ssrc) == -1) {
2966 LOG_RTCERR2(GetLocalSSRC, vie_channel_, send_ssrc);
2967 return false;
2968 }
2969 if (rtp->SetLocalSSRC(channel_id, send_ssrc) == -1) {
2970 LOG_RTCERR2(SetLocalSSRC, channel_id, send_ssrc);
2971 return false;
2972 }
2973 } // Else this is the the default channel and we don't change the SSRC.
2974
2975 // Disable color enhancement since it is a bit too aggressive.
2976 if (engine()->vie()->image()->EnableColorEnhancement(channel_id,
2977 false) != 0) {
2978 LOG_RTCERR1(EnableColorEnhancement, channel_id);
2979 return false;
2980 }
2981
2982 if (!SetReceiveCodecs(channel_info.get())) {
2983 return false;
2984 }
2985
2986 int buffer_latency =
2987 options_.buffered_mode_latency.GetWithDefaultIfUnset(
2988 cricket::kBufferedModeDisabled);
2989 if (buffer_latency != cricket::kBufferedModeDisabled) {
2990 if (engine()->vie()->rtp()->SetReceiverBufferingMode(
2991 channel_id, buffer_latency) != 0) {
2992 LOG_RTCERR2(SetReceiverBufferingMode, channel_id, buffer_latency);
2993 }
2994 }
2995
2996 if (render_started_) {
2997 if (engine_->vie()->render()->StartRender(channel_id) != 0) {
2998 LOG_RTCERR1(StartRender, channel_id);
2999 return false;
3000 }
3001 }
3002
3003 // Register decoder observer for incoming framerate and bitrate.
3004 if (engine()->vie()->codec()->RegisterDecoderObserver(
3005 channel_id, *channel_info->decoder_observer()) != 0) {
3006 LOG_RTCERR1(RegisterDecoderObserver, channel_info->decoder_observer());
3007 return false;
3008 }
3009
3010 recv_channels_[remote_ssrc_key] = channel_info.release();
3011 return true;
3012}
3013
3014bool WebRtcVideoMediaChannel::ConfigureSending(int channel_id,
3015 uint32 local_ssrc_key) {
3016 // The ssrc key can be zero or correspond to an SSRC.
3017 // Make sure the default channel isn't configured more than once.
3018 if (local_ssrc_key == 0 && send_channels_.find(0) != send_channels_.end()) {
3019 return false;
3020 }
3021 // Make sure that the SSRC is not already in use.
3022 uint32 dummy_key;
3023 if (GetSendChannelKey(local_ssrc_key, &dummy_key)) {
3024 return false;
3025 }
3026 int vie_capture = 0;
3027 webrtc::ViEExternalCapture* external_capture = NULL;
3028 // Register external capture.
3029 if (engine()->vie()->capture()->AllocateExternalCaptureDevice(
3030 vie_capture, external_capture) != 0) {
3031 LOG_RTCERR0(AllocateExternalCaptureDevice);
3032 return false;
3033 }
3034
3035 // Connect external capture.
3036 if (engine()->vie()->capture()->ConnectCaptureDevice(
3037 vie_capture, channel_id) != 0) {
3038 LOG_RTCERR2(ConnectCaptureDevice, vie_capture, channel_id);
3039 return false;
3040 }
3041 talk_base::scoped_ptr<WebRtcVideoChannelSendInfo> send_channel(
3042 new WebRtcVideoChannelSendInfo(channel_id, vie_capture,
3043 external_capture,
3044 engine()->cpu_monitor()));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00003045#ifdef USE_WEBRTC_DEV_BRANCH
3046 if (engine()->vie()->base()->RegisterCpuOveruseObserver(
3047 channel_id, send_channel->overuse_observer())) {
3048 LOG_RTCERR1(RegisterCpuOveruseObserver, channel_id);
3049 return false;
3050 }
3051#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003052 send_channel->ApplyCpuOptions(options_);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00003053 send_channel->SignalCpuAdaptationUnable.connect(this,
3054 &WebRtcVideoMediaChannel::OnCpuAdaptationUnable);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003055
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00003056 if (options_.cpu_overuse_detection.GetWithDefaultIfUnset(false)) {
3057 send_channel->SetCpuOveruseDetection(true);
3058 }
3059
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003060 // Register encoder observer for outgoing framerate and bitrate.
3061 if (engine()->vie()->codec()->RegisterEncoderObserver(
3062 channel_id, *send_channel->encoder_observer()) != 0) {
3063 LOG_RTCERR1(RegisterEncoderObserver, send_channel->encoder_observer());
3064 return false;
3065 }
3066
3067 if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetSendTimestampOffsetStatus,
3068 channel_id, send_extensions_, kRtpTimestampOffsetHeaderExtension)) {
3069 return false;
3070 }
3071
3072 if (!SetHeaderExtension(&webrtc::ViERTP_RTCP::SetSendAbsoluteSendTimeStatus,
3073 channel_id, send_extensions_, kRtpAbsoluteSendTimeHeaderExtension)) {
3074 return false;
3075 }
3076
3077 if (options_.video_leaky_bucket.GetWithDefaultIfUnset(false)) {
3078 if (engine()->vie()->rtp()->SetTransmissionSmoothingStatus(channel_id,
3079 true) != 0) {
3080 LOG_RTCERR2(SetTransmissionSmoothingStatus, channel_id, true);
3081 return false;
3082 }
3083 }
3084
3085 int buffer_latency =
3086 options_.buffered_mode_latency.GetWithDefaultIfUnset(
3087 cricket::kBufferedModeDisabled);
3088 if (buffer_latency != cricket::kBufferedModeDisabled) {
3089 if (engine()->vie()->rtp()->SetSenderBufferingMode(
3090 channel_id, buffer_latency) != 0) {
3091 LOG_RTCERR2(SetSenderBufferingMode, channel_id, buffer_latency);
3092 }
3093 }
3094 // The remb status direction correspond to the RTP stream (and not the RTCP
3095 // stream). I.e. if send remb is enabled it means it is receiving remote
3096 // rembs and should use them to estimate bandwidth. Receive remb mean that
3097 // remb packets will be generated and that the channel should be included in
3098 // it. If remb is enabled all channels are allowed to contribute to the remb
3099 // but only receive channels will ever end up actually contributing. This
3100 // keeps the logic simple.
3101 if (engine_->vie()->rtp()->SetRembStatus(channel_id,
3102 remb_enabled_,
3103 remb_enabled_) != 0) {
3104 LOG_RTCERR3(SetRembStatus, channel_id, remb_enabled_, remb_enabled_);
3105 return false;
3106 }
3107 if (!SetNackFec(channel_id, send_red_type_, send_fec_type_, nack_enabled_)) {
3108 // Logged in SetNackFec. Don't spam the logs.
3109 return false;
3110 }
3111
3112 send_channels_[local_ssrc_key] = send_channel.release();
3113
3114 return true;
3115}
3116
3117bool WebRtcVideoMediaChannel::SetNackFec(int channel_id,
3118 int red_payload_type,
3119 int fec_payload_type,
3120 bool nack_enabled) {
3121 bool enable = (red_payload_type != -1 && fec_payload_type != -1 &&
3122 !InConferenceMode());
3123 if (enable) {
3124 if (engine_->vie()->rtp()->SetHybridNACKFECStatus(
3125 channel_id, nack_enabled, red_payload_type, fec_payload_type) != 0) {
3126 LOG_RTCERR4(SetHybridNACKFECStatus,
3127 channel_id, nack_enabled, red_payload_type, fec_payload_type);
3128 return false;
3129 }
3130 LOG(LS_INFO) << "Hybrid NACK/FEC enabled for channel " << channel_id;
3131 } else {
3132 if (engine_->vie()->rtp()->SetNACKStatus(channel_id, nack_enabled) != 0) {
3133 LOG_RTCERR1(SetNACKStatus, channel_id);
3134 return false;
3135 }
3136 LOG(LS_INFO) << "NACK enabled for channel " << channel_id;
3137 }
3138 return true;
3139}
3140
3141bool WebRtcVideoMediaChannel::SetSendCodec(const webrtc::VideoCodec& codec,
3142 int min_bitrate,
3143 int start_bitrate,
3144 int max_bitrate) {
3145 bool ret_val = true;
3146 for (SendChannelMap::iterator iter = send_channels_.begin();
3147 iter != send_channels_.end(); ++iter) {
3148 WebRtcVideoChannelSendInfo* send_channel = iter->second;
3149 ret_val = SetSendCodec(send_channel, codec, min_bitrate, start_bitrate,
3150 max_bitrate) && ret_val;
3151 }
3152 if (ret_val) {
3153 // All SetSendCodec calls were successful. Update the global state
3154 // accordingly.
3155 send_codec_.reset(new webrtc::VideoCodec(codec));
3156 send_min_bitrate_ = min_bitrate;
3157 send_start_bitrate_ = start_bitrate;
3158 send_max_bitrate_ = max_bitrate;
3159 } else {
3160 // At least one SetSendCodec call failed, rollback.
3161 for (SendChannelMap::iterator iter = send_channels_.begin();
3162 iter != send_channels_.end(); ++iter) {
3163 WebRtcVideoChannelSendInfo* send_channel = iter->second;
3164 if (send_codec_) {
3165 SetSendCodec(send_channel, *send_codec_.get(), send_min_bitrate_,
3166 send_start_bitrate_, send_max_bitrate_);
3167 }
3168 }
3169 }
3170 return ret_val;
3171}
3172
3173bool WebRtcVideoMediaChannel::SetSendCodec(
3174 WebRtcVideoChannelSendInfo* send_channel,
3175 const webrtc::VideoCodec& codec,
3176 int min_bitrate,
3177 int start_bitrate,
3178 int max_bitrate) {
3179 if (!send_channel) {
3180 return false;
3181 }
3182 const int channel_id = send_channel->channel_id();
3183 // Make a copy of the codec
3184 webrtc::VideoCodec target_codec = codec;
3185 target_codec.startBitrate = start_bitrate;
3186 target_codec.minBitrate = min_bitrate;
3187 target_codec.maxBitrate = max_bitrate;
3188
3189 // Set the default number of temporal layers for VP8.
3190 if (webrtc::kVideoCodecVP8 == codec.codecType) {
3191 target_codec.codecSpecific.VP8.numberOfTemporalLayers =
3192 kDefaultNumberOfTemporalLayers;
3193
3194 // Turn off the VP8 error resilience
3195 target_codec.codecSpecific.VP8.resilience = webrtc::kResilienceOff;
3196
3197 bool enable_denoising =
3198 options_.video_noise_reduction.GetWithDefaultIfUnset(false);
3199 target_codec.codecSpecific.VP8.denoisingOn = enable_denoising;
3200 }
3201
3202 // Register external encoder if codec type is supported by encoder factory.
3203 if (engine()->IsExternalEncoderCodecType(codec.codecType) &&
3204 !send_channel->IsEncoderRegistered(target_codec.plType)) {
3205 webrtc::VideoEncoder* encoder =
3206 engine()->CreateExternalEncoder(codec.codecType);
3207 if (encoder) {
3208 if (engine()->vie()->ext_codec()->RegisterExternalSendCodec(
3209 channel_id, target_codec.plType, encoder, false) == 0) {
3210 send_channel->RegisterEncoder(target_codec.plType, encoder);
3211 } else {
3212 LOG_RTCERR2(RegisterExternalSendCodec, channel_id, target_codec.plName);
3213 engine()->DestroyExternalEncoder(encoder);
3214 }
3215 }
3216 }
3217
3218 // Resolution and framerate may vary for different send channels.
3219 const VideoFormat& video_format = send_channel->video_format();
3220 UpdateVideoCodec(video_format, &target_codec);
3221
3222 if (target_codec.width == 0 && target_codec.height == 0) {
3223 const uint32 ssrc = send_channel->stream_params()->first_ssrc();
3224 LOG(LS_INFO) << "0x0 resolution selected. Captured frames will be dropped "
3225 << "for ssrc: " << ssrc << ".";
3226 } else {
3227 MaybeChangeStartBitrate(channel_id, &target_codec);
3228 if (0 != engine()->vie()->codec()->SetSendCodec(channel_id, target_codec)) {
3229 LOG_RTCERR2(SetSendCodec, channel_id, target_codec.plName);
3230 return false;
3231 }
3232
3233 }
3234 send_channel->set_interval(
3235 cricket::VideoFormat::FpsToInterval(target_codec.maxFramerate));
3236 return true;
3237}
3238
3239
3240static std::string ToString(webrtc::VideoCodecComplexity complexity) {
3241 switch (complexity) {
3242 case webrtc::kComplexityNormal:
3243 return "normal";
3244 case webrtc::kComplexityHigh:
3245 return "high";
3246 case webrtc::kComplexityHigher:
3247 return "higher";
3248 case webrtc::kComplexityMax:
3249 return "max";
3250 default:
3251 return "unknown";
3252 }
3253}
3254
3255static std::string ToString(webrtc::VP8ResilienceMode resilience) {
3256 switch (resilience) {
3257 case webrtc::kResilienceOff:
3258 return "off";
3259 case webrtc::kResilientStream:
3260 return "stream";
3261 case webrtc::kResilientFrames:
3262 return "frames";
3263 default:
3264 return "unknown";
3265 }
3266}
3267
3268void WebRtcVideoMediaChannel::LogSendCodecChange(const std::string& reason) {
3269 webrtc::VideoCodec vie_codec;
3270 if (engine()->vie()->codec()->GetSendCodec(vie_channel_, vie_codec) != 0) {
3271 LOG_RTCERR1(GetSendCodec, vie_channel_);
3272 return;
3273 }
3274
3275 LOG(LS_INFO) << reason << " : selected video codec "
3276 << vie_codec.plName << "/"
3277 << vie_codec.width << "x" << vie_codec.height << "x"
3278 << static_cast<int>(vie_codec.maxFramerate) << "fps"
3279 << "@" << vie_codec.maxBitrate << "kbps"
3280 << " (min=" << vie_codec.minBitrate << "kbps,"
3281 << " start=" << vie_codec.startBitrate << "kbps)";
3282 LOG(LS_INFO) << "Video max quantization: " << vie_codec.qpMax;
3283 if (webrtc::kVideoCodecVP8 == vie_codec.codecType) {
3284 LOG(LS_INFO) << "VP8 number of temporal layers: "
3285 << static_cast<int>(
3286 vie_codec.codecSpecific.VP8.numberOfTemporalLayers);
3287 LOG(LS_INFO) << "VP8 options : "
3288 << "picture loss indication = "
3289 << vie_codec.codecSpecific.VP8.pictureLossIndicationOn
3290 << ", feedback mode = "
3291 << vie_codec.codecSpecific.VP8.feedbackModeOn
3292 << ", complexity = "
3293 << ToString(vie_codec.codecSpecific.VP8.complexity)
3294 << ", resilience = "
3295 << ToString(vie_codec.codecSpecific.VP8.resilience)
3296 << ", denoising = "
3297 << vie_codec.codecSpecific.VP8.denoisingOn
3298 << ", error concealment = "
3299 << vie_codec.codecSpecific.VP8.errorConcealmentOn
3300 << ", automatic resize = "
3301 << vie_codec.codecSpecific.VP8.automaticResizeOn
3302 << ", frame dropping = "
3303 << vie_codec.codecSpecific.VP8.frameDroppingOn
3304 << ", key frame interval = "
3305 << vie_codec.codecSpecific.VP8.keyFrameInterval;
3306 }
3307
3308}
3309
3310bool WebRtcVideoMediaChannel::SetReceiveCodecs(
3311 WebRtcVideoChannelRecvInfo* info) {
3312 int red_type = -1;
3313 int fec_type = -1;
3314 int channel_id = info->channel_id();
3315 for (std::vector<webrtc::VideoCodec>::iterator it = receive_codecs_.begin();
3316 it != receive_codecs_.end(); ++it) {
3317 if (it->codecType == webrtc::kVideoCodecRED) {
3318 red_type = it->plType;
3319 } else if (it->codecType == webrtc::kVideoCodecULPFEC) {
3320 fec_type = it->plType;
3321 }
3322 if (engine()->vie()->codec()->SetReceiveCodec(channel_id, *it) != 0) {
3323 LOG_RTCERR2(SetReceiveCodec, channel_id, it->plName);
3324 return false;
3325 }
3326 if (!info->IsDecoderRegistered(it->plType) &&
3327 it->codecType != webrtc::kVideoCodecRED &&
3328 it->codecType != webrtc::kVideoCodecULPFEC) {
3329 webrtc::VideoDecoder* decoder =
3330 engine()->CreateExternalDecoder(it->codecType);
3331 if (decoder) {
3332 if (engine()->vie()->ext_codec()->RegisterExternalReceiveCodec(
3333 channel_id, it->plType, decoder) == 0) {
3334 info->RegisterDecoder(it->plType, decoder);
3335 } else {
3336 LOG_RTCERR2(RegisterExternalReceiveCodec, channel_id, it->plName);
3337 engine()->DestroyExternalDecoder(decoder);
3338 }
3339 }
3340 }
3341 }
3342
3343 // Start receiving packets if at least one receive codec has been set.
3344 if (!receive_codecs_.empty()) {
3345 if (engine()->vie()->base()->StartReceive(channel_id) != 0) {
3346 LOG_RTCERR1(StartReceive, channel_id);
3347 return false;
3348 }
3349 }
3350 return true;
3351}
3352
3353int WebRtcVideoMediaChannel::GetRecvChannelNum(uint32 ssrc) {
3354 if (ssrc == first_receive_ssrc_) {
3355 return vie_channel_;
3356 }
3357 RecvChannelMap::iterator it = recv_channels_.find(ssrc);
3358 return (it != recv_channels_.end()) ? it->second->channel_id() : -1;
3359}
3360
3361// If the new frame size is different from the send codec size we set on vie,
3362// we need to reset the send codec on vie.
3363// The new send codec size should not exceed send_codec_ which is controlled
3364// only by the 'jec' logic.
3365bool WebRtcVideoMediaChannel::MaybeResetVieSendCodec(
3366 WebRtcVideoChannelSendInfo* send_channel,
3367 int new_width,
3368 int new_height,
3369 bool is_screencast,
3370 bool* reset) {
3371 if (reset) {
3372 *reset = false;
3373 }
3374 ASSERT(send_codec_.get() != NULL);
3375
3376 webrtc::VideoCodec target_codec = *send_codec_.get();
3377 const VideoFormat& video_format = send_channel->video_format();
3378 UpdateVideoCodec(video_format, &target_codec);
3379
3380 // Vie send codec size should not exceed target_codec.
3381 int target_width = new_width;
3382 int target_height = new_height;
3383 if (!is_screencast &&
3384 (new_width > target_codec.width || new_height > target_codec.height)) {
3385 target_width = target_codec.width;
3386 target_height = target_codec.height;
3387 }
3388
3389 // Get current vie codec.
3390 webrtc::VideoCodec vie_codec;
3391 const int channel_id = send_channel->channel_id();
3392 if (engine()->vie()->codec()->GetSendCodec(channel_id, vie_codec) != 0) {
3393 LOG_RTCERR1(GetSendCodec, channel_id);
3394 return false;
3395 }
3396 const int cur_width = vie_codec.width;
3397 const int cur_height = vie_codec.height;
3398
3399 // Only reset send codec when there is a size change. Additionally,
3400 // automatic resize needs to be turned off when screencasting and on when
3401 // not screencasting.
3402 // Don't allow automatic resizing for screencasting.
3403 bool automatic_resize = !is_screencast;
3404 // Turn off VP8 frame dropping when screensharing as the current model does
3405 // not work well at low fps.
3406 bool vp8_frame_dropping = !is_screencast;
3407 // Disable denoising for screencasting.
3408 bool enable_denoising =
3409 options_.video_noise_reduction.GetWithDefaultIfUnset(false);
3410 bool denoising = !is_screencast && enable_denoising;
3411 bool reset_send_codec =
3412 target_width != cur_width || target_height != cur_height ||
3413 automatic_resize != vie_codec.codecSpecific.VP8.automaticResizeOn ||
3414 denoising != vie_codec.codecSpecific.VP8.denoisingOn ||
3415 vp8_frame_dropping != vie_codec.codecSpecific.VP8.frameDroppingOn;
3416
3417 if (reset_send_codec) {
3418 // Set the new codec on vie.
3419 vie_codec.width = target_width;
3420 vie_codec.height = target_height;
3421 vie_codec.maxFramerate = target_codec.maxFramerate;
3422 vie_codec.startBitrate = target_codec.startBitrate;
3423 vie_codec.codecSpecific.VP8.automaticResizeOn = automatic_resize;
3424 vie_codec.codecSpecific.VP8.denoisingOn = denoising;
3425 vie_codec.codecSpecific.VP8.frameDroppingOn = vp8_frame_dropping;
3426 // TODO(mflodman): Remove 'is_screencast' check when screen cast settings
3427 // are treated correctly in WebRTC.
3428 if (!is_screencast)
3429 MaybeChangeStartBitrate(channel_id, &vie_codec);
3430
3431 if (engine()->vie()->codec()->SetSendCodec(channel_id, vie_codec) != 0) {
3432 LOG_RTCERR1(SetSendCodec, channel_id);
3433 return false;
3434 }
3435 if (reset) {
3436 *reset = true;
3437 }
3438 LogSendCodecChange("Capture size changed");
3439 }
3440
3441 return true;
3442}
3443
3444void WebRtcVideoMediaChannel::MaybeChangeStartBitrate(
3445 int channel_id, webrtc::VideoCodec* video_codec) {
3446 if (video_codec->startBitrate < video_codec->minBitrate) {
3447 video_codec->startBitrate = video_codec->minBitrate;
3448 } else if (video_codec->startBitrate > video_codec->maxBitrate) {
3449 video_codec->startBitrate = video_codec->maxBitrate;
3450 }
3451
3452 // Use a previous target bitrate, if there is one.
3453 unsigned int current_target_bitrate = 0;
3454 if (engine()->vie()->codec()->GetCodecTargetBitrate(
3455 channel_id, &current_target_bitrate) == 0) {
3456 // Convert to kbps.
3457 current_target_bitrate /= 1000;
3458 if (current_target_bitrate > video_codec->maxBitrate) {
3459 current_target_bitrate = video_codec->maxBitrate;
3460 }
3461 if (current_target_bitrate > video_codec->startBitrate) {
3462 video_codec->startBitrate = current_target_bitrate;
3463 }
3464 }
3465}
3466
3467void WebRtcVideoMediaChannel::OnMessage(talk_base::Message* msg) {
3468 FlushBlackFrameData* black_frame_data =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00003469 static_cast<FlushBlackFrameData*>(msg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003470 FlushBlackFrame(black_frame_data->ssrc, black_frame_data->timestamp);
3471 delete black_frame_data;
3472}
3473
3474int WebRtcVideoMediaChannel::SendPacket(int channel, const void* data,
3475 int len) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003476 talk_base::Buffer packet(data, len, kMaxRtpPacketLen);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003477 return MediaChannel::SendPacket(&packet) ? len : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003478}
3479
3480int WebRtcVideoMediaChannel::SendRTCPPacket(int channel,
3481 const void* data,
3482 int len) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003483 talk_base::Buffer packet(data, len, kMaxRtpPacketLen);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003484 return MediaChannel::SendRtcp(&packet) ? len : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003485}
3486
3487void WebRtcVideoMediaChannel::QueueBlackFrame(uint32 ssrc, int64 timestamp,
3488 int framerate) {
3489 if (timestamp) {
3490 FlushBlackFrameData* black_frame_data = new FlushBlackFrameData(
3491 ssrc,
3492 timestamp);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00003493 const int delay_ms = static_cast<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003494 2 * cricket::VideoFormat::FpsToInterval(framerate) *
3495 talk_base::kNumMillisecsPerSec / talk_base::kNumNanosecsPerSec);
3496 worker_thread()->PostDelayed(delay_ms, this, 0, black_frame_data);
3497 }
3498}
3499
3500void WebRtcVideoMediaChannel::FlushBlackFrame(uint32 ssrc, int64 timestamp) {
3501 WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(ssrc);
3502 if (!send_channel) {
3503 return;
3504 }
3505 talk_base::scoped_ptr<const VideoFrame> black_frame_ptr;
3506
3507 const WebRtcLocalStreamInfo* channel_stream_info =
3508 send_channel->local_stream_info();
3509 int64 last_frame_time_stamp = channel_stream_info->time_stamp();
3510 if (last_frame_time_stamp == timestamp) {
3511 size_t last_frame_width = 0;
3512 size_t last_frame_height = 0;
3513 int64 last_frame_elapsed_time = 0;
3514 channel_stream_info->GetLastFrameInfo(&last_frame_width, &last_frame_height,
3515 &last_frame_elapsed_time);
3516 if (!last_frame_width || !last_frame_height) {
3517 return;
3518 }
3519 WebRtcVideoFrame black_frame;
3520 // Black frame is not screencast.
3521 const bool screencasting = false;
3522 const int64 timestamp_delta = send_channel->interval();
3523 if (!black_frame.InitToBlack(send_codec_->width, send_codec_->height, 1, 1,
3524 last_frame_elapsed_time + timestamp_delta,
3525 last_frame_time_stamp + timestamp_delta) ||
3526 !SendFrame(send_channel, &black_frame, screencasting)) {
3527 LOG(LS_ERROR) << "Failed to send black frame.";
3528 }
3529 }
3530}
3531
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00003532void WebRtcVideoMediaChannel::OnCpuAdaptationUnable() {
3533 // ssrc is hardcoded to 0. This message is based on a system wide issue,
3534 // so finding which ssrc caused it doesn't matter.
3535 SignalMediaError(0, VideoMediaChannel::ERROR_REC_CPU_MAX_CANT_DOWNGRADE);
3536}
3537
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003538void WebRtcVideoMediaChannel::SetNetworkTransmissionState(
3539 bool is_transmitting) {
3540 LOG(LS_INFO) << "SetNetworkTransmissionState: " << is_transmitting;
3541 for (SendChannelMap::iterator iter = send_channels_.begin();
3542 iter != send_channels_.end(); ++iter) {
3543 WebRtcVideoChannelSendInfo* send_channel = iter->second;
3544 int channel_id = send_channel->channel_id();
3545 engine_->vie()->network()->SetNetworkTransmissionState(channel_id,
3546 is_transmitting);
3547 }
3548}
3549
3550bool WebRtcVideoMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
3551 int channel_id, const RtpHeaderExtension* extension) {
3552 bool enable = false;
3553 int id = 0;
3554 if (extension) {
3555 enable = true;
3556 id = extension->id;
3557 }
3558 if ((engine_->vie()->rtp()->*setter)(channel_id, enable, id) != 0) {
3559 LOG_RTCERR4(*setter, extension->uri, channel_id, enable, id);
3560 return false;
3561 }
3562 return true;
3563}
3564
3565bool WebRtcVideoMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
3566 int channel_id, const std::vector<RtpHeaderExtension>& extensions,
3567 const char header_extension_uri[]) {
3568 const RtpHeaderExtension* extension = FindHeaderExtension(extensions,
3569 header_extension_uri);
3570 return SetHeaderExtension(setter, channel_id, extension);
3571}
3572} // namespace cricket
3573
3574#endif // HAVE_WEBRTC_VIDEO