webrtcvideoengine2.cc revision 3bf3d238c8c4578e444e5a601684db68c79a29ca
1b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org/*
2b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * libjingle
3b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * Copyright 2014 Google Inc.
4b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
5b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * Redistribution and use in source and binary forms, with or without
6b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * modification, are permitted provided that the following conditions are met:
7b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
8b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
9b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     this list of conditions and the following disclaimer.
10b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
11b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     this list of conditions and the following disclaimer in the documentation
12b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     and/or other materials provided with the distribution.
13b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *  3. The name of the author may not be used to endorse or promote products
14b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     derived from this software without specific prior written permission.
15b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
16b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org */
27b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
28b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#ifdef HAVE_WEBRTC_VIDEO
29b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvideoengine2.h"
30b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
313c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org#include <set>
32b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include <string>
33b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
34b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "libyuv/convert_from.h"
35b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/base/videocapturer.h"
36b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/base/videorenderer.h"
37df9bbbee56f4d9ecef93b3c46964b6f29803f81bbuildbot@webrtc.org#include "talk/media/webrtc/constants.h"
38b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvideocapturer.h"
39b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvideoframe.h"
40b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvoiceengine.h"
41a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/buffer.h"
42a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/logging.h"
43a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/stringutils.h"
44b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "webrtc/call.h"
45776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org#include "webrtc/video_decoder.h"
46ab990ae43a2b84b103cb3c50bc38502375c13e68pbos@webrtc.org#include "webrtc/video_encoder.h"
47b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
48b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#define UNIMPLEMENTED                                                 \
49b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_ERROR) << "Call to unimplemented function " << __FUNCTION__; \
50b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  ASSERT(false)
51b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
52b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgnamespace cricket {
537fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgnamespace {
547fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
557fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic bool CodecNameMatches(const std::string& name1,
567fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                             const std::string& name2) {
577fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return _stricmp(name1.c_str(), name2.c_str()) == 0;
587fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
597fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
607fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org// True if codec is supported by a software implementation that's always
617fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org// available.
627fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic bool CodecIsInternallySupported(const std::string& codec_name) {
637fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return CodecNameMatches(codec_name, kVp8CodecName);
647fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
657fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
667fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {
677fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  std::stringstream out;
687fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  out << '{';
697fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
707fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    out << codecs[i].ToString();
717fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (i != codecs.size() - 1) {
727fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      out << ", ";
737fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
747fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
757fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  out << '}';
767fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return out.str();
777fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
787fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
797fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) {
807fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  bool has_video = false;
817fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
827fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (!codecs[i].ValidateCodecFormat()) {
837fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      return false;
847fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
857fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (codecs[i].GetCodecType() == VideoCodec::CODEC_VIDEO) {
867fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      has_video = true;
877fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
887fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
897fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (!has_video) {
907fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    LOG(LS_ERROR) << "Setting codecs without a video codec is invalid: "
917fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                  << CodecVectorToString(codecs);
927fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return false;
937fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
947fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return true;
957fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
967fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
977fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic std::string RtpExtensionsToString(
987fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
997fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  std::stringstream out;
1007fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  out << '{';
1017fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
1027fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    out << "{" << extensions[i].uri << ": " << extensions[i].id << "}";
1037fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (i != extensions.size() - 1) {
1047fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      out << ", ";
1057fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
1067fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
1077fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  out << '}';
1087fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return out.str();
1097fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
1107fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
1117fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}  // namespace
112b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
113b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// This constant is really an on/off, lower-level configurable NACK history
114b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// duration hasn't been implemented.
115b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kNackHistoryMs = 1000;
116b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
117933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.orgstatic const int kDefaultQpMax = 56;
118933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.org
119b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kDefaultRtcpReceiverReportSsrc = 1;
120b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1217fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org// External video encoders are given payloads 120-127. This also means that we
1227fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org// only support up to 8 external payload types.
1237fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic const int kExternalVideoPayloadTypeBase = 120;
1247fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org#ifndef NDEBUG
1257fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic const size_t kMaxExternalVideoCodecs = 8;
1267fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org#endif
1277fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
128b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstruct VideoCodecPref {
129b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  int payload_type;
13097fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.org  int width;
13197fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.org  int height;
132b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const char* name;
133b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  int rtx_payload_type;
13497fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.org} kDefaultVideoCodecPref = {100, 640, 400, kVp8CodecName, 96};
135b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1367fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgconst char kH264CodecName[] = "H264";
1377fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
13897fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.orgVideoCodecPref kRedPref = {116, -1, -1, kRedCodecName, -1};
13997fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.orgVideoCodecPref kUlpfecPref = {117, -1, -1, kUlpfecCodecName, -1};
140b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
141b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs,
142b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   const VideoCodec& requested_codec,
143b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   VideoCodec* matching_codec) {
144b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
145b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (requested_codec.Matches(codecs[i])) {
146b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      *matching_codec = codecs[i];
147b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
148b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
149b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
150b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
151b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
152b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
153f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.orgstatic void AddDefaultFeedbackParams(VideoCodec* codec) {
154f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  const FeedbackParam kFir(kRtcpFbParamCcm, kRtcpFbCcmParamFir);
155f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  codec->AddFeedbackParam(kFir);
156f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  const FeedbackParam kNack(kRtcpFbParamNack, kParamValueEmpty);
157f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  codec->AddFeedbackParam(kNack);
158f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  const FeedbackParam kPli(kRtcpFbParamNack, kRtcpFbNackParamPli);
159f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  codec->AddFeedbackParam(kPli);
160f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  const FeedbackParam kRemb(kRtcpFbParamRemb, kParamValueEmpty);
161f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  codec->AddFeedbackParam(kRemb);
162f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org}
163f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org
164f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.orgstatic bool IsNackEnabled(const VideoCodec& codec) {
165f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  return codec.HasFeedbackParam(
166f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org      FeedbackParam(kRtcpFbParamNack, kParamValueEmpty));
167f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org}
168f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org
169257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.orgstatic bool IsRembEnabled(const VideoCodec& codec) {
170257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org  return codec.HasFeedbackParam(
171257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org      FeedbackParam(kRtcpFbParamRemb, kParamValueEmpty));
172257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org}
173257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org
174b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic VideoCodec DefaultVideoCodec() {
175b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodec default_codec(kDefaultVideoCodecPref.payload_type,
176b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           kDefaultVideoCodecPref.name,
17797fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.org                           kDefaultVideoCodecPref.width,
17897fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.org                           kDefaultVideoCodecPref.height,
179b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           kDefaultFramerate,
180b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           0);
181f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  AddDefaultFeedbackParams(&default_codec);
182b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return default_codec;
183b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
184b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
185b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic VideoCodec DefaultRedCodec() {
186b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return VideoCodec(kRedPref.payload_type, kRedPref.name, 0, 0, 0, 0);
187b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
188b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
189b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic VideoCodec DefaultUlpfecCodec() {
190b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return VideoCodec(kUlpfecPref.payload_type, kUlpfecPref.name, 0, 0, 0, 0);
191b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
192b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
193b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic std::vector<VideoCodec> DefaultVideoCodecs() {
194b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<VideoCodec> codecs;
195b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  codecs.push_back(DefaultVideoCodec());
196b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  codecs.push_back(DefaultRedCodec());
197b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  codecs.push_back(DefaultUlpfecCodec());
198b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (kDefaultVideoCodecPref.rtx_payload_type != -1) {
199b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codecs.push_back(
200b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        VideoCodec::CreateRtxCodec(kDefaultVideoCodecPref.rtx_payload_type,
201b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   kDefaultVideoCodecPref.payload_type));
202b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
203b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return codecs;
204b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
205b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2063c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.orgstatic bool ValidateRtpHeaderExtensionIds(
2073c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
2083c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  std::set<int> extensions_used;
2093c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
2103c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    if (extensions[i].id < 0 || extensions[i].id >= 15 ||
2113c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org        !extensions_used.insert(extensions[i].id).second) {
2123c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      LOG(LS_ERROR) << "RTP extensions are with incorrect or duplicate ids.";
2133c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      return false;
2143c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    }
2153c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  }
2163c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  return true;
2173c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org}
2183c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org
2193c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.orgstatic std::vector<webrtc::RtpExtension> FilterRtpExtensions(
2203c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
2213c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  std::vector<webrtc::RtpExtension> webrtc_extensions;
2223c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
2233c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    // Unsupported extensions will be ignored.
2243c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    if (webrtc::RtpExtension::IsSupported(extensions[i].uri)) {
2253c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      webrtc_extensions.push_back(webrtc::RtpExtension(
2263c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org          extensions[i].uri, extensions[i].id));
2273c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    } else {
2283c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      LOG(LS_WARNING) << "Unsupported RTP extension: " << extensions[i].uri;
2293c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    }
2303c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  }
2313c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  return webrtc_extensions;
2323c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org}
2333c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org
2340d523eea831e616c415c61765127ed5eb17e5f11pbos@webrtc.orgWebRtcVideoEncoderFactory2::~WebRtcVideoEncoderFactory2() {
2350d523eea831e616c415c61765127ed5eb17e5f11pbos@webrtc.org}
2360d523eea831e616c415c61765127ed5eb17e5f11pbos@webrtc.org
237d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.orgstd::vector<webrtc::VideoStream> WebRtcVideoEncoderFactory2::CreateVideoStreams(
238d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoCodec& codec,
239d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoOptions& options,
240d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    size_t num_streams) {
241d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  if (num_streams != 1) {
242d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    LOG(LS_ERROR) << "Unsupported number of streams: " << num_streams;
243d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    return std::vector<webrtc::VideoStream>();
2446ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  }
245b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
246d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  webrtc::VideoStream stream;
247d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.width = codec.width;
248d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.height = codec.height;
249d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.max_framerate =
250d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org      codec.framerate != 0 ? codec.framerate : kDefaultFramerate;
251d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
252d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  int min_bitrate = kMinVideoBitrate;
253d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  codec.GetParam(kCodecParamMinBitrate, &min_bitrate);
254d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  int max_bitrate = kMaxVideoBitrate;
255d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  codec.GetParam(kCodecParamMaxBitrate, &max_bitrate);
256d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.min_bitrate_bps = min_bitrate * 1000;
257d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate * 1000;
258d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
259933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.org  int max_qp = kDefaultQpMax;
260d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
261d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.max_qp = max_qp;
262d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  std::vector<webrtc::VideoStream> streams;
263d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  streams.push_back(stream);
264d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  return streams;
265d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org}
266b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2676f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.orgvoid* WebRtcVideoEncoderFactory2::CreateVideoEncoderSettings(
2686f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    const VideoCodec& codec,
2696f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    const VideoOptions& options) {
2707fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (CodecNameMatches(codec.name, kVp8CodecName)) {
2716cd6ba8ae016200a7a13b43294b8faf5d1d4affdpbos@webrtc.org    webrtc::VideoCodecVP8* settings = new webrtc::VideoCodecVP8(
2726cd6ba8ae016200a7a13b43294b8faf5d1d4affdpbos@webrtc.org        webrtc::VideoEncoder::GetDefaultVp8Settings());
2736f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    options.video_noise_reduction.Get(&settings->denoisingOn);
2746f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    return settings;
2756f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  }
2766f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  return NULL;
2776f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org}
2786f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
2796f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.orgvoid WebRtcVideoEncoderFactory2::DestroyVideoEncoderSettings(
2806f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    const VideoCodec& codec,
2816f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    void* encoder_settings) {
2826f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  if (encoder_settings == NULL) {
2836f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    return;
2846f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  }
2857fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (CodecNameMatches(codec.name, kVp8CodecName)) {
2866f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    delete reinterpret_cast<webrtc::VideoCodecVP8*>(encoder_settings);
2876f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  }
288d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org}
289d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
290afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgDefaultUnsignalledSsrcHandler::DefaultUnsignalledSsrcHandler()
291afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    : default_recv_ssrc_(0), default_renderer_(NULL) {}
292afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
293afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgUnsignalledSsrcHandler::Action DefaultUnsignalledSsrcHandler::OnUnsignalledSsrc(
294afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    VideoMediaChannel* channel,
295afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    uint32_t ssrc) {
296afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  if (default_recv_ssrc_ != 0) {  // Already one default stream.
297afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Unknown SSRC, but default receive stream already set.";
298afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return kDropPacket;
299afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
300afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
301afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  StreamParams sp;
302afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  sp.ssrcs.push_back(ssrc);
303afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << ".";
304afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  if (!channel->AddRecvStream(sp)) {
305afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Could not create default receive stream.";
306afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
307afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
308afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  channel->SetRenderer(ssrc, default_renderer_);
309afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  default_recv_ssrc_ = ssrc;
310afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  return kDeliverPacket;
311afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
312afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
31342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.orgWebRtcCallFactory::~WebRtcCallFactory() {
31442684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org}
31542684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.orgwebrtc::Call* WebRtcCallFactory::CreateCall(
31642684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org    const webrtc::Call::Config& config) {
31742684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  return webrtc::Call::Create(config);
31842684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org}
31942684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org
320afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgVideoRenderer* DefaultUnsignalledSsrcHandler::GetDefaultRenderer() const {
321afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  return default_renderer_;
322afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
323afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
324afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgvoid DefaultUnsignalledSsrcHandler::SetDefaultRenderer(
325afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    VideoMediaChannel* channel,
326afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    VideoRenderer* renderer) {
327afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  default_renderer_ = renderer;
328afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  if (default_recv_ssrc_ != 0) {
329afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    channel->SetRenderer(default_recv_ssrc_, default_renderer_);
330afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
331afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
332afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
33397fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.orgWebRtcVideoEngine2::WebRtcVideoEngine2()
334b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org    : worker_thread_(NULL),
335b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      voice_engine_(NULL),
336992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org      default_codec_format_(kDefaultVideoCodecPref.width,
337992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                            kDefaultVideoCodecPref.height,
338992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                            FPS_TO_INTERVAL(kDefaultFramerate),
339992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                            FOURCC_ANY),
340b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      initialized_(false),
341b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      cpu_monitor_(new rtc::CpuMonitor(NULL)),
34242684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org      call_factory_(&default_call_factory_),
3430a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org      external_decoder_factory_(NULL),
3440a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org      external_encoder_factory_(NULL) {
345b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()";
3467fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  video_codecs_ = GetSupportedCodecs();
347587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  rtp_header_extensions_.push_back(
348587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org      RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
349587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org                         kRtpTimestampOffsetHeaderExtensionDefaultId));
350587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  rtp_header_extensions_.push_back(
351587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org      RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
352587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org                         kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
353b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
354b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
355b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoEngine2::~WebRtcVideoEngine2() {
356b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2";
357b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
358b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (initialized_) {
359b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    Terminate();
360b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
361b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
362b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
36342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.orgvoid WebRtcVideoEngine2::SetCallFactory(WebRtcCallFactory* call_factory) {
3647fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  assert(!initialized_);
36542684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  call_factory_ = call_factory;
36642684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org}
36742684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org
368d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgbool WebRtcVideoEngine2::Init(rtc::Thread* worker_thread) {
369b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::Init";
370b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  worker_thread_ = worker_thread;
371b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  ASSERT(worker_thread_ != NULL);
372b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
373b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  cpu_monitor_->set_thread(worker_thread_);
374b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) {
375b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Failed to start CPU monitor.";
376b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    cpu_monitor_.reset();
377b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
378b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
379b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  initialized_ = true;
380b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
381b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
382b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
383b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoEngine2::Terminate() {
384b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::Terminate";
385b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
386b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  cpu_monitor_->Stop();
387b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
388b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  initialized_ = false;
389b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
390b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
391b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgint WebRtcVideoEngine2::GetCapabilities() { return VIDEO_RECV | VIDEO_SEND; }
392b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
393b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::SetDefaultEncoderConfig(
394b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoEncoderConfig& config) {
3958fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  const VideoCodec& codec = config.max_codec;
3968fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  // TODO(pbos): Make use of external encoder factory.
3977fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (!CodecIsInternallySupported(codec.name)) {
3988fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    LOG(LS_ERROR) << "SetDefaultEncoderConfig, codec not supported:"
3998fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org                  << codec.ToString();
4008fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    return false;
4018fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  }
4028fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org
403992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org  default_codec_format_ =
404992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org      VideoFormat(codec.width,
405992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                  codec.height,
406992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                  VideoFormat::FpsToInterval(codec.framerate),
407992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                  FOURCC_ANY);
4088fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  video_codecs_.clear();
4098fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  video_codecs_.push_back(codec);
410b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
411b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
412b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
413b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgVideoEncoderConfig WebRtcVideoEngine2::GetDefaultEncoderConfig() const {
414b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return VideoEncoderConfig(DefaultVideoCodec());
415b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
416b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
417b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel(
4181ecbe45c7e4c9142896cb2810d699558518f4f28buildbot@webrtc.org    const VideoOptions& options,
419b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VoiceMediaChannel* voice_channel) {
4207fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  assert(initialized_);
421b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "CreateChannel: "
422b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (voice_channel != NULL ? "With" : "Without")
423fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org               << " voice channel. Options: " << options.ToString();
4247fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  WebRtcVideoChannel2* channel =
4257fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      new WebRtcVideoChannel2(call_factory_,
4263bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org                              voice_engine_,
4277fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                              voice_channel,
428fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org                              options,
4297fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                              external_encoder_factory_,
4307fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                              external_decoder_factory_,
4317fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                              GetVideoEncoderFactory());
432b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!channel->Init()) {
433b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    delete channel;
434b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
435b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
436e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  channel->SetRecvCodecs(video_codecs_);
437b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return channel;
438b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
439b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
440b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgconst std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const {
441b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return video_codecs_;
442b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
443b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
444b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgconst std::vector<RtpHeaderExtension>&
445b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoEngine2::rtp_header_extensions() const {
446b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return rtp_header_extensions_;
447b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
448b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
449b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoEngine2::SetLogging(int min_sev, const char* filter) {
450b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Set up logging.
451b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetLogging: " << min_sev << '"' << filter << '"';
452b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // if min_sev == -1, we keep the current log level.
453b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (min_sev < 0) {
454b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    assert(min_sev == -1);
455b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
456b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
457b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
458b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
4590a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.orgvoid WebRtcVideoEngine2::SetExternalDecoderFactory(
4600a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org    WebRtcVideoDecoderFactory* decoder_factory) {
4617fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  assert(!initialized_);
4620a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  external_decoder_factory_ = decoder_factory;
4630a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org}
4640a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org
4650a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.orgvoid WebRtcVideoEngine2::SetExternalEncoderFactory(
4660a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org    WebRtcVideoEncoderFactory* encoder_factory) {
4677fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  assert(!initialized_);
4680a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  external_encoder_factory_ = encoder_factory;
4697fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
4707fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  video_codecs_ = GetSupportedCodecs();
4710a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org}
4720a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org
473b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::EnableTimedRender() {
474b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Figure out whether this can be removed.
475b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
476b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
477b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
478b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Checks to see whether we comprehend and could receive a particular codec
479b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) {
480b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Probe encoder factory to figure out that the codec is supported
481b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // if supported by the encoder factory. Add a corresponding test that fails
482b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // with this code (that doesn't ask the factory).
4838fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  for (size_t j = 0; j < video_codecs_.size(); ++j) {
4848fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0);
4858fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    if (codec.Matches(in)) {
4868fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org      return true;
487b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
488b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
489b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
490b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
491b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
492b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Tells whether the |requested| codec can be transmitted or not. If it can be
493b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// transmitted |out| is set with the best settings supported. Aspect ratio will
494b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// be set as close to |current|'s as possible. If not set |requested|'s
495b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// dimensions will be used for aspect ratio matching.
496b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested,
497b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                      const VideoCodec& current,
498b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                      VideoCodec* out) {
499b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(out != NULL);
500b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
501b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (requested.width != requested.height &&
502b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      (requested.height == 0 || requested.width == 0)) {
503b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // 0xn and nx0 are invalid resolutions.
504b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
505b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
506b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
507b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodec matching_codec;
508b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!FindFirstMatchingCodec(video_codecs_, requested, &matching_codec)) {
509b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Codec not supported.
510b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
511b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
512b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
513b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->id = requested.id;
514b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->name = requested.name;
515b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->preference = requested.preference;
516b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->params = requested.params;
517b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->framerate =
518d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org      rtc::_min(requested.framerate, matching_codec.framerate);
519b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->params = requested.params;
520b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->feedback_params = requested.feedback_params;
5218fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  out->width = requested.width;
5228fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  out->height = requested.height;
5238fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  if (requested.width == 0 && requested.height == 0) {
5248fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    return true;
5258fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  }
5268fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org
5278fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  while (out->width > matching_codec.width) {
5288fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    out->width /= 2;
5298fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    out->height /= 2;
5308fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  }
5318fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org
5328fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  return out->width > 0 && out->height > 0;
533b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
534b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
535b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) {
536b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (initialized_) {
537b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init";
538b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
539b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
540b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  voice_engine_ = voice_engine;
541b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
542b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
543b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
544b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Ignore spammy trace messages, mostly from the stats API when we haven't
545b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// gotten RTCP info yet from the remote side.
546b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) {
547b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  static const char* const kTracesToIgnore[] = {NULL};
548b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (const char* const* p = kTracesToIgnore; *p; ++p) {
549b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (trace.find(*p) == 0) {
550b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
551b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
552b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
553b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
554b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
555b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
556d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.orgWebRtcVideoEncoderFactory2* WebRtcVideoEngine2::GetVideoEncoderFactory() {
557d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  return &default_video_encoder_factory_;
558b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
559b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
5607fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstd::vector<VideoCodec> WebRtcVideoEngine2::GetSupportedCodecs() const {
5617fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  std::vector<VideoCodec> supported_codecs = DefaultVideoCodecs();
5627fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
5637fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (external_encoder_factory_ == NULL) {
5647fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return supported_codecs;
5657fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
5667fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
5677fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  assert(external_encoder_factory_->codecs().size() <= kMaxExternalVideoCodecs);
5687fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
5697fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      external_encoder_factory_->codecs();
5707fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
5717fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    // Don't add internally-supported codecs twice.
5727fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (CodecIsInternallySupported(codecs[i].name)) {
5737fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      continue;
5747fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
5757fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
5767fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    VideoCodec codec(kExternalVideoPayloadTypeBase + static_cast<int>(i),
5777fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].name,
5787fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].max_width,
5797fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].max_height,
5807fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].max_fps,
5817fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     0);
5827fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
5837fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    AddDefaultFeedbackParams(&codec);
5847fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    supported_codecs.push_back(codec);
5857fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
5867fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return supported_codecs;
5877fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
5887fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
5896ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org// Thin map between VideoFrame and an existing webrtc::I420VideoFrame
590b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// to avoid having to copy the rendered VideoFrame prematurely.
591b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// This implementation is only safe to use in a const context and should never
592b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// be written to.
5936ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.orgclass WebRtcVideoRenderFrame : public VideoFrame {
594b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org public:
595b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  explicit WebRtcVideoRenderFrame(const webrtc::I420VideoFrame* frame)
596b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      : frame_(frame) {}
597b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
598b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual bool InitToBlack(int w,
599b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           int h,
600b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           size_t pixel_width,
601b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           size_t pixel_height,
602b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           int64 elapsed_time,
603b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           int64 time_stamp) OVERRIDE {
604b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
605b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
606b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
607b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
608b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual bool Reset(uint32 fourcc,
609b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int w,
610b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int h,
611b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int dw,
612b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int dh,
613b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     uint8* sample,
614b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     size_t sample_size,
615b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     size_t pixel_width,
616b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     size_t pixel_height,
617b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int64 elapsed_time,
618b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int64 time_stamp,
619b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int rotation) OVERRIDE {
620b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
621b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
622b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
623b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
624b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetWidth() const OVERRIDE {
625b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return static_cast<size_t>(frame_->width());
626b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
627b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetHeight() const OVERRIDE {
628b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return static_cast<size_t>(frame_->height());
629b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
630b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
631b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual const uint8* GetYPlane() const OVERRIDE {
632b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->buffer(webrtc::kYPlane);
633b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
634b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual const uint8* GetUPlane() const OVERRIDE {
635b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->buffer(webrtc::kUPlane);
636b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
637b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual const uint8* GetVPlane() const OVERRIDE {
638b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->buffer(webrtc::kVPlane);
639b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
640b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
641b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual uint8* GetYPlane() OVERRIDE {
642b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
643b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
644b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
645b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual uint8* GetUPlane() OVERRIDE {
646b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
647b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
648b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
649b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual uint8* GetVPlane() OVERRIDE {
650b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
651b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
652b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
653b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
654b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int32 GetYPitch() const OVERRIDE {
655b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->stride(webrtc::kYPlane);
656b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
657b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int32 GetUPitch() const OVERRIDE {
658b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->stride(webrtc::kUPlane);
659b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
660b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int32 GetVPitch() const OVERRIDE {
661b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->stride(webrtc::kVPlane);
662b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
663b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
664b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual void* GetNativeHandle() const OVERRIDE { return NULL; }
665b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
666b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetPixelWidth() const OVERRIDE { return 1; }
667b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetPixelHeight() const OVERRIDE { return 1; }
668b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
669b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int64 GetElapsedTime() const OVERRIDE {
670b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Convert millisecond render time to ns timestamp.
671d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    return frame_->render_time_ms() * rtc::kNumNanosecsPerMillisec;
672b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
673b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int64 GetTimeStamp() const OVERRIDE {
674b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Convert 90K rtp timestamp to ns timestamp.
675d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    return (frame_->timestamp() / 90) * rtc::kNumNanosecsPerMillisec;
676b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
677b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual void SetElapsedTime(int64 elapsed_time) OVERRIDE { UNIMPLEMENTED; }
678b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual void SetTimeStamp(int64 time_stamp) OVERRIDE { UNIMPLEMENTED; }
679b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
680b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int GetRotation() const OVERRIDE {
681b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
682b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return ROTATION_0;
683b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
684b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
685b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual VideoFrame* Copy() const OVERRIDE {
686b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
687b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
688b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
689b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
690b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual bool MakeExclusive() OVERRIDE {
691b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
692b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
693b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
694b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
695b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t CopyToBuffer(uint8* buffer, size_t size) const {
696b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
697b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return 0;
698b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
699b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
700b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(fbarchard): Refactor into base class and share with LMI
701b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t ConvertToRgbBuffer(uint32 to_fourcc,
702b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    uint8* buffer,
703b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    size_t size,
704b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    int stride_rgb) const OVERRIDE {
705b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    size_t width = GetWidth();
706b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    size_t height = GetHeight();
707b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    size_t needed = (stride_rgb >= 0 ? stride_rgb : -stride_rgb) * height;
708b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (size < needed) {
709b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_WARNING) << "RGB buffer is not large enough";
710b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return needed;
711b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
712b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
713b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (libyuv::ConvertFromI420(GetYPlane(),
714b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetYPitch(),
715b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetUPlane(),
716b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetUPitch(),
717b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetVPlane(),
718b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetVPitch(),
719b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                buffer,
720b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                stride_rgb,
721b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                static_cast<int>(width),
722b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                static_cast<int>(height),
723b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                to_fourcc)) {
724b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "RGB type not supported: " << to_fourcc;
725b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return 0;  // 0 indicates error
726b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
727b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return needed;
728b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
729b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
730b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org protected:
731b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual VideoFrame* CreateEmptyFrame(int w,
732b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       int h,
733b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       size_t pixel_width,
734b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       size_t pixel_height,
735b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       int64 elapsed_time,
736b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       int64 time_stamp) const OVERRIDE {
737b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoFrame* frame = new WebRtcVideoFrame();
738b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    frame->InitToBlack(
739b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        w, h, pixel_width, pixel_height, elapsed_time, time_stamp);
740b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame;
741b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
742b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
743b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org private:
744b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const webrtc::I420VideoFrame* const frame_;
745b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org};
746b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
747b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoChannel2(
74842684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org    WebRtcCallFactory* call_factory,
7493bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org    WebRtcVoiceEngine* voice_engine,
750b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VoiceMediaChannel* voice_channel,
751fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org    const VideoOptions& options,
7527fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    WebRtcVideoEncoderFactory* external_encoder_factory,
7537fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    WebRtcVideoDecoderFactory* external_decoder_factory,
754b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoEncoderFactory2* encoder_factory)
755b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org    : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
7563bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org      voice_channel_(voice_channel),
7577fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      external_encoder_factory_(external_encoder_factory),
7587fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      external_decoder_factory_(external_decoder_factory),
759b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      encoder_factory_(encoder_factory) {
760fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org  SetDefaultOptions();
761fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org  options_.SetAll(options);
762b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::Call::Config config(this);
76342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  config.overuse_callback = this;
7643bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org  if (voice_engine != NULL) {
7653bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org    config.voice_engine = voice_engine->voe()->engine();
7663bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org  }
767fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org
768fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org  // Set start bitrate for the call. A default is provided by SetDefaultOptions.
769fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org  int start_bitrate_kbps;
770fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org  options_.video_start_bitrate.Get(&start_bitrate_kbps);
771fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org  config.stream_start_bitrate_bps = start_bitrate_kbps * 1000;
772fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org
77342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  call_.reset(call_factory->CreateCall(config));
774b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
775b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc;
776b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = false;
777b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  default_send_ssrc_ = 0;
7786f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org}
7796f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
7806f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.orgvoid WebRtcVideoChannel2::SetDefaultOptions() {
78142684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  options_.cpu_overuse_detection.Set(false);
7825ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org  options_.suspend_below_min_bitrate.Set(false);
78342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  options_.use_payload_padding.Set(false);
78442684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  options_.video_noise_reduction.Set(true);
785fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org  options_.video_start_bitrate.Set(
786fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org      webrtc::Call::Config::kDefaultStartBitrateBps / 1000);
787efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  options_.screencast_min_bitrate.Set(0);
788b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
789b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
790b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::~WebRtcVideoChannel2() {
791b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
792b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
793b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
794b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
795b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    delete it->second;
796b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
797b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
798d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
799b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           receive_streams_.begin();
800b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != receive_streams_.end();
801b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
802b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    delete it->second;
803b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
804b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
805b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
806b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::Init() { return true; }
807b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
808b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
809b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs);
810b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
811b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
812b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
813b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
814b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs);
815b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (mapped_codecs.empty()) {
816b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "SetRecvCodecs called without video codec payloads.";
817b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
818b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
819b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
820b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Add a decoder factory which controls supported codecs.
821b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Blocked on webrtc:2854.
822b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
8237fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (!CodecNameMatches(mapped_codecs[i].codec.name, kVp8CodecName)) {
824b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "SetRecvCodecs called with unsupported codec: '"
825b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << mapped_codecs[i].codec.name << "'";
826b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return false;
827b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
828b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
829b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
830b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  recv_codecs_ = mapped_codecs;
831d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
832575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
833d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
834d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           receive_streams_.begin();
835d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       it != receive_streams_.end();
836d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       ++it) {
837d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRecvCodecs(recv_codecs_);
838d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
839d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
840b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
841b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
842b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
843b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
844b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetSendCodecs: " << CodecVectorToString(codecs);
845b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
846b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
847b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
848b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
849b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const std::vector<VideoCodecSettings> supported_codecs =
850b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      FilterSupportedCodecs(MapCodecs(codecs));
851b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
852b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (supported_codecs.empty()) {
853b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No video codecs supported by encoder factory.";
854b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
855b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
856b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
857b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  send_codec_.Set(supported_codecs.front());
858b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString();
859b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
860575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
861d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
862d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           send_streams_.begin();
863d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       it != send_streams_.end();
864d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       ++it) {
865d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    assert(it->second != NULL);
866d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetCodec(supported_codecs.front());
867d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
868b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
869b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
870b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
871b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
872b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) {
873b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodecSettings codec_settings;
874b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!send_codec_.Get(&codec_settings)) {
875b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "GetSendCodec: No send codec set.";
876b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
877b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
878b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  *codec = codec_settings.codec;
879b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
880b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
881b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
882b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendStreamFormat(uint32 ssrc,
883b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                              const VideoFormat& format) {
884b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetSendStreamFormat:" << ssrc << " -> "
885b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << format.ToString();
886575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
887b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
888b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
889b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
890b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return send_streams_[ssrc]->SetVideoFormat(format);
891b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
892b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
893b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRender(bool render) {
894b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement. Or refactor away as it shouldn't be needed.
895b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetRender: " << (render ? "true" : "false");
896b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
897b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
898b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
899b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSend(bool send) {
900b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false");
901b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send && !send_codec_.IsSet()) {
902b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "SetSend(true) called before setting codec.";
903b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
904b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
905b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send) {
906b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    StartAllSendStreams();
907b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
908b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    StopAllSendStreams();
909b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
910b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = send;
911b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
912b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
913b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
914b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
915b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
916b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sp.ssrcs.empty()) {
917b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No SSRCs in stream parameters.";
918b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
919b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
920b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
921b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
922b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);
923b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Make sure none of sp.ssrcs are used, not just the identifying
924b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // ssrc.
925575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
926b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) != send_streams_.end()) {
927b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Send stream with ssrc '" << ssrc << "' already exists.";
928b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
929b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
930b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
9315301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  std::vector<uint32> primary_ssrcs;
9325301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetPrimarySsrcs(&primary_ssrcs);
9335301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  std::vector<uint32> rtx_ssrcs;
9345301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetFidSsrcs(primary_ssrcs, &rtx_ssrcs);
9355301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) {
9365301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    LOG(LS_ERROR)
9375301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org        << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): "
9385301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org        << sp.ToString();
939b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
940b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
941b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
942b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  WebRtcVideoSendStream* stream =
9436ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      new WebRtcVideoSendStream(call_.get(),
9447fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                                external_encoder_factory_,
9455301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                                encoder_factory_,
9466ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org                                options_,
9475301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                                send_codec_,
9485301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                                sp,
9495301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                                send_rtp_extensions_);
9505301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
951b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  send_streams_[ssrc] = stream;
952b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
953b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) {
954b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    rtcp_receiver_report_ssrc_ = ssrc;
955b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
956b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (default_send_ssrc_ == 0) {
957b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_send_ssrc_ = ssrc;
958b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
959b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sending_) {
960b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    stream->Start();
961b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
962b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
963b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
964b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
965b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
966b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RemoveSendStream(uint32 ssrc) {
967b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
968b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
969b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
970b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (default_send_ssrc_ == 0) {
971b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "No default send stream active.";
972b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return false;
973b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
974b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
975b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "Removing default stream: " << default_send_ssrc_;
976b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    ssrc = default_send_ssrc_;
977b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
978b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
979575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  WebRtcVideoSendStream* removed_stream;
980575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  {
981575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    rtc::CritScope stream_lock(&stream_crit_);
982575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    std::map<uint32, WebRtcVideoSendStream*>::iterator it =
983575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org        send_streams_.find(ssrc);
984575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    if (it == send_streams_.end()) {
985575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org      return false;
986575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    }
987575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org
988575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    removed_stream = it->second;
989575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    send_streams_.erase(it);
990b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
991b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
992575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  delete removed_stream;
993b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
994b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == default_send_ssrc_) {
995b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_send_ssrc_ = 0;
996b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
997b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
998b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
999b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1000b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1001b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) {
1002b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
1003b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(sp.ssrcs.size() > 0);
1004b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1005b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
1006b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);  // TODO(pbos): Is this ever valid?
1007b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1008b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Check if any of the SSRCs overlap.
1009575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1010b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (receive_streams_.find(ssrc) != receive_streams_.end()) {
1011b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Receive stream for SSRC " << ssrc << "already exists.";
1012b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1013b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1014b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1015bd249bc711b3c9efd142eb8de3df489282fe693epbos@webrtc.org  webrtc::VideoReceiveStream::Config config;
1016d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  ConfigureReceiverRtp(&config, sp);
10173bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org
10183bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org  // Set up A/V sync if there is a VoiceChannel.
10193bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org  // TODO(pbos): The A/V is synched by the receiving channel. So we need to know
10203bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org  // the SSRC of the remote audio channel in order to sync the correct webrtc
10213bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org  // VoiceEngine channel. For now sync the first channel in non-conference to
10223bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org  // match existing behavior in WebRtcVideoEngine.
10233bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org  if (voice_channel_ != NULL && receive_streams_.empty() &&
10243bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org      !options_.conference_mode.GetWithDefaultIfUnset(false)) {
10253bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org    config.audio_channel_id =
10263bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org        static_cast<WebRtcVoiceMediaChannel*>(voice_channel_)->voe_channel();
10273bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org  }
10283bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org
1029776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  receive_streams_[ssrc] = new WebRtcVideoReceiveStream(
1030776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org      call_.get(), external_decoder_factory_, config, recv_codecs_);
1031d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1032d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  return true;
1033d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1034d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1035d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::ConfigureReceiverRtp(
1036d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    webrtc::VideoReceiveStream::Config* config,
1037d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const StreamParams& sp) const {
1038d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
1039d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1040d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.remote_ssrc = ssrc;
1041d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.local_ssrc = rtcp_receiver_report_ssrc_;
1042b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1043d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.extensions = recv_rtp_extensions_;
1044257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org
1045b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): This protection is against setting the same local ssrc as
1046b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // remote which is not permitted by the lower-level API. RTCP requires a
1047b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // corresponding sender SSRC. Figure out what to do when we don't have
1048b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // (receive-only) or know a good local SSRC.
1049d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (config->rtp.remote_ssrc == config->rtp.local_ssrc) {
1050d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    if (config->rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) {
1051d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc;
1052b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    } else {
1053d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1;
1054b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1055b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1056b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1057d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (size_t i = 0; i < recv_codecs_.size(); ++i) {
1058d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    if (recv_codecs_[i].codec.id == kDefaultVideoCodecPref.payload_type) {
1059d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      config->rtp.fec = recv_codecs_[i].fec;
1060d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      uint32 rtx_ssrc;
1061d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      if (recv_codecs_[i].rtx_payload_type != -1 &&
1062d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org          sp.GetFidSsrc(ssrc, &rtx_ssrc)) {
1063d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org        config->rtp.rtx[kDefaultVideoCodecPref.payload_type].ssrc = rtx_ssrc;
1064d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org        config->rtp.rtx[kDefaultVideoCodecPref.payload_type].payload_type =
1065d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org            recv_codecs_[i].rtx_payload_type;
1066b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
1067d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      break;
1068b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1069b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1070b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1071b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1072b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1073b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) {
1074b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1075b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1076afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported.";
1077afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return false;
1078b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1079b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1080575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1081d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator stream =
1082b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      receive_streams_.find(ssrc);
1083b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (stream == receive_streams_.end()) {
1084b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc;
1085b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1086b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1087d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  delete stream->second;
1088b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  receive_streams_.erase(stream);
1089b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1090b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1091b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1092b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1093b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
1094b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " "
1095b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (renderer ? "(ptr)" : "NULL");
1096b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1097afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    default_unsignalled_ssrc_handler_.SetDefaultRenderer(this, renderer);
1098d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return true;
1099b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1100b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1101575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1102d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1103d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      receive_streams_.find(ssrc);
1104d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (it == receive_streams_.end()) {
1105d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return false;
1106b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1107b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1108b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  it->second->SetRenderer(renderer);
1109b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1110b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1111b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1112b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetRenderer(uint32 ssrc, VideoRenderer** renderer) {
1113b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1114afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    *renderer = default_unsignalled_ssrc_handler_.GetDefaultRenderer();
1115afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return *renderer != NULL;
1116b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1117b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1118575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1119d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1120d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      receive_streams_.find(ssrc);
1121d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (it == receive_streams_.end()) {
1122b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1123b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1124b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  *renderer = it->second->GetRenderer();
1125b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1126b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1127b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1128b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetStats(const StatsOptions& options,
1129b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   VideoMediaInfo* info) {
1130e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info->Clear();
1131e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  FillSenderStats(info);
1132e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  FillReceiverStats(info);
1133e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  FillBandwidthEstimationStats(info);
1134b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1135b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1136b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1137e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillSenderStats(VideoMediaInfo* video_media_info) {
1138575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1139e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1140e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           send_streams_.begin();
1141e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       it != send_streams_.end();
1142e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       ++it) {
1143e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    video_media_info->senders.push_back(it->second->GetVideoSenderInfo());
1144e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1145e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1146e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1147e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) {
1148575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1149e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1150e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           receive_streams_.begin();
1151e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       it != receive_streams_.end();
1152e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       ++it) {
1153e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    video_media_info->receivers.push_back(it->second->GetVideoReceiverInfo());
1154e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1155e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1156e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1157e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillBandwidthEstimationStats(
1158e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    VideoMediaInfo* video_media_info) {
1159e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  // TODO(pbos): Implement.
1160e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1161e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1162b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetCapturer(uint32 ssrc, VideoCapturer* capturer) {
1163b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> "
1164b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (capturer != NULL ? "(capturer)" : "NULL");
1165b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);
1166575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1167b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
1168b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1169b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1170b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1171b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return send_streams_[ssrc]->SetCapturer(capturer);
1172b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1173b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1174b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendIntraFrame() {
1175b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1176b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
1177b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1178b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1179b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1180b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RequestIntraFrame() {
1181b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1182b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
1183b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1184b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1185b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1186b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnPacketReceived(
1187d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::Buffer* packet,
1188d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
11894e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org  const webrtc::PacketReceiver::DeliveryStatus delivery_result =
11904e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      call_->Receiver()->DeliverPacket(
11914e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length());
11924e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org  switch (delivery_result) {
11934e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_OK:
11944e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      return;
11954e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR:
11964e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      return;
11974e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC:
11984e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      break;
1199b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1200b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1201b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 ssrc = 0;
1202b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!GetRtpSsrc(packet->data(), packet->length(), &ssrc)) {
1203b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1204b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1205b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1206afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  // TODO(pbos): Make sure that the unsignalled SSRC uses the video payload.
1207afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  // Also figure out whether RTX needs to be handled.
1208afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) {
1209afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    case UnsignalledSsrcHandler::kDropPacket:
1210afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org      return;
1211afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    case UnsignalledSsrcHandler::kDeliverPacket:
1212afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org      break;
1213afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
1214b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
12151e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org  if (call_->Receiver()->DeliverPacket(
12161e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
12171e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org      webrtc::PacketReceiver::DELIVERY_OK) {
1218afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery.";
1219b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1220b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1221b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1222b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1223b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnRtcpReceived(
1224d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::Buffer* packet,
1225d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
12261e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org  if (call_->Receiver()->DeliverPacket(
12271e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
12281e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org      webrtc::PacketReceiver::DELIVERY_OK) {
1229b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "Failed to deliver RTCP packet.";
1230b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1231b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1232b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1233b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnReadyToSend(bool ready) {
123426c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org  LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
123526c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org  call_->SignalNetworkState(ready ? webrtc::Call::kNetworkUp
123626c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org                                  : webrtc::Call::kNetworkDown);
1237b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1238b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1239b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::MuteStream(uint32 ssrc, bool mute) {
1240b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "MuteStream: " << ssrc << " -> "
1241b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << (mute ? "mute" : "unmute");
1242b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);
1243575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1244b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
1245b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1246b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1247b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1248ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org
1249ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org  send_streams_[ssrc]->MuteStream(mute);
1250ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org  return true;
1251b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1252b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1253b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
1254b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
1255587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: "
1256587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org               << RtpExtensionsToString(extensions);
12573c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  if (!ValidateRtpHeaderExtensionIds(extensions))
12583c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    return false;
1259d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
12603c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  recv_rtp_extensions_ = FilterRtpExtensions(extensions);
1261575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1262d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1263d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           receive_streams_.begin();
1264d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       it != receive_streams_.end();
1265d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       ++it) {
1266d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRtpExtensions(recv_rtp_extensions_);
1267d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1268b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1269b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1270b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1271b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
1272b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
1273587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  LOG(LS_INFO) << "SetSendRtpHeaderExtensions: "
1274587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org               << RtpExtensionsToString(extensions);
12753c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  if (!ValidateRtpHeaderExtensionIds(extensions))
12763c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    return false;
12773c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org
12783c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  send_rtp_extensions_ = FilterRtpExtensions(extensions);
1279575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1280d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1281d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           send_streams_.begin();
1282d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       it != send_streams_.end();
1283d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       ++it) {
1284d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRtpExtensions(send_rtp_extensions_);
1285d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1286b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1287b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1288b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1289b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetMaxSendBandwidth(int bps) {
1290b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1291b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetMaxSendBandwidth: " << bps;
1292b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1293b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1294b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1295b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) {
1296b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetOptions: " << options.ToString();
1297b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  options_.SetAll(options);
1298575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
12995301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
13005301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org           send_streams_.begin();
13015301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org       it != send_streams_.end();
13025301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org       ++it) {
13035301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    it->second->SetOptions(options_);
13045301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1305b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1306b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1307b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1308b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) {
1309b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  MediaChannel::SetInterface(iface);
1310b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Set the RTP recv/send buffer to a bigger size
1311b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  MediaChannel::SetOption(NetworkInterface::ST_RTP,
1312d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org                          rtc::Socket::OPT_RCVBUF,
1313b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                          kVideoRtpBufferSize);
1314b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1315ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // Speculative change to increase the outbound socket buffer size.
1316ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // In b/15152257, we are seeing a significant number of packets discarded
1317ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // due to lack of socket buffer space, although it's not yet clear what the
1318ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // ideal value should be.
1319ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  MediaChannel::SetOption(NetworkInterface::ST_RTP,
1320ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org                          rtc::Socket::OPT_SNDBUF,
1321ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org                          kVideoRtpBufferSize);
1322b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1323b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1324b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::UpdateAspectRatio(int ratio_w, int ratio_h) {
1325b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1326b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1327b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1328d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgvoid WebRtcVideoChannel2::OnMessage(rtc::Message* msg) {
1329b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Ignored.
1330b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1331b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
133242684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.orgvoid WebRtcVideoChannel2::OnLoadUpdate(Load load) {
1333575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
133442684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
133542684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org           send_streams_.begin();
133642684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org       it != send_streams_.end();
133742684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org       ++it) {
133842684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org    it->second->OnCpuResolutionRequest(load == kOveruse
133942684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org                                           ? CoordinatedVideoAdapter::DOWNGRADE
134042684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org                                           : CoordinatedVideoAdapter::UPGRADE);
134142684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  }
134242684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org}
134342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org
1344b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendRtp(const uint8_t* data, size_t len) {
1345d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
1346b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return MediaChannel::SendPacket(&packet);
1347b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1348b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1349b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendRtcp(const uint8_t* data, size_t len) {
1350d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
1351b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return MediaChannel::SendRtcp(&packet);
1352b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1353b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1354b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::StartAllSendStreams() {
1355575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1356b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1357b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
1358b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
1359b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
1360b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    it->second->Start();
1361b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1362b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1363b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1364b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::StopAllSendStreams() {
1365575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1366b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1367b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
1368b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
1369b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
1370b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    it->second->Stop();
1371b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1372b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1373b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
13746ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters::
13756ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    VideoSendStreamParameters(
13766ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const webrtc::VideoSendStream::Config& config,
13776ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const VideoOptions& options,
13785301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org        const Settable<VideoCodecSettings>& codec_settings)
13795301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    : config(config), options(options), codec_settings(codec_settings) {
13806ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org}
13816ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
1382b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
1383b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    webrtc::Call* call,
13847fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    WebRtcVideoEncoderFactory* external_encoder_factory,
13855301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    WebRtcVideoEncoderFactory2* encoder_factory,
13866ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    const VideoOptions& options,
13875301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const Settable<VideoCodecSettings>& codec_settings,
13885301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const StreamParams& sp,
13895301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const std::vector<webrtc::RtpExtension>& rtp_extensions)
1390b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    : call_(call),
13917fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      external_encoder_factory_(external_encoder_factory),
1392b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      encoder_factory_(encoder_factory),
1393b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      stream_(NULL),
1394b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      parameters_(webrtc::VideoSendStream::Config(), options, codec_settings),
13957fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      allocated_encoder_(NULL, webrtc::kVideoCodecUnknown, false),
1396b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      capturer_(NULL),
1397b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      sending_(false),
13985301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org      muted_(false) {
13995301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.max_packet_size = kVideoMtu;
14005301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
14015301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetPrimarySsrcs(&parameters_.config.rtp.ssrcs);
14025301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetFidSsrcs(parameters_.config.rtp.ssrcs,
14035301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                 &parameters_.config.rtp.rtx.ssrcs);
14045301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.c_name = sp.cname;
14055301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.extensions = rtp_extensions;
14065301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
14075301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  VideoCodecSettings params;
14085301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (codec_settings.Get(&params)) {
14095301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    SetCodec(params);
14105301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1411b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1412b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1413b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() {
1414b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  DisconnectCapturer();
14155301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (stream_ != NULL) {
14165301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    call_->DestroyVideoSendStream(stream_);
14175301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
14187fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  DestroyVideoEncoder(&allocated_encoder_);
1419b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1420b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1421b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic void SetWebRtcFrameToBlack(webrtc::I420VideoFrame* video_frame) {
1422b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(video_frame != NULL);
1423b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  memset(video_frame->buffer(webrtc::kYPlane),
1424b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         16,
1425b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         video_frame->allocated_size(webrtc::kYPlane));
1426b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  memset(video_frame->buffer(webrtc::kUPlane),
1427b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         128,
1428b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         video_frame->allocated_size(webrtc::kUPlane));
1429b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  memset(video_frame->buffer(webrtc::kVPlane),
1430b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         128,
1431b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         video_frame->allocated_size(webrtc::kVPlane));
1432b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1433b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1434b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic void CreateBlackFrame(webrtc::I420VideoFrame* video_frame,
1435b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                             int width,
1436b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                             int height) {
1437b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  video_frame->CreateEmptyFrame(
1438b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      width, height, width, (width + 1) / 2, (width + 1) / 2);
1439b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  SetWebRtcFrameToBlack(video_frame);
1440b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1441b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1442b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic void ConvertToI420VideoFrame(const VideoFrame& frame,
1443b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    webrtc::I420VideoFrame* i420_frame) {
1444b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  i420_frame->CreateFrame(
1445b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetYPitch() * frame.GetHeight()),
1446b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      frame.GetYPlane(),
1447b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetUPitch() * ((frame.GetHeight() + 1) / 2)),
1448b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      frame.GetUPlane(),
1449b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetVPitch() * ((frame.GetHeight() + 1) / 2)),
1450b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      frame.GetVPlane(),
1451b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetWidth()),
1452b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetHeight()),
1453b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetYPitch()),
1454b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetUPitch()),
1455b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetVPitch()));
1456b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1457b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1458b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
1459b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VideoCapturer* capturer,
1460b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFrame* frame) {
1461b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "InputFrame: " << frame->GetWidth() << "x"
1462b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << frame->GetHeight();
1463b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Lock before copying, can be called concurrently when swapping input source.
1464d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope frame_cs(&frame_lock_);
1465d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org  ConvertToI420VideoFrame(*frame, &video_frame_);
1466d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org
1467d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
14685301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (stream_ == NULL) {
14695301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    LOG(LS_WARNING) << "Capturer inputting frames before send codecs are "
14705301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                       "configured, dropping.";
14715301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    return;
14725301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1473b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (format_.width == 0) {  // Dropping frames.
1474b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    assert(format_.height == 0);
1475b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "VideoFormat 0x0 set, Dropping frame.";
1476b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1477b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1478d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org  if (muted_) {
1479d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org    // Create a black frame to transmit instead.
1480d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org    CreateBlackFrame(&video_frame_,
1481d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org                     static_cast<int>(frame->GetWidth()),
1482d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org                     static_cast<int>(frame->GetHeight()));
1483d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org  }
1484b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Reconfigure codec if necessary.
1485c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  SetDimensions(
1486c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org      video_frame_.width(), video_frame_.height(), capturer->IsScreencast());
1487c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org
1488b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x"
1489b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << video_frame_.height() << " -> (codec) "
1490bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org                  << parameters_.encoder_config.streams.back().width << "x"
1491bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org                  << parameters_.encoder_config.streams.back().height;
1492b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  stream_->Input()->SwapFrame(&video_frame_);
1493b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1494b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1495b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer(
1496b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VideoCapturer* capturer) {
1497b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!DisconnectCapturer() && capturer == NULL) {
1498b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1499b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1500b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1501b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  {
1502d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::CritScope cs(&lock_);
1503b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
15049359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org    if (capturer == NULL) {
15059359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org      if (stream_ != NULL) {
15069359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
15079359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        webrtc::I420VideoFrame black_frame;
15089359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org
15099359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        int width = format_.width;
15109359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        int height = format_.height;
15119359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        int half_width = (width + 1) / 2;
15129359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        black_frame.CreateEmptyFrame(
15139359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org            width, height, width, half_width, half_width);
15149359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        SetWebRtcFrameToBlack(&black_frame);
1515c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org        SetDimensions(width, height, false);
15169359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        stream_->Input()->SwapFrame(&black_frame);
15179359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org      }
1518b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1519b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      capturer_ = NULL;
1520b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
1521b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1522b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1523b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    capturer_ = capturer;
1524b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1525b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Lock cannot be held while connecting the capturer to prevent lock-order
1526b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // violations.
1527b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame);
1528b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1529b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1530b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1531b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat(
1532b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFormat& format) {
1533b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if ((format.width == 0 || format.height == 0) &&
1534b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      format.width != format.height) {
1535b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Can't set VideoFormat, width or height is zero (but not "
1536b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     "both, 0x0 drops frames).";
1537b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1538b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1539b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1540d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1541b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (format.width == 0 && format.height == 0) {
1542b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_INFO)
1543b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        << "0x0 resolution selected. Captured frames will be dropped for ssrc: "
15446ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        << parameters_.config.rtp.ssrcs[0] << ".";
1545b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
1546b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // TODO(pbos): Fix me, this only affects the last stream!
1547bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org    parameters_.encoder_config.streams.back().max_framerate =
1548b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        VideoFormat::IntervalToFps(format.interval);
1549c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    SetDimensions(format.width, format.height, false);
1550b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1551b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1552b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  format_ = format;
1553b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1554b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1555b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1556ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::MuteStream(bool mute) {
1557d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1558b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  muted_ = mute;
1559b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1560b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1561b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() {
1562963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org  cricket::VideoCapturer* capturer;
1563963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org  {
1564963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org    rtc::CritScope cs(&lock_);
1565963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org    if (capturer_ == NULL) {
1566963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org      return false;
1567963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org    }
1568963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org    capturer = capturer_;
1569963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org    capturer_ = NULL;
1570b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1571963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org  capturer->SignalVideoFrame.disconnect(this);
1572b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1573b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1574b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
15755301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions(
15765301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoOptions& options) {
1577d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
15785301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  VideoCodecSettings codec_settings;
15795301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (parameters_.codec_settings.Get(&codec_settings)) {
15805301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    SetCodecAndOptions(codec_settings, options);
15815301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  } else {
15825301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    parameters_.options = options;
15835301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
15845301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org}
15857fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
1586b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
15875301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoCodecSettings& codec_settings) {
1588d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
15895301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  SetCodecAndOptions(codec_settings, parameters_.options);
15905301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org}
15917fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
15927fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgwebrtc::VideoCodecType CodecTypeFromName(const std::string& name) {
15937fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (CodecNameMatches(name, kVp8CodecName)) {
15947fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return webrtc::kVideoCodecVP8;
15957fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  } else if (CodecNameMatches(name, kH264CodecName)) {
15967fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return webrtc::kVideoCodecH264;
15977fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
15987fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return webrtc::kVideoCodecUnknown;
15997fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
16007fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
16017fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder
16027fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder(
16037fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    const VideoCodec& codec) {
16047fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  webrtc::VideoCodecType type = CodecTypeFromName(codec.name);
16057fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
16067fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  // Do not re-create encoders of the same type.
16077fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) {
16087fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return allocated_encoder_;
16097fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
16107fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
16117fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (external_encoder_factory_ != NULL) {
16127fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    webrtc::VideoEncoder* encoder =
16137fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org        external_encoder_factory_->CreateVideoEncoder(type);
16147fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (encoder != NULL) {
16157fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      return AllocatedEncoder(encoder, type, true);
16167fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
16177fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
16187fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
16197fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (type == webrtc::kVideoCodecVP8) {
16207fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return AllocatedEncoder(
16217fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org        webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp8), type, false);
16227fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
16237fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
16247fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  // This shouldn't happen, we should not be trying to create something we don't
16257fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  // support.
16267fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  assert(false);
16277fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false);
16287fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
16297fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
16307fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder(
16317fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    AllocatedEncoder* encoder) {
16327fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (encoder->external) {
16337fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    external_encoder_factory_->DestroyVideoEncoder(encoder->encoder);
16347fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  } else {
16357fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    delete encoder->encoder;
16367fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
16377fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
16387fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
16395301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions(
16405301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoCodecSettings& codec_settings,
16415301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoOptions& options) {
16426ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  std::vector<webrtc::VideoStream> video_streams =
16436ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      encoder_factory_->CreateVideoStreams(
16445301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org          codec_settings.codec, options, parameters_.config.rtp.ssrcs.size());
16456ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  if (video_streams.empty()) {
1646b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1647b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1648bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config.streams = video_streams;
16495301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  format_ = VideoFormat(codec_settings.codec.width,
16505301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                        codec_settings.codec.height,
1651b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        VideoFormat::FpsToInterval(30),
1652b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        FOURCC_I420);
16536ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
16547fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec);
16557fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  parameters_.config.encoder_settings.encoder = new_encoder.encoder;
16565301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.encoder_settings.payload_name = codec_settings.codec.name;
16575301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.encoder_settings.payload_type = codec_settings.codec.id;
16585301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.fec = codec_settings.fec;
16595301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
16605301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  // Set RTX payload type if RTX is enabled.
16615301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (!parameters_.config.rtp.rtx.ssrcs.empty()) {
16625301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type;
1663543e589205af006f6b999a2c5df51d3fb722d925pbos@webrtc.org
1664543e589205af006f6b999a2c5df51d3fb722d925pbos@webrtc.org    options.use_payload_padding.Get(
1665543e589205af006f6b999a2c5df51d3fb722d925pbos@webrtc.org        &parameters_.config.rtp.rtx.pad_with_redundant_payloads);
16665301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
16675301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
16685301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (IsNackEnabled(codec_settings.codec)) {
16695301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    parameters_.config.rtp.nack.rtp_history_ms = kNackHistoryMs;
16705301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
16715301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
16725ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org  options.suspend_below_min_bitrate.Get(
16735ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org      &parameters_.config.suspend_below_min_bitrate);
16745ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org
16755301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.codec_settings.Set(codec_settings);
16766ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.options = options;
1677543e589205af006f6b999a2c5df51d3fb722d925pbos@webrtc.org
1678b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  RecreateWebRtcStream();
16797fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (allocated_encoder_.encoder != new_encoder.encoder) {
16807fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    DestroyVideoEncoder(&allocated_encoder_);
16817fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    allocated_encoder_ = new_encoder;
16827fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
1683b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1684b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1685d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions(
1686d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<webrtc::RtpExtension>& rtp_extensions) {
1687d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1688d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  parameters_.config.rtp.extensions = rtp_extensions;
1689d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  RecreateWebRtcStream();
1690d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1691d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1692c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(
1693c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    int width,
1694c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    int height,
1695efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    bool is_screencast) {
1696efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  if (last_dimensions_.width == width && last_dimensions_.height == height &&
1697efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org      last_dimensions_.is_screencast == is_screencast) {
1698efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    // Configured using the same parameters, do not reconfigure.
1699efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    return;
1700efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  }
1701efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org
1702efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  last_dimensions_.width = width;
1703efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  last_dimensions_.height = height;
1704efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  last_dimensions_.is_screencast = is_screencast;
1705efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org
1706bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  assert(!parameters_.encoder_config.streams.empty());
1707b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetDimensions: " << width << "x" << height;
1708c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org
1709c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  VideoCodecSettings codec_settings;
1710c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  parameters_.codec_settings.Get(&codec_settings);
1711c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  // Restrict dimensions according to codec max.
1712efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  if (!is_screencast) {
1713c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    if (codec_settings.codec.width < width)
1714c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org      width = codec_settings.codec.width;
1715c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    if (codec_settings.codec.height < height)
1716c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org      height = codec_settings.codec.height;
1717c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  }
1718c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org
1719bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  webrtc::VideoEncoderConfig encoder_config = parameters_.encoder_config;
1720bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  encoder_config.encoder_specific_settings =
1721bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
1722bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org                                                   parameters_.options);
17236f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
1724efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  if (is_screencast) {
1725efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    int screencast_min_bitrate_kbps;
1726efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    parameters_.options.screencast_min_bitrate.Get(
1727efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org        &screencast_min_bitrate_kbps);
1728efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    encoder_config.min_transmit_bitrate_bps =
1729efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org        screencast_min_bitrate_kbps * 1000;
1730efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    encoder_config.content_type = webrtc::VideoEncoderConfig::kScreenshare;
1731efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  } else {
1732efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    encoder_config.min_transmit_bitrate_bps = 0;
1733efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    encoder_config.content_type = webrtc::VideoEncoderConfig::kRealtimeVideo;
1734efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  }
1735efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org
1736cddd17c0f89cfaa9d2f21118ae90b45dae3b4aeepbos@webrtc.org  VideoCodec codec = codec_settings.codec;
1737cddd17c0f89cfaa9d2f21118ae90b45dae3b4aeepbos@webrtc.org  codec.width = width;
1738cddd17c0f89cfaa9d2f21118ae90b45dae3b4aeepbos@webrtc.org  codec.height = height;
1739cddd17c0f89cfaa9d2f21118ae90b45dae3b4aeepbos@webrtc.org
1740bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  encoder_config.streams = encoder_factory_->CreateVideoStreams(
1741bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      codec, parameters_.options, parameters_.config.rtp.ssrcs.size());
17426f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
1743bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config);
1744bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org
1745bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  encoder_factory_->DestroyVideoEncoderSettings(
1746bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      codec_settings.codec,
1747bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      encoder_config.encoder_specific_settings);
1748bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org
1749bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  encoder_config.encoder_specific_settings = NULL;
17506f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
17516f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  if (!stream_reconfigured) {
1752b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: "
1753b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << width << "x" << height;
1754b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1755b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1756cddd17c0f89cfaa9d2f21118ae90b45dae3b4aeepbos@webrtc.org
1757bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config = encoder_config;
1758b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1759b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1760b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::Start() {
1761d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
17625301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  assert(stream_ != NULL);
1763b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  stream_->Start();
1764b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = true;
1765b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1766b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1767b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::Stop() {
1768d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
17695301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (stream_ != NULL) {
17705301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    stream_->Stop();
17715301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1772b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = false;
1773b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1774b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1775e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgVideoSenderInfo
1776e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
1777e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  VideoSenderInfo info;
1778d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1779e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  for (size_t i = 0; i < parameters_.config.rtp.ssrcs.size(); ++i) {
1780e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.add_ssrc(parameters_.config.rtp.ssrcs[i]);
1781e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1782e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1783c3d2bd28a3e8badc434a5081dd36f4ac41b4e3f2pbos@webrtc.org  if (stream_ == NULL) {
1784c3d2bd28a3e8badc434a5081dd36f4ac41b4e3f2pbos@webrtc.org    return info;
1785c3d2bd28a3e8badc434a5081dd36f4ac41b4e3f2pbos@webrtc.org  }
1786c3d2bd28a3e8badc434a5081dd36f4ac41b4e3f2pbos@webrtc.org
1787e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  webrtc::VideoSendStream::Stats stats = stream_->GetStats();
1788e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_input = stats.input_frame_rate;
1789e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_sent = stats.encode_frame_rate;
1790e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1791e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  for (std::map<uint32_t, webrtc::StreamStats>::iterator it =
1792e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           stats.substreams.begin();
1793e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       it != stats.substreams.end();
1794e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       ++it) {
1795e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    // TODO(pbos): Wire up additional stats, such as padding bytes.
1796e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    webrtc::StreamStats stream_stats = it->second;
1797e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.bytes_sent += stream_stats.rtp_stats.bytes +
1798e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                       stream_stats.rtp_stats.header_bytes +
1799e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                       stream_stats.rtp_stats.padding_bytes;
1800e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.packets_sent += stream_stats.rtp_stats.packets;
1801e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.packets_lost += stream_stats.rtcp_stats.cumulative_lost;
1802e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1803e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1804e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  if (!stats.substreams.empty()) {
1805e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    // TODO(pbos): Report fraction lost per SSRC.
1806e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    webrtc::StreamStats first_stream_stats = stats.substreams.begin()->second;
1807e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.fraction_lost =
1808e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org        static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) /
1809e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org        (1 << 8);
1810e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1811e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1812e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  if (capturer_ != NULL && !capturer_->IsMuted()) {
1813e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    VideoFormat last_captured_frame_format;
1814e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    capturer_->GetStats(&info.adapt_frame_drops,
1815e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                        &info.effects_frame_drops,
1816e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                        &info.capturer_frame_time,
1817e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                        &last_captured_frame_format);
1818e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.input_frame_width = last_captured_frame_format.width;
1819e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.input_frame_height = last_captured_frame_format.height;
1820e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.send_frame_width =
1821bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org        static_cast<int>(parameters_.encoder_config.streams.front().width);
1822e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.send_frame_height =
1823bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org        static_cast<int>(parameters_.encoder_config.streams.front().height);
1824e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1825e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1826e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  // TODO(pbos): Support or remove the following stats.
1827e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.packets_cached = -1;
1828e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.rtt_ms = -1;
1829e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1830e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  return info;
1831e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1832e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
183342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::OnCpuResolutionRequest(
183442684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org    CoordinatedVideoAdapter::AdaptRequest adapt_request) {
183542684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  rtc::CritScope cs(&lock_);
183642684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  bool adapt_cpu;
183742684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  parameters_.options.cpu_overuse_detection.Get(&adapt_cpu);
183842684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  if (!adapt_cpu) {
183942684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org    return;
184042684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  }
184142684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  if (capturer_ == NULL || capturer_->video_adapter() == NULL) {
184242684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org    return;
184342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  }
184442684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org
184542684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  capturer_->video_adapter()->OnCpuResolutionRequest(adapt_request);
184642684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org}
184742684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org
1848b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
1849b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (stream_ != NULL) {
1850b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    call_->DestroyVideoSendStream(stream_);
1851b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
18526ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
18536f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  VideoCodecSettings codec_settings;
18546f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  parameters_.codec_settings.Get(&codec_settings);
1855bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config.encoder_specific_settings =
1856bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
1857bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org                                                   parameters_.options);
1858bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org
1859bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  stream_ = call_->CreateVideoSendStream(parameters_.config,
1860bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org                                         parameters_.encoder_config);
18616f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
1862bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  encoder_factory_->DestroyVideoEncoderSettings(
1863bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      codec_settings.codec,
1864bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      parameters_.encoder_config.encoder_specific_settings);
18656f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
1866bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config.encoder_specific_settings = NULL;
18676f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
1868b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sending_) {
1869b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    stream_->Start();
1870b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1871b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1872b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1873d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
1874d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    webrtc::Call* call,
1875776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    WebRtcVideoDecoderFactory* external_decoder_factory,
1876d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const webrtc::VideoReceiveStream::Config& config,
1877d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<VideoCodecSettings>& recv_codecs)
1878d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    : call_(call),
1879d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      stream_(NULL),
1880b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      config_(config),
1881776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org      external_decoder_factory_(external_decoder_factory),
1882b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      renderer_(NULL),
1883d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      last_width_(-1),
1884b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      last_height_(-1) {
1885d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.renderer = this;
1886d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // SetRecvCodecs will also reset (start) the VideoReceiveStream.
1887d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  SetRecvCodecs(recv_codecs);
1888d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1889d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1890d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() {
1891d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  call_->DestroyVideoReceiveStream(stream_);
1892776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  ClearDecoders();
1893d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1894d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1895d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs(
1896d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<VideoCodecSettings>& recv_codecs) {
1897d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // TODO(pbos): Reconfigure RTX based on incoming recv_codecs.
1898d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // TODO(pbos): Base receive codecs off recv_codecs_ and set up using a
1899d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // DecoderFactory similar to send side. Pending webrtc:2854.
1900d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // Also set up default codecs if there's nothing in recv_codecs_.
1901776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  ClearDecoders();
1902776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
1903776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  AllocatedDecoder allocated_decoder(
1904776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org      webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kVp8), false);
1905776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  allocated_decoders_.push_back(allocated_decoder);
1906776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
1907776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  webrtc::VideoReceiveStream::Decoder decoder;
1908776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  decoder.decoder = allocated_decoder.decoder;
1909776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  decoder.payload_type = kDefaultVideoCodecPref.payload_type;
1910776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  decoder.payload_name = "VP8";
1911776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
1912776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  config_.decoders.push_back(decoder);
1913d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1914d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.rtp.fec = recv_codecs.front().fec;
1915d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1916257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org  config_.rtp.nack.rtp_history_ms =
1917257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org      IsNackEnabled(recv_codecs.begin()->codec) ? kNackHistoryMs : 0;
1918257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org  config_.rtp.remb = IsRembEnabled(recv_codecs.begin()->codec);
1919257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org
1920d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  RecreateWebRtcStream();
1921d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1922d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1923d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions(
1924d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<webrtc::RtpExtension>& extensions) {
1925d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.rtp.extensions = extensions;
1926d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  RecreateWebRtcStream();
1927d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1928d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1929d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() {
1930d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (stream_ != NULL) {
1931d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    call_->DestroyVideoReceiveStream(stream_);
1932d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1933d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  stream_ = call_->CreateVideoReceiveStream(config_);
1934d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  stream_->Start();
1935d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1936d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1937776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::ClearDecoders() {
1938776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  for (size_t i = 0; i < allocated_decoders_.size(); ++i) {
1939776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    if (allocated_decoders_[i].external) {
1940776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org      external_decoder_factory_->DestroyVideoDecoder(
1941776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org          allocated_decoders_[i].decoder);
1942776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    } else {
1943776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org      delete allocated_decoders_[i].decoder;
1944776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    }
1945776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  }
1946776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  allocated_decoders_.clear();
1947776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org}
1948776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
1949d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame(
1950d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const webrtc::I420VideoFrame& frame,
1951d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    int time_to_render_ms) {
1952d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
1953d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (renderer_ == NULL) {
1954d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer.";
1955d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return;
1956d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1957d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1958d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (frame.width() != last_width_ || frame.height() != last_height_) {
1959d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    SetSize(frame.width(), frame.height());
1960d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1961d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1962d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  LOG(LS_VERBOSE) << "RenderFrame: (" << frame.width() << "x" << frame.height()
1963d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org                  << ")";
1964d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1965d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  const WebRtcVideoRenderFrame render_frame(&frame);
1966d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  renderer_->RenderFrame(&render_frame);
1967d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1968d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1969d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRenderer(
1970d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    cricket::VideoRenderer* renderer) {
1971d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
1972d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  renderer_ = renderer;
1973d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (renderer_ != NULL && last_width_ != -1) {
1974d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    SetSize(last_width_, last_height_);
1975d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1976d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1977d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1978d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgVideoRenderer* WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetRenderer() {
1979d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // TODO(pbos): Remove GetRenderer and all uses of it, it's thread-unsafe by
1980d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // design.
1981d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
1982d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  return renderer_;
1983d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1984d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1985d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width,
1986d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org                                                            int height) {
1987d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
1988d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (!renderer_->SetSize(width, height, 0)) {
1989d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    LOG(LS_ERROR) << "Could not set renderer size.";
1990d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1991d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  last_width_ = width;
1992d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  last_height_ = height;
1993d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1994d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1995e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgVideoReceiverInfo
1996e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() {
1997e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  VideoReceiverInfo info;
1998e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.add_ssrc(config_.rtp.remote_ssrc);
1999e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  webrtc::VideoReceiveStream::Stats stats = stream_->GetStats();
2000e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.bytes_rcvd = stats.rtp_stats.bytes + stats.rtp_stats.header_bytes +
2001e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                    stats.rtp_stats.padding_bytes;
2002e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.packets_rcvd = stats.rtp_stats.packets;
2003e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2004e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_rcvd = stats.network_frame_rate;
2005e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_decoded = stats.decode_frame_rate;
2006e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_output = stats.render_frame_rate;
2007e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2008d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope frame_cs(&renderer_lock_);
2009e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.frame_width = last_width_;
2010e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.frame_height = last_height_;
2011e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2012e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  // TODO(pbos): Support or remove the following stats.
2013e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.packets_concealed = -1;
2014e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2015e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  return info;
2016e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
2017e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2018b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings()
2019b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    : rtx_payload_type(-1) {}
2020b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2021b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
2022b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) {
2023b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(!codecs.empty());
2024b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2025b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<VideoCodecSettings> video_codecs;
2026b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<int, bool> payload_used;
2027e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  std::map<int, VideoCodec::CodecType> payload_codec_type;
2028b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<int, int> rtx_mapping;  // video payload type -> rtx payload type.
2029b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2030b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::FecConfig fec_settings;
2031b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2032b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
2033b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoCodec& in_codec = codecs[i];
2034b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    int payload_type = in_codec.id;
2035b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2036b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (payload_used[payload_type]) {
2037b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "Payload type already registered: "
2038b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << in_codec.ToString();
2039b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return std::vector<VideoCodecSettings>();
2040b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
2041b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    payload_used[payload_type] = true;
2042e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    payload_codec_type[payload_type] = in_codec.GetCodecType();
2043b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2044b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    switch (in_codec.GetCodecType()) {
2045b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_RED: {
2046b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        // RED payload type, should not have duplicates.
2047b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        assert(fec_settings.red_payload_type == -1);
2048b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        fec_settings.red_payload_type = in_codec.id;
2049b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
2050b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
2051b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2052b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_ULPFEC: {
2053b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        // ULPFEC payload type, should not have duplicates.
2054b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        assert(fec_settings.ulpfec_payload_type == -1);
2055b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        fec_settings.ulpfec_payload_type = in_codec.id;
2056b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
2057b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
2058b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2059b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_RTX: {
2060b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        int associated_payload_type;
2061b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        if (!in_codec.GetParam(kCodecParamAssociatedPayloadType,
2062b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                               &associated_payload_type)) {
2063b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          LOG(LS_ERROR) << "RTX codec without associated payload type: "
2064b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        << in_codec.ToString();
2065b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          return std::vector<VideoCodecSettings>();
2066b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        }
2067b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        rtx_mapping[associated_payload_type] = in_codec.id;
2068b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
2069b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
2070b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2071b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_VIDEO:
2072b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        break;
2073b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
2074b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2075b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs.push_back(VideoCodecSettings());
2076b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs.back().codec = in_codec;
2077b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
2078b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2079b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // One of these codecs should have been a video codec. Only having FEC
2080b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // parameters into this code is a logic error.
2081b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(!video_codecs.empty());
2082b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2083e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  for (std::map<int, int>::const_iterator it = rtx_mapping.begin();
2084e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org       it != rtx_mapping.end();
2085e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org       ++it) {
2086e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    if (!payload_used[it->first]) {
2087e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      LOG(LS_ERROR) << "RTX mapped to payload not in codec list.";
2088e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      return std::vector<VideoCodecSettings>();
2089e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    }
2090e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO) {
2091e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      LOG(LS_ERROR) << "RTX not mapped to regular video codec.";
2092e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      return std::vector<VideoCodecSettings>();
2093e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    }
2094e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  }
2095e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org
2096b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Write tests that figure out that I have not verified that RTX
2097b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // codecs aren't mapped to bogus payloads.
2098b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < video_codecs.size(); ++i) {
2099b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs[i].fec = fec_settings;
2100b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (rtx_mapping[video_codecs[i].codec.id] != 0) {
2101b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id];
2102b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
2103b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
2104b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2105b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return video_codecs;
2106b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
2107b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2108b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
2109b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::FilterSupportedCodecs(
2110b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs) {
2111b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<VideoCodecSettings> supported_codecs;
2112b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
21137fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    const VideoCodecSettings& codec = mapped_codecs[i];
21147fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (CodecIsInternallySupported(codec.codec.name)) {
21157fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      supported_codecs.push_back(codec);
21167fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
21177fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
21187fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (external_encoder_factory_ == NULL) {
21197fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      continue;
21207fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
21217fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    const std::vector<WebRtcVideoEncoderFactory::VideoCodec> external_codecs =
21227fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org        external_encoder_factory_->codecs();
21237fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    for (size_t c = 0; c < external_codecs.size(); ++c) {
21247fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      if (CodecNameMatches(codec.codec.name, external_codecs[c].name)) {
21257fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org        supported_codecs.push_back(codec);
21267fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org        break;
21277fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      }
2128b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
2129b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
2130b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return supported_codecs;
2131b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
2132b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2133b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}  // namespace cricket
2134b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2135b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#endif  // HAVE_WEBRTC_VIDEO
2136