webrtcvideoengine2.cc revision 0a2087a7110e2455ce68f2c85068df5ae447508f
1b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org/*
2b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * libjingle
3b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * Copyright 2014 Google Inc.
4b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
5b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * Redistribution and use in source and binary forms, with or without
6b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * modification, are permitted provided that the following conditions are met:
7b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
8b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
9b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     this list of conditions and the following disclaimer.
10b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
11b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     this list of conditions and the following disclaimer in the documentation
12b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     and/or other materials provided with the distribution.
13b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *  3. The name of the author may not be used to endorse or promote products
14b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     derived from this software without specific prior written permission.
15b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
16b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org */
27b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
28b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#ifdef HAVE_WEBRTC_VIDEO
29b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvideoengine2.h"
30b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
313c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org#include <set>
32b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include <string>
33b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
34b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "libyuv/convert_from.h"
35b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/base/videocapturer.h"
36b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/base/videorenderer.h"
37df9bbbee56f4d9ecef93b3c46964b6f29803f81bbuildbot@webrtc.org#include "talk/media/webrtc/constants.h"
38b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvideocapturer.h"
39b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvideoframe.h"
40b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvoiceengine.h"
41a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/buffer.h"
42a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/logging.h"
43a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/stringutils.h"
44b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "webrtc/call.h"
45ab990ae43a2b84b103cb3c50bc38502375c13e68pbos@webrtc.org#include "webrtc/video_encoder.h"
46b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
47b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#define UNIMPLEMENTED                                                 \
48b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_ERROR) << "Call to unimplemented function " << __FUNCTION__; \
49b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  ASSERT(false)
50b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
51b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgnamespace cricket {
52b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
53b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// This constant is really an on/off, lower-level configurable NACK history
54b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// duration hasn't been implemented.
55b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kNackHistoryMs = 1000;
56b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
57933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.orgstatic const int kDefaultQpMax = 56;
58933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.org
59b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kDefaultRtcpReceiverReportSsrc = 1;
60b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
61b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstruct VideoCodecPref {
62b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  int payload_type;
6397fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.org  int width;
6497fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.org  int height;
65b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const char* name;
66b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  int rtx_payload_type;
6797fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.org} kDefaultVideoCodecPref = {100, 640, 400, kVp8CodecName, 96};
68b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
6997fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.orgVideoCodecPref kRedPref = {116, -1, -1, kRedCodecName, -1};
7097fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.orgVideoCodecPref kUlpfecPref = {117, -1, -1, kUlpfecCodecName, -1};
71b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
72b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs,
73b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   const VideoCodec& requested_codec,
74b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   VideoCodec* matching_codec) {
75b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
76b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (requested_codec.Matches(codecs[i])) {
77b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      *matching_codec = codecs[i];
78b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
79b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
80b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
81b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
82b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
83b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
84f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.orgstatic void AddDefaultFeedbackParams(VideoCodec* codec) {
85f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  const FeedbackParam kFir(kRtcpFbParamCcm, kRtcpFbCcmParamFir);
86f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  codec->AddFeedbackParam(kFir);
87f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  const FeedbackParam kNack(kRtcpFbParamNack, kParamValueEmpty);
88f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  codec->AddFeedbackParam(kNack);
89f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  const FeedbackParam kPli(kRtcpFbParamNack, kRtcpFbNackParamPli);
90f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  codec->AddFeedbackParam(kPli);
91f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  const FeedbackParam kRemb(kRtcpFbParamRemb, kParamValueEmpty);
92f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  codec->AddFeedbackParam(kRemb);
93f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org}
94f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org
95f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.orgstatic bool IsNackEnabled(const VideoCodec& codec) {
96f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  return codec.HasFeedbackParam(
97f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org      FeedbackParam(kRtcpFbParamNack, kParamValueEmpty));
98f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org}
99f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org
100257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.orgstatic bool IsRembEnabled(const VideoCodec& codec) {
101257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org  return codec.HasFeedbackParam(
102257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org      FeedbackParam(kRtcpFbParamRemb, kParamValueEmpty));
103257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org}
104257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org
105b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic VideoCodec DefaultVideoCodec() {
106b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodec default_codec(kDefaultVideoCodecPref.payload_type,
107b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           kDefaultVideoCodecPref.name,
10897fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.org                           kDefaultVideoCodecPref.width,
10997fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.org                           kDefaultVideoCodecPref.height,
110b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           kDefaultFramerate,
111b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           0);
112f99c2f2dbcaab24b45295cb9e06c3c52ad349d81pbos@webrtc.org  AddDefaultFeedbackParams(&default_codec);
113b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return default_codec;
114b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
115b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
116b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic VideoCodec DefaultRedCodec() {
117b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return VideoCodec(kRedPref.payload_type, kRedPref.name, 0, 0, 0, 0);
118b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
119b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
120b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic VideoCodec DefaultUlpfecCodec() {
121b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return VideoCodec(kUlpfecPref.payload_type, kUlpfecPref.name, 0, 0, 0, 0);
122b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
123b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
124b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic std::vector<VideoCodec> DefaultVideoCodecs() {
125b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<VideoCodec> codecs;
126b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  codecs.push_back(DefaultVideoCodec());
127b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  codecs.push_back(DefaultRedCodec());
128b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  codecs.push_back(DefaultUlpfecCodec());
129b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (kDefaultVideoCodecPref.rtx_payload_type != -1) {
130b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codecs.push_back(
131b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        VideoCodec::CreateRtxCodec(kDefaultVideoCodecPref.rtx_payload_type,
132b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   kDefaultVideoCodecPref.payload_type));
133b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
134b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return codecs;
135b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
136b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1373c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.orgstatic bool ValidateRtpHeaderExtensionIds(
1383c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
1393c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  std::set<int> extensions_used;
1403c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
1413c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    if (extensions[i].id < 0 || extensions[i].id >= 15 ||
1423c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org        !extensions_used.insert(extensions[i].id).second) {
1433c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      LOG(LS_ERROR) << "RTP extensions are with incorrect or duplicate ids.";
1443c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      return false;
1453c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    }
1463c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  }
1473c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  return true;
1483c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org}
1493c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org
1503c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.orgstatic std::vector<webrtc::RtpExtension> FilterRtpExtensions(
1513c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
1523c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  std::vector<webrtc::RtpExtension> webrtc_extensions;
1533c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
1543c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    // Unsupported extensions will be ignored.
1553c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    if (webrtc::RtpExtension::IsSupported(extensions[i].uri)) {
1563c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      webrtc_extensions.push_back(webrtc::RtpExtension(
1573c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org          extensions[i].uri, extensions[i].id));
1583c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    } else {
1593c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      LOG(LS_WARNING) << "Unsupported RTP extension: " << extensions[i].uri;
1603c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    }
1613c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  }
1623c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  return webrtc_extensions;
1633c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org}
1643c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org
1650d523eea831e616c415c61765127ed5eb17e5f11pbos@webrtc.orgWebRtcVideoEncoderFactory2::~WebRtcVideoEncoderFactory2() {
1660d523eea831e616c415c61765127ed5eb17e5f11pbos@webrtc.org}
1670d523eea831e616c415c61765127ed5eb17e5f11pbos@webrtc.org
168d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.orgstd::vector<webrtc::VideoStream> WebRtcVideoEncoderFactory2::CreateVideoStreams(
169d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoCodec& codec,
170d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoOptions& options,
171d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    size_t num_streams) {
172d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  assert(SupportsCodec(codec));
173d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  if (num_streams != 1) {
174d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    LOG(LS_ERROR) << "Unsupported number of streams: " << num_streams;
175d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    return std::vector<webrtc::VideoStream>();
1766ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  }
177b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
178d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  webrtc::VideoStream stream;
179d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.width = codec.width;
180d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.height = codec.height;
181d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.max_framerate =
182d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org      codec.framerate != 0 ? codec.framerate : kDefaultFramerate;
183d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
184d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  int min_bitrate = kMinVideoBitrate;
185d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  codec.GetParam(kCodecParamMinBitrate, &min_bitrate);
186d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  int max_bitrate = kMaxVideoBitrate;
187d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  codec.GetParam(kCodecParamMaxBitrate, &max_bitrate);
188d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.min_bitrate_bps = min_bitrate * 1000;
189d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate * 1000;
190d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
191933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.org  int max_qp = kDefaultQpMax;
192d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
193d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.max_qp = max_qp;
194d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  std::vector<webrtc::VideoStream> streams;
195d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  streams.push_back(stream);
196d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  return streams;
197d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org}
198b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
199d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.orgwebrtc::VideoEncoder* WebRtcVideoEncoderFactory2::CreateVideoEncoder(
200d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoCodec& codec,
201d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoOptions& options) {
202d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  assert(SupportsCodec(codec));
2036f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  if (_stricmp(codec.name.c_str(), kVp8CodecName) == 0) {
204ab990ae43a2b84b103cb3c50bc38502375c13e68pbos@webrtc.org    return webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp8);
2056f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  }
2066f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  // This shouldn't happen, we should be able to create encoders for all codecs
2076f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  // we support.
2086f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  assert(false);
2096f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  return NULL;
2106f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org}
2116f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
2126f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.orgvoid* WebRtcVideoEncoderFactory2::CreateVideoEncoderSettings(
2136f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    const VideoCodec& codec,
2146f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    const VideoOptions& options) {
2156f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  assert(SupportsCodec(codec));
2166f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  if (_stricmp(codec.name.c_str(), kVp8CodecName) == 0) {
2176cd6ba8ae016200a7a13b43294b8faf5d1d4affdpbos@webrtc.org    webrtc::VideoCodecVP8* settings = new webrtc::VideoCodecVP8(
2186cd6ba8ae016200a7a13b43294b8faf5d1d4affdpbos@webrtc.org        webrtc::VideoEncoder::GetDefaultVp8Settings());
2196f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    options.video_noise_reduction.Get(&settings->denoisingOn);
2206f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    return settings;
2216f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  }
2226f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  return NULL;
2236f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org}
2246f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
2256f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.orgvoid WebRtcVideoEncoderFactory2::DestroyVideoEncoderSettings(
2266f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    const VideoCodec& codec,
2276f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    void* encoder_settings) {
2286f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  assert(SupportsCodec(codec));
2296f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  if (encoder_settings == NULL) {
2306f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    return;
2316f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  }
2326f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  if (_stricmp(codec.name.c_str(), kVp8CodecName) == 0) {
2336f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    delete reinterpret_cast<webrtc::VideoCodecVP8*>(encoder_settings);
2346f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  }
235d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org}
236d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
237d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.orgbool WebRtcVideoEncoderFactory2::SupportsCodec(const VideoCodec& codec) {
238df9bbbee56f4d9ecef93b3c46964b6f29803f81bbuildbot@webrtc.org  return _stricmp(codec.name.c_str(), kVp8CodecName) == 0;
239d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org}
240b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
241afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgDefaultUnsignalledSsrcHandler::DefaultUnsignalledSsrcHandler()
242afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    : default_recv_ssrc_(0), default_renderer_(NULL) {}
243afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
244afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgUnsignalledSsrcHandler::Action DefaultUnsignalledSsrcHandler::OnUnsignalledSsrc(
245afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    VideoMediaChannel* channel,
246afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    uint32_t ssrc) {
247afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  if (default_recv_ssrc_ != 0) {  // Already one default stream.
248afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Unknown SSRC, but default receive stream already set.";
249afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return kDropPacket;
250afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
251afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
252afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  StreamParams sp;
253afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  sp.ssrcs.push_back(ssrc);
254afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << ".";
255afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  if (!channel->AddRecvStream(sp)) {
256afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Could not create default receive stream.";
257afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
258afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
259afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  channel->SetRenderer(ssrc, default_renderer_);
260afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  default_recv_ssrc_ = ssrc;
261afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  return kDeliverPacket;
262afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
263afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
264afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgVideoRenderer* DefaultUnsignalledSsrcHandler::GetDefaultRenderer() const {
265afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  return default_renderer_;
266afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
267afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
268afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgvoid DefaultUnsignalledSsrcHandler::SetDefaultRenderer(
269afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    VideoMediaChannel* channel,
270afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    VideoRenderer* renderer) {
271afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  default_renderer_ = renderer;
272afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  if (default_recv_ssrc_ != 0) {
273afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    channel->SetRenderer(default_recv_ssrc_, default_renderer_);
274afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
275afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
276afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
27797fdeb8329cf5c328fa531c0a61c3dd181eb4833pbos@webrtc.orgWebRtcVideoEngine2::WebRtcVideoEngine2()
278b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org    : worker_thread_(NULL),
279b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      voice_engine_(NULL),
280b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      video_codecs_(DefaultVideoCodecs()),
281992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org      default_codec_format_(kDefaultVideoCodecPref.width,
282992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                            kDefaultVideoCodecPref.height,
283992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                            FPS_TO_INTERVAL(kDefaultFramerate),
284992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                            FOURCC_ANY),
285b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      initialized_(false),
286b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      cpu_monitor_(new rtc::CpuMonitor(NULL)),
2870a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org      channel_factory_(NULL),
2880a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org      external_decoder_factory_(NULL),
2890a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org      external_encoder_factory_(NULL) {
290b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()";
291587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  rtp_header_extensions_.push_back(
292587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org      RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
293587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org                         kRtpTimestampOffsetHeaderExtensionDefaultId));
294587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  rtp_header_extensions_.push_back(
295587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org      RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
296587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org                         kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
297b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
298b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
299b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.orgvoid WebRtcVideoEngine2::SetChannelFactory(
300b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org    WebRtcVideoChannelFactory* channel_factory) {
301b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org  channel_factory_ = channel_factory;
302b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org}
303b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org
304b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoEngine2::~WebRtcVideoEngine2() {
305b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2";
306b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
307b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (initialized_) {
308b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    Terminate();
309b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
310b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
311b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
312d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgbool WebRtcVideoEngine2::Init(rtc::Thread* worker_thread) {
313b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::Init";
314b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  worker_thread_ = worker_thread;
315b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  ASSERT(worker_thread_ != NULL);
316b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
317b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  cpu_monitor_->set_thread(worker_thread_);
318b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) {
319b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Failed to start CPU monitor.";
320b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    cpu_monitor_.reset();
321b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
322b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
323b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  initialized_ = true;
324b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
325b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
326b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
327b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoEngine2::Terminate() {
328b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::Terminate";
329b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
330b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  cpu_monitor_->Stop();
331b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
332b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  initialized_ = false;
333b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
334b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
335b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgint WebRtcVideoEngine2::GetCapabilities() { return VIDEO_RECV | VIDEO_SEND; }
336b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
337b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::SetDefaultEncoderConfig(
338b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoEncoderConfig& config) {
3398fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  const VideoCodec& codec = config.max_codec;
3408fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  // TODO(pbos): Make use of external encoder factory.
3418fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  if (!GetVideoEncoderFactory()->SupportsCodec(codec)) {
3428fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    LOG(LS_ERROR) << "SetDefaultEncoderConfig, codec not supported:"
3438fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org                  << codec.ToString();
3448fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    return false;
3458fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  }
3468fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org
347992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org  default_codec_format_ =
348992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org      VideoFormat(codec.width,
349992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                  codec.height,
350992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                  VideoFormat::FpsToInterval(codec.framerate),
351992febb9978d2ded1a2c3c8a42ea18ee071ca3aebuildbot@webrtc.org                  FOURCC_ANY);
3528fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  video_codecs_.clear();
3538fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  video_codecs_.push_back(codec);
354b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
355b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
356b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
357b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgVideoEncoderConfig WebRtcVideoEngine2::GetDefaultEncoderConfig() const {
358b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return VideoEncoderConfig(DefaultVideoCodec());
359b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
360b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
361b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel(
362b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VoiceMediaChannel* voice_channel) {
363b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "CreateChannel: "
364b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (voice_channel != NULL ? "With" : "Without")
365b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << " voice channel.";
366b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  WebRtcVideoChannel2* channel =
367b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      channel_factory_ != NULL
368b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          ? channel_factory_->Create(this, voice_channel)
369b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          : new WebRtcVideoChannel2(
3700d523eea831e616c415c61765127ed5eb17e5f11pbos@webrtc.org                this, voice_channel, GetVideoEncoderFactory());
371b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!channel->Init()) {
372b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    delete channel;
373b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
374b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
375e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  channel->SetRecvCodecs(video_codecs_);
376b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return channel;
377b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
378b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
379b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgconst std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const {
380b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return video_codecs_;
381b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
382b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
383b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgconst std::vector<RtpHeaderExtension>&
384b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoEngine2::rtp_header_extensions() const {
385b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return rtp_header_extensions_;
386b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
387b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
388b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoEngine2::SetLogging(int min_sev, const char* filter) {
389b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Set up logging.
390b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetLogging: " << min_sev << '"' << filter << '"';
391b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // if min_sev == -1, we keep the current log level.
392b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (min_sev < 0) {
393b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    assert(min_sev == -1);
394b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
395b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
396b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
397b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
3980a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.orgvoid WebRtcVideoEngine2::SetExternalDecoderFactory(
3990a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org    WebRtcVideoDecoderFactory* decoder_factory) {
4000a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  external_decoder_factory_ = decoder_factory;
4010a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org}
4020a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org
4030a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.orgvoid WebRtcVideoEngine2::SetExternalEncoderFactory(
4040a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org    WebRtcVideoEncoderFactory* encoder_factory) {
4050a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  if (external_encoder_factory_ == encoder_factory) {
4060a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org    return;
4070a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  }
4080a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  if (external_encoder_factory_) {
4090a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org    external_encoder_factory_->RemoveObserver(this);
4100a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  }
4110a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  external_encoder_factory_ = encoder_factory;
4120a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  if (external_encoder_factory_) {
4130a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org    external_encoder_factory_->AddObserver(this);
4140a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  }
4150a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org
4160a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  // Invoke OnCodecAvailable() here in case the list of codecs is already
4170a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  // available when the encoder factory is installed. If not the encoder
4180a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  // factory will invoke the callback later when the codecs become available.
4190a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  OnCodecsAvailable();
4200a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org}
4210a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org
422b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::EnableTimedRender() {
423b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Figure out whether this can be removed.
424b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
425b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
426b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
427b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Checks to see whether we comprehend and could receive a particular codec
428b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) {
429b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Probe encoder factory to figure out that the codec is supported
430b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // if supported by the encoder factory. Add a corresponding test that fails
431b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // with this code (that doesn't ask the factory).
4328fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  for (size_t j = 0; j < video_codecs_.size(); ++j) {
4338fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0);
4348fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    if (codec.Matches(in)) {
4358fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org      return true;
436b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
437b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
438b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
439b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
440b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
441b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Tells whether the |requested| codec can be transmitted or not. If it can be
442b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// transmitted |out| is set with the best settings supported. Aspect ratio will
443b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// be set as close to |current|'s as possible. If not set |requested|'s
444b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// dimensions will be used for aspect ratio matching.
445b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested,
446b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                      const VideoCodec& current,
447b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                      VideoCodec* out) {
448b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(out != NULL);
449b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
450b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (requested.width != requested.height &&
451b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      (requested.height == 0 || requested.width == 0)) {
452b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // 0xn and nx0 are invalid resolutions.
453b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
454b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
455b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
456b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodec matching_codec;
457b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!FindFirstMatchingCodec(video_codecs_, requested, &matching_codec)) {
458b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Codec not supported.
459b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
460b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
461b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
462b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->id = requested.id;
463b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->name = requested.name;
464b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->preference = requested.preference;
465b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->params = requested.params;
466b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->framerate =
467d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org      rtc::_min(requested.framerate, matching_codec.framerate);
468b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->params = requested.params;
469b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->feedback_params = requested.feedback_params;
4708fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  out->width = requested.width;
4718fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  out->height = requested.height;
4728fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  if (requested.width == 0 && requested.height == 0) {
4738fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    return true;
4748fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  }
4758fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org
4768fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  while (out->width > matching_codec.width) {
4778fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    out->width /= 2;
4788fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    out->height /= 2;
4798fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  }
4808fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org
4818fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  return out->width > 0 && out->height > 0;
482b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
483b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
484b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) {
485b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (initialized_) {
486b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init";
487b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
488b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
489b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  voice_engine_ = voice_engine;
490b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
491b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
492b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
493b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Ignore spammy trace messages, mostly from the stats API when we haven't
494b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// gotten RTCP info yet from the remote side.
495b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) {
496b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  static const char* const kTracesToIgnore[] = {NULL};
497b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (const char* const* p = kTracesToIgnore; *p; ++p) {
498b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (trace.find(*p) == 0) {
499b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
500b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
501b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
502b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
503b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
504b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
505d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.orgWebRtcVideoEncoderFactory2* WebRtcVideoEngine2::GetVideoEncoderFactory() {
506d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  return &default_video_encoder_factory_;
507b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
508b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
5090a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.orgvoid WebRtcVideoEngine2::OnCodecsAvailable() {
5100a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  // TODO(pbos): Implement.
5110a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org}
5126ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org// Thin map between VideoFrame and an existing webrtc::I420VideoFrame
513b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// to avoid having to copy the rendered VideoFrame prematurely.
514b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// This implementation is only safe to use in a const context and should never
515b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// be written to.
5166ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.orgclass WebRtcVideoRenderFrame : public VideoFrame {
517b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org public:
518b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  explicit WebRtcVideoRenderFrame(const webrtc::I420VideoFrame* frame)
519b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      : frame_(frame) {}
520b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
521b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual bool InitToBlack(int w,
522b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           int h,
523b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           size_t pixel_width,
524b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           size_t pixel_height,
525b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           int64 elapsed_time,
526b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           int64 time_stamp) OVERRIDE {
527b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
528b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
529b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
530b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
531b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual bool Reset(uint32 fourcc,
532b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int w,
533b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int h,
534b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int dw,
535b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int dh,
536b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     uint8* sample,
537b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     size_t sample_size,
538b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     size_t pixel_width,
539b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     size_t pixel_height,
540b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int64 elapsed_time,
541b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int64 time_stamp,
542b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int rotation) OVERRIDE {
543b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
544b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
545b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
546b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
547b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetWidth() const OVERRIDE {
548b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return static_cast<size_t>(frame_->width());
549b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
550b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetHeight() const OVERRIDE {
551b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return static_cast<size_t>(frame_->height());
552b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
553b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
554b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual const uint8* GetYPlane() const OVERRIDE {
555b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->buffer(webrtc::kYPlane);
556b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
557b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual const uint8* GetUPlane() const OVERRIDE {
558b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->buffer(webrtc::kUPlane);
559b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
560b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual const uint8* GetVPlane() const OVERRIDE {
561b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->buffer(webrtc::kVPlane);
562b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
563b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
564b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual uint8* GetYPlane() OVERRIDE {
565b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
566b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
567b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
568b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual uint8* GetUPlane() OVERRIDE {
569b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
570b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
571b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
572b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual uint8* GetVPlane() OVERRIDE {
573b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
574b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
575b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
576b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
577b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int32 GetYPitch() const OVERRIDE {
578b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->stride(webrtc::kYPlane);
579b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
580b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int32 GetUPitch() const OVERRIDE {
581b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->stride(webrtc::kUPlane);
582b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
583b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int32 GetVPitch() const OVERRIDE {
584b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->stride(webrtc::kVPlane);
585b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
586b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
587b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual void* GetNativeHandle() const OVERRIDE { return NULL; }
588b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
589b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetPixelWidth() const OVERRIDE { return 1; }
590b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetPixelHeight() const OVERRIDE { return 1; }
591b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
592b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int64 GetElapsedTime() const OVERRIDE {
593b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Convert millisecond render time to ns timestamp.
594d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    return frame_->render_time_ms() * rtc::kNumNanosecsPerMillisec;
595b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
596b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int64 GetTimeStamp() const OVERRIDE {
597b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Convert 90K rtp timestamp to ns timestamp.
598d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    return (frame_->timestamp() / 90) * rtc::kNumNanosecsPerMillisec;
599b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
600b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual void SetElapsedTime(int64 elapsed_time) OVERRIDE { UNIMPLEMENTED; }
601b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual void SetTimeStamp(int64 time_stamp) OVERRIDE { UNIMPLEMENTED; }
602b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
603b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int GetRotation() const OVERRIDE {
604b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
605b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return ROTATION_0;
606b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
607b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
608b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual VideoFrame* Copy() const OVERRIDE {
609b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
610b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
611b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
612b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
613b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual bool MakeExclusive() OVERRIDE {
614b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
615b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
616b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
617b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
618b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t CopyToBuffer(uint8* buffer, size_t size) const {
619b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
620b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return 0;
621b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
622b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
623b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(fbarchard): Refactor into base class and share with LMI
624b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t ConvertToRgbBuffer(uint32 to_fourcc,
625b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    uint8* buffer,
626b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    size_t size,
627b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    int stride_rgb) const OVERRIDE {
628b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    size_t width = GetWidth();
629b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    size_t height = GetHeight();
630b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    size_t needed = (stride_rgb >= 0 ? stride_rgb : -stride_rgb) * height;
631b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (size < needed) {
632b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_WARNING) << "RGB buffer is not large enough";
633b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return needed;
634b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
635b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
636b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (libyuv::ConvertFromI420(GetYPlane(),
637b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetYPitch(),
638b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetUPlane(),
639b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetUPitch(),
640b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetVPlane(),
641b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetVPitch(),
642b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                buffer,
643b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                stride_rgb,
644b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                static_cast<int>(width),
645b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                static_cast<int>(height),
646b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                to_fourcc)) {
647b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "RGB type not supported: " << to_fourcc;
648b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return 0;  // 0 indicates error
649b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
650b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return needed;
651b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
652b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
653b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org protected:
654b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual VideoFrame* CreateEmptyFrame(int w,
655b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       int h,
656b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       size_t pixel_width,
657b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       size_t pixel_height,
658b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       int64 elapsed_time,
659b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       int64 time_stamp) const OVERRIDE {
660b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoFrame* frame = new WebRtcVideoFrame();
661b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    frame->InitToBlack(
662b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        w, h, pixel_width, pixel_height, elapsed_time, time_stamp);
663b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame;
664b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
665b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
666b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org private:
667b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const webrtc::I420VideoFrame* const frame_;
668b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org};
669b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
670b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoChannel2(
671b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoEngine2* engine,
672b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VoiceMediaChannel* voice_channel,
673b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoEncoderFactory2* encoder_factory)
674b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org    : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
675b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      encoder_factory_(encoder_factory) {
676b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Connect the video and audio with |voice_channel|.
677b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::Call::Config config(this);
678b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  Construct(webrtc::Call::Create(config), engine);
679b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
680b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
681b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoChannel2(
682b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    webrtc::Call* call,
683b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoEngine2* engine,
684b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoEncoderFactory2* encoder_factory)
685b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org    : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
686b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      encoder_factory_(encoder_factory) {
687b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  Construct(call, engine);
688b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
689b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
690b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::Construct(webrtc::Call* call,
691b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    WebRtcVideoEngine2* engine) {
692b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc;
693b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = false;
694b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  call_.reset(call);
695b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  default_send_ssrc_ = 0;
6966f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
6976f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  SetDefaultOptions();
6986f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org}
6996f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
7006f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.orgvoid WebRtcVideoChannel2::SetDefaultOptions() {
7016f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  options_.video_noise_reduction.Set(true);
702543e589205af006f6b999a2c5df51d3fb722d925pbos@webrtc.org  options_.use_payload_padding.Set(false);
7035ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org  options_.suspend_below_min_bitrate.Set(false);
704b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
705b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
706b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::~WebRtcVideoChannel2() {
707b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
708b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
709b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
710b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
711b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    delete it->second;
712b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
713b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
714d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
715b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           receive_streams_.begin();
716b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != receive_streams_.end();
717b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
718b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    delete it->second;
719b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
720b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
721b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
722b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::Init() { return true; }
723b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
724b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgnamespace {
725b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
726b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {
727b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::stringstream out;
728b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out << '{';
729b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
730b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    out << codecs[i].ToString();
731b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (i != codecs.size() - 1) {
732b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      out << ", ";
733b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
734b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
735b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out << '}';
736b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return out.str();
737b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
738b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
739e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.orgstatic bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) {
740e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  bool has_video = false;
741e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
742e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    if (!codecs[i].ValidateCodecFormat()) {
743e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      return false;
744e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    }
745e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    if (codecs[i].GetCodecType() == VideoCodec::CODEC_VIDEO) {
746e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      has_video = true;
747e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    }
748e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  }
749e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  if (!has_video) {
750e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    LOG(LS_ERROR) << "Setting codecs without a video codec is invalid: "
751e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org                  << CodecVectorToString(codecs);
752e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    return false;
753e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  }
754e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  return true;
755e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org}
756e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org
757587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.orgstatic std::string RtpExtensionsToString(
758587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
759587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  std::stringstream out;
760587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  out << '{';
761587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
762587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org    out << "{" << extensions[i].uri << ": " << extensions[i].id << "}";
763587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org    if (i != extensions.size() - 1) {
764587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org      out << ", ";
765587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org    }
766587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  }
767587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  out << '}';
768587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  return out.str();
769587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org}
770587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org
771b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}  // namespace
772b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
773b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
774b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs);
775b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
776b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
777b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
778b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
779b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs);
780b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (mapped_codecs.empty()) {
781b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "SetRecvCodecs called without video codec payloads.";
782b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
783b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
784b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
785b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Add a decoder factory which controls supported codecs.
786b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Blocked on webrtc:2854.
787b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
788df9bbbee56f4d9ecef93b3c46964b6f29803f81bbuildbot@webrtc.org    if (_stricmp(mapped_codecs[i].codec.name.c_str(), kVp8CodecName) != 0) {
789b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "SetRecvCodecs called with unsupported codec: '"
790b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << mapped_codecs[i].codec.name << "'";
791b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return false;
792b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
793b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
794b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
795b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  recv_codecs_ = mapped_codecs;
796d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
797d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
798d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           receive_streams_.begin();
799d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       it != receive_streams_.end();
800d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       ++it) {
801d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRecvCodecs(recv_codecs_);
802d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
803d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
804b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
805b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
806b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
807b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
808b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetSendCodecs: " << CodecVectorToString(codecs);
809b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
810b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
811b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
812b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
813b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const std::vector<VideoCodecSettings> supported_codecs =
814b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      FilterSupportedCodecs(MapCodecs(codecs));
815b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
816b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (supported_codecs.empty()) {
817b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No video codecs supported by encoder factory.";
818b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
819b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
820b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
821b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  send_codec_.Set(supported_codecs.front());
822b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString();
823b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
824d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
825d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           send_streams_.begin();
826d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       it != send_streams_.end();
827d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       ++it) {
828d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    assert(it->second != NULL);
829d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetCodec(supported_codecs.front());
830d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
831b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
832b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
833b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
834b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
835b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) {
836b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodecSettings codec_settings;
837b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!send_codec_.Get(&codec_settings)) {
838b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "GetSendCodec: No send codec set.";
839b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
840b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
841b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  *codec = codec_settings.codec;
842b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
843b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
844b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
845b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendStreamFormat(uint32 ssrc,
846b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                              const VideoFormat& format) {
847b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetSendStreamFormat:" << ssrc << " -> "
848b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << format.ToString();
849b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
850b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
851b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
852b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return send_streams_[ssrc]->SetVideoFormat(format);
853b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
854b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
855b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRender(bool render) {
856b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement. Or refactor away as it shouldn't be needed.
857b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetRender: " << (render ? "true" : "false");
858b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
859b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
860b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
861b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSend(bool send) {
862b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false");
863b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send && !send_codec_.IsSet()) {
864b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "SetSend(true) called before setting codec.";
865b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
866b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
867b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send) {
868b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    StartAllSendStreams();
869b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
870b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    StopAllSendStreams();
871b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
872b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = send;
873b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
874b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
875b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
876b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
877b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
878b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sp.ssrcs.empty()) {
879b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No SSRCs in stream parameters.";
880b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
881b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
882b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
883b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
884b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);
885b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Make sure none of sp.ssrcs are used, not just the identifying
886b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // ssrc.
887b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) != send_streams_.end()) {
888b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Send stream with ssrc '" << ssrc << "' already exists.";
889b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
890b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
891b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
8925301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  std::vector<uint32> primary_ssrcs;
8935301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetPrimarySsrcs(&primary_ssrcs);
8945301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  std::vector<uint32> rtx_ssrcs;
8955301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetFidSsrcs(primary_ssrcs, &rtx_ssrcs);
8965301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) {
8975301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    LOG(LS_ERROR)
8985301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org        << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): "
8995301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org        << sp.ToString();
900b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
901b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
902b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
903b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  WebRtcVideoSendStream* stream =
9046ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      new WebRtcVideoSendStream(call_.get(),
9055301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                                encoder_factory_,
9066ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org                                options_,
9075301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                                send_codec_,
9085301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                                sp,
9095301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                                send_rtp_extensions_);
9105301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
911b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  send_streams_[ssrc] = stream;
912b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
913b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) {
914b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    rtcp_receiver_report_ssrc_ = ssrc;
915b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
916b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (default_send_ssrc_ == 0) {
917b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_send_ssrc_ = ssrc;
918b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
919b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sending_) {
920b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    stream->Start();
921b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
922b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
923b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
924b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
925b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
926b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RemoveSendStream(uint32 ssrc) {
927b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
928b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
929b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
930b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (default_send_ssrc_ == 0) {
931b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "No default send stream active.";
932b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return false;
933b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
934b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
935b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "Removing default stream: " << default_send_ssrc_;
936b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    ssrc = default_send_ssrc_;
937b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
938b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
939b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<uint32, WebRtcVideoSendStream*>::iterator it =
940b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      send_streams_.find(ssrc);
941b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (it == send_streams_.end()) {
942b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
943b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
944b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
945b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  delete it->second;
946b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  send_streams_.erase(it);
947b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
948b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == default_send_ssrc_) {
949b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_send_ssrc_ = 0;
950b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
951b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
952b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
953b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
954b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
955b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) {
956b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
957b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(sp.ssrcs.size() > 0);
958b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
959b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
960b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);  // TODO(pbos): Is this ever valid?
961b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
962b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Check if any of the SSRCs overlap.
963b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (receive_streams_.find(ssrc) != receive_streams_.end()) {
964b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Receive stream for SSRC " << ssrc << "already exists.";
965b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
966b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
967b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
968bd249bc711b3c9efd142eb8de3df489282fe693epbos@webrtc.org  webrtc::VideoReceiveStream::Config config;
969d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  ConfigureReceiverRtp(&config, sp);
970d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  receive_streams_[ssrc] =
971d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      new WebRtcVideoReceiveStream(call_.get(), config, recv_codecs_);
972d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
973d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  return true;
974d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
975d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
976d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::ConfigureReceiverRtp(
977d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    webrtc::VideoReceiveStream::Config* config,
978d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const StreamParams& sp) const {
979d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
980d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
981d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.remote_ssrc = ssrc;
982d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.local_ssrc = rtcp_receiver_report_ssrc_;
983b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
984d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.extensions = recv_rtp_extensions_;
985257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org
986b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): This protection is against setting the same local ssrc as
987b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // remote which is not permitted by the lower-level API. RTCP requires a
988b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // corresponding sender SSRC. Figure out what to do when we don't have
989b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // (receive-only) or know a good local SSRC.
990d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (config->rtp.remote_ssrc == config->rtp.local_ssrc) {
991d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    if (config->rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) {
992d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc;
993b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    } else {
994d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1;
995b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
996b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
997b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
998d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (size_t i = 0; i < recv_codecs_.size(); ++i) {
999d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    if (recv_codecs_[i].codec.id == kDefaultVideoCodecPref.payload_type) {
1000d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      config->rtp.fec = recv_codecs_[i].fec;
1001d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      uint32 rtx_ssrc;
1002d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      if (recv_codecs_[i].rtx_payload_type != -1 &&
1003d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org          sp.GetFidSsrc(ssrc, &rtx_ssrc)) {
1004d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org        config->rtp.rtx[kDefaultVideoCodecPref.payload_type].ssrc = rtx_ssrc;
1005d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org        config->rtp.rtx[kDefaultVideoCodecPref.payload_type].payload_type =
1006d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org            recv_codecs_[i].rtx_payload_type;
1007b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
1008d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      break;
1009b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1010b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1011b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1012b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1013b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1014b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) {
1015b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1016b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1017afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported.";
1018afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return false;
1019b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1020b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1021d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator stream =
1022b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      receive_streams_.find(ssrc);
1023b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (stream == receive_streams_.end()) {
1024b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc;
1025b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1026b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1027d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  delete stream->second;
1028b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  receive_streams_.erase(stream);
1029b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1030b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1031b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1032b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1033b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
1034b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " "
1035b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (renderer ? "(ptr)" : "NULL");
1036b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1037afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    default_unsignalled_ssrc_handler_.SetDefaultRenderer(this, renderer);
1038d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return true;
1039b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1040b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1041d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1042d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      receive_streams_.find(ssrc);
1043d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (it == receive_streams_.end()) {
1044d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return false;
1045b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1046b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1047b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  it->second->SetRenderer(renderer);
1048b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1049b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1050b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1051b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetRenderer(uint32 ssrc, VideoRenderer** renderer) {
1052b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1053afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    *renderer = default_unsignalled_ssrc_handler_.GetDefaultRenderer();
1054afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return *renderer != NULL;
1055b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1056b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1057d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1058d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      receive_streams_.find(ssrc);
1059d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (it == receive_streams_.end()) {
1060b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1061b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1062b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  *renderer = it->second->GetRenderer();
1063b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1064b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1065b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1066b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetStats(const StatsOptions& options,
1067b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   VideoMediaInfo* info) {
1068e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info->Clear();
1069e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  FillSenderStats(info);
1070e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  FillReceiverStats(info);
1071e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  FillBandwidthEstimationStats(info);
1072b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1073b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1074b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1075e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillSenderStats(VideoMediaInfo* video_media_info) {
1076e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1077e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           send_streams_.begin();
1078e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       it != send_streams_.end();
1079e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       ++it) {
1080e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    video_media_info->senders.push_back(it->second->GetVideoSenderInfo());
1081e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1082e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1083e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1084e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) {
1085e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1086e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           receive_streams_.begin();
1087e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       it != receive_streams_.end();
1088e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       ++it) {
1089e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    video_media_info->receivers.push_back(it->second->GetVideoReceiverInfo());
1090e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1091e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1092e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1093e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillBandwidthEstimationStats(
1094e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    VideoMediaInfo* video_media_info) {
1095e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  // TODO(pbos): Implement.
1096e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1097e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1098b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetCapturer(uint32 ssrc, VideoCapturer* capturer) {
1099b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> "
1100b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (capturer != NULL ? "(capturer)" : "NULL");
1101b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);
1102b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
1103b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1104b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1105b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1106b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return send_streams_[ssrc]->SetCapturer(capturer);
1107b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1108b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1109b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendIntraFrame() {
1110b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1111b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
1112b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1113b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1114b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1115b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RequestIntraFrame() {
1116b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1117b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
1118b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1119b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1120b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1121b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnPacketReceived(
1122d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::Buffer* packet,
1123d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
11244e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org  const webrtc::PacketReceiver::DeliveryStatus delivery_result =
11254e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      call_->Receiver()->DeliverPacket(
11264e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length());
11274e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org  switch (delivery_result) {
11284e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_OK:
11294e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      return;
11304e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR:
11314e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      return;
11324e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC:
11334e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      break;
1134b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1135b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1136b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 ssrc = 0;
1137b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!GetRtpSsrc(packet->data(), packet->length(), &ssrc)) {
1138b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1139b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1140b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1141afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  // TODO(pbos): Make sure that the unsignalled SSRC uses the video payload.
1142afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  // Also figure out whether RTX needs to be handled.
1143afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) {
1144afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    case UnsignalledSsrcHandler::kDropPacket:
1145afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org      return;
1146afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    case UnsignalledSsrcHandler::kDeliverPacket:
1147afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org      break;
1148afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
1149b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
11501e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org  if (call_->Receiver()->DeliverPacket(
11511e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
11521e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org      webrtc::PacketReceiver::DELIVERY_OK) {
1153afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery.";
1154b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1155b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1156b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1157b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1158b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnRtcpReceived(
1159d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::Buffer* packet,
1160d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
11611e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org  if (call_->Receiver()->DeliverPacket(
11621e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
11631e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org      webrtc::PacketReceiver::DELIVERY_OK) {
1164b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "Failed to deliver RTCP packet.";
1165b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1166b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1167b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1168b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnReadyToSend(bool ready) {
116926c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org  LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
117026c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org  call_->SignalNetworkState(ready ? webrtc::Call::kNetworkUp
117126c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org                                  : webrtc::Call::kNetworkDown);
1172b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1173b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1174b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::MuteStream(uint32 ssrc, bool mute) {
1175b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "MuteStream: " << ssrc << " -> "
1176b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << (mute ? "mute" : "unmute");
1177b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);
1178b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
1179b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1180b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1181b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1182ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org
1183ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org  send_streams_[ssrc]->MuteStream(mute);
1184ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org  return true;
1185b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1186b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1187b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
1188b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
1189587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: "
1190587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org               << RtpExtensionsToString(extensions);
11913c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  if (!ValidateRtpHeaderExtensionIds(extensions))
11923c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    return false;
1193d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
11943c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  recv_rtp_extensions_ = FilterRtpExtensions(extensions);
1195d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1196d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           receive_streams_.begin();
1197d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       it != receive_streams_.end();
1198d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       ++it) {
1199d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRtpExtensions(recv_rtp_extensions_);
1200d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1201b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1202b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1203b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1204b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
1205b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
1206587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  LOG(LS_INFO) << "SetSendRtpHeaderExtensions: "
1207587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org               << RtpExtensionsToString(extensions);
12083c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  if (!ValidateRtpHeaderExtensionIds(extensions))
12093c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    return false;
12103c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org
12113c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  send_rtp_extensions_ = FilterRtpExtensions(extensions);
1212d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1213d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           send_streams_.begin();
1214d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       it != send_streams_.end();
1215d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       ++it) {
1216d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRtpExtensions(send_rtp_extensions_);
1217d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1218b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1219b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1220b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1221b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetStartSendBandwidth(int bps) {
1222b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1223b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetStartSendBandwidth: " << bps;
1224b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1225b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1226b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1227b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetMaxSendBandwidth(int bps) {
1228b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1229b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetMaxSendBandwidth: " << bps;
1230b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1231b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1232b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1233b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) {
1234b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetOptions: " << options.ToString();
1235b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  options_.SetAll(options);
12365301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
12375301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org           send_streams_.begin();
12385301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org       it != send_streams_.end();
12395301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org       ++it) {
12405301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    it->second->SetOptions(options_);
12415301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1242b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1243b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1244b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1245b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) {
1246b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  MediaChannel::SetInterface(iface);
1247b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Set the RTP recv/send buffer to a bigger size
1248b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  MediaChannel::SetOption(NetworkInterface::ST_RTP,
1249d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org                          rtc::Socket::OPT_RCVBUF,
1250b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                          kVideoRtpBufferSize);
1251b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1252b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(sriniv): Remove or re-enable this.
1253b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // As part of b/8030474, send-buffer is size now controlled through
1254b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // portallocator flags.
1255b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // network_interface_->SetOption(NetworkInterface::ST_RTP,
1256d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  //                              rtc::Socket::OPT_SNDBUF,
1257b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  //                              kVideoRtpBufferSize);
1258b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1259b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1260b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::UpdateAspectRatio(int ratio_w, int ratio_h) {
1261b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1262b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1263b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1264d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgvoid WebRtcVideoChannel2::OnMessage(rtc::Message* msg) {
1265b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Ignored.
1266b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1267b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1268b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendRtp(const uint8_t* data, size_t len) {
1269d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
1270b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return MediaChannel::SendPacket(&packet);
1271b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1272b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1273b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendRtcp(const uint8_t* data, size_t len) {
1274d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
1275b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return MediaChannel::SendRtcp(&packet);
1276b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1277b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1278b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::StartAllSendStreams() {
1279b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1280b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
1281b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
1282b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
1283b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    it->second->Start();
1284b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1285b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1286b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1287b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::StopAllSendStreams() {
1288b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1289b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
1290b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
1291b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
1292b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    it->second->Stop();
1293b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1294b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1295b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
12966ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters::
12976ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    VideoSendStreamParameters(
12986ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const webrtc::VideoSendStream::Config& config,
12996ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const VideoOptions& options,
13005301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org        const Settable<VideoCodecSettings>& codec_settings)
13015301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    : config(config), options(options), codec_settings(codec_settings) {
13026ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org}
13036ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
1304b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
1305b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    webrtc::Call* call,
13065301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    WebRtcVideoEncoderFactory2* encoder_factory,
13076ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    const VideoOptions& options,
13085301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const Settable<VideoCodecSettings>& codec_settings,
13095301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const StreamParams& sp,
13105301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const std::vector<webrtc::RtpExtension>& rtp_extensions)
1311b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    : call_(call),
1312b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      encoder_factory_(encoder_factory),
1313b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      stream_(NULL),
1314b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      parameters_(webrtc::VideoSendStream::Config(), options, codec_settings),
1315b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      capturer_(NULL),
1316b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      sending_(false),
13175301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org      muted_(false) {
13185301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.max_packet_size = kVideoMtu;
13195301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
13205301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetPrimarySsrcs(&parameters_.config.rtp.ssrcs);
13215301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetFidSsrcs(parameters_.config.rtp.ssrcs,
13225301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                 &parameters_.config.rtp.rtx.ssrcs);
13235301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.c_name = sp.cname;
13245301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.extensions = rtp_extensions;
13255301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
13265301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  VideoCodecSettings params;
13275301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (codec_settings.Get(&params)) {
13285301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    SetCodec(params);
13295301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1330b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1331b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1332b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() {
1333b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  DisconnectCapturer();
13345301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (stream_ != NULL) {
13355301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    call_->DestroyVideoSendStream(stream_);
13365301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
13376ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  delete parameters_.config.encoder_settings.encoder;
1338b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1339b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1340b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic void SetWebRtcFrameToBlack(webrtc::I420VideoFrame* video_frame) {
1341b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(video_frame != NULL);
1342b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  memset(video_frame->buffer(webrtc::kYPlane),
1343b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         16,
1344b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         video_frame->allocated_size(webrtc::kYPlane));
1345b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  memset(video_frame->buffer(webrtc::kUPlane),
1346b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         128,
1347b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         video_frame->allocated_size(webrtc::kUPlane));
1348b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  memset(video_frame->buffer(webrtc::kVPlane),
1349b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         128,
1350b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         video_frame->allocated_size(webrtc::kVPlane));
1351b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1352b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1353b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic void CreateBlackFrame(webrtc::I420VideoFrame* video_frame,
1354b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                             int width,
1355b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                             int height) {
1356b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  video_frame->CreateEmptyFrame(
1357b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      width, height, width, (width + 1) / 2, (width + 1) / 2);
1358b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  SetWebRtcFrameToBlack(video_frame);
1359b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1360b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1361b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic void ConvertToI420VideoFrame(const VideoFrame& frame,
1362b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    webrtc::I420VideoFrame* i420_frame) {
1363b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  i420_frame->CreateFrame(
1364b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetYPitch() * frame.GetHeight()),
1365b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      frame.GetYPlane(),
1366b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetUPitch() * ((frame.GetHeight() + 1) / 2)),
1367b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      frame.GetUPlane(),
1368b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetVPitch() * ((frame.GetHeight() + 1) / 2)),
1369b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      frame.GetVPlane(),
1370b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetWidth()),
1371b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetHeight()),
1372b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetYPitch()),
1373b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetUPitch()),
1374b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetVPitch()));
1375b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1376b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1377b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
1378b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VideoCapturer* capturer,
1379b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFrame* frame) {
1380b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "InputFrame: " << frame->GetWidth() << "x"
1381b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << frame->GetHeight();
1382b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Lock before copying, can be called concurrently when swapping input source.
1383d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope frame_cs(&frame_lock_);
1384b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!muted_) {
1385b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    ConvertToI420VideoFrame(*frame, &video_frame_);
1386b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
1387c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    // Create a black frame to transmit instead.
1388c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    CreateBlackFrame(&video_frame_,
1389c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org                     static_cast<int>(frame->GetWidth()),
1390c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org                     static_cast<int>(frame->GetHeight()));
1391b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1392d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
13935301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (stream_ == NULL) {
13945301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    LOG(LS_WARNING) << "Capturer inputting frames before send codecs are "
13955301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                       "configured, dropping.";
13965301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    return;
13975301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1398b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (format_.width == 0) {  // Dropping frames.
1399b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    assert(format_.height == 0);
1400b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "VideoFormat 0x0 set, Dropping frame.";
1401b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1402b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1403b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Reconfigure codec if necessary.
1404c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  SetDimensions(
1405c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org      video_frame_.width(), video_frame_.height(), capturer->IsScreencast());
1406c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org
1407b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x"
1408b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << video_frame_.height() << " -> (codec) "
1409bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org                  << parameters_.encoder_config.streams.back().width << "x"
1410bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org                  << parameters_.encoder_config.streams.back().height;
1411b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  stream_->Input()->SwapFrame(&video_frame_);
1412b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1413b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1414b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer(
1415b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VideoCapturer* capturer) {
1416b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!DisconnectCapturer() && capturer == NULL) {
1417b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1418b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1419b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1420b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  {
1421d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::CritScope cs(&lock_);
1422b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
14239359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org    if (capturer == NULL) {
14249359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org      if (stream_ != NULL) {
14259359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
14269359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        webrtc::I420VideoFrame black_frame;
14279359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org
14289359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        int width = format_.width;
14299359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        int height = format_.height;
14309359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        int half_width = (width + 1) / 2;
14319359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        black_frame.CreateEmptyFrame(
14329359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org            width, height, width, half_width, half_width);
14339359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        SetWebRtcFrameToBlack(&black_frame);
1434c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org        SetDimensions(width, height, false);
14359359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        stream_->Input()->SwapFrame(&black_frame);
14369359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org      }
1437b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1438b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      capturer_ = NULL;
1439b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
1440b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1441b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1442b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    capturer_ = capturer;
1443b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1444b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Lock cannot be held while connecting the capturer to prevent lock-order
1445b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // violations.
1446b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame);
1447b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1448b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1449b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1450b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat(
1451b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFormat& format) {
1452b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if ((format.width == 0 || format.height == 0) &&
1453b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      format.width != format.height) {
1454b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Can't set VideoFormat, width or height is zero (but not "
1455b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     "both, 0x0 drops frames).";
1456b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1457b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1458b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1459d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1460b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (format.width == 0 && format.height == 0) {
1461b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_INFO)
1462b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        << "0x0 resolution selected. Captured frames will be dropped for ssrc: "
14636ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        << parameters_.config.rtp.ssrcs[0] << ".";
1464b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
1465b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // TODO(pbos): Fix me, this only affects the last stream!
1466bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org    parameters_.encoder_config.streams.back().max_framerate =
1467b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        VideoFormat::IntervalToFps(format.interval);
1468c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    SetDimensions(format.width, format.height, false);
1469b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1470b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1471b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  format_ = format;
1472b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1473b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1474b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1475ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::MuteStream(bool mute) {
1476d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1477b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  muted_ = mute;
1478b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1479b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1480b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() {
1481d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1482b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (capturer_ == NULL) {
1483b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1484b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1485b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  capturer_->SignalVideoFrame.disconnect(this);
1486b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  capturer_ = NULL;
1487b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1488b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1489b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
14905301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions(
14915301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoOptions& options) {
1492d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
14935301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  VideoCodecSettings codec_settings;
14945301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (parameters_.codec_settings.Get(&codec_settings)) {
14955301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    SetCodecAndOptions(codec_settings, options);
14965301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  } else {
14975301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    parameters_.options = options;
14985301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
14995301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org}
1500b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
15015301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoCodecSettings& codec_settings) {
1502d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
15035301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  SetCodecAndOptions(codec_settings, parameters_.options);
15045301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org}
15055301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions(
15065301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoCodecSettings& codec_settings,
15075301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoOptions& options) {
15086ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  std::vector<webrtc::VideoStream> video_streams =
15096ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      encoder_factory_->CreateVideoStreams(
15105301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org          codec_settings.codec, options, parameters_.config.rtp.ssrcs.size());
15116ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  if (video_streams.empty()) {
1512b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1513b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1514bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config.streams = video_streams;
15155301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  format_ = VideoFormat(codec_settings.codec.width,
15165301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                        codec_settings.codec.height,
1517b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        VideoFormat::FpsToInterval(30),
1518b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        FOURCC_I420);
15196ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
15206ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  webrtc::VideoEncoder* old_encoder =
15216ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      parameters_.config.encoder_settings.encoder;
15226ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.config.encoder_settings.encoder =
15235301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org      encoder_factory_->CreateVideoEncoder(codec_settings.codec, options);
15245301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.encoder_settings.payload_name = codec_settings.codec.name;
15255301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.encoder_settings.payload_type = codec_settings.codec.id;
15265301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.fec = codec_settings.fec;
15275301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
15285301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  // Set RTX payload type if RTX is enabled.
15295301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (!parameters_.config.rtp.rtx.ssrcs.empty()) {
15305301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type;
1531543e589205af006f6b999a2c5df51d3fb722d925pbos@webrtc.org
1532543e589205af006f6b999a2c5df51d3fb722d925pbos@webrtc.org    options.use_payload_padding.Get(
1533543e589205af006f6b999a2c5df51d3fb722d925pbos@webrtc.org        &parameters_.config.rtp.rtx.pad_with_redundant_payloads);
15345301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
15355301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
15365301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (IsNackEnabled(codec_settings.codec)) {
15375301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    parameters_.config.rtp.nack.rtp_history_ms = kNackHistoryMs;
15385301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
15395301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
15405ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org  options.suspend_below_min_bitrate.Get(
15415ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org      &parameters_.config.suspend_below_min_bitrate);
15425ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org
15435301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.codec_settings.Set(codec_settings);
15446ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.options = options;
1545543e589205af006f6b999a2c5df51d3fb722d925pbos@webrtc.org
1546b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  RecreateWebRtcStream();
1547b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  delete old_encoder;
1548b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1549b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1550d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions(
1551d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<webrtc::RtpExtension>& rtp_extensions) {
1552d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1553d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  parameters_.config.rtp.extensions = rtp_extensions;
1554d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  RecreateWebRtcStream();
1555d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1556d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1557c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(
1558c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    int width,
1559c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    int height,
1560c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    bool override_max) {
1561bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  assert(!parameters_.encoder_config.streams.empty());
1562b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetDimensions: " << width << "x" << height;
1563c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org
1564c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  VideoCodecSettings codec_settings;
1565c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  parameters_.codec_settings.Get(&codec_settings);
1566c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  // Restrict dimensions according to codec max.
1567c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  if (!override_max) {
1568c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    if (codec_settings.codec.width < width)
1569c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org      width = codec_settings.codec.width;
1570c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    if (codec_settings.codec.height < height)
1571c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org      height = codec_settings.codec.height;
1572c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  }
1573c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org
1574bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  if (parameters_.encoder_config.streams.back().width == width &&
1575bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      parameters_.encoder_config.streams.back().height == height) {
1576b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1577b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1578b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1579bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  webrtc::VideoEncoderConfig encoder_config = parameters_.encoder_config;
1580bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  encoder_config.encoder_specific_settings =
1581bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
1582bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org                                                   parameters_.options);
15836f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
1584cddd17c0f89cfaa9d2f21118ae90b45dae3b4aeepbos@webrtc.org  VideoCodec codec = codec_settings.codec;
1585cddd17c0f89cfaa9d2f21118ae90b45dae3b4aeepbos@webrtc.org  codec.width = width;
1586cddd17c0f89cfaa9d2f21118ae90b45dae3b4aeepbos@webrtc.org  codec.height = height;
1587cddd17c0f89cfaa9d2f21118ae90b45dae3b4aeepbos@webrtc.org
1588bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  encoder_config.streams = encoder_factory_->CreateVideoStreams(
1589bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      codec, parameters_.options, parameters_.config.rtp.ssrcs.size());
15906f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
1591bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config);
1592bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org
1593bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  encoder_factory_->DestroyVideoEncoderSettings(
1594bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      codec_settings.codec,
1595bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      encoder_config.encoder_specific_settings);
1596bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org
1597bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  encoder_config.encoder_specific_settings = NULL;
15986f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
15996f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  if (!stream_reconfigured) {
1600b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: "
1601b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << width << "x" << height;
1602b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1603b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1604cddd17c0f89cfaa9d2f21118ae90b45dae3b4aeepbos@webrtc.org
1605bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config = encoder_config;
1606b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1607b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1608b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::Start() {
1609d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
16105301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  assert(stream_ != NULL);
1611b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  stream_->Start();
1612b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = true;
1613b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1614b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1615b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::Stop() {
1616d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
16175301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (stream_ != NULL) {
16185301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    stream_->Stop();
16195301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1620b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = false;
1621b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1622b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1623e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgVideoSenderInfo
1624e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
1625e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  VideoSenderInfo info;
1626d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1627e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  for (size_t i = 0; i < parameters_.config.rtp.ssrcs.size(); ++i) {
1628e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.add_ssrc(parameters_.config.rtp.ssrcs[i]);
1629e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1630e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1631c3d2bd28a3e8badc434a5081dd36f4ac41b4e3f2pbos@webrtc.org  if (stream_ == NULL) {
1632c3d2bd28a3e8badc434a5081dd36f4ac41b4e3f2pbos@webrtc.org    return info;
1633c3d2bd28a3e8badc434a5081dd36f4ac41b4e3f2pbos@webrtc.org  }
1634c3d2bd28a3e8badc434a5081dd36f4ac41b4e3f2pbos@webrtc.org
1635e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  webrtc::VideoSendStream::Stats stats = stream_->GetStats();
1636e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_input = stats.input_frame_rate;
1637e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_sent = stats.encode_frame_rate;
1638e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1639e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  for (std::map<uint32_t, webrtc::StreamStats>::iterator it =
1640e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           stats.substreams.begin();
1641e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       it != stats.substreams.end();
1642e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       ++it) {
1643e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    // TODO(pbos): Wire up additional stats, such as padding bytes.
1644e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    webrtc::StreamStats stream_stats = it->second;
1645e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.bytes_sent += stream_stats.rtp_stats.bytes +
1646e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                       stream_stats.rtp_stats.header_bytes +
1647e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                       stream_stats.rtp_stats.padding_bytes;
1648e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.packets_sent += stream_stats.rtp_stats.packets;
1649e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.packets_lost += stream_stats.rtcp_stats.cumulative_lost;
1650e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1651e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1652e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  if (!stats.substreams.empty()) {
1653e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    // TODO(pbos): Report fraction lost per SSRC.
1654e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    webrtc::StreamStats first_stream_stats = stats.substreams.begin()->second;
1655e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.fraction_lost =
1656e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org        static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) /
1657e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org        (1 << 8);
1658e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1659e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1660e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  if (capturer_ != NULL && !capturer_->IsMuted()) {
1661e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    VideoFormat last_captured_frame_format;
1662e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    capturer_->GetStats(&info.adapt_frame_drops,
1663e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                        &info.effects_frame_drops,
1664e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                        &info.capturer_frame_time,
1665e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                        &last_captured_frame_format);
1666e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.input_frame_width = last_captured_frame_format.width;
1667e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.input_frame_height = last_captured_frame_format.height;
1668e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.send_frame_width =
1669bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org        static_cast<int>(parameters_.encoder_config.streams.front().width);
1670e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.send_frame_height =
1671bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org        static_cast<int>(parameters_.encoder_config.streams.front().height);
1672e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1673e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1674e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  // TODO(pbos): Support or remove the following stats.
1675e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.packets_cached = -1;
1676e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.rtt_ms = -1;
1677e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1678e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  return info;
1679e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1680e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1681b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
1682b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (stream_ != NULL) {
1683b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    call_->DestroyVideoSendStream(stream_);
1684b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
16856ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
16866f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  VideoCodecSettings codec_settings;
16876f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  parameters_.codec_settings.Get(&codec_settings);
1688bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config.encoder_specific_settings =
1689bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      encoder_factory_->CreateVideoEncoderSettings(codec_settings.codec,
1690bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org                                                   parameters_.options);
1691bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org
1692bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  stream_ = call_->CreateVideoSendStream(parameters_.config,
1693bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org                                         parameters_.encoder_config);
16946f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
1695bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  encoder_factory_->DestroyVideoEncoderSettings(
1696bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      codec_settings.codec,
1697bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org      parameters_.encoder_config.encoder_specific_settings);
16986f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
1699bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config.encoder_specific_settings = NULL;
17006f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
1701b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sending_) {
1702b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    stream_->Start();
1703b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1704b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1705b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1706d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
1707d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    webrtc::Call* call,
1708d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const webrtc::VideoReceiveStream::Config& config,
1709d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<VideoCodecSettings>& recv_codecs)
1710d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    : call_(call),
1711d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      stream_(NULL),
1712b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      config_(config),
1713b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      renderer_(NULL),
1714d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      last_width_(-1),
1715b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      last_height_(-1) {
1716d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.renderer = this;
1717d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // SetRecvCodecs will also reset (start) the VideoReceiveStream.
1718d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  SetRecvCodecs(recv_codecs);
1719d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1720d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1721d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() {
1722d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  call_->DestroyVideoReceiveStream(stream_);
1723d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1724d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1725d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs(
1726d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<VideoCodecSettings>& recv_codecs) {
1727d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // TODO(pbos): Reconfigure RTX based on incoming recv_codecs.
1728d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // TODO(pbos): Base receive codecs off recv_codecs_ and set up using a
1729d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // DecoderFactory similar to send side. Pending webrtc:2854.
1730d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // Also set up default codecs if there's nothing in recv_codecs_.
1731d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  webrtc::VideoCodec codec;
1732d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  memset(&codec, 0, sizeof(codec));
1733d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1734d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  codec.plType = kDefaultVideoCodecPref.payload_type;
1735d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  strcpy(codec.plName, kDefaultVideoCodecPref.name);
1736d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  codec.codecType = webrtc::kVideoCodecVP8;
1737d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  codec.codecSpecific.VP8.resilience = webrtc::kResilientStream;
1738d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  codec.codecSpecific.VP8.numberOfTemporalLayers = 1;
1739d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  codec.codecSpecific.VP8.denoisingOn = true;
1740d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  codec.codecSpecific.VP8.errorConcealmentOn = false;
1741d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  codec.codecSpecific.VP8.automaticResizeOn = false;
1742d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  codec.codecSpecific.VP8.frameDroppingOn = true;
1743d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  codec.codecSpecific.VP8.keyFrameInterval = 3000;
1744d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // Bitrates don't matter and are ignored for the receiver. This is put in to
1745d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // have the current underlying implementation accept the VideoCodec.
1746d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  codec.minBitrate = codec.startBitrate = codec.maxBitrate = 300;
1747d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.codecs.clear();
1748d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.codecs.push_back(codec);
1749d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1750d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.rtp.fec = recv_codecs.front().fec;
1751d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1752257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org  config_.rtp.nack.rtp_history_ms =
1753257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org      IsNackEnabled(recv_codecs.begin()->codec) ? kNackHistoryMs : 0;
1754257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org  config_.rtp.remb = IsRembEnabled(recv_codecs.begin()->codec);
1755257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org
1756d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  RecreateWebRtcStream();
1757d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1758d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1759d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions(
1760d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<webrtc::RtpExtension>& extensions) {
1761d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.rtp.extensions = extensions;
1762d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  RecreateWebRtcStream();
1763d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1764d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1765d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() {
1766d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (stream_ != NULL) {
1767d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    call_->DestroyVideoReceiveStream(stream_);
1768d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1769d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  stream_ = call_->CreateVideoReceiveStream(config_);
1770d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  stream_->Start();
1771d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1772d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1773d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame(
1774d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const webrtc::I420VideoFrame& frame,
1775d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    int time_to_render_ms) {
1776d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
1777d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (renderer_ == NULL) {
1778d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer.";
1779d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return;
1780d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1781d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1782d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (frame.width() != last_width_ || frame.height() != last_height_) {
1783d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    SetSize(frame.width(), frame.height());
1784d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1785d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1786d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  LOG(LS_VERBOSE) << "RenderFrame: (" << frame.width() << "x" << frame.height()
1787d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org                  << ")";
1788d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1789d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  const WebRtcVideoRenderFrame render_frame(&frame);
1790d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  renderer_->RenderFrame(&render_frame);
1791d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1792d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1793d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRenderer(
1794d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    cricket::VideoRenderer* renderer) {
1795d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
1796d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  renderer_ = renderer;
1797d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (renderer_ != NULL && last_width_ != -1) {
1798d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    SetSize(last_width_, last_height_);
1799d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1800d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1801d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1802d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgVideoRenderer* WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetRenderer() {
1803d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // TODO(pbos): Remove GetRenderer and all uses of it, it's thread-unsafe by
1804d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // design.
1805d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
1806d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  return renderer_;
1807d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1808d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1809d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width,
1810d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org                                                            int height) {
1811d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
1812d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (!renderer_->SetSize(width, height, 0)) {
1813d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    LOG(LS_ERROR) << "Could not set renderer size.";
1814d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1815d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  last_width_ = width;
1816d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  last_height_ = height;
1817d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1818d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1819e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgVideoReceiverInfo
1820e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() {
1821e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  VideoReceiverInfo info;
1822e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.add_ssrc(config_.rtp.remote_ssrc);
1823e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  webrtc::VideoReceiveStream::Stats stats = stream_->GetStats();
1824e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.bytes_rcvd = stats.rtp_stats.bytes + stats.rtp_stats.header_bytes +
1825e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org                    stats.rtp_stats.padding_bytes;
1826e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.packets_rcvd = stats.rtp_stats.packets;
1827e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1828e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_rcvd = stats.network_frame_rate;
1829e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_decoded = stats.decode_frame_rate;
1830e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_output = stats.render_frame_rate;
1831e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1832d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope frame_cs(&renderer_lock_);
1833e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.frame_width = last_width_;
1834e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.frame_height = last_height_;
1835e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1836e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  // TODO(pbos): Support or remove the following stats.
1837e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.packets_concealed = -1;
1838e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1839e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  return info;
1840e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1841e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1842b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings()
1843b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    : rtx_payload_type(-1) {}
1844b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1845b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
1846b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) {
1847b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(!codecs.empty());
1848b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1849b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<VideoCodecSettings> video_codecs;
1850b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<int, bool> payload_used;
1851e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  std::map<int, VideoCodec::CodecType> payload_codec_type;
1852b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<int, int> rtx_mapping;  // video payload type -> rtx payload type.
1853b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1854b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::FecConfig fec_settings;
1855b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1856b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
1857b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoCodec& in_codec = codecs[i];
1858b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    int payload_type = in_codec.id;
1859b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1860b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (payload_used[payload_type]) {
1861b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "Payload type already registered: "
1862b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << in_codec.ToString();
1863b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return std::vector<VideoCodecSettings>();
1864b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1865b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    payload_used[payload_type] = true;
1866e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    payload_codec_type[payload_type] = in_codec.GetCodecType();
1867b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1868b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    switch (in_codec.GetCodecType()) {
1869b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_RED: {
1870b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        // RED payload type, should not have duplicates.
1871b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        assert(fec_settings.red_payload_type == -1);
1872b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        fec_settings.red_payload_type = in_codec.id;
1873b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
1874b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
1875b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1876b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_ULPFEC: {
1877b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        // ULPFEC payload type, should not have duplicates.
1878b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        assert(fec_settings.ulpfec_payload_type == -1);
1879b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        fec_settings.ulpfec_payload_type = in_codec.id;
1880b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
1881b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
1882b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1883b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_RTX: {
1884b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        int associated_payload_type;
1885b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        if (!in_codec.GetParam(kCodecParamAssociatedPayloadType,
1886b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                               &associated_payload_type)) {
1887b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          LOG(LS_ERROR) << "RTX codec without associated payload type: "
1888b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        << in_codec.ToString();
1889b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          return std::vector<VideoCodecSettings>();
1890b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        }
1891b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        rtx_mapping[associated_payload_type] = in_codec.id;
1892b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
1893b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
1894b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1895b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_VIDEO:
1896b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        break;
1897b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1898b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1899b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs.push_back(VideoCodecSettings());
1900b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs.back().codec = in_codec;
1901b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1902b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1903b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // One of these codecs should have been a video codec. Only having FEC
1904b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // parameters into this code is a logic error.
1905b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(!video_codecs.empty());
1906b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1907e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  for (std::map<int, int>::const_iterator it = rtx_mapping.begin();
1908e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org       it != rtx_mapping.end();
1909e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org       ++it) {
1910e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    if (!payload_used[it->first]) {
1911e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      LOG(LS_ERROR) << "RTX mapped to payload not in codec list.";
1912e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      return std::vector<VideoCodecSettings>();
1913e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    }
1914e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO) {
1915e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      LOG(LS_ERROR) << "RTX not mapped to regular video codec.";
1916e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      return std::vector<VideoCodecSettings>();
1917e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    }
1918e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  }
1919e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org
1920b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Write tests that figure out that I have not verified that RTX
1921b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // codecs aren't mapped to bogus payloads.
1922b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < video_codecs.size(); ++i) {
1923b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs[i].fec = fec_settings;
1924b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (rtx_mapping[video_codecs[i].codec.id] != 0) {
1925b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id];
1926b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1927b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1928b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1929b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return video_codecs;
1930b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1931b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1932b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
1933b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::FilterSupportedCodecs(
1934b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs) {
1935b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<VideoCodecSettings> supported_codecs;
1936b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
1937b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (encoder_factory_->SupportsCodec(mapped_codecs[i].codec)) {
1938b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      supported_codecs.push_back(mapped_codecs[i]);
1939b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1940b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1941b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return supported_codecs;
1942b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1943b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1944b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}  // namespace cricket
1945b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1946b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#endif  // HAVE_WEBRTC_VIDEO
1947