webrtcvideoengine2.cc revision d41eaeb7cded2b2cda83f53aa320cf18e2d07380
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
31b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#ifdef HAVE_CONFIG_H
32b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include <config.h>
33b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#endif
34b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
35b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include <math.h>
36b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
37b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include <string>
38b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
39b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "libyuv/convert_from.h"
40b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/base/buffer.h"
41b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/base/logging.h"
42b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/base/stringutils.h"
43b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/base/videocapturer.h"
44b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/base/videorenderer.h"
45b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvideocapturer.h"
46b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvideoframe.h"
47b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvoiceengine.h"
48b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "webrtc/call.h"
49b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// TODO(pbos): Move codecs out of modules (webrtc:3070).
50b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
51b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
52b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#define UNIMPLEMENTED                                                 \
53b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_ERROR) << "Call to unimplemented function " << __FUNCTION__; \
54b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  ASSERT(false)
55b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
56b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgnamespace cricket {
57b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
58b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kCpuMonitorPeriodMs = 2000;  // 2 seconds.
59b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
60b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// This constant is really an on/off, lower-level configurable NACK history
61b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// duration hasn't been implemented.
62b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kNackHistoryMs = 1000;
63b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
64b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kDefaultFramerate = 30;
65b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kMinVideoBitrate = 50;
66b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kMaxVideoBitrate = 2000;
67b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
68b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kVideoMtu = 1200;
69b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kVideoRtpBufferSize = 65536;
70b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
71b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const char kVp8PayloadName[] = "VP8";
72b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
73b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kDefaultRtcpReceiverReportSsrc = 1;
74b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
75b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstruct VideoCodecPref {
76b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  int payload_type;
77b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const char* name;
78b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  int rtx_payload_type;
79b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org} kDefaultVideoCodecPref = {100, kVp8PayloadName, 96};
80b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
81b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgVideoCodecPref kRedPref = {116, kRedCodecName, -1};
82b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgVideoCodecPref kUlpfecPref = {117, kUlpfecCodecName, -1};
83b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
84b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// The formats are sorted by the descending order of width. We use the order to
85b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// find the next format for CPU and bandwidth adaptation.
86b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgconst VideoFormatPod kDefaultVideoFormat = {
87b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    640, 400, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY};
88b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgconst VideoFormatPod kVideoFormats[] = {
89b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {1280, 800, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
90b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {1280, 720, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
91b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {960, 600, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
92b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {960, 540, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
93b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    kDefaultVideoFormat,
94b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {640, 360, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
95b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {640, 480, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
96b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {480, 300, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
97b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {480, 270, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
98b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {480, 360, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
99b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {320, 200, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
100b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {320, 180, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
101b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {320, 240, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
102b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {240, 150, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
103b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {240, 135, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
104b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {240, 180, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
105b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {160, 100, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
106b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {160, 90, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
107b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    {160, 120, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY}, };
108b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
109b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs,
110b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   const VideoCodec& requested_codec,
111b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   VideoCodec* matching_codec) {
112b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
113b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (requested_codec.Matches(codecs[i])) {
114b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      *matching_codec = codecs[i];
115b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
116b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
117b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
118b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
119b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
120b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic bool FindBestVideoFormat(int max_width,
121b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                int max_height,
122b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                int aspect_width,
123b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                int aspect_height,
124b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                VideoFormat* video_format) {
125b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(max_width > 0);
126b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(max_height > 0);
127b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(aspect_width > 0);
128b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(aspect_height > 0);
129b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoFormat best_format;
130b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (int i = 0; i < ARRAY_SIZE(kVideoFormats); ++i) {
131b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFormat format(kVideoFormats[i]);
132b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
133b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Skip any format that is larger than the local or remote maximums, or
134b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // smaller than the current best match
135b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (format.width > max_width || format.height > max_height ||
136b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        (format.width < best_format.width &&
137b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         format.height < best_format.height)) {
138b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      continue;
139b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
140b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
141b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // If we don't have any matches yet, this is the best so far.
142b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (best_format.width == 0) {
143b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      best_format = format;
144b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      continue;
145b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
146b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
147b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Prefer closer aspect ratios i.e:
148b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // |format| aspect - requested aspect <
149b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // |best_format| aspect - requested aspect
150b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (abs(format.width * aspect_height * best_format.height -
151b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org            aspect_width * format.height * best_format.height) <
152b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        abs(best_format.width * aspect_height * format.height -
153b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org            aspect_width * format.height * best_format.height)) {
154b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      best_format = format;
155b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
156b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
157b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (best_format.width != 0) {
158b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    *video_format = best_format;
159b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return true;
160b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
161b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
162b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
163b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
164b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic VideoCodec DefaultVideoCodec() {
165b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodec default_codec(kDefaultVideoCodecPref.payload_type,
166b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           kDefaultVideoCodecPref.name,
167b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           kDefaultVideoFormat.width,
168b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           kDefaultVideoFormat.height,
169b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           kDefaultFramerate,
170b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           0);
171b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return default_codec;
172b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
173b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
174b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic VideoCodec DefaultRedCodec() {
175b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return VideoCodec(kRedPref.payload_type, kRedPref.name, 0, 0, 0, 0);
176b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
177b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
178b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic VideoCodec DefaultUlpfecCodec() {
179b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return VideoCodec(kUlpfecPref.payload_type, kUlpfecPref.name, 0, 0, 0, 0);
180b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
181b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
182b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic std::vector<VideoCodec> DefaultVideoCodecs() {
183b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<VideoCodec> codecs;
184b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  codecs.push_back(DefaultVideoCodec());
185b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  codecs.push_back(DefaultRedCodec());
186b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  codecs.push_back(DefaultUlpfecCodec());
187b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (kDefaultVideoCodecPref.rtx_payload_type != -1) {
188b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codecs.push_back(
189b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        VideoCodec::CreateRtxCodec(kDefaultVideoCodecPref.rtx_payload_type,
190b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   kDefaultVideoCodecPref.payload_type));
191b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
192b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return codecs;
193b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
194b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1950d523eea831e616c415c61765127ed5eb17e5f11pbos@webrtc.orgWebRtcVideoEncoderFactory2::~WebRtcVideoEncoderFactory2() {
1960d523eea831e616c415c61765127ed5eb17e5f11pbos@webrtc.org}
1970d523eea831e616c415c61765127ed5eb17e5f11pbos@webrtc.org
198d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.orgstd::vector<webrtc::VideoStream> WebRtcVideoEncoderFactory2::CreateVideoStreams(
199d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoCodec& codec,
200d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoOptions& options,
201d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    size_t num_streams) {
202d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  assert(SupportsCodec(codec));
203d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  if (num_streams != 1) {
204d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    LOG(LS_ERROR) << "Unsupported number of streams: " << num_streams;
205d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    return std::vector<webrtc::VideoStream>();
2066ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  }
207b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
208d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  webrtc::VideoStream stream;
209d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.width = codec.width;
210d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.height = codec.height;
211d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.max_framerate =
212d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org      codec.framerate != 0 ? codec.framerate : kDefaultFramerate;
213d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
214d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  int min_bitrate = kMinVideoBitrate;
215d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  codec.GetParam(kCodecParamMinBitrate, &min_bitrate);
216d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  int max_bitrate = kMaxVideoBitrate;
217d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  codec.GetParam(kCodecParamMaxBitrate, &max_bitrate);
218d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.min_bitrate_bps = min_bitrate * 1000;
219d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate * 1000;
220d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
221d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  int max_qp = 56;
222d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
223d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.max_qp = max_qp;
224d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  std::vector<webrtc::VideoStream> streams;
225d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  streams.push_back(stream);
226d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  return streams;
227d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org}
228b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
229d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.orgwebrtc::VideoEncoder* WebRtcVideoEncoderFactory2::CreateVideoEncoder(
230d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoCodec& codec,
231d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoOptions& options) {
232d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  assert(SupportsCodec(codec));
233d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  return webrtc::VP8Encoder::Create();
234d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org}
235d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
236d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.orgbool WebRtcVideoEncoderFactory2::SupportsCodec(const VideoCodec& codec) {
237d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  return _stricmp(codec.name.c_str(), kVp8PayloadName) == 0;
238d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org}
239b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
240b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoEngine2::WebRtcVideoEngine2() {
241b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Construct without a factory or voice engine.
242b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  Construct(NULL, NULL, new talk_base::CpuMonitor(NULL));
243b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
244b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
245b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoEngine2::WebRtcVideoEngine2(
246b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoChannelFactory* channel_factory) {
247b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Construct without a voice engine.
248b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  Construct(channel_factory, NULL, new talk_base::CpuMonitor(NULL));
249b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
250b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
251b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoEngine2::Construct(WebRtcVideoChannelFactory* channel_factory,
252b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   WebRtcVoiceEngine* voice_engine,
253b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   talk_base::CpuMonitor* cpu_monitor) {
254b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2";
255b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  worker_thread_ = NULL;
256b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  voice_engine_ = voice_engine;
257b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  initialized_ = false;
258b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  capture_started_ = false;
259b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  cpu_monitor_.reset(cpu_monitor);
260b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  channel_factory_ = channel_factory;
261b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
262b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  video_codecs_ = DefaultVideoCodecs();
263b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  default_codec_format_ = VideoFormat(kDefaultVideoFormat);
264b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
265b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
266b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoEngine2::~WebRtcVideoEngine2() {
267b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2";
268b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
269b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (initialized_) {
270b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    Terminate();
271b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
272b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
273b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
274b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::Init(talk_base::Thread* worker_thread) {
275b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::Init";
276b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  worker_thread_ = worker_thread;
277b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  ASSERT(worker_thread_ != NULL);
278b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
279b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  cpu_monitor_->set_thread(worker_thread_);
280b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!cpu_monitor_->Start(kCpuMonitorPeriodMs)) {
281b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Failed to start CPU monitor.";
282b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    cpu_monitor_.reset();
283b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
284b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
285b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  initialized_ = true;
286b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
287b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
288b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
289b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoEngine2::Terminate() {
290b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::Terminate";
291b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
292b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  cpu_monitor_->Stop();
293b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
294b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  initialized_ = false;
295b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
296b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
297b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgint WebRtcVideoEngine2::GetCapabilities() { return VIDEO_RECV | VIDEO_SEND; }
298b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
299b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::SetOptions(const VideoOptions& options) {
300b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Do we need this? This is a no-op in the existing
301b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // WebRtcVideoEngine implementation.
302b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetOptions: " << options.ToString();
303b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  //  options_ = options;
304b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
305b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
306b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
307b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::SetDefaultEncoderConfig(
308b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoEncoderConfig& config) {
309b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement. Should be covered by corresponding unit tests.
310b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetDefaultEncoderConfig()";
311b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
312b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
313b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
314b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgVideoEncoderConfig WebRtcVideoEngine2::GetDefaultEncoderConfig() const {
315b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return VideoEncoderConfig(DefaultVideoCodec());
316b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
317b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
318b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel(
319b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VoiceMediaChannel* voice_channel) {
320b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "CreateChannel: "
321b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (voice_channel != NULL ? "With" : "Without")
322b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << " voice channel.";
323b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  WebRtcVideoChannel2* channel =
324b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      channel_factory_ != NULL
325b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          ? channel_factory_->Create(this, voice_channel)
326b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          : new WebRtcVideoChannel2(
3270d523eea831e616c415c61765127ed5eb17e5f11pbos@webrtc.org                this, voice_channel, GetVideoEncoderFactory());
328b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!channel->Init()) {
329b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    delete channel;
330b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
331b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
332b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return channel;
333b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
334b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
335b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgconst std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const {
336b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return video_codecs_;
337b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
338b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
339b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgconst std::vector<RtpHeaderExtension>&
340b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoEngine2::rtp_header_extensions() const {
341b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return rtp_header_extensions_;
342b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
343b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
344b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoEngine2::SetLogging(int min_sev, const char* filter) {
345b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Set up logging.
346b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetLogging: " << min_sev << '"' << filter << '"';
347b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // if min_sev == -1, we keep the current log level.
348b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (min_sev < 0) {
349b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    assert(min_sev == -1);
350b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
351b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
352b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
353b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
354b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::EnableTimedRender() {
355b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Figure out whether this can be removed.
356b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
357b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
358b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
359b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::SetLocalRenderer(VideoRenderer* renderer) {
360b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement or remove. Unclear which stream should be rendered
361b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // locally even.
362b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
363b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
364b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
365b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Checks to see whether we comprehend and could receive a particular codec
366b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) {
367b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Probe encoder factory to figure out that the codec is supported
368b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // if supported by the encoder factory. Add a corresponding test that fails
369b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // with this code (that doesn't ask the factory).
370b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (int i = 0; i < ARRAY_SIZE(kVideoFormats); ++i) {
371b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFormat fmt(kVideoFormats[i]);
372b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if ((in.width != 0 || in.height != 0) &&
373b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        (fmt.width != in.width || fmt.height != in.height)) {
374b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      continue;
375b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
376b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    for (size_t j = 0; j < video_codecs_.size(); ++j) {
377b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0);
378b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      if (codec.Matches(in)) {
379b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        return true;
380b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
381b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
382b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
383b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
384b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
385b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
386b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Tells whether the |requested| codec can be transmitted or not. If it can be
387b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// transmitted |out| is set with the best settings supported. Aspect ratio will
388b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// be set as close to |current|'s as possible. If not set |requested|'s
389b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// dimensions will be used for aspect ratio matching.
390b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested,
391b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                      const VideoCodec& current,
392b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                      VideoCodec* out) {
393b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(out != NULL);
394b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
395b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
396b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (requested.width != requested.height &&
397b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      (requested.height == 0 || requested.width == 0)) {
398b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // 0xn and nx0 are invalid resolutions.
399b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
400b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
401b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
402b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodec matching_codec;
403b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!FindFirstMatchingCodec(video_codecs_, requested, &matching_codec)) {
404b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Codec not supported.
405b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
406b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
407b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
408b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Pick the best quality that is within their and our bounds and has the
409b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // correct aspect ratio.
410b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoFormat format;
411b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (requested.width == 0 && requested.height == 0) {
412b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Special case with resolution 0. The channel should not send frames.
413b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
414b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    int max_width = talk_base::_min(requested.width, matching_codec.width);
415b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    int max_height = talk_base::_min(requested.height, matching_codec.height);
416b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    int aspect_width = max_width;
417b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    int aspect_height = max_height;
418b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (current.width > 0 && current.height > 0) {
419b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      aspect_width = current.width;
420b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      aspect_height = current.height;
421b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
422b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (!FindBestVideoFormat(
423b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org            max_width, max_height, aspect_width, aspect_height, &format)) {
424b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return false;
425b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
426b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
427b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
428b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->id = requested.id;
429b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->name = requested.name;
430b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->preference = requested.preference;
431b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->params = requested.params;
432b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->framerate =
433b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      talk_base::_min(requested.framerate, matching_codec.framerate);
434b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->width = format.width;
435b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->height = format.height;
436b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->params = requested.params;
437b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->feedback_params = requested.feedback_params;
438b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
439b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
440b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
441b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) {
442b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (initialized_) {
443b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "SetVoiceEngine can not be called after Init";
444b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
445b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
446b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  voice_engine_ = voice_engine;
447b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
448b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
449b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
450b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Ignore spammy trace messages, mostly from the stats API when we haven't
451b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// gotten RTCP info yet from the remote side.
452b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) {
453b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  static const char* const kTracesToIgnore[] = {NULL};
454b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (const char* const* p = kTracesToIgnore; *p; ++p) {
455b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (trace.find(*p) == 0) {
456b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
457b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
458b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
459b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
460b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
461b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
462d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.orgWebRtcVideoEncoderFactory2* WebRtcVideoEngine2::GetVideoEncoderFactory() {
463d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  return &default_video_encoder_factory_;
464b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
465b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
4666ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org// Thin map between VideoFrame and an existing webrtc::I420VideoFrame
467b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// to avoid having to copy the rendered VideoFrame prematurely.
468b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// This implementation is only safe to use in a const context and should never
469b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// be written to.
4706ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.orgclass WebRtcVideoRenderFrame : public VideoFrame {
471b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org public:
472b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  explicit WebRtcVideoRenderFrame(const webrtc::I420VideoFrame* frame)
473b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      : frame_(frame) {}
474b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
475b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual bool InitToBlack(int w,
476b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           int h,
477b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           size_t pixel_width,
478b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           size_t pixel_height,
479b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           int64 elapsed_time,
480b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                           int64 time_stamp) OVERRIDE {
481b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
482b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
483b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
484b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
485b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual bool Reset(uint32 fourcc,
486b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int w,
487b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int h,
488b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int dw,
489b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int dh,
490b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     uint8* sample,
491b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     size_t sample_size,
492b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     size_t pixel_width,
493b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     size_t pixel_height,
494b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int64 elapsed_time,
495b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int64 time_stamp,
496b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     int rotation) OVERRIDE {
497b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
498b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
499b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
500b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
501b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetWidth() const OVERRIDE {
502b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return static_cast<size_t>(frame_->width());
503b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
504b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetHeight() const OVERRIDE {
505b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return static_cast<size_t>(frame_->height());
506b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
507b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
508b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual const uint8* GetYPlane() const OVERRIDE {
509b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->buffer(webrtc::kYPlane);
510b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
511b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual const uint8* GetUPlane() const OVERRIDE {
512b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->buffer(webrtc::kUPlane);
513b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
514b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual const uint8* GetVPlane() const OVERRIDE {
515b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->buffer(webrtc::kVPlane);
516b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
517b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
518b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual uint8* GetYPlane() OVERRIDE {
519b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
520b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
521b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
522b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual uint8* GetUPlane() OVERRIDE {
523b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
524b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
525b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
526b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual uint8* GetVPlane() OVERRIDE {
527b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
528b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
529b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
530b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
531b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int32 GetYPitch() const OVERRIDE {
532b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->stride(webrtc::kYPlane);
533b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
534b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int32 GetUPitch() const OVERRIDE {
535b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->stride(webrtc::kUPlane);
536b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
537b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int32 GetVPitch() const OVERRIDE {
538b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->stride(webrtc::kVPlane);
539b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
540b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
541b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual void* GetNativeHandle() const OVERRIDE { return NULL; }
542b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
543b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetPixelWidth() const OVERRIDE { return 1; }
544b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t GetPixelHeight() const OVERRIDE { return 1; }
545b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
546b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int64 GetElapsedTime() const OVERRIDE {
547b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Convert millisecond render time to ns timestamp.
548b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame_->render_time_ms() * talk_base::kNumNanosecsPerMillisec;
549b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
550b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int64 GetTimeStamp() const OVERRIDE {
551b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Convert 90K rtp timestamp to ns timestamp.
552b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return (frame_->timestamp() / 90) * talk_base::kNumNanosecsPerMillisec;
553b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
554b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual void SetElapsedTime(int64 elapsed_time) OVERRIDE { UNIMPLEMENTED; }
555b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual void SetTimeStamp(int64 time_stamp) OVERRIDE { UNIMPLEMENTED; }
556b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
557b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual int GetRotation() const OVERRIDE {
558b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
559b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return ROTATION_0;
560b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
561b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
562b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual VideoFrame* Copy() const OVERRIDE {
563b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
564b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
565b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
566b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
567b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual bool MakeExclusive() OVERRIDE {
568b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
569b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
570b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
571b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
572b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t CopyToBuffer(uint8* buffer, size_t size) const {
573b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    UNIMPLEMENTED;
574b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return 0;
575b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
576b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
577b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(fbarchard): Refactor into base class and share with LMI
578b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual size_t ConvertToRgbBuffer(uint32 to_fourcc,
579b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    uint8* buffer,
580b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    size_t size,
581b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    int stride_rgb) const OVERRIDE {
582b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    size_t width = GetWidth();
583b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    size_t height = GetHeight();
584b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    size_t needed = (stride_rgb >= 0 ? stride_rgb : -stride_rgb) * height;
585b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (size < needed) {
586b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_WARNING) << "RGB buffer is not large enough";
587b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return needed;
588b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
589b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
590b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (libyuv::ConvertFromI420(GetYPlane(),
591b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetYPitch(),
592b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetUPlane(),
593b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetUPitch(),
594b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetVPlane(),
595b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                GetVPitch(),
596b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                buffer,
597b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                stride_rgb,
598b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                static_cast<int>(width),
599b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                static_cast<int>(height),
600b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                to_fourcc)) {
601b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "RGB type not supported: " << to_fourcc;
602b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return 0;  // 0 indicates error
603b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
604b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return needed;
605b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
606b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
607b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org protected:
608b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  virtual VideoFrame* CreateEmptyFrame(int w,
609b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       int h,
610b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       size_t pixel_width,
611b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       size_t pixel_height,
612b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       int64 elapsed_time,
613b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                       int64 time_stamp) const OVERRIDE {
614b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // TODO(pbos): Remove WebRtcVideoFrame dependency, and have a non-const
615b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // version of I420VideoFrame wrapped.
616b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoFrame* frame = new WebRtcVideoFrame();
617b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    frame->InitToBlack(
618b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        w, h, pixel_width, pixel_height, elapsed_time, time_stamp);
619b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return frame;
620b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
621b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
622b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org private:
623b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const webrtc::I420VideoFrame* const frame_;
624b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org};
625b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
626b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoRenderer::WebRtcVideoRenderer()
627b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    : last_width_(-1), last_height_(-1), renderer_(NULL) {}
628b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
629b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoRenderer::RenderFrame(const webrtc::I420VideoFrame& frame,
630b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                      int time_to_render_ms) {
631b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope crit(&lock_);
632b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (renderer_ == NULL) {
633b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer.";
634b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
635b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
636b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
637b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (frame.width() != last_width_ || frame.height() != last_height_) {
638b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    SetSize(frame.width(), frame.height());
639b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
640b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
641b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "RenderFrame: (" << frame.width() << "x" << frame.height()
642b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << ")";
643b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
644b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const WebRtcVideoRenderFrame render_frame(&frame);
645b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  renderer_->RenderFrame(&render_frame);
646b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
647b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
648b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoRenderer::SetRenderer(cricket::VideoRenderer* renderer) {
649b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope crit(&lock_);
650b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  renderer_ = renderer;
651b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (renderer_ != NULL && last_width_ != -1) {
652b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    SetSize(last_width_, last_height_);
653b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
654b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
655b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
656b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgVideoRenderer* WebRtcVideoRenderer::GetRenderer() {
657b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope crit(&lock_);
658b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return renderer_;
659b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
660b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
661b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoRenderer::SetSize(int width, int height) {
662b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope crit(&lock_);
663b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!renderer_->SetSize(width, height, 0)) {
664b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Could not set renderer size.";
665b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
666b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  last_width_ = width;
667b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  last_height_ = height;
668b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
669b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
670b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// WebRtcVideoChannel2
671b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
672b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoChannel2(
673b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoEngine2* engine,
674b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VoiceMediaChannel* voice_channel,
675b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoEncoderFactory2* encoder_factory)
676b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    : encoder_factory_(encoder_factory) {
677b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Connect the video and audio with |voice_channel|.
678b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::Call::Config config(this);
679b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  Construct(webrtc::Call::Create(config), engine);
680b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
681b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
682b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoChannel2(
683b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    webrtc::Call* call,
684b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoEngine2* engine,
685b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoEncoderFactory2* encoder_factory)
686b5a22b14648c53874b4b76368a1a2271d985e875pbos@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_renderer_ = NULL;
696b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  default_send_ssrc_ = 0;
697b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  default_recv_ssrc_ = 0;
698b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
699b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
700b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::~WebRtcVideoChannel2() {
701b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
702b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
703b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
704b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
705b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    delete it->second;
706b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
707b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
708b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, webrtc::VideoReceiveStream*>::iterator it =
709b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           receive_streams_.begin();
710b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != receive_streams_.end();
711b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
712b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    assert(it->second != NULL);
713b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    call_->DestroyVideoReceiveStream(it->second);
714b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
715b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
716b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoRenderer*>::iterator it = renderers_.begin();
717b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != renderers_.end();
718b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
719b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    assert(it->second != NULL);
720b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    delete it->second;
721b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
722b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
723b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
724b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::Init() { return true; }
725b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
726b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgnamespace {
727b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
728b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) {
729b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
730b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (!codecs[i].ValidateCodecFormat()) {
731b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return false;
732b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
733b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
734b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
735b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
736b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
737b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {
738b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::stringstream out;
739b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out << '{';
740b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
741b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    out << codecs[i].ToString();
742b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (i != codecs.size() - 1) {
743b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      out << ", ";
744b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
745b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
746b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out << '}';
747b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return out.str();
748b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
749b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
750b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}  // namespace
751b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
752b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
753b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Must these receive codecs propagate to existing receive
754b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // streams?
755b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs);
756b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
757b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
758b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
759b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
760b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs);
761b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (mapped_codecs.empty()) {
762b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "SetRecvCodecs called without video codec payloads.";
763b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
764b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
765b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
766b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Add a decoder factory which controls supported codecs.
767b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Blocked on webrtc:2854.
768b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
769b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (_stricmp(mapped_codecs[i].codec.name.c_str(), kVp8PayloadName) != 0) {
770b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "SetRecvCodecs called with unsupported codec: '"
771b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << mapped_codecs[i].codec.name << "'";
772b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return false;
773b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
774b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
775b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
776b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  recv_codecs_ = mapped_codecs;
777b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
778b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
779b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
780b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
781b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetSendCodecs: " << CodecVectorToString(codecs);
782b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
783b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
784b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
785b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
786b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const std::vector<VideoCodecSettings> supported_codecs =
787b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      FilterSupportedCodecs(MapCodecs(codecs));
788b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
789b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (supported_codecs.empty()) {
790b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No video codecs supported by encoder factory.";
791b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
792b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
793b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
794b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  send_codec_.Set(supported_codecs.front());
795b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString();
796b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
797b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  SetCodecForAllSendStreams(supported_codecs.front());
798b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
799b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
800b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
801b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
802b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) {
803b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodecSettings codec_settings;
804b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!send_codec_.Get(&codec_settings)) {
805b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "GetSendCodec: No send codec set.";
806b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
807b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
808b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  *codec = codec_settings.codec;
809b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
810b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
811b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
812b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendStreamFormat(uint32 ssrc,
813b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                              const VideoFormat& format) {
814b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetSendStreamFormat:" << ssrc << " -> "
815b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << format.ToString();
816b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
817b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
818b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
819b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return send_streams_[ssrc]->SetVideoFormat(format);
820b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
821b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
822b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRender(bool render) {
823b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement. Or refactor away as it shouldn't be needed.
824b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetRender: " << (render ? "true" : "false");
825b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
826b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
827b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
828b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSend(bool send) {
829b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false");
830b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send && !send_codec_.IsSet()) {
831b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "SetSend(true) called before setting codec.";
832b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
833b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
834b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send) {
835b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    StartAllSendStreams();
836b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
837b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    StopAllSendStreams();
838b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
839b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = send;
840b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
841b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
842b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
843b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic bool ConfigureSendSsrcs(webrtc::VideoSendStream::Config* config,
844b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                               const StreamParams& sp) {
845b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!sp.has_ssrc_groups()) {
846b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    config->rtp.ssrcs = sp.ssrcs;
847b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return true;
848b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
849b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
850b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sp.get_ssrc_group(kFecSsrcGroupSemantics) != NULL) {
851b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Standalone FEC SSRCs not supported.";
852b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
853b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
854b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
855b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const SsrcGroup* sim_group = sp.get_ssrc_group(kSimSsrcGroupSemantics);
856b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sim_group == NULL) {
857b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Grouped StreamParams without regular SSRC group: "
858b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << sp.ToString();
859b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
860b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
861b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
862b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Map RTX SSRCs.
863b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<uint32_t> rtx_ssrcs;
864b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < sim_group->ssrcs.size(); ++i) {
865b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    uint32_t rtx_ssrc;
866b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (!sp.GetFidSsrc(sim_group->ssrcs[i], &rtx_ssrc)) {
867b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      continue;
868b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
869b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    rtx_ssrcs.push_back(rtx_ssrc);
870b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
871b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!rtx_ssrcs.empty() && sim_group->ssrcs.size() != rtx_ssrcs.size()) {
872b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR)
873b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): "
874b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        << sp.ToString();
875b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
876b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
877b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  config->rtp.rtx.ssrcs = rtx_ssrcs;
878b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  config->rtp.ssrcs = sim_group->ssrcs;
879b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
880b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
881b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
882b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
883b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
884b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sp.ssrcs.empty()) {
885b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No SSRCs in stream parameters.";
886b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
887b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
888b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
889b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
890b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);
891b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Make sure none of sp.ssrcs are used, not just the identifying
892b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // ssrc.
893b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) != send_streams_.end()) {
894b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Send stream with ssrc '" << ssrc << "' already exists.";
895b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
896b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
897b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
898b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::VideoSendStream::Config config = call_->GetDefaultSendConfig();
899b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
900b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!ConfigureSendSsrcs(&config, sp)) {
901b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
902b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
903b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
904b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodecSettings codec_settings;
905b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!send_codec_.Get(&codec_settings)) {
906b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // TODO(pbos): Set up a temporary fake encoder for VideoSendStream instead
907b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // of setting default codecs not to break CreateEncoderSettings.
908b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    SetSendCodecs(DefaultVideoCodecs());
909b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    assert(send_codec_.IsSet());
910b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    send_codec_.Get(&codec_settings);
911b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // This is only to bring up defaults to make VideoSendStream setup easier
912b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // and avoid complexity. We still don't want to allow sending with the
913b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // default codec.
914b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    send_codec_.Clear();
915b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
916b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
917b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // CreateEncoderSettings will allocate a suitable VideoEncoder instance
918b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // matching current settings.
9196ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  std::vector<webrtc::VideoStream> video_streams =
9206ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      encoder_factory_->CreateVideoStreams(
9216ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org          codec_settings.codec, options_, config.rtp.ssrcs.size());
9226ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  if (video_streams.empty()) {
923b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
924b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
925b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
9266ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  config.encoder_settings.encoder =
9276ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      encoder_factory_->CreateVideoEncoder(codec_settings.codec, options_);
9286ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  config.encoder_settings.payload_name = codec_settings.codec.name;
9296ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  config.encoder_settings.payload_type = codec_settings.codec.id;
930b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  config.rtp.c_name = sp.cname;
931b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  config.rtp.fec = codec_settings.fec;
932b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!config.rtp.rtx.ssrcs.empty()) {
933b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    config.rtp.rtx.payload_type = codec_settings.rtx_payload_type;
934b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
935b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
936b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  config.rtp.nack.rtp_history_ms = kNackHistoryMs;
937b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  config.rtp.max_packet_size = kVideoMtu;
938b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
939b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  WebRtcVideoSendStream* stream =
9406ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      new WebRtcVideoSendStream(call_.get(),
9416ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org                                config,
9426ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org                                options_,
9436ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org                                codec_settings.codec,
9446ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org                                video_streams,
9456ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org                                encoder_factory_);
946b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  send_streams_[ssrc] = stream;
947b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
948b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) {
949b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    rtcp_receiver_report_ssrc_ = ssrc;
950b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
951b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (default_send_ssrc_ == 0) {
952b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_send_ssrc_ = ssrc;
953b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
954b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sending_) {
955b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    stream->Start();
956b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
957b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
958b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
959b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
960b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
961b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RemoveSendStream(uint32 ssrc) {
962b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
963b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
964b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
965b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (default_send_ssrc_ == 0) {
966b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "No default send stream active.";
967b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return false;
968b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
969b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
970b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "Removing default stream: " << default_send_ssrc_;
971b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    ssrc = default_send_ssrc_;
972b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
973b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
974b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<uint32, WebRtcVideoSendStream*>::iterator it =
975b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      send_streams_.find(ssrc);
976b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (it == send_streams_.end()) {
977b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
978b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
979b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
980b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  delete it->second;
981b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  send_streams_.erase(it);
982b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
983b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == default_send_ssrc_) {
984b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_send_ssrc_ = 0;
985b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
986b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
987b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
988b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
989b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
990b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) {
991b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
992b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(sp.ssrcs.size() > 0);
993b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
994b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
995b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);  // TODO(pbos): Is this ever valid?
996b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (default_recv_ssrc_ == 0) {
997b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_recv_ssrc_ = ssrc;
998b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
999b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1000b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Check if any of the SSRCs overlap.
1001b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (receive_streams_.find(ssrc) != receive_streams_.end()) {
1002b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Receive stream for SSRC " << ssrc << "already exists.";
1003b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1004b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1005b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1006b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::VideoReceiveStream::Config config = call_->GetDefaultReceiveConfig();
1007b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  config.rtp.remote_ssrc = ssrc;
1008b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  config.rtp.local_ssrc = rtcp_receiver_report_ssrc_;
1009b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 rtx_ssrc = 0;
1010b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sp.GetFidSsrc(ssrc, &rtx_ssrc)) {
1011b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // TODO(pbos): Right now, VideoReceiveStream accepts any rtx payload, this
1012b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    //             should use the actual codec payloads that may be received.
1013b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    //             (for each receive payload, set rtx[payload].ssrc = rtx_ssrc.
1014b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    config.rtp.rtx[0].ssrc = rtx_ssrc;
1015b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1016b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1017198647473ba207d59dc94216ef38496d43d15592pbos@webrtc.org  config.rtp.nack.rtp_history_ms = kNackHistoryMs;
1018b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  config.rtp.remb = true;
1019b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): This protection is against setting the same local ssrc as
1020b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // remote which is not permitted by the lower-level API. RTCP requires a
1021b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // corresponding sender SSRC. Figure out what to do when we don't have
1022b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // (receive-only) or know a good local SSRC.
1023b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (config.rtp.remote_ssrc == config.rtp.local_ssrc) {
1024b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (config.rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) {
1025b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      config.rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc;
1026b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    } else {
1027b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      config.rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1;
1028b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1029b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1030b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  bool default_renderer_used = false;
1031b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoRenderer*>::iterator it = renderers_.begin();
1032b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != renderers_.end();
1033b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
1034b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (it->second->GetRenderer() == default_renderer_) {
1035b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      default_renderer_used = true;
1036b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      break;
1037b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1038b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1039b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1040b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(renderers_[ssrc] == NULL);
1041b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  renderers_[ssrc] = new WebRtcVideoRenderer();
1042b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!default_renderer_used) {
1043b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    renderers_[ssrc]->SetRenderer(default_renderer_);
1044b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1045b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  config.renderer = renderers_[ssrc];
1046b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1047b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  {
1048b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // TODO(pbos): Base receive codecs off recv_codecs_ and set up using a
1049b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // DecoderFactory similar to send side. Pending webrtc:2854.
1050b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Also set up default codecs if there's nothing in recv_codecs_.
1051b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    webrtc::VideoCodec codec;
1052b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    memset(&codec, 0, sizeof(codec));
1053b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1054b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codec.plType = kDefaultVideoCodecPref.payload_type;
1055b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    strcpy(codec.plName, kDefaultVideoCodecPref.name);
1056b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codec.codecType = webrtc::kVideoCodecVP8;
1057b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codec.codecSpecific.VP8.resilience = webrtc::kResilientStream;
1058b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codec.codecSpecific.VP8.numberOfTemporalLayers = 1;
1059b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codec.codecSpecific.VP8.denoisingOn = true;
1060b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codec.codecSpecific.VP8.errorConcealmentOn = false;
1061b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codec.codecSpecific.VP8.automaticResizeOn = false;
1062b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codec.codecSpecific.VP8.frameDroppingOn = true;
1063b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codec.codecSpecific.VP8.keyFrameInterval = 3000;
1064b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Bitrates don't matter and are ignored for the receiver. This is put in to
1065b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // have the current underlying implementation accept the VideoCodec.
1066b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    codec.minBitrate = codec.startBitrate = codec.maxBitrate = 300;
1067b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    config.codecs.push_back(codec);
1068b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    for (size_t i = 0; i < recv_codecs_.size(); ++i) {
1069b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      if (recv_codecs_[i].codec.id == codec.plType) {
1070b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        config.rtp.fec = recv_codecs_[i].fec;
1071b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        if (recv_codecs_[i].rtx_payload_type != -1 && rtx_ssrc != 0) {
1072b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          config.rtp.rtx[codec.plType].ssrc = rtx_ssrc;
1073b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          config.rtp.rtx[codec.plType].payload_type =
1074b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org              recv_codecs_[i].rtx_payload_type;
1075b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        }
1076b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        break;
1077b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
1078b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1079b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1080b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1081b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::VideoReceiveStream* receive_stream =
1082b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      call_->CreateVideoReceiveStream(config);
1083b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(receive_stream != NULL);
1084b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1085b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  receive_streams_[ssrc] = receive_stream;
1086b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  receive_stream->Start();
1087b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1088b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1089b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1090b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1091b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) {
1092b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1093b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1094b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    ssrc = default_recv_ssrc_;
1095b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1096b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1097b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<uint32, webrtc::VideoReceiveStream*>::iterator stream =
1098b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      receive_streams_.find(ssrc);
1099b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (stream == receive_streams_.end()) {
1100b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc;
1101b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1102b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1103b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  call_->DestroyVideoReceiveStream(stream->second);
1104b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  receive_streams_.erase(stream);
1105b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1106b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<uint32, WebRtcVideoRenderer*>::iterator renderer =
1107b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      renderers_.find(ssrc);
1108b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(renderer != renderers_.end());
1109b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  delete renderer->second;
1110b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  renderers_.erase(renderer);
1111b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1112b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == default_recv_ssrc_) {
1113b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_recv_ssrc_ = 0;
1114b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1115b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1116b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1117b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1118b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1119b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
1120b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " "
1121b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (renderer ? "(ptr)" : "NULL");
1122b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  bool is_default_ssrc = false;
1123b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1124b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    is_default_ssrc = true;
1125b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    ssrc = default_recv_ssrc_;
1126b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_renderer_ = renderer;
1127b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1128b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1129b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<uint32, WebRtcVideoRenderer*>::iterator it = renderers_.find(ssrc);
1130b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (it == renderers_.end()) {
1131b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return is_default_ssrc;
1132b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1133b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1134b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  it->second->SetRenderer(renderer);
1135b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1136b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1137b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1138b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetRenderer(uint32 ssrc, VideoRenderer** renderer) {
1139b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1140b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (default_renderer_ == NULL) {
1141b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return false;
1142b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1143b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    *renderer = default_renderer_;
1144b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return true;
1145b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1146b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1147b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<uint32, WebRtcVideoRenderer*>::iterator it = renderers_.find(ssrc);
1148b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (it == renderers_.end()) {
1149b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1150b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1151b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  *renderer = it->second->GetRenderer();
1152b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1153b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1154b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1155b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetStats(const StatsOptions& options,
1156b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   VideoMediaInfo* info) {
1157b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1158b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1159b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1160b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1161b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetCapturer(uint32 ssrc, VideoCapturer* capturer) {
1162b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> "
1163b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (capturer != NULL ? "(capturer)" : "NULL");
1164b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);
1165b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
1166b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1167b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1168b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1169b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return send_streams_[ssrc]->SetCapturer(capturer);
1170b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1171b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1172b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendIntraFrame() {
1173b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1174b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
1175b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1176b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1177b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1178b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RequestIntraFrame() {
1179b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1180b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
1181b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1182b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1183b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1184b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnPacketReceived(
1185b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    talk_base::Buffer* packet,
1186b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const talk_base::PacketTime& packet_time) {
11874e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org  const webrtc::PacketReceiver::DeliveryStatus delivery_result =
11884e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      call_->Receiver()->DeliverPacket(
11894e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length());
11904e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org  switch (delivery_result) {
11914e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_OK:
11924e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      return;
11934e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR:
11944e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      return;
11954e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC:
11964e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      break;
1197b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1198b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1199b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 ssrc = 0;
1200b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (default_recv_ssrc_ != 0) {  // Already one default stream.
12014e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    LOG(LS_WARNING) << "Unknown SSRC, but default receive stream already set.";
1202b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1203b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1204b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1205b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!GetRtpSsrc(packet->data(), packet->length(), &ssrc)) {
1206b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1207b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1208b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1209b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  StreamParams sp;
1210b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sp.ssrcs.push_back(ssrc);
1211c34bb3a88627672d99b1c037d36dbeb23407fae4pbos@webrtc.org  LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << ".";
1212b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  AddRecvStream(sp);
1213b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
12141e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org  if (call_->Receiver()->DeliverPacket(
12151e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
12161e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org      webrtc::PacketReceiver::DELIVERY_OK) {
12171e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org    LOG(LS_WARNING) << "Failed to deliver RTP packet after creating default "
12181e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org                       "receiver.";
1219b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1220b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1221b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1222b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1223b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnRtcpReceived(
1224b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    talk_base::Buffer* packet,
1225b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const talk_base::PacketTime& packet_time) {
12261e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org  if (call_->Receiver()->DeliverPacket(
12271e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
12281e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org      webrtc::PacketReceiver::DELIVERY_OK) {
1229b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "Failed to deliver RTCP packet.";
1230b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1231b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1232b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1233b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnReadyToSend(bool ready) {
1234b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "OnReadySend: " << (ready ? "Ready." : "Not ready.");
1235b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1236b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1237b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::MuteStream(uint32 ssrc, bool mute) {
1238b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "MuteStream: " << ssrc << " -> "
1239b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << (mute ? "mute" : "unmute");
1240b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(ssrc != 0);
1241b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
1242b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1243b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1244b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1245b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return send_streams_[ssrc]->MuteStream(mute);
1246b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1247b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1248b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
1249b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
1250b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1251b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetRecvRtpHeaderExtensions()";
1252b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1253b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1254b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1255b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
1256b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
1257b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1258b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetSendRtpHeaderExtensions()";
1259b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1260b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1261b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1262b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetStartSendBandwidth(int bps) {
1263b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1264b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetStartSendBandwidth: " << bps;
1265b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1266b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1267b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1268b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetMaxSendBandwidth(int bps) {
1269b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1270b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetMaxSendBandwidth: " << bps;
1271b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1272b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1273b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1274b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) {
1275b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetOptions: " << options.ToString();
1276b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  options_.SetAll(options);
1277b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1278b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1279b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1280b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) {
1281b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  MediaChannel::SetInterface(iface);
1282b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Set the RTP recv/send buffer to a bigger size
1283b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  MediaChannel::SetOption(NetworkInterface::ST_RTP,
1284b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                          talk_base::Socket::OPT_RCVBUF,
1285b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                          kVideoRtpBufferSize);
1286b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1287b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(sriniv): Remove or re-enable this.
1288b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // As part of b/8030474, send-buffer is size now controlled through
1289b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // portallocator flags.
1290b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // network_interface_->SetOption(NetworkInterface::ST_RTP,
1291b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  //                              talk_base::Socket::OPT_SNDBUF,
1292b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  //                              kVideoRtpBufferSize);
1293b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1294b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1295b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::UpdateAspectRatio(int ratio_w, int ratio_h) {
1296b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1297b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1298b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1299b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnMessage(talk_base::Message* msg) {
1300b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Ignored.
1301b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1302b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1303b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendRtp(const uint8_t* data, size_t len) {
1304b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::Buffer packet(data, len, kMaxRtpPacketLen);
1305b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return MediaChannel::SendPacket(&packet);
1306b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1307b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1308b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendRtcp(const uint8_t* data, size_t len) {
1309b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::Buffer packet(data, len, kMaxRtpPacketLen);
1310b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return MediaChannel::SendRtcp(&packet);
1311b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1312b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1313b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::StartAllSendStreams() {
1314b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1315b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
1316b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
1317b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
1318b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    it->second->Start();
1319b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1320b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1321b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1322b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::StopAllSendStreams() {
1323b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1324b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
1325b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
1326b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
1327b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    it->second->Stop();
1328b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1329b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1330b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1331b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::SetCodecForAllSendStreams(
1332b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const WebRtcVideoChannel2::VideoCodecSettings& codec) {
1333b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1334b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
1335b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
1336b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
1337b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    assert(it->second != NULL);
1338b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    it->second->SetCodec(options_, codec);
1339b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1340b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1341b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
13426ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters::
13436ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    VideoSendStreamParameters(
13446ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const webrtc::VideoSendStream::Config& config,
13456ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const VideoOptions& options,
13466ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const VideoCodec& codec,
13476ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const std::vector<webrtc::VideoStream>& video_streams)
13486ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    : config(config),
13496ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      options(options),
13506ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      codec(codec),
13516ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      video_streams(video_streams) {
13526ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org}
13536ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
1354b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
1355b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    webrtc::Call* call,
1356b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const webrtc::VideoSendStream::Config& config,
13576ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    const VideoOptions& options,
13586ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    const VideoCodec& codec,
13596ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    const std::vector<webrtc::VideoStream>& video_streams,
1360b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    WebRtcVideoEncoderFactory2* encoder_factory)
1361b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    : call_(call),
13626ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      parameters_(config, options, codec, video_streams),
1363b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      encoder_factory_(encoder_factory),
1364b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      capturer_(NULL),
1365b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      stream_(NULL),
1366b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      sending_(false),
1367b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      muted_(false),
13686ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      format_(static_cast<int>(video_streams.back().height),
13696ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org              static_cast<int>(video_streams.back().width),
13706ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org              VideoFormat::FpsToInterval(video_streams.back().max_framerate),
1371b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org              FOURCC_I420) {
1372b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  RecreateWebRtcStream();
1373b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1374b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1375b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() {
1376b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  DisconnectCapturer();
1377b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  call_->DestroyVideoSendStream(stream_);
13786ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  delete parameters_.config.encoder_settings.encoder;
1379b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1380b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1381b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic void SetWebRtcFrameToBlack(webrtc::I420VideoFrame* video_frame) {
1382b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(video_frame != NULL);
1383b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  memset(video_frame->buffer(webrtc::kYPlane),
1384b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         16,
1385b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         video_frame->allocated_size(webrtc::kYPlane));
1386b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  memset(video_frame->buffer(webrtc::kUPlane),
1387b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         128,
1388b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         video_frame->allocated_size(webrtc::kUPlane));
1389b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  memset(video_frame->buffer(webrtc::kVPlane),
1390b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         128,
1391b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org         video_frame->allocated_size(webrtc::kVPlane));
1392b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1393b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1394b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic void CreateBlackFrame(webrtc::I420VideoFrame* video_frame,
1395b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                             int width,
1396b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                             int height) {
1397b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  video_frame->CreateEmptyFrame(
1398b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      width, height, width, (width + 1) / 2, (width + 1) / 2);
1399b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  SetWebRtcFrameToBlack(video_frame);
1400b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1401b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1402b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic void ConvertToI420VideoFrame(const VideoFrame& frame,
1403b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                    webrtc::I420VideoFrame* i420_frame) {
1404b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  i420_frame->CreateFrame(
1405b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetYPitch() * frame.GetHeight()),
1406b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      frame.GetYPlane(),
1407b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetUPitch() * ((frame.GetHeight() + 1) / 2)),
1408b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      frame.GetUPlane(),
1409b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetVPitch() * ((frame.GetHeight() + 1) / 2)),
1410b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      frame.GetVPlane(),
1411b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetWidth()),
1412b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetHeight()),
1413b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetYPitch()),
1414b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetUPitch()),
1415b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      static_cast<int>(frame.GetVPitch()));
1416b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1417b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1418b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
1419b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VideoCapturer* capturer,
1420b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFrame* frame) {
1421b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "InputFrame: " << frame->GetWidth() << "x"
1422b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << frame->GetHeight();
1423b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  bool is_screencast = capturer->IsScreencast();
1424b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Lock before copying, can be called concurrently when swapping input source.
1425b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope frame_cs(&frame_lock_);
1426b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!muted_) {
1427b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    ConvertToI420VideoFrame(*frame, &video_frame_);
1428b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
1429b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Create a tiny black frame to transmit instead.
1430b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    CreateBlackFrame(&video_frame_, 1, 1);
1431b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    is_screencast = false;
1432b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1433b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope cs(&lock_);
1434b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (format_.width == 0) {  // Dropping frames.
1435b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    assert(format_.height == 0);
1436b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "VideoFormat 0x0 set, Dropping frame.";
1437b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1438b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1439b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Reconfigure codec if necessary.
1440b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (is_screencast) {
1441b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    SetDimensions(video_frame_.width(), video_frame_.height());
1442b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1443b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x"
1444b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << video_frame_.height() << " -> (codec) "
14456ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org                  << parameters_.video_streams.back().width << "x"
14466ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org                  << parameters_.video_streams.back().height;
1447b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  stream_->Input()->SwapFrame(&video_frame_);
1448b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1449b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1450b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer(
1451b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VideoCapturer* capturer) {
1452b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!DisconnectCapturer() && capturer == NULL) {
1453b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1454b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1455b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1456b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  {
1457b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    talk_base::CritScope cs(&lock_);
1458b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1459b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (capturer == NULL) {
1460b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
1461b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      webrtc::I420VideoFrame black_frame;
1462b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1463b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      int width = format_.width;
1464b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      int height = format_.height;
1465b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      int half_width = (width + 1) / 2;
1466b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      black_frame.CreateEmptyFrame(
1467b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          width, height, width, half_width, half_width);
1468b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      SetWebRtcFrameToBlack(&black_frame);
1469b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      SetDimensions(width, height);
1470b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      stream_->Input()->SwapFrame(&black_frame);
1471b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1472b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      capturer_ = NULL;
1473b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
1474b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1475b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1476b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    capturer_ = capturer;
1477b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1478b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Lock cannot be held while connecting the capturer to prevent lock-order
1479b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // violations.
1480b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame);
1481b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1482b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1483b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1484b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat(
1485b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFormat& format) {
1486b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if ((format.width == 0 || format.height == 0) &&
1487b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      format.width != format.height) {
1488b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Can't set VideoFormat, width or height is zero (but not "
1489b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     "both, 0x0 drops frames).";
1490b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1491b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1492b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1493b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope cs(&lock_);
1494b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (format.width == 0 && format.height == 0) {
1495b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_INFO)
1496b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        << "0x0 resolution selected. Captured frames will be dropped for ssrc: "
14976ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        << parameters_.config.rtp.ssrcs[0] << ".";
1498b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
1499b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // TODO(pbos): Fix me, this only affects the last stream!
15006ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    parameters_.video_streams.back().max_framerate =
1501b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        VideoFormat::IntervalToFps(format.interval);
1502b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    SetDimensions(format.width, format.height);
1503b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1504b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1505b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  format_ = format;
1506b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1507b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1508b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1509b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::MuteStream(bool mute) {
1510b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope cs(&lock_);
1511b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  bool was_muted = muted_;
1512b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  muted_ = mute;
1513b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return was_muted != mute;
1514b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1515b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1516b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() {
1517b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope cs(&lock_);
1518b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (capturer_ == NULL) {
1519b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1520b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1521b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  capturer_->SignalVideoFrame.disconnect(this);
1522b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  capturer_ = NULL;
1523b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1524b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1525b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1526b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
1527b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoOptions& options,
1528b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoCodecSettings& codec) {
1529b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope cs(&lock_);
15306ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
15316ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  std::vector<webrtc::VideoStream> video_streams =
15326ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      encoder_factory_->CreateVideoStreams(
15336ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org          codec.codec, options, parameters_.video_streams.size());
15346ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  if (video_streams.empty()) {
1535b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1536b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
15376ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.video_streams = video_streams;
1538b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  format_ = VideoFormat(codec.codec.width,
1539b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        codec.codec.height,
1540b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        VideoFormat::FpsToInterval(30),
1541b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        FOURCC_I420);
15426ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
15436ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  webrtc::VideoEncoder* old_encoder =
15446ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      parameters_.config.encoder_settings.encoder;
15456ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.config.encoder_settings.encoder =
15466ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      encoder_factory_->CreateVideoEncoder(codec.codec, options);
15476ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.config.rtp.fec = codec.fec;
1548b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Should changing RTX payload type be allowed?
15496ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.codec = codec.codec;
15506ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.options = options;
1551b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  RecreateWebRtcStream();
1552b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  delete old_encoder;
1553b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1554b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1555b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(int width,
15566ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org                                                               int height) {
15576ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  assert(!parameters_.video_streams.empty());
1558b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetDimensions: " << width << "x" << height;
15596ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  if (parameters_.video_streams.back().width == width &&
15606ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      parameters_.video_streams.back().height == height) {
1561b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1562b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1563b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1564b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Fix me, this only affects the last stream!
15656ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.video_streams.back().width = width;
15666ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.video_streams.back().height = height;
15676ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
15686ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  // TODO(pbos): Wire up encoder_parameters, webrtc:3424.
15696ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  if (!stream_->ReconfigureVideoEncoder(parameters_.video_streams, NULL)) {
1570b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: "
1571b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << width << "x" << height;
1572b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1573b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1574b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1575b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1576b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::Start() {
1577b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope cs(&lock_);
1578b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  stream_->Start();
1579b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = true;
1580b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1581b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1582b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::Stop() {
1583b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  talk_base::CritScope cs(&lock_);
1584b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  stream_->Stop();
1585b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = false;
1586b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1587b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1588b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
1589b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (stream_ != NULL) {
1590b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    call_->DestroyVideoSendStream(stream_);
1591b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
15926ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
15936ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  // TODO(pbos): Wire up encoder_parameters, webrtc:3424.
15946ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  stream_ = call_->CreateVideoSendStream(
15956ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      parameters_.config, parameters_.video_streams, NULL);
1596b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sending_) {
1597b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    stream_->Start();
1598b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1599b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1600b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1601b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings()
1602b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    : rtx_payload_type(-1) {}
1603b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1604b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
1605b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) {
1606b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(!codecs.empty());
1607b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1608b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<VideoCodecSettings> video_codecs;
1609b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<int, bool> payload_used;
1610b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<int, int> rtx_mapping;  // video payload type -> rtx payload type.
1611b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1612b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::FecConfig fec_settings;
1613b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1614b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
1615b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoCodec& in_codec = codecs[i];
1616b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    int payload_type = in_codec.id;
1617b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1618b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (payload_used[payload_type]) {
1619b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "Payload type already registered: "
1620b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << in_codec.ToString();
1621b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return std::vector<VideoCodecSettings>();
1622b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1623b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    payload_used[payload_type] = true;
1624b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1625b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    switch (in_codec.GetCodecType()) {
1626b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_RED: {
1627b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        // RED payload type, should not have duplicates.
1628b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        assert(fec_settings.red_payload_type == -1);
1629b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        fec_settings.red_payload_type = in_codec.id;
1630b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
1631b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
1632b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1633b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_ULPFEC: {
1634b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        // ULPFEC payload type, should not have duplicates.
1635b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        assert(fec_settings.ulpfec_payload_type == -1);
1636b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        fec_settings.ulpfec_payload_type = in_codec.id;
1637b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
1638b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
1639b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1640b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_RTX: {
1641b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        int associated_payload_type;
1642b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        if (!in_codec.GetParam(kCodecParamAssociatedPayloadType,
1643b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                               &associated_payload_type)) {
1644b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          LOG(LS_ERROR) << "RTX codec without associated payload type: "
1645b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        << in_codec.ToString();
1646b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          return std::vector<VideoCodecSettings>();
1647b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        }
1648b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        rtx_mapping[associated_payload_type] = in_codec.id;
1649b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
1650b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
1651b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1652b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_VIDEO:
1653b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        break;
1654b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1655b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1656b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs.push_back(VideoCodecSettings());
1657b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs.back().codec = in_codec;
1658b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1659b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1660b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // One of these codecs should have been a video codec. Only having FEC
1661b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // parameters into this code is a logic error.
1662b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  assert(!video_codecs.empty());
1663b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1664b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Write tests that figure out that I have not verified that RTX
1665b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // codecs aren't mapped to bogus payloads.
1666b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < video_codecs.size(); ++i) {
1667b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs[i].fec = fec_settings;
1668b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (rtx_mapping[video_codecs[i].codec.id] != 0) {
1669b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id];
1670b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1671b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1672b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1673b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return video_codecs;
1674b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1675b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1676b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
1677b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::FilterSupportedCodecs(
1678b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs) {
1679b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<VideoCodecSettings> supported_codecs;
1680b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
1681b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (encoder_factory_->SupportsCodec(mapped_codecs[i].codec)) {
1682b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      supported_codecs.push_back(mapped_codecs[i]);
1683b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1684b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1685b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return supported_codecs;
1686b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1687b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1688b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}  // namespace cricket
1689b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1690b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#endif  // HAVE_WEBRTC_VIDEO
1691