187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org/*
287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * libjingle
387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * Copyright 2014 Google Inc.
487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org *
587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * Redistribution and use in source and binary forms, with or without
687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * modification, are permitted provided that the following conditions are met:
787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org *
887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org *     this list of conditions and the following disclaimer.
1087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
1187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org *     this list of conditions and the following disclaimer in the documentation
1287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org *     and/or other materials provided with the distribution.
1387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org *  3. The name of the author may not be used to endorse or promote products
1487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org *     derived from this software without specific prior written permission.
1587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org *
1687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
1787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
1987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org */
2787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
2887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#ifdef HAVE_WEBRTC_VIDEO
2987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#include "talk/media/webrtc/webrtcvideoengine2.h"
3087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
31d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org#include <set>
3287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#include <string>
3387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
3487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#include "libyuv/convert_from.h"
3587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#include "talk/media/base/videocapturer.h"
3687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#include "talk/media/base/videorenderer.h"
3707a14a70ebfd14b91c5fb61040f02112e0d9c0e7buildbot@webrtc.org#include "talk/media/webrtc/constants.h"
3887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#include "talk/media/webrtc/webrtcvideocapturer.h"
3987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#include "talk/media/webrtc/webrtcvideoframe.h"
4087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#include "talk/media/webrtc/webrtcvoiceengine.h"
41cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/buffer.h"
42cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/logging.h"
43cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/stringutils.h"
4487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#include "webrtc/call.h"
456a97b89328066fe976b587e16034c6d49d98e7fdpbos@webrtc.org#include "webrtc/video_encoder.h"
4687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
4787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#define UNIMPLEMENTED                                                 \
4887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_ERROR) << "Call to unimplemented function " << __FUNCTION__; \
4987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  ASSERT(false)
5087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
5187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgnamespace cricket {
5287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
5387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// This constant is really an on/off, lower-level configurable NACK history
5487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// duration hasn't been implemented.
5587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstatic const int kNackHistoryMs = 1000;
5687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
57f6cfdbfa66a2ff7cfd93df5d49d6cf624cd80d95buildbot@webrtc.orgstatic const int kDefaultQpMax = 56;
58f6cfdbfa66a2ff7cfd93df5d49d6cf624cd80d95buildbot@webrtc.org
5987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstatic const int kDefaultRtcpReceiverReportSsrc = 1;
6087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
6187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstruct VideoCodecPref {
6287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  int payload_type;
63d0f3c32952f7ed87c6273de7a75c373a3a42af12pbos@webrtc.org  int width;
64d0f3c32952f7ed87c6273de7a75c373a3a42af12pbos@webrtc.org  int height;
6587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  const char* name;
6687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  int rtx_payload_type;
67d0f3c32952f7ed87c6273de7a75c373a3a42af12pbos@webrtc.org} kDefaultVideoCodecPref = {100, 640, 400, kVp8CodecName, 96};
6887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
69d0f3c32952f7ed87c6273de7a75c373a3a42af12pbos@webrtc.orgVideoCodecPref kRedPref = {116, -1, -1, kRedCodecName, -1};
70d0f3c32952f7ed87c6273de7a75c373a3a42af12pbos@webrtc.orgVideoCodecPref kUlpfecPref = {117, -1, -1, kUlpfecCodecName, -1};
7187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
7287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstatic bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs,
7387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                   const VideoCodec& requested_codec,
7487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                   VideoCodec* matching_codec) {
7587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
7687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    if (requested_codec.Matches(codecs[i])) {
7787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      *matching_codec = codecs[i];
7887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      return true;
7987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
8087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
8187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return false;
8287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
8387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
84aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.orgstatic void AddDefaultFeedbackParams(VideoCodec* codec) {
85aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org  const FeedbackParam kFir(kRtcpFbParamCcm, kRtcpFbCcmParamFir);
86aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org  codec->AddFeedbackParam(kFir);
87aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org  const FeedbackParam kNack(kRtcpFbParamNack, kParamValueEmpty);
88aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org  codec->AddFeedbackParam(kNack);
89aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org  const FeedbackParam kPli(kRtcpFbParamNack, kRtcpFbNackParamPli);
90aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org  codec->AddFeedbackParam(kPli);
91aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org  const FeedbackParam kRemb(kRtcpFbParamRemb, kParamValueEmpty);
92aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org  codec->AddFeedbackParam(kRemb);
93aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org}
94aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org
95aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.orgstatic bool IsNackEnabled(const VideoCodec& codec) {
96aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org  return codec.HasFeedbackParam(
97aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org      FeedbackParam(kRtcpFbParamNack, kParamValueEmpty));
98aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org}
99aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org
10095bea28dc0d19730835d78de995a3c29c8eec4ddpbos@webrtc.orgstatic bool IsRembEnabled(const VideoCodec& codec) {
10195bea28dc0d19730835d78de995a3c29c8eec4ddpbos@webrtc.org  return codec.HasFeedbackParam(
10295bea28dc0d19730835d78de995a3c29c8eec4ddpbos@webrtc.org      FeedbackParam(kRtcpFbParamRemb, kParamValueEmpty));
10395bea28dc0d19730835d78de995a3c29c8eec4ddpbos@webrtc.org}
10495bea28dc0d19730835d78de995a3c29c8eec4ddpbos@webrtc.org
10587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstatic VideoCodec DefaultVideoCodec() {
10687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  VideoCodec default_codec(kDefaultVideoCodecPref.payload_type,
10787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                           kDefaultVideoCodecPref.name,
108d0f3c32952f7ed87c6273de7a75c373a3a42af12pbos@webrtc.org                           kDefaultVideoCodecPref.width,
109d0f3c32952f7ed87c6273de7a75c373a3a42af12pbos@webrtc.org                           kDefaultVideoCodecPref.height,
11087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                           kDefaultFramerate,
11187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                           0);
112aa77587108ff0860ec9775b00403171b8ba51371pbos@webrtc.org  AddDefaultFeedbackParams(&default_codec);
11387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return default_codec;
11487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
11587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
11687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstatic VideoCodec DefaultRedCodec() {
11787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return VideoCodec(kRedPref.payload_type, kRedPref.name, 0, 0, 0, 0);
11887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
11987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
12087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstatic VideoCodec DefaultUlpfecCodec() {
12187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return VideoCodec(kUlpfecPref.payload_type, kUlpfecPref.name, 0, 0, 0, 0);
12287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
12387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
12487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstatic std::vector<VideoCodec> DefaultVideoCodecs() {
12587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  std::vector<VideoCodec> codecs;
12687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  codecs.push_back(DefaultVideoCodec());
12787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  codecs.push_back(DefaultRedCodec());
12887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  codecs.push_back(DefaultUlpfecCodec());
12987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (kDefaultVideoCodecPref.rtx_payload_type != -1) {
13087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    codecs.push_back(
13187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        VideoCodec::CreateRtxCodec(kDefaultVideoCodecPref.rtx_payload_type,
13287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                   kDefaultVideoCodecPref.payload_type));
13387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
13487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return codecs;
13587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
13687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
137d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.orgstatic bool ValidateRtpHeaderExtensionIds(
138d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
139d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  std::set<int> extensions_used;
140d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
141d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org    if (extensions[i].id < 0 || extensions[i].id >= 15 ||
142d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org        !extensions_used.insert(extensions[i].id).second) {
143d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org      LOG(LS_ERROR) << "RTP extensions are with incorrect or duplicate ids.";
144d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org      return false;
145d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org    }
146d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  }
147d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  return true;
148d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org}
149d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org
150d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.orgstatic std::vector<webrtc::RtpExtension> FilterRtpExtensions(
151d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
152d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  std::vector<webrtc::RtpExtension> webrtc_extensions;
153d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
154d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org    // Unsupported extensions will be ignored.
155d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org    if (webrtc::RtpExtension::IsSupported(extensions[i].uri)) {
156d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org      webrtc_extensions.push_back(webrtc::RtpExtension(
157d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org          extensions[i].uri, extensions[i].id));
158d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org    } else {
159d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org      LOG(LS_WARNING) << "Unsupported RTP extension: " << extensions[i].uri;
160d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org    }
161d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  }
162d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  return webrtc_extensions;
163d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org}
164d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org
165b931d7ed64da901b09f353355fcc39c8a78e0c28pbos@webrtc.orgWebRtcVideoEncoderFactory2::~WebRtcVideoEncoderFactory2() {
166b931d7ed64da901b09f353355fcc39c8a78e0c28pbos@webrtc.org}
167b931d7ed64da901b09f353355fcc39c8a78e0c28pbos@webrtc.org
168d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.orgstd::vector<webrtc::VideoStream> WebRtcVideoEncoderFactory2::CreateVideoStreams(
169d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org    const VideoCodec& codec,
170d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org    const VideoOptions& options,
171d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org    size_t num_streams) {
172d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  assert(SupportsCodec(codec));
173d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  if (num_streams != 1) {
174d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org    LOG(LS_ERROR) << "Unsupported number of streams: " << num_streams;
175d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org    return std::vector<webrtc::VideoStream>();
176725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org  }
17787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
178d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  webrtc::VideoStream stream;
179d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  stream.width = codec.width;
180d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  stream.height = codec.height;
181d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  stream.max_framerate =
182d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org      codec.framerate != 0 ? codec.framerate : kDefaultFramerate;
183d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org
184d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  int min_bitrate = kMinVideoBitrate;
185d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  codec.GetParam(kCodecParamMinBitrate, &min_bitrate);
186d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  int max_bitrate = kMaxVideoBitrate;
187d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  codec.GetParam(kCodecParamMaxBitrate, &max_bitrate);
188d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  stream.min_bitrate_bps = min_bitrate * 1000;
189d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate * 1000;
190d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org
191f6cfdbfa66a2ff7cfd93df5d49d6cf624cd80d95buildbot@webrtc.org  int max_qp = kDefaultQpMax;
192d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
193d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  stream.max_qp = max_qp;
194d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  std::vector<webrtc::VideoStream> streams;
195d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  streams.push_back(stream);
196d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  return streams;
197d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org}
19887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
199d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.orgwebrtc::VideoEncoder* WebRtcVideoEncoderFactory2::CreateVideoEncoder(
200d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org    const VideoCodec& codec,
201d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org    const VideoOptions& options) {
202d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  assert(SupportsCodec(codec));
203ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  if (_stricmp(codec.name.c_str(), kVp8CodecName) == 0) {
2046a97b89328066fe976b587e16034c6d49d98e7fdpbos@webrtc.org    return webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp8);
205ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  }
206ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  // This shouldn't happen, we should be able to create encoders for all codecs
207ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  // we support.
208ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  assert(false);
209ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  return NULL;
210ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org}
211ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org
212ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.orgvoid* WebRtcVideoEncoderFactory2::CreateVideoEncoderSettings(
213ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org    const VideoCodec& codec,
214ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org    const VideoOptions& options) {
215ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  assert(SupportsCodec(codec));
216ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  if (_stricmp(codec.name.c_str(), kVp8CodecName) == 0) {
2178f804c79226e998286f4c9e8f5f8ce3918c29654pbos@webrtc.org    webrtc::VideoCodecVP8* settings = new webrtc::VideoCodecVP8(
2188f804c79226e998286f4c9e8f5f8ce3918c29654pbos@webrtc.org        webrtc::VideoEncoder::GetDefaultVp8Settings());
219ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org    options.video_noise_reduction.Get(&settings->denoisingOn);
220ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org    return settings;
221ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  }
222ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  return NULL;
223ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org}
224ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org
225ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.orgvoid WebRtcVideoEncoderFactory2::DestroyVideoEncoderSettings(
226ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org    const VideoCodec& codec,
227ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org    void* encoder_settings) {
228ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  assert(SupportsCodec(codec));
229ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  if (encoder_settings == NULL) {
230ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org    return;
231ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  }
232ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  if (_stricmp(codec.name.c_str(), kVp8CodecName) == 0) {
233ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org    delete reinterpret_cast<webrtc::VideoCodecVP8*>(encoder_settings);
234ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  }
235d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org}
236d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org
237d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.orgbool WebRtcVideoEncoderFactory2::SupportsCodec(const VideoCodec& codec) {
23807a14a70ebfd14b91c5fb61040f02112e0d9c0e7buildbot@webrtc.org  return _stricmp(codec.name.c_str(), kVp8CodecName) == 0;
239d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org}
24087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
2419ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.orgDefaultUnsignalledSsrcHandler::DefaultUnsignalledSsrcHandler()
2429ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    : default_recv_ssrc_(0), default_renderer_(NULL) {}
2439ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org
2449ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.orgUnsignalledSsrcHandler::Action DefaultUnsignalledSsrcHandler::OnUnsignalledSsrc(
2459ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    VideoMediaChannel* channel,
2469ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    uint32_t ssrc) {
2479ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  if (default_recv_ssrc_ != 0) {  // Already one default stream.
2489ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    LOG(LS_WARNING) << "Unknown SSRC, but default receive stream already set.";
2499ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    return kDropPacket;
2509ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  }
2519ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org
2529ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  StreamParams sp;
2539ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  sp.ssrcs.push_back(ssrc);
2549ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << ".";
2559ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  if (!channel->AddRecvStream(sp)) {
2569ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    LOG(LS_WARNING) << "Could not create default receive stream.";
2579ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  }
2589ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org
2599ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  channel->SetRenderer(ssrc, default_renderer_);
2609ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  default_recv_ssrc_ = ssrc;
2619ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  return kDeliverPacket;
2629ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org}
2639ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org
2649ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.orgVideoRenderer* DefaultUnsignalledSsrcHandler::GetDefaultRenderer() const {
2659ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  return default_renderer_;
2669ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org}
2679ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org
2689ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.orgvoid DefaultUnsignalledSsrcHandler::SetDefaultRenderer(
2699ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    VideoMediaChannel* channel,
2709ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    VideoRenderer* renderer) {
2719ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  default_renderer_ = renderer;
2729ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  if (default_recv_ssrc_ != 0) {
2739ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    channel->SetRenderer(default_recv_ssrc_, default_renderer_);
2749ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  }
2759ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org}
2769ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org
277d0f3c32952f7ed87c6273de7a75c373a3a42af12pbos@webrtc.orgWebRtcVideoEngine2::WebRtcVideoEngine2()
278faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org    : worker_thread_(NULL),
279faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org      voice_engine_(NULL),
280faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org      video_codecs_(DefaultVideoCodecs()),
2810fbcf962cd3d7148bf77a996c6f31ba4afc99bacbuildbot@webrtc.org      default_codec_format_(kDefaultVideoCodecPref.width,
2820fbcf962cd3d7148bf77a996c6f31ba4afc99bacbuildbot@webrtc.org                            kDefaultVideoCodecPref.height,
2830fbcf962cd3d7148bf77a996c6f31ba4afc99bacbuildbot@webrtc.org                            FPS_TO_INTERVAL(kDefaultFramerate),
2840fbcf962cd3d7148bf77a996c6f31ba4afc99bacbuildbot@webrtc.org                            FOURCC_ANY),
285faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org      initialized_(false),
286faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org      cpu_monitor_(new rtc::CpuMonitor(NULL)),
287d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org      channel_factory_(NULL),
288d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org      external_decoder_factory_(NULL),
289d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org      external_encoder_factory_(NULL) {
290faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()";
291f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org  rtp_header_extensions_.push_back(
292f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org      RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
293f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org                         kRtpTimestampOffsetHeaderExtensionDefaultId));
294f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org  rtp_header_extensions_.push_back(
295f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org      RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
296f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org                         kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
29787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
29887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
299faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.orgvoid WebRtcVideoEngine2::SetChannelFactory(
300faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org    WebRtcVideoChannelFactory* channel_factory) {
301faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org  channel_factory_ = channel_factory;
302faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org}
303faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org
30487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgWebRtcVideoEngine2::~WebRtcVideoEngine2() {
30587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2";
30687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
30787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (initialized_) {
30887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    Terminate();
30987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
31087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
31187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
3122a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgbool WebRtcVideoEngine2::Init(rtc::Thread* worker_thread) {
31387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::Init";
31487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  worker_thread_ = worker_thread;
31587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  ASSERT(worker_thread_ != NULL);
31687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
31787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  cpu_monitor_->set_thread(worker_thread_);
31887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) {
31987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_ERROR) << "Failed to start CPU monitor.";
32087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    cpu_monitor_.reset();
32187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
32287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
32387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  initialized_ = true;
32487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
32587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
32687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
32787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoEngine2::Terminate() {
32887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::Terminate";
32987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
33087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  cpu_monitor_->Stop();
33187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
33287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  initialized_ = false;
33387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
33487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
33587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgint WebRtcVideoEngine2::GetCapabilities() { return VIDEO_RECV | VIDEO_SEND; }
33687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
33787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoEngine2::SetDefaultEncoderConfig(
33887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    const VideoEncoderConfig& config) {
3394c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  const VideoCodec& codec = config.max_codec;
3404c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  // TODO(pbos): Make use of external encoder factory.
3414c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  if (!GetVideoEncoderFactory()->SupportsCodec(codec)) {
3424c09a710a007655061a0cc34da461897890b905apbos@webrtc.org    LOG(LS_ERROR) << "SetDefaultEncoderConfig, codec not supported:"
3434c09a710a007655061a0cc34da461897890b905apbos@webrtc.org                  << codec.ToString();
3444c09a710a007655061a0cc34da461897890b905apbos@webrtc.org    return false;
3454c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  }
3464c09a710a007655061a0cc34da461897890b905apbos@webrtc.org
3470fbcf962cd3d7148bf77a996c6f31ba4afc99bacbuildbot@webrtc.org  default_codec_format_ =
3480fbcf962cd3d7148bf77a996c6f31ba4afc99bacbuildbot@webrtc.org      VideoFormat(codec.width,
3490fbcf962cd3d7148bf77a996c6f31ba4afc99bacbuildbot@webrtc.org                  codec.height,
3500fbcf962cd3d7148bf77a996c6f31ba4afc99bacbuildbot@webrtc.org                  VideoFormat::FpsToInterval(codec.framerate),
3510fbcf962cd3d7148bf77a996c6f31ba4afc99bacbuildbot@webrtc.org                  FOURCC_ANY);
3524c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  video_codecs_.clear();
3534c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  video_codecs_.push_back(codec);
35487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
35587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
35687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
35787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgVideoEncoderConfig WebRtcVideoEngine2::GetDefaultEncoderConfig() const {
35887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return VideoEncoderConfig(DefaultVideoCodec());
35987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
36087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
36187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgWebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel(
36287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    VoiceMediaChannel* voice_channel) {
36387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "CreateChannel: "
36487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org               << (voice_channel != NULL ? "With" : "Without")
36587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org               << " voice channel.";
36687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  WebRtcVideoChannel2* channel =
36787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      channel_factory_ != NULL
36887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org          ? channel_factory_->Create(this, voice_channel)
36987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org          : new WebRtcVideoChannel2(
370b931d7ed64da901b09f353355fcc39c8a78e0c28pbos@webrtc.org                this, voice_channel, GetVideoEncoderFactory());
37187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (!channel->Init()) {
37287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    delete channel;
37387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return NULL;
37487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
3752352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org  channel->SetRecvCodecs(video_codecs_);
37687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return channel;
37787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
37887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
37987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgconst std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const {
38087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return video_codecs_;
38187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
38287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
38387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgconst std::vector<RtpHeaderExtension>&
38487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgWebRtcVideoEngine2::rtp_header_extensions() const {
38587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return rtp_header_extensions_;
38687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
38787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
38887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoEngine2::SetLogging(int min_sev, const char* filter) {
38987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Set up logging.
39087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "SetLogging: " << min_sev << '"' << filter << '"';
39187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // if min_sev == -1, we keep the current log level.
39287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (min_sev < 0) {
39387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    assert(min_sev == -1);
39487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return;
39587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
39687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
39787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
398d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.orgvoid WebRtcVideoEngine2::SetExternalDecoderFactory(
399d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org    WebRtcVideoDecoderFactory* decoder_factory) {
400d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  external_decoder_factory_ = decoder_factory;
401d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org}
402d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org
403d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.orgvoid WebRtcVideoEngine2::SetExternalEncoderFactory(
404d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org    WebRtcVideoEncoderFactory* encoder_factory) {
405d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  if (external_encoder_factory_ == encoder_factory) {
406d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org    return;
407d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  }
408d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  if (external_encoder_factory_) {
409d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org    external_encoder_factory_->RemoveObserver(this);
410d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  }
411d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  external_encoder_factory_ = encoder_factory;
412d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  if (external_encoder_factory_) {
413d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org    external_encoder_factory_->AddObserver(this);
414d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  }
415d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org
416d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  // Invoke OnCodecAvailable() here in case the list of codecs is already
417d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  // available when the encoder factory is installed. If not the encoder
418d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  // factory will invoke the callback later when the codecs become available.
419d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  OnCodecsAvailable();
420d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org}
421d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org
42287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoEngine2::EnableTimedRender() {
42387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Figure out whether this can be removed.
42487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
42587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
42687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
42787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// Checks to see whether we comprehend and could receive a particular codec
42887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) {
42987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Probe encoder factory to figure out that the codec is supported
43087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // if supported by the encoder factory. Add a corresponding test that fails
43187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // with this code (that doesn't ask the factory).
4324c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  for (size_t j = 0; j < video_codecs_.size(); ++j) {
4334c09a710a007655061a0cc34da461897890b905apbos@webrtc.org    VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0);
4344c09a710a007655061a0cc34da461897890b905apbos@webrtc.org    if (codec.Matches(in)) {
4354c09a710a007655061a0cc34da461897890b905apbos@webrtc.org      return true;
43687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
43787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
43887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return false;
43987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
44087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
44187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// Tells whether the |requested| codec can be transmitted or not. If it can be
44287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// transmitted |out| is set with the best settings supported. Aspect ratio will
44387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// be set as close to |current|'s as possible. If not set |requested|'s
44487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// dimensions will be used for aspect ratio matching.
44587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested,
44687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                      const VideoCodec& current,
44787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                      VideoCodec* out) {
44887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  assert(out != NULL);
44987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
45087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (requested.width != requested.height &&
45187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      (requested.height == 0 || requested.width == 0)) {
45287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    // 0xn and nx0 are invalid resolutions.
45387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
45487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
45587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
45687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  VideoCodec matching_codec;
45787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (!FindFirstMatchingCodec(video_codecs_, requested, &matching_codec)) {
45887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    // Codec not supported.
45987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
46087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
46187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
46287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  out->id = requested.id;
46387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  out->name = requested.name;
46487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  out->preference = requested.preference;
46587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  out->params = requested.params;
46687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  out->framerate =
4672a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      rtc::_min(requested.framerate, matching_codec.framerate);
46887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  out->params = requested.params;
46987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  out->feedback_params = requested.feedback_params;
4704c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  out->width = requested.width;
4714c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  out->height = requested.height;
4724c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  if (requested.width == 0 && requested.height == 0) {
4734c09a710a007655061a0cc34da461897890b905apbos@webrtc.org    return true;
4744c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  }
4754c09a710a007655061a0cc34da461897890b905apbos@webrtc.org
4764c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  while (out->width > matching_codec.width) {
4774c09a710a007655061a0cc34da461897890b905apbos@webrtc.org    out->width /= 2;
4784c09a710a007655061a0cc34da461897890b905apbos@webrtc.org    out->height /= 2;
4794c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  }
4804c09a710a007655061a0cc34da461897890b905apbos@webrtc.org
4814c09a710a007655061a0cc34da461897890b905apbos@webrtc.org  return out->width > 0 && out->height > 0;
48287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
48387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
48487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoEngine2::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) {
48587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (initialized_) {
48687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init";
48787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
48887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
48987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  voice_engine_ = voice_engine;
49087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
49187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
49287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
49387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// Ignore spammy trace messages, mostly from the stats API when we haven't
49487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// gotten RTCP info yet from the remote side.
49587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) {
49687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  static const char* const kTracesToIgnore[] = {NULL};
49787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  for (const char* const* p = kTracesToIgnore; *p; ++p) {
49887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    if (trace.find(*p) == 0) {
49987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      return true;
50087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
50187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
50287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return false;
50387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
50487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
505d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.orgWebRtcVideoEncoderFactory2* WebRtcVideoEngine2::GetVideoEncoderFactory() {
506d2ca8ce545ec2286578cf7a86240b24254e03fdbbuildbot@webrtc.org  return &default_video_encoder_factory_;
50787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
50887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
509d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.orgvoid WebRtcVideoEngine2::OnCodecsAvailable() {
510d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org  // TODO(pbos): Implement.
511d08c6be2eadc755e14f16ae4ed8dcccf926ab021pbos@webrtc.org}
512725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org// Thin map between VideoFrame and an existing webrtc::I420VideoFrame
51387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// to avoid having to copy the rendered VideoFrame prematurely.
51487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// This implementation is only safe to use in a const context and should never
51587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org// be written to.
516725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.orgclass WebRtcVideoRenderFrame : public VideoFrame {
51787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org public:
51887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  explicit WebRtcVideoRenderFrame(const webrtc::I420VideoFrame* frame)
51987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      : frame_(frame) {}
52087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
52187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual bool InitToBlack(int w,
52287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                           int h,
52387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                           size_t pixel_width,
52487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                           size_t pixel_height,
52587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                           int64 elapsed_time,
52687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                           int64 time_stamp) OVERRIDE {
52787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    UNIMPLEMENTED;
52887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
52987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
53087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
53187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual bool Reset(uint32 fourcc,
53287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     int w,
53387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     int h,
53487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     int dw,
53587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     int dh,
53687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     uint8* sample,
53787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     size_t sample_size,
53887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     size_t pixel_width,
53987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     size_t pixel_height,
54087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     int64 elapsed_time,
54187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     int64 time_stamp,
54287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     int rotation) OVERRIDE {
54387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    UNIMPLEMENTED;
54487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
54587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
54687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
54787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual size_t GetWidth() const OVERRIDE {
54887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return static_cast<size_t>(frame_->width());
54987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
55087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual size_t GetHeight() const OVERRIDE {
55187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return static_cast<size_t>(frame_->height());
55287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
55387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
55487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual const uint8* GetYPlane() const OVERRIDE {
55587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return frame_->buffer(webrtc::kYPlane);
55687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
55787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual const uint8* GetUPlane() const OVERRIDE {
55887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return frame_->buffer(webrtc::kUPlane);
55987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
56087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual const uint8* GetVPlane() const OVERRIDE {
56187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return frame_->buffer(webrtc::kVPlane);
56287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
56387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
56487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual uint8* GetYPlane() OVERRIDE {
56587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    UNIMPLEMENTED;
56687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return NULL;
56787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
56887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual uint8* GetUPlane() OVERRIDE {
56987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    UNIMPLEMENTED;
57087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return NULL;
57187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
57287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual uint8* GetVPlane() OVERRIDE {
57387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    UNIMPLEMENTED;
57487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return NULL;
57587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
57687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
57787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual int32 GetYPitch() const OVERRIDE {
57887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return frame_->stride(webrtc::kYPlane);
57987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
58087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual int32 GetUPitch() const OVERRIDE {
58187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return frame_->stride(webrtc::kUPlane);
58287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
58387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual int32 GetVPitch() const OVERRIDE {
58487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return frame_->stride(webrtc::kVPlane);
58587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
58687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
58787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual void* GetNativeHandle() const OVERRIDE { return NULL; }
58887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
58987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual size_t GetPixelWidth() const OVERRIDE { return 1; }
59087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual size_t GetPixelHeight() const OVERRIDE { return 1; }
59187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
59287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual int64 GetElapsedTime() const OVERRIDE {
59387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    // Convert millisecond render time to ns timestamp.
5942a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    return frame_->render_time_ms() * rtc::kNumNanosecsPerMillisec;
59587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
59687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual int64 GetTimeStamp() const OVERRIDE {
59787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    // Convert 90K rtp timestamp to ns timestamp.
5982a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    return (frame_->timestamp() / 90) * rtc::kNumNanosecsPerMillisec;
59987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
60087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual void SetElapsedTime(int64 elapsed_time) OVERRIDE { UNIMPLEMENTED; }
60187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual void SetTimeStamp(int64 time_stamp) OVERRIDE { UNIMPLEMENTED; }
60287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
60387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual int GetRotation() const OVERRIDE {
60487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    UNIMPLEMENTED;
60587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return ROTATION_0;
60687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
60787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
60887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual VideoFrame* Copy() const OVERRIDE {
60987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    UNIMPLEMENTED;
61087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return NULL;
61187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
61287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
61387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual bool MakeExclusive() OVERRIDE {
61487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    UNIMPLEMENTED;
61587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
61687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
61787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
61887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual size_t CopyToBuffer(uint8* buffer, size_t size) const {
61987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    UNIMPLEMENTED;
62087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return 0;
62187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
62287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
62387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(fbarchard): Refactor into base class and share with LMI
62487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual size_t ConvertToRgbBuffer(uint32 to_fourcc,
62587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                    uint8* buffer,
62687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                    size_t size,
62787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                    int stride_rgb) const OVERRIDE {
62887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    size_t width = GetWidth();
62987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    size_t height = GetHeight();
63087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    size_t needed = (stride_rgb >= 0 ? stride_rgb : -stride_rgb) * height;
63187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    if (size < needed) {
63287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      LOG(LS_WARNING) << "RGB buffer is not large enough";
63387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      return needed;
63487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
63587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
63687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    if (libyuv::ConvertFromI420(GetYPlane(),
63787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                GetYPitch(),
63887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                GetUPlane(),
63987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                GetUPitch(),
64087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                GetVPlane(),
64187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                GetVPitch(),
64287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                buffer,
64387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                stride_rgb,
64487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                static_cast<int>(width),
64587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                static_cast<int>(height),
64687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                to_fourcc)) {
64787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      LOG(LS_ERROR) << "RGB type not supported: " << to_fourcc;
64887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      return 0;  // 0 indicates error
64987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
65087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return needed;
65187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
65287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
65387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org protected:
65487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  virtual VideoFrame* CreateEmptyFrame(int w,
65587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                       int h,
65687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                       size_t pixel_width,
65787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                       size_t pixel_height,
65887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                       int64 elapsed_time,
65987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                       int64 time_stamp) const OVERRIDE {
66087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    WebRtcVideoFrame* frame = new WebRtcVideoFrame();
66187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    frame->InitToBlack(
66287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        w, h, pixel_width, pixel_height, elapsed_time, time_stamp);
66387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return frame;
66487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
66587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
66687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org private:
66787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  const webrtc::I420VideoFrame* const frame_;
66887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org};
66987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
67087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoChannel2(
67187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    WebRtcVideoEngine2* engine,
67287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    VoiceMediaChannel* voice_channel,
67387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    WebRtcVideoEncoderFactory2* encoder_factory)
674faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org    : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
675faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org      encoder_factory_(encoder_factory) {
67687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Connect the video and audio with |voice_channel|.
67787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  webrtc::Call::Config config(this);
67887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  Construct(webrtc::Call::Create(config), engine);
67987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
68087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
68187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoChannel2(
68287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    webrtc::Call* call,
68387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    WebRtcVideoEngine2* engine,
68487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    WebRtcVideoEncoderFactory2* encoder_factory)
685faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org    : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
686faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org      encoder_factory_(encoder_factory) {
68787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  Construct(call, engine);
68887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
68987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
69087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::Construct(webrtc::Call* call,
69187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                    WebRtcVideoEngine2* engine) {
69287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc;
69387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  sending_ = false;
69487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  call_.reset(call);
69587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  default_send_ssrc_ = 0;
696ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org
697ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  SetDefaultOptions();
698ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org}
699ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org
700ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.orgvoid WebRtcVideoChannel2::SetDefaultOptions() {
701ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  options_.video_noise_reduction.Set(true);
7027a0d4a7b261cc6dbcbf57dbd24ca87abfc1c4cacpbos@webrtc.org  options_.use_payload_padding.Set(false);
703ec5639581fcefb40c2d49c874f5269c4a0b87616pbos@webrtc.org  options_.suspend_below_min_bitrate.Set(false);
70487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
70587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
70687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgWebRtcVideoChannel2::~WebRtcVideoChannel2() {
70787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
70887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org           send_streams_.begin();
70987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org       it != send_streams_.end();
71087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org       ++it) {
71187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    delete it->second;
71287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
71387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
71432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
71587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org           receive_streams_.begin();
71687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org       it != receive_streams_.end();
71787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org       ++it) {
71887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    delete it->second;
71987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
72087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
72187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
72287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::Init() { return true; }
72387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
72487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgnamespace {
72587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
72687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstatic std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {
72787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  std::stringstream out;
72887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  out << '{';
72987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
73087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    out << codecs[i].ToString();
73187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    if (i != codecs.size() - 1) {
73287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      out << ", ";
73387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
73487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
73587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  out << '}';
73687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return out.str();
73787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
73887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
7392352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.orgstatic bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) {
7402352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org  bool has_video = false;
7412352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
7422352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org    if (!codecs[i].ValidateCodecFormat()) {
7432352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org      return false;
7442352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org    }
7452352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org    if (codecs[i].GetCodecType() == VideoCodec::CODEC_VIDEO) {
7462352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org      has_video = true;
7472352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org    }
7482352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org  }
7492352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org  if (!has_video) {
7502352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org    LOG(LS_ERROR) << "Setting codecs without a video codec is invalid: "
7512352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org                  << CodecVectorToString(codecs);
7522352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org    return false;
7532352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org  }
7542352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org  return true;
7552352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org}
7562352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org
757f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.orgstatic std::string RtpExtensionsToString(
758f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
759f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org  std::stringstream out;
760f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org  out << '{';
761f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
762f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org    out << "{" << extensions[i].uri << ": " << extensions[i].id << "}";
763f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org    if (i != extensions.size() - 1) {
764f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org      out << ", ";
765f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org    }
766f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org  }
767f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org  out << '}';
768f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org  return out.str();
769f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org}
770f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org
77187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}  // namespace
77287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
77387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
77487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs);
77587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
77687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
77787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
77887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
77987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs);
78087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (mapped_codecs.empty()) {
78187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_ERROR) << "SetRecvCodecs called without video codec payloads.";
78287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
78387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
78487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
78587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Add a decoder factory which controls supported codecs.
78687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // Blocked on webrtc:2854.
78787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
78807a14a70ebfd14b91c5fb61040f02112e0d9c0e7buildbot@webrtc.org    if (_stricmp(mapped_codecs[i].codec.name.c_str(), kVp8CodecName) != 0) {
78987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      LOG(LS_ERROR) << "SetRecvCodecs called with unsupported codec: '"
79087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                    << mapped_codecs[i].codec.name << "'";
79187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      return false;
79287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
79387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
79487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
79587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  recv_codecs_ = mapped_codecs;
79632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
79732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
79832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org           receive_streams_.begin();
79932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org       it != receive_streams_.end();
80032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org       ++it) {
80132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    it->second->SetRecvCodecs(recv_codecs_);
80232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  }
80332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
80487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
80587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
80687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
80787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
80887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "SetSendCodecs: " << CodecVectorToString(codecs);
80987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
81087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
81187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
81287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
81387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  const std::vector<VideoCodecSettings> supported_codecs =
81487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      FilterSupportedCodecs(MapCodecs(codecs));
81587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
81687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (supported_codecs.empty()) {
81787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_ERROR) << "No video codecs supported by encoder factory.";
81887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
81987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
82087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
82187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  send_codec_.Set(supported_codecs.front());
82287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString();
82387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
82432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
82532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org           send_streams_.begin();
82632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org       it != send_streams_.end();
82732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org       ++it) {
82832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    assert(it->second != NULL);
82932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    it->second->SetCodec(supported_codecs.front());
83032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  }
83187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
83287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
83387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
83487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
83587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) {
83687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  VideoCodecSettings codec_settings;
83787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (!send_codec_.Get(&codec_settings)) {
83887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_VERBOSE) << "GetSendCodec: No send codec set.";
83987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
84087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
84187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  *codec = codec_settings.codec;
84287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
84387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
84487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
84587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetSendStreamFormat(uint32 ssrc,
84687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                              const VideoFormat& format) {
84787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "SetSendStreamFormat:" << ssrc << " -> "
84887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                  << format.ToString();
84987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
85087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
85187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
85287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return send_streams_[ssrc]->SetVideoFormat(format);
85387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
85487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
85587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetRender(bool render) {
85687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Implement. Or refactor away as it shouldn't be needed.
85787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "SetRender: " << (render ? "true" : "false");
85887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
85987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
86087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
86187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetSend(bool send) {
86287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false");
86387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (send && !send_codec_.IsSet()) {
86487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_ERROR) << "SetSend(true) called before setting codec.";
86587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
86687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
86787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (send) {
86887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    StartAllSendStreams();
86987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  } else {
87087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    StopAllSendStreams();
87187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
87287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  sending_ = send;
87387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
87487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
87587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
87687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
87787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
87887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (sp.ssrcs.empty()) {
87987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_ERROR) << "No SSRCs in stream parameters.";
88087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
88187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
88287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
88387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
88487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  assert(ssrc != 0);
88587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Make sure none of sp.ssrcs are used, not just the identifying
88687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // ssrc.
88787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (send_streams_.find(ssrc) != send_streams_.end()) {
88887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_ERROR) << "Send stream with ssrc '" << ssrc << "' already exists.";
88987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
89087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
89187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
89261499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  std::vector<uint32> primary_ssrcs;
89361499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  sp.GetPrimarySsrcs(&primary_ssrcs);
89461499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  std::vector<uint32> rtx_ssrcs;
89561499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  sp.GetFidSsrcs(primary_ssrcs, &rtx_ssrcs);
89661499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) {
89761499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    LOG(LS_ERROR)
89861499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org        << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): "
89961499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org        << sp.ToString();
90087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
90187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
90287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
90387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  WebRtcVideoSendStream* stream =
904725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org      new WebRtcVideoSendStream(call_.get(),
90561499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org                                encoder_factory_,
906725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org                                options_,
90761499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org                                send_codec_,
90861499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org                                sp,
90961499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org                                send_rtp_extensions_);
91061499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org
91187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  send_streams_[ssrc] = stream;
91287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
91387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) {
91487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    rtcp_receiver_report_ssrc_ = ssrc;
91587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
91687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (default_send_ssrc_ == 0) {
91787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    default_send_ssrc_ = ssrc;
91887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
91987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (sending_) {
92087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    stream->Start();
92187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
92287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
92387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
92487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
92587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
92687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::RemoveSendStream(uint32 ssrc) {
92787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
92887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
92987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (ssrc == 0) {
93087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    if (default_send_ssrc_ == 0) {
93187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      LOG(LS_ERROR) << "No default send stream active.";
93287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      return false;
93387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
93487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
93587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_VERBOSE) << "Removing default stream: " << default_send_ssrc_;
93687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    ssrc = default_send_ssrc_;
93787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
93887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
93987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  std::map<uint32, WebRtcVideoSendStream*>::iterator it =
94087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      send_streams_.find(ssrc);
94187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (it == send_streams_.end()) {
94287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
94387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
94487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
94587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  delete it->second;
94687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  send_streams_.erase(it);
94787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
94887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (ssrc == default_send_ssrc_) {
94987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    default_send_ssrc_ = 0;
95087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
95187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
95287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
95387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
95487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
95587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) {
95687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
95787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  assert(sp.ssrcs.size() > 0);
95887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
95987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
96087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  assert(ssrc != 0);  // TODO(pbos): Is this ever valid?
96187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
96287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Check if any of the SSRCs overlap.
96387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (receive_streams_.find(ssrc) != receive_streams_.end()) {
96487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_ERROR) << "Receive stream for SSRC " << ssrc << "already exists.";
96587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
96687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
96787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
968fdd800a7edaa11fd431cea1ed673e991a746e63bpbos@webrtc.org  webrtc::VideoReceiveStream::Config config;
96932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  ConfigureReceiverRtp(&config, sp);
97032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  receive_streams_[ssrc] =
97132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org      new WebRtcVideoReceiveStream(call_.get(), config, recv_codecs_);
97232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
97332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  return true;
97432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org}
97532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
97632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.orgvoid WebRtcVideoChannel2::ConfigureReceiverRtp(
97732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    webrtc::VideoReceiveStream::Config* config,
97832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    const StreamParams& sp) const {
97932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
98032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
98132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  config->rtp.remote_ssrc = ssrc;
98232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  config->rtp.local_ssrc = rtcp_receiver_report_ssrc_;
98387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
98432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  config->rtp.extensions = recv_rtp_extensions_;
98595bea28dc0d19730835d78de995a3c29c8eec4ddpbos@webrtc.org
98687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): This protection is against setting the same local ssrc as
98787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // remote which is not permitted by the lower-level API. RTCP requires a
98887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // corresponding sender SSRC. Figure out what to do when we don't have
98987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // (receive-only) or know a good local SSRC.
99032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  if (config->rtp.remote_ssrc == config->rtp.local_ssrc) {
99132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    if (config->rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) {
99232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc;
99387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    } else {
99432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1;
99587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
99687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
99787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
99832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  for (size_t i = 0; i < recv_codecs_.size(); ++i) {
99932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    if (recv_codecs_[i].codec.id == kDefaultVideoCodecPref.payload_type) {
100032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org      config->rtp.fec = recv_codecs_[i].fec;
100132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org      uint32 rtx_ssrc;
100232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org      if (recv_codecs_[i].rtx_payload_type != -1 &&
100332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org          sp.GetFidSsrc(ssrc, &rtx_ssrc)) {
100432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org        config->rtp.rtx[kDefaultVideoCodecPref.payload_type].ssrc = rtx_ssrc;
100532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org        config->rtp.rtx[kDefaultVideoCodecPref.payload_type].payload_type =
100632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org            recv_codecs_[i].rtx_payload_type;
100787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      }
100832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org      break;
100987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
101087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
101187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
101287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
101387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
101487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) {
101587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
101687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (ssrc == 0) {
10179ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported.";
10189ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    return false;
101987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
102087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
102132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator stream =
102287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      receive_streams_.find(ssrc);
102387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (stream == receive_streams_.end()) {
102487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc;
102587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
102687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
102732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  delete stream->second;
102887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  receive_streams_.erase(stream);
102987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
103087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
103187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
103287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
103387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
103487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " "
103587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org               << (renderer ? "(ptr)" : "NULL");
103687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (ssrc == 0) {
10379ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    default_unsignalled_ssrc_handler_.SetDefaultRenderer(this, renderer);
103832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    return true;
103987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
104087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
104132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
104232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org      receive_streams_.find(ssrc);
104332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  if (it == receive_streams_.end()) {
104432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    return false;
104587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
104687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
104787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  it->second->SetRenderer(renderer);
104887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
104987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
105087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
105187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::GetRenderer(uint32 ssrc, VideoRenderer** renderer) {
105287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (ssrc == 0) {
10539ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    *renderer = default_unsignalled_ssrc_handler_.GetDefaultRenderer();
10549ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    return *renderer != NULL;
105587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
105687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
105732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
105832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org      receive_streams_.find(ssrc);
105932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  if (it == receive_streams_.end()) {
106087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
106187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
106287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  *renderer = it->second->GetRenderer();
106387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
106487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
106587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
106687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::GetStats(const StatsOptions& options,
106787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                   VideoMediaInfo* info) {
10687724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info->Clear();
10697724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  FillSenderStats(info);
10707724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  FillReceiverStats(info);
10717724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  FillBandwidthEstimationStats(info);
107287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
107387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
107487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
10757724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.orgvoid WebRtcVideoChannel2::FillSenderStats(VideoMediaInfo* video_media_info) {
10767724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
10777724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org           send_streams_.begin();
10787724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org       it != send_streams_.end();
10797724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org       ++it) {
10807724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    video_media_info->senders.push_back(it->second->GetVideoSenderInfo());
10817724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  }
10827724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org}
10837724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
10847724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.orgvoid WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) {
10857724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
10867724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org           receive_streams_.begin();
10877724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org       it != receive_streams_.end();
10887724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org       ++it) {
10897724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    video_media_info->receivers.push_back(it->second->GetVideoReceiverInfo());
10907724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  }
10917724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org}
10927724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
10937724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.orgvoid WebRtcVideoChannel2::FillBandwidthEstimationStats(
10947724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    VideoMediaInfo* video_media_info) {
10957724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  // TODO(pbos): Implement.
10967724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org}
10977724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
109887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetCapturer(uint32 ssrc, VideoCapturer* capturer) {
109987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> "
110087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org               << (capturer != NULL ? "(capturer)" : "NULL");
110187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  assert(ssrc != 0);
110287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
110387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
110487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
110587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
110687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return send_streams_[ssrc]->SetCapturer(capturer);
110787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
110887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
110987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SendIntraFrame() {
111087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Implement.
111187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
111287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
111387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
111487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
111587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::RequestIntraFrame() {
111687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Implement.
111787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
111887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
111987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
112087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
112187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::OnPacketReceived(
11222a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::Buffer* packet,
11232a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
11248ed4b07ccb4b81b9618ff3e66c8e7fe6707e4a7cpbos@webrtc.org  const webrtc::PacketReceiver::DeliveryStatus delivery_result =
11258ed4b07ccb4b81b9618ff3e66c8e7fe6707e4a7cpbos@webrtc.org      call_->Receiver()->DeliverPacket(
11268ed4b07ccb4b81b9618ff3e66c8e7fe6707e4a7cpbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length());
11278ed4b07ccb4b81b9618ff3e66c8e7fe6707e4a7cpbos@webrtc.org  switch (delivery_result) {
11288ed4b07ccb4b81b9618ff3e66c8e7fe6707e4a7cpbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_OK:
11298ed4b07ccb4b81b9618ff3e66c8e7fe6707e4a7cpbos@webrtc.org      return;
11308ed4b07ccb4b81b9618ff3e66c8e7fe6707e4a7cpbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR:
11318ed4b07ccb4b81b9618ff3e66c8e7fe6707e4a7cpbos@webrtc.org      return;
11328ed4b07ccb4b81b9618ff3e66c8e7fe6707e4a7cpbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC:
11338ed4b07ccb4b81b9618ff3e66c8e7fe6707e4a7cpbos@webrtc.org      break;
113487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
113587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
113687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  uint32 ssrc = 0;
113787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (!GetRtpSsrc(packet->data(), packet->length(), &ssrc)) {
113887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return;
113987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
114087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
11419ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  // TODO(pbos): Make sure that the unsignalled SSRC uses the video payload.
11429ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  // Also figure out whether RTX needs to be handled.
11439ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) {
11449ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    case UnsignalledSsrcHandler::kDropPacket:
11459ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org      return;
11469ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    case UnsignalledSsrcHandler::kDeliverPacket:
11479ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org      break;
11489ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org  }
114987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
1150175d728c5742d83af7a30f4d21077e540d705ac0pbos@webrtc.org  if (call_->Receiver()->DeliverPacket(
1151175d728c5742d83af7a30f4d21077e540d705ac0pbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
1152175d728c5742d83af7a30f4d21077e540d705ac0pbos@webrtc.org      webrtc::PacketReceiver::DELIVERY_OK) {
11539ebf75e35979cec9a6e7330e6ac3fe1caeaf0302pbos@webrtc.org    LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery.";
115487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return;
115587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
115687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
115787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
115887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::OnRtcpReceived(
11592a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::Buffer* packet,
11602a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
1161175d728c5742d83af7a30f4d21077e540d705ac0pbos@webrtc.org  if (call_->Receiver()->DeliverPacket(
1162175d728c5742d83af7a30f4d21077e540d705ac0pbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
1163175d728c5742d83af7a30f4d21077e540d705ac0pbos@webrtc.org      webrtc::PacketReceiver::DELIVERY_OK) {
116487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_WARNING) << "Failed to deliver RTCP packet.";
116587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
116687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
116787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
116887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::OnReadyToSend(bool ready) {
11695f2d3eac8887e8814441f898cd08ce5c8135c18dpbos@webrtc.org  LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
11705f2d3eac8887e8814441f898cd08ce5c8135c18dpbos@webrtc.org  call_->SignalNetworkState(ready ? webrtc::Call::kNetworkUp
11715f2d3eac8887e8814441f898cd08ce5c8135c18dpbos@webrtc.org                                  : webrtc::Call::kNetworkDown);
117287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
117387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
117487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::MuteStream(uint32 ssrc, bool mute) {
117587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "MuteStream: " << ssrc << " -> "
117687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                  << (mute ? "mute" : "unmute");
117787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  assert(ssrc != 0);
117887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
117987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
118087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
118187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
1182ba39a2fa6de680dd8b3b9ec548ebc06f9683ced3pbos@webrtc.org
1183ba39a2fa6de680dd8b3b9ec548ebc06f9683ced3pbos@webrtc.org  send_streams_[ssrc]->MuteStream(mute);
1184ba39a2fa6de680dd8b3b9ec548ebc06f9683ced3pbos@webrtc.org  return true;
118587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
118687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
118787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
118887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
1189f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org  LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: "
1190f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org               << RtpExtensionsToString(extensions);
1191d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  if (!ValidateRtpHeaderExtensionIds(extensions))
1192d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org    return false;
119332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
1194d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  recv_rtp_extensions_ = FilterRtpExtensions(extensions);
119532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
119632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org           receive_streams_.begin();
119732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org       it != receive_streams_.end();
119832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org       ++it) {
119932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    it->second->SetRtpExtensions(recv_rtp_extensions_);
120032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  }
120187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
120287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
120387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
120487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
120587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
1206f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org  LOG(LS_INFO) << "SetSendRtpHeaderExtensions: "
1207f0150cc22727b9ecda7a3433e5ea9672711bec64pbos@webrtc.org               << RtpExtensionsToString(extensions);
1208d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  if (!ValidateRtpHeaderExtensionIds(extensions))
1209d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org    return false;
1210d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org
1211d7058ccf68063d7b08c584a696cf8629c7c12dffpbos@webrtc.org  send_rtp_extensions_ = FilterRtpExtensions(extensions);
121232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
121332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org           send_streams_.begin();
121432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org       it != send_streams_.end();
121532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org       ++it) {
121632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    it->second->SetRtpExtensions(send_rtp_extensions_);
121732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  }
121887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
121987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
122087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
122187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetStartSendBandwidth(int bps) {
122287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Implement.
122387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "SetStartSendBandwidth: " << bps;
122487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
122587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
122687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
122787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetMaxSendBandwidth(int bps) {
122887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Implement.
122987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "SetMaxSendBandwidth: " << bps;
123087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
123187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
123287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
123387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) {
123487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "SetOptions: " << options.ToString();
123587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  options_.SetAll(options);
123661499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
123761499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org           send_streams_.begin();
123861499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org       it != send_streams_.end();
123961499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org       ++it) {
124061499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    it->second->SetOptions(options_);
124161499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  }
124287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
124387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
124487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
124587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) {
124687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  MediaChannel::SetInterface(iface);
124787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // Set the RTP recv/send buffer to a bigger size
124887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  MediaChannel::SetOption(NetworkInterface::ST_RTP,
12492a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                          rtc::Socket::OPT_RCVBUF,
125087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                          kVideoRtpBufferSize);
125187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
125287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(sriniv): Remove or re-enable this.
125387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // As part of b/8030474, send-buffer is size now controlled through
125487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // portallocator flags.
125587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // network_interface_->SetOption(NetworkInterface::ST_RTP,
12562a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  //                              rtc::Socket::OPT_SNDBUF,
125787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  //                              kVideoRtpBufferSize);
125887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
125987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
126087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::UpdateAspectRatio(int ratio_w, int ratio_h) {
126187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Implement.
126287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
126387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
12642a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid WebRtcVideoChannel2::OnMessage(rtc::Message* msg) {
126587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // Ignored.
126687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
126787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
126887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SendRtp(const uint8_t* data, size_t len) {
12692a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
127087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return MediaChannel::SendPacket(&packet);
127187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
127287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
127387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::SendRtcp(const uint8_t* data, size_t len) {
12742a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
127587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return MediaChannel::SendRtcp(&packet);
127687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
127787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
127887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::StartAllSendStreams() {
127987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
128087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org           send_streams_.begin();
128187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org       it != send_streams_.end();
128287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org       ++it) {
128387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    it->second->Start();
128487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
128587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
128687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
128787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::StopAllSendStreams() {
128887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
128987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org           send_streams_.begin();
129087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org       it != send_streams_.end();
129187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org       ++it) {
129287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    it->second->Stop();
129387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
129487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
129587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
1296725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters::
1297725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org    VideoSendStreamParameters(
1298725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org        const webrtc::VideoSendStream::Config& config,
1299725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org        const VideoOptions& options,
130061499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org        const Settable<VideoCodecSettings>& codec_settings)
130161499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    : config(config), options(options), codec_settings(codec_settings) {
1302725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org}
1303725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org
130487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
130587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    webrtc::Call* call,
130661499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    WebRtcVideoEncoderFactory2* encoder_factory,
1307725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org    const VideoOptions& options,
130861499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    const Settable<VideoCodecSettings>& codec_settings,
130961499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    const StreamParams& sp,
131061499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    const std::vector<webrtc::RtpExtension>& rtp_extensions)
131187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    : call_(call),
131287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      encoder_factory_(encoder_factory),
131387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      stream_(NULL),
1314faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org      parameters_(webrtc::VideoSendStream::Config(), options, codec_settings),
1315faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org      capturer_(NULL),
131687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      sending_(false),
131761499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org      muted_(false) {
131861499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  parameters_.config.rtp.max_packet_size = kVideoMtu;
131961499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org
132061499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  sp.GetPrimarySsrcs(&parameters_.config.rtp.ssrcs);
132161499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  sp.GetFidSsrcs(parameters_.config.rtp.ssrcs,
132261499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org                 &parameters_.config.rtp.rtx.ssrcs);
132361499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  parameters_.config.rtp.c_name = sp.cname;
132461499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  parameters_.config.rtp.extensions = rtp_extensions;
132561499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org
132661499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  VideoCodecSettings params;
132761499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  if (codec_settings.Get(&params)) {
132861499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    SetCodec(params);
132961499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  }
133087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
133187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
133287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() {
133387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  DisconnectCapturer();
133461499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  if (stream_ != NULL) {
133561499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    call_->DestroyVideoSendStream(stream_);
133661499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  }
1337725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org  delete parameters_.config.encoder_settings.encoder;
133887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
133987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
134087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstatic void SetWebRtcFrameToBlack(webrtc::I420VideoFrame* video_frame) {
134187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  assert(video_frame != NULL);
134287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  memset(video_frame->buffer(webrtc::kYPlane),
134387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org         16,
134487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org         video_frame->allocated_size(webrtc::kYPlane));
134587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  memset(video_frame->buffer(webrtc::kUPlane),
134687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org         128,
134787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org         video_frame->allocated_size(webrtc::kUPlane));
134887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  memset(video_frame->buffer(webrtc::kVPlane),
134987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org         128,
135087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org         video_frame->allocated_size(webrtc::kVPlane));
135187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
135287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
135387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstatic void CreateBlackFrame(webrtc::I420VideoFrame* video_frame,
135487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                             int width,
135587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                             int height) {
135687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  video_frame->CreateEmptyFrame(
135787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      width, height, width, (width + 1) / 2, (width + 1) / 2);
135887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  SetWebRtcFrameToBlack(video_frame);
135987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
136087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
136187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstatic void ConvertToI420VideoFrame(const VideoFrame& frame,
136287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                                    webrtc::I420VideoFrame* i420_frame) {
136387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  i420_frame->CreateFrame(
136487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      static_cast<int>(frame.GetYPitch() * frame.GetHeight()),
136587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      frame.GetYPlane(),
136687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      static_cast<int>(frame.GetUPitch() * ((frame.GetHeight() + 1) / 2)),
136787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      frame.GetUPlane(),
136887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      static_cast<int>(frame.GetVPitch() * ((frame.GetHeight() + 1) / 2)),
136987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      frame.GetVPlane(),
137087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      static_cast<int>(frame.GetWidth()),
137187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      static_cast<int>(frame.GetHeight()),
137287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      static_cast<int>(frame.GetYPitch()),
137387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      static_cast<int>(frame.GetUPitch()),
137487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      static_cast<int>(frame.GetVPitch()));
137587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
137687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
137787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
137887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    VideoCapturer* capturer,
137987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    const VideoFrame* frame) {
138087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "InputFrame: " << frame->GetWidth() << "x"
138187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                  << frame->GetHeight();
138287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // Lock before copying, can be called concurrently when swapping input source.
13832a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope frame_cs(&frame_lock_);
138447740f2c26aea1b3b7830abdcba063a12a61d009pbos@webrtc.org  ConvertToI420VideoFrame(*frame, &video_frame_);
138547740f2c26aea1b3b7830abdcba063a12a61d009pbos@webrtc.org
13862a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&lock_);
138761499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  if (stream_ == NULL) {
138861499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    LOG(LS_WARNING) << "Capturer inputting frames before send codecs are "
138961499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org                       "configured, dropping.";
139061499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    return;
139161499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  }
139287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (format_.width == 0) {  // Dropping frames.
139387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    assert(format_.height == 0);
139487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_VERBOSE) << "VideoFormat 0x0 set, Dropping frame.";
139587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return;
139687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
139747740f2c26aea1b3b7830abdcba063a12a61d009pbos@webrtc.org  if (muted_) {
139847740f2c26aea1b3b7830abdcba063a12a61d009pbos@webrtc.org    // Create a black frame to transmit instead.
139947740f2c26aea1b3b7830abdcba063a12a61d009pbos@webrtc.org    CreateBlackFrame(&video_frame_,
140047740f2c26aea1b3b7830abdcba063a12a61d009pbos@webrtc.org                     static_cast<int>(frame->GetWidth()),
140147740f2c26aea1b3b7830abdcba063a12a61d009pbos@webrtc.org                     static_cast<int>(frame->GetHeight()));
140247740f2c26aea1b3b7830abdcba063a12a61d009pbos@webrtc.org  }
140387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // Reconfigure codec if necessary.
1404baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org  SetDimensions(
1405baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org      video_frame_.width(), video_frame_.height(), capturer->IsScreencast());
1406baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org
140787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x"
140887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                  << video_frame_.height() << " -> (codec) "
1409ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org                  << parameters_.encoder_config.streams.back().width << "x"
1410ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org                  << parameters_.encoder_config.streams.back().height;
141187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  stream_->Input()->SwapFrame(&video_frame_);
141287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
141387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
141487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer(
141587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    VideoCapturer* capturer) {
141687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (!DisconnectCapturer() && capturer == NULL) {
141787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
141887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
141987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
142087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  {
14212a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::CritScope cs(&lock_);
142287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
1423fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org    if (capturer == NULL) {
1424fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org      if (stream_ != NULL) {
1425fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org        LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
1426fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org        webrtc::I420VideoFrame black_frame;
1427fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org
1428fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org        int width = format_.width;
1429fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org        int height = format_.height;
1430fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org        int half_width = (width + 1) / 2;
1431fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org        black_frame.CreateEmptyFrame(
1432fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org            width, height, width, half_width, half_width);
1433fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org        SetWebRtcFrameToBlack(&black_frame);
1434baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org        SetDimensions(width, height, false);
1435fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org        stream_->Input()->SwapFrame(&black_frame);
1436fbfc394ffc0d57d37f983b0cee170742b4c46cc6pbos@webrtc.org      }
143787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
143887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      capturer_ = NULL;
143987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      return true;
144087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
144187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
144287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    capturer_ = capturer;
144387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
144487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // Lock cannot be held while connecting the capturer to prevent lock-order
144587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // violations.
144687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame);
144787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
144887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
144987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
145087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat(
145187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    const VideoFormat& format) {
145287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if ((format.width == 0 || format.height == 0) &&
145387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      format.width != format.height) {
145487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_ERROR) << "Can't set VideoFormat, width or height is zero (but not "
145587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                     "both, 0x0 drops frames).";
145687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
145787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
145887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
14592a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&lock_);
146087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (format.width == 0 && format.height == 0) {
146187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_INFO)
146287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        << "0x0 resolution selected. Captured frames will be dropped for ssrc: "
1463725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org        << parameters_.config.rtp.ssrcs[0] << ".";
146487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  } else {
146587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    // TODO(pbos): Fix me, this only affects the last stream!
1466ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org    parameters_.encoder_config.streams.back().max_framerate =
146787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        VideoFormat::IntervalToFps(format.interval);
1468baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org    SetDimensions(format.width, format.height, false);
146987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
147087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
147187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  format_ = format;
147287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
147387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
147487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
1475ba39a2fa6de680dd8b3b9ec548ebc06f9683ced3pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::MuteStream(bool mute) {
14762a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&lock_);
147787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  muted_ = mute;
147887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
147987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
148087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() {
14812a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&lock_);
148287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (capturer_ == NULL) {
148387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return false;
148487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
148587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  capturer_->SignalVideoFrame.disconnect(this);
148687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  capturer_ = NULL;
148787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return true;
148887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
148987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
149061499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions(
149161499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    const VideoOptions& options) {
14922a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&lock_);
149361499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  VideoCodecSettings codec_settings;
149461499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  if (parameters_.codec_settings.Get(&codec_settings)) {
149561499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    SetCodecAndOptions(codec_settings, options);
149661499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  } else {
149761499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    parameters_.options = options;
149861499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  }
149961499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org}
150087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
150161499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    const VideoCodecSettings& codec_settings) {
15022a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&lock_);
150361499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  SetCodecAndOptions(codec_settings, parameters_.options);
150461499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org}
150561499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions(
150661499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    const VideoCodecSettings& codec_settings,
150761499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    const VideoOptions& options) {
1508725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org  std::vector<webrtc::VideoStream> video_streams =
1509725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org      encoder_factory_->CreateVideoStreams(
151061499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org          codec_settings.codec, options, parameters_.config.rtp.ssrcs.size());
1511725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org  if (video_streams.empty()) {
151287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return;
151387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
1514ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  parameters_.encoder_config.streams = video_streams;
151561499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  format_ = VideoFormat(codec_settings.codec.width,
151661499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org                        codec_settings.codec.height,
151787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                        VideoFormat::FpsToInterval(30),
151887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                        FOURCC_I420);
1519725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org
1520725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org  webrtc::VideoEncoder* old_encoder =
1521725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org      parameters_.config.encoder_settings.encoder;
1522725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org  parameters_.config.encoder_settings.encoder =
152361499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org      encoder_factory_->CreateVideoEncoder(codec_settings.codec, options);
152461499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  parameters_.config.encoder_settings.payload_name = codec_settings.codec.name;
152561499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  parameters_.config.encoder_settings.payload_type = codec_settings.codec.id;
152661499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  parameters_.config.rtp.fec = codec_settings.fec;
152761499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org
152861499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  // Set RTX payload type if RTX is enabled.
152961499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  if (!parameters_.config.rtp.rtx.ssrcs.empty()) {
153061499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type;
15317a0d4a7b261cc6dbcbf57dbd24ca87abfc1c4cacpbos@webrtc.org
15327a0d4a7b261cc6dbcbf57dbd24ca87abfc1c4cacpbos@webrtc.org    options.use_payload_padding.Get(
15337a0d4a7b261cc6dbcbf57dbd24ca87abfc1c4cacpbos@webrtc.org        &parameters_.config.rtp.rtx.pad_with_redundant_payloads);
153461499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  }
153561499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org
153661499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  if (IsNackEnabled(codec_settings.codec)) {
153761499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    parameters_.config.rtp.nack.rtp_history_ms = kNackHistoryMs;
153861499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  }
153961499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org
1540ec5639581fcefb40c2d49c874f5269c4a0b87616pbos@webrtc.org  options.suspend_below_min_bitrate.Get(
1541ec5639581fcefb40c2d49c874f5269c4a0b87616pbos@webrtc.org      &parameters_.config.suspend_below_min_bitrate);
1542ec5639581fcefb40c2d49c874f5269c4a0b87616pbos@webrtc.org
154361499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  parameters_.codec_settings.Set(codec_settings);
1544725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org  parameters_.options = options;
15457a0d4a7b261cc6dbcbf57dbd24ca87abfc1c4cacpbos@webrtc.org
154687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  RecreateWebRtcStream();
154787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  delete old_encoder;
154887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
154987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
155032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions(
155132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    const std::vector<webrtc::RtpExtension>& rtp_extensions) {
15522a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&lock_);
155332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  parameters_.config.rtp.extensions = rtp_extensions;
155432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  RecreateWebRtcStream();
155532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org}
155632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
1557baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(
1558baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org    int width,
1559baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org    int height,
1560baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org    bool override_max) {
1561ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  assert(!parameters_.encoder_config.streams.empty());
156287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  LOG(LS_VERBOSE) << "SetDimensions: " << width << "x" << height;
1563baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org
1564baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org  VideoCodecSettings codec_settings;
1565baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org  parameters_.codec_settings.Get(&codec_settings);
1566baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org  // Restrict dimensions according to codec max.
1567baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org  if (!override_max) {
1568baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org    if (codec_settings.codec.width < width)
1569baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org      width = codec_settings.codec.width;
1570baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org    if (codec_settings.codec.height < height)
1571baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org      height = codec_settings.codec.height;
1572baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org  }
1573baa196a1777c920c593110d6bafeea8bf9282de3pbos@webrtc.org
1574ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  if (parameters_.encoder_config.streams.back().width == width &&
1575ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org      parameters_.encoder_config.streams.back().height == height) {
157687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return;
157787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
157887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
1579ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  webrtc::VideoEncoderConfig encoder_config = parameters_.encoder_config;
1580ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  encoder_config.encoder_specific_settings =
1581ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org      encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
1582ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org                                                   parameters_.options);
1583ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org
158443d397ff84588095360214c8dcda7254028b7456pbos@webrtc.org  VideoCodec codec = codec_settings.codec;
158543d397ff84588095360214c8dcda7254028b7456pbos@webrtc.org  codec.width = width;
158643d397ff84588095360214c8dcda7254028b7456pbos@webrtc.org  codec.height = height;
158743d397ff84588095360214c8dcda7254028b7456pbos@webrtc.org
1588ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  encoder_config.streams = encoder_factory_->CreateVideoStreams(
1589ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org      codec, parameters_.options, parameters_.config.rtp.ssrcs.size());
1590ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org
1591ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config);
1592ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org
1593ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  encoder_factory_->DestroyVideoEncoderSettings(
1594ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org      codec_settings.codec,
1595ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org      encoder_config.encoder_specific_settings);
1596ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org
1597ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  encoder_config.encoder_specific_settings = NULL;
1598ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org
1599ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  if (!stream_reconfigured) {
160087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: "
160187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                    << width << "x" << height;
160287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    return;
160387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
160443d397ff84588095360214c8dcda7254028b7456pbos@webrtc.org
1605ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  parameters_.encoder_config = encoder_config;
160687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
160787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
160887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::Start() {
16092a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&lock_);
161061499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  assert(stream_ != NULL);
161187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  stream_->Start();
161287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  sending_ = true;
161387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
161487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
161587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::Stop() {
16162a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&lock_);
161761499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  if (stream_ != NULL) {
161861499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org    stream_->Stop();
161961499560dd39b9d4050c4fac2054ce76daa185cfpbos@webrtc.org  }
162087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  sending_ = false;
162187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
162287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
16237724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.orgVideoSenderInfo
16247724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
16257724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  VideoSenderInfo info;
16262a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope cs(&lock_);
16277724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  for (size_t i = 0; i < parameters_.config.rtp.ssrcs.size(); ++i) {
16287724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    info.add_ssrc(parameters_.config.rtp.ssrcs[i]);
16297724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  }
16307724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
163193d0f92d0811b4fd4f87431018d5631a546bb334pbos@webrtc.org  if (stream_ == NULL) {
163293d0f92d0811b4fd4f87431018d5631a546bb334pbos@webrtc.org    return info;
163393d0f92d0811b4fd4f87431018d5631a546bb334pbos@webrtc.org  }
163493d0f92d0811b4fd4f87431018d5631a546bb334pbos@webrtc.org
16357724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  webrtc::VideoSendStream::Stats stats = stream_->GetStats();
16367724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.framerate_input = stats.input_frame_rate;
16377724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.framerate_sent = stats.encode_frame_rate;
16387724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
16397724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  for (std::map<uint32_t, webrtc::StreamStats>::iterator it =
16407724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org           stats.substreams.begin();
16417724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org       it != stats.substreams.end();
16427724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org       ++it) {
16437724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    // TODO(pbos): Wire up additional stats, such as padding bytes.
16447724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    webrtc::StreamStats stream_stats = it->second;
16457724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    info.bytes_sent += stream_stats.rtp_stats.bytes +
16467724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org                       stream_stats.rtp_stats.header_bytes +
16477724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org                       stream_stats.rtp_stats.padding_bytes;
16487724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    info.packets_sent += stream_stats.rtp_stats.packets;
16497724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    info.packets_lost += stream_stats.rtcp_stats.cumulative_lost;
16507724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  }
16517724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
16527724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  if (!stats.substreams.empty()) {
16537724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    // TODO(pbos): Report fraction lost per SSRC.
16547724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    webrtc::StreamStats first_stream_stats = stats.substreams.begin()->second;
16557724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    info.fraction_lost =
16567724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org        static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) /
16577724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org        (1 << 8);
16587724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  }
16597724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
16607724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  if (capturer_ != NULL && !capturer_->IsMuted()) {
16617724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    VideoFormat last_captured_frame_format;
16627724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    capturer_->GetStats(&info.adapt_frame_drops,
16637724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org                        &info.effects_frame_drops,
16647724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org                        &info.capturer_frame_time,
16657724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org                        &last_captured_frame_format);
16667724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    info.input_frame_width = last_captured_frame_format.width;
16677724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    info.input_frame_height = last_captured_frame_format.height;
16687724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    info.send_frame_width =
1669ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org        static_cast<int>(parameters_.encoder_config.streams.front().width);
16707724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org    info.send_frame_height =
1671ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org        static_cast<int>(parameters_.encoder_config.streams.front().height);
16727724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  }
16737724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
16747724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  // TODO(pbos): Support or remove the following stats.
16757724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.packets_cached = -1;
16767724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.rtt_ms = -1;
16777724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
16787724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  return info;
16797724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org}
16807724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
168187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
168287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (stream_ != NULL) {
168387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    call_->DestroyVideoSendStream(stream_);
168487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
1685725448760ec749e62f2a3843a491c278599d1963pbos@webrtc.org
1686ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  VideoCodecSettings codec_settings;
1687ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org  parameters_.codec_settings.Get(&codec_settings);
1688ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  parameters_.encoder_config.encoder_specific_settings =
1689ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org      encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
1690ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org                                                   parameters_.options);
1691ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org
1692ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  stream_ = call_->CreateVideoSendStream(parameters_.config,
1693ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org                                         parameters_.encoder_config);
1694ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org
1695ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  encoder_factory_->DestroyVideoEncoderSettings(
1696ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org      codec_settings.codec,
1697ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org      parameters_.encoder_config.encoder_specific_settings);
1698ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org
1699ce453652c492556c3b22dcf37df975ed2c3daba1pbos@webrtc.org  parameters_.encoder_config.encoder_specific_settings = NULL;
1700ccce52e7cc31c93e49ba32f84d83d7b88e74051apbos@webrtc.org
170187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  if (sending_) {
170287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    stream_->Start();
170387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
170487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
170587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
170632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
170732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    webrtc::Call* call,
170832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    const webrtc::VideoReceiveStream::Config& config,
170932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    const std::vector<VideoCodecSettings>& recv_codecs)
171032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    : call_(call),
171132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org      stream_(NULL),
1712faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org      config_(config),
1713faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org      renderer_(NULL),
171432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org      last_width_(-1),
1715faebccea1be83ffdc22d9d084dd4dfa132b5e02epbos@webrtc.org      last_height_(-1) {
171632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  config_.renderer = this;
171732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  // SetRecvCodecs will also reset (start) the VideoReceiveStream.
171832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  SetRecvCodecs(recv_codecs);
171932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org}
172032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
172132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() {
172232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  call_->DestroyVideoReceiveStream(stream_);
172332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org}
172432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
172532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs(
172632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    const std::vector<VideoCodecSettings>& recv_codecs) {
172732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  // TODO(pbos): Reconfigure RTX based on incoming recv_codecs.
172832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  // TODO(pbos): Base receive codecs off recv_codecs_ and set up using a
172932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  // DecoderFactory similar to send side. Pending webrtc:2854.
173032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  // Also set up default codecs if there's nothing in recv_codecs_.
173132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  webrtc::VideoCodec codec;
173232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  memset(&codec, 0, sizeof(codec));
173332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
173432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  codec.plType = kDefaultVideoCodecPref.payload_type;
173532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  strcpy(codec.plName, kDefaultVideoCodecPref.name);
173632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  codec.codecType = webrtc::kVideoCodecVP8;
173732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  codec.codecSpecific.VP8.resilience = webrtc::kResilientStream;
173832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  codec.codecSpecific.VP8.numberOfTemporalLayers = 1;
173932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  codec.codecSpecific.VP8.denoisingOn = true;
174032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  codec.codecSpecific.VP8.errorConcealmentOn = false;
174132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  codec.codecSpecific.VP8.automaticResizeOn = false;
174232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  codec.codecSpecific.VP8.frameDroppingOn = true;
174332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  codec.codecSpecific.VP8.keyFrameInterval = 3000;
174432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  // Bitrates don't matter and are ignored for the receiver. This is put in to
174532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  // have the current underlying implementation accept the VideoCodec.
174632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  codec.minBitrate = codec.startBitrate = codec.maxBitrate = 300;
174732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  config_.codecs.clear();
174832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  config_.codecs.push_back(codec);
174932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
175032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  config_.rtp.fec = recv_codecs.front().fec;
175132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
175295bea28dc0d19730835d78de995a3c29c8eec4ddpbos@webrtc.org  config_.rtp.nack.rtp_history_ms =
175395bea28dc0d19730835d78de995a3c29c8eec4ddpbos@webrtc.org      IsNackEnabled(recv_codecs.begin()->codec) ? kNackHistoryMs : 0;
175495bea28dc0d19730835d78de995a3c29c8eec4ddpbos@webrtc.org  config_.rtp.remb = IsRembEnabled(recv_codecs.begin()->codec);
175595bea28dc0d19730835d78de995a3c29c8eec4ddpbos@webrtc.org
175632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  RecreateWebRtcStream();
175732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org}
175832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
175932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions(
176032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    const std::vector<webrtc::RtpExtension>& extensions) {
176132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  config_.rtp.extensions = extensions;
176232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  RecreateWebRtcStream();
176332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org}
176432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
176532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() {
176632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  if (stream_ != NULL) {
176732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    call_->DestroyVideoReceiveStream(stream_);
176832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  }
176932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  stream_ = call_->CreateVideoReceiveStream(config_);
177032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  stream_->Start();
177132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org}
177232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
177332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame(
177432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    const webrtc::I420VideoFrame& frame,
177532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    int time_to_render_ms) {
17762a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
177732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  if (renderer_ == NULL) {
177832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer.";
177932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    return;
178032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  }
178132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
178232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  if (frame.width() != last_width_ || frame.height() != last_height_) {
178332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    SetSize(frame.width(), frame.height());
178432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  }
178532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
178632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  LOG(LS_VERBOSE) << "RenderFrame: (" << frame.width() << "x" << frame.height()
178732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org                  << ")";
178832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
178932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  const WebRtcVideoRenderFrame render_frame(&frame);
179032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  renderer_->RenderFrame(&render_frame);
179132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org}
179232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
179332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRenderer(
179432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    cricket::VideoRenderer* renderer) {
17952a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
179632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  renderer_ = renderer;
179732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  if (renderer_ != NULL && last_width_ != -1) {
179832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    SetSize(last_width_, last_height_);
179932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  }
180032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org}
180132723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
180232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.orgVideoRenderer* WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetRenderer() {
180332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  // TODO(pbos): Remove GetRenderer and all uses of it, it's thread-unsafe by
180432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  // design.
18052a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
180632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  return renderer_;
180732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org}
180832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
180932723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width,
181032723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org                                                            int height) {
18112a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
181232723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  if (!renderer_->SetSize(width, height, 0)) {
181332723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org    LOG(LS_ERROR) << "Could not set renderer size.";
181432723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  }
181532723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  last_width_ = width;
181632723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org  last_height_ = height;
181732723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org}
181832723567bade6a7ee1198fba34a4d04374c96359pbos@webrtc.org
18197724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.orgVideoReceiverInfo
18207724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() {
18217724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  VideoReceiverInfo info;
18227724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.add_ssrc(config_.rtp.remote_ssrc);
18237724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  webrtc::VideoReceiveStream::Stats stats = stream_->GetStats();
18247724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.bytes_rcvd = stats.rtp_stats.bytes + stats.rtp_stats.header_bytes +
18257724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org                    stats.rtp_stats.padding_bytes;
18267724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.packets_rcvd = stats.rtp_stats.packets;
18277724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
18287724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.framerate_rcvd = stats.network_frame_rate;
18297724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.framerate_decoded = stats.decode_frame_rate;
18307724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.framerate_output = stats.render_frame_rate;
18317724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
18322a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::CritScope frame_cs(&renderer_lock_);
18337724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.frame_width = last_width_;
18347724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.frame_height = last_height_;
18357724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
18367724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  // TODO(pbos): Support or remove the following stats.
18377724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  info.packets_concealed = -1;
18387724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
18397724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org  return info;
18407724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org}
18417724e69fe70bdcd448f171353d326d378f03be6bpbos@webrtc.org
184287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgWebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings()
184387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    : rtx_payload_type(-1) {}
184487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
184587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
184687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgWebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) {
184787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  assert(!codecs.empty());
184887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
184987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  std::vector<VideoCodecSettings> video_codecs;
185087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  std::map<int, bool> payload_used;
18512352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org  std::map<int, VideoCodec::CodecType> payload_codec_type;
185287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  std::map<int, int> rtx_mapping;  // video payload type -> rtx payload type.
185387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
185487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  webrtc::FecConfig fec_settings;
185587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
185687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
185787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    const VideoCodec& in_codec = codecs[i];
185887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    int payload_type = in_codec.id;
185987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
186087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    if (payload_used[payload_type]) {
186187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      LOG(LS_ERROR) << "Payload type already registered: "
186287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                    << in_codec.ToString();
186387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      return std::vector<VideoCodecSettings>();
186487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
186587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    payload_used[payload_type] = true;
18662352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org    payload_codec_type[payload_type] = in_codec.GetCodecType();
186787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
186887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    switch (in_codec.GetCodecType()) {
186987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      case VideoCodec::CODEC_RED: {
187087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        // RED payload type, should not have duplicates.
187187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        assert(fec_settings.red_payload_type == -1);
187287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        fec_settings.red_payload_type = in_codec.id;
187387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        continue;
187487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      }
187587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
187687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      case VideoCodec::CODEC_ULPFEC: {
187787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        // ULPFEC payload type, should not have duplicates.
187887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        assert(fec_settings.ulpfec_payload_type == -1);
187987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        fec_settings.ulpfec_payload_type = in_codec.id;
188087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        continue;
188187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      }
188287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
188387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      case VideoCodec::CODEC_RTX: {
188487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        int associated_payload_type;
188587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        if (!in_codec.GetParam(kCodecParamAssociatedPayloadType,
188687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                               &associated_payload_type)) {
188787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org          LOG(LS_ERROR) << "RTX codec without associated payload type: "
188887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org                        << in_codec.ToString();
188987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org          return std::vector<VideoCodecSettings>();
189087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        }
189187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        rtx_mapping[associated_payload_type] = in_codec.id;
189287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        continue;
189387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      }
189487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
189587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      case VideoCodec::CODEC_VIDEO:
189687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org        break;
189787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
189887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
189987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    video_codecs.push_back(VideoCodecSettings());
190087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    video_codecs.back().codec = in_codec;
190187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
190287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
190387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // One of these codecs should have been a video codec. Only having FEC
190487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // parameters into this code is a logic error.
190587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  assert(!video_codecs.empty());
190687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
19072352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org  for (std::map<int, int>::const_iterator it = rtx_mapping.begin();
19082352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org       it != rtx_mapping.end();
19092352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org       ++it) {
19102352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org    if (!payload_used[it->first]) {
19112352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org      LOG(LS_ERROR) << "RTX mapped to payload not in codec list.";
19122352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org      return std::vector<VideoCodecSettings>();
19132352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org    }
19142352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org    if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO) {
19152352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org      LOG(LS_ERROR) << "RTX not mapped to regular video codec.";
19162352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org      return std::vector<VideoCodecSettings>();
19172352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org    }
19182352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org  }
19192352cb302a3c072473044373f1792624b61bba4bpbos@webrtc.org
192087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // TODO(pbos): Write tests that figure out that I have not verified that RTX
192187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  // codecs aren't mapped to bogus payloads.
192287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  for (size_t i = 0; i < video_codecs.size(); ++i) {
192387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    video_codecs[i].fec = fec_settings;
192487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    if (rtx_mapping[video_codecs[i].codec.id] != 0) {
192587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id];
192687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
192787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
192887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
192987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return video_codecs;
193087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
193187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
193287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
193387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.orgWebRtcVideoChannel2::FilterSupportedCodecs(
193487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs) {
193587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  std::vector<VideoCodecSettings> supported_codecs;
193687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
193787e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    if (encoder_factory_->SupportsCodec(mapped_codecs[i].codec)) {
193887e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org      supported_codecs.push_back(mapped_codecs[i]);
193987e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org    }
194087e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  }
194187e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org  return supported_codecs;
194287e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}
194387e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
194487e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org}  // namespace cricket
194587e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org
194687e1f97b7bf06f8554aa27adae4357f81cff3e6bpbos@webrtc.org#endif  // HAVE_WEBRTC_VIDEO
1947