video_receive_stream.cc revision d89920b74a173b7bf80c6760908a382c095a66cc
11f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher/*
21f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
31f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher *
4d9b631e9e82c9e0d0e14b7f3d0f2965c523b113dplougher *  Use of this source code is governed by a BSD-style license
5f6cd337f8de328e2b448b9f29c00d9132748f7feplougher *  that can be found in the LICENSE file in the root of the source
61f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher *  tree. An additional intellectual property rights grant can be found
71f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher *  in the file PATENTS.  All contributing project authors may
81f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher *  be found in the AUTHORS file in the root of the source tree.
91f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher */
101f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
111f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include "webrtc/video/video_receive_stream.h"
121f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
131f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include <stdlib.h>
141f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
151f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include <string>
161f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
171f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include "webrtc/base/checks.h"
181f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
191f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include "webrtc/system_wrappers/interface/clock.h"
201f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include "webrtc/system_wrappers/interface/logging.h"
211f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include "webrtc/video/receive_statistics_proxy.h"
221f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include "webrtc/video_encoder.h"
231f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher#include "webrtc/video_receive_stream.h"
2406a19d326d8a13f8ef000d9197af9bb584c3f922plougher
25e69aac119c4660c567d5159729b9875c3330e4bbploughernamespace webrtc {
26e69aac119c4660c567d5159729b9875c3330e4bbplougherstd::string VideoReceiveStream::Decoder::ToString() const {
271b899fc316f7eba7a31da12dc0c9b69ada441059plougher  std::stringstream ss;
281b899fc316f7eba7a31da12dc0c9b69ada441059plougher  ss << "{decoder: " << (decoder != nullptr ? "(VideoDecoder)" : "nullptr");
291b899fc316f7eba7a31da12dc0c9b69ada441059plougher  ss << ", payload_type: " << payload_type;
301f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << ", payload_name: " << payload_name;
311f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << ", is_renderer: " << (is_renderer ? "yes" : "no");
321f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << ", expected_delay_ms: " << expected_delay_ms;
331f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << '}';
341f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
351f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  return ss.str();
361f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
371f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
381f413c84d736495fd61ff05ebe52c3a01a4d95c2plougherstd::string VideoReceiveStream::Config::ToString() const {
391f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  std::stringstream ss;
401f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << "{decoders: [";
418cb05cde913bb04297020629566540981a649273plougher  for (size_t i = 0; i < decoders.size(); ++i) {
4287c0c4afbf3b8ecc814f6bac4d90b70d1e109f44plougher    ss << decoders[i].ToString();
438cb05cde913bb04297020629566540981a649273plougher    if (i != decoders.size() - 1)
448cb05cde913bb04297020629566540981a649273plougher      ss << ", ";
458cb05cde913bb04297020629566540981a649273plougher  }
468cb05cde913bb04297020629566540981a649273plougher  ss << ']';
471f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << ", rtp: " << rtp.ToString();
488cb05cde913bb04297020629566540981a649273plougher  ss << ", renderer: " << (renderer != nullptr ? "(renderer)" : "nullptr");
491f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << ", render_delay_ms: " << render_delay_ms;
501b899fc316f7eba7a31da12dc0c9b69ada441059plougher  if (!sync_group.empty())
511b899fc316f7eba7a31da12dc0c9b69ada441059plougher    ss << ", sync_group: " << sync_group;
521f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << ", pre_decode_callback: "
531f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher     << (pre_decode_callback != nullptr ? "(EncodedFrameObserver)" : "nullptr");
541f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << ", pre_render_callback: "
551f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher     << (pre_render_callback != nullptr ? "(I420FrameCallback)" : "nullptr");
561f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << ", target_delay_ms: " << target_delay_ms;
571f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << '}';
588cb05cde913bb04297020629566540981a649273plougher
598cb05cde913bb04297020629566540981a649273plougher  return ss.str();
608cb05cde913bb04297020629566540981a649273plougher}
611f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
621f413c84d736495fd61ff05ebe52c3a01a4d95c2plougherstd::string VideoReceiveStream::Config::Rtp::ToString() const {
631f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  std::stringstream ss;
641f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << "{remote_ssrc: " << remote_ssrc;
658cb05cde913bb04297020629566540981a649273plougher  ss << ", local_ssrc: " << local_ssrc;
668cb05cde913bb04297020629566540981a649273plougher  ss << ", rtcp_mode: " << (rtcp_mode == newapi::kRtcpCompound
678cb05cde913bb04297020629566540981a649273plougher                                ? "kRtcpCompound"
681f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher                                : "kRtcpReducedSize");
69e69aac119c4660c567d5159729b9875c3330e4bbplougher  ss << ", rtcp_xr: ";
70e69aac119c4660c567d5159729b9875c3330e4bbplougher  ss << "{receiver_reference_time_report: "
711f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher     << (rtcp_xr.receiver_reference_time_report ? "on" : "off");
721f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << '}';
731f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << ", remb: " << (remb ? "on" : "off");
741f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}';
7506a19d326d8a13f8ef000d9197af9bb584c3f922plougher  ss << ", fec: " << fec.ToString();
7661343797593e92ad2cf75b221398c138e1fee058plougher  ss << ", rtx: {";
771f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  for (auto& kv : rtx) {
781f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    ss << kv.first << " -> ";
798cb05cde913bb04297020629566540981a649273plougher    ss << "{ssrc: " << kv.second.ssrc;
801f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    ss << ", payload_type: " << kv.second.payload_type;
818cb05cde913bb04297020629566540981a649273plougher    ss << '}';
821f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  }
831f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  ss << '}';
8406a19d326d8a13f8ef000d9197af9bb584c3f922plougher  ss << ", extensions: [";
851f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  for (size_t i = 0; i < extensions.size(); ++i) {
86e69aac119c4660c567d5159729b9875c3330e4bbplougher    ss << extensions[i].ToString();
87e69aac119c4660c567d5159729b9875c3330e4bbplougher    if (i != extensions.size() - 1)
88e69aac119c4660c567d5159729b9875c3330e4bbplougher      ss << ", ";
891f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  }
90e69aac119c4660c567d5159729b9875c3330e4bbplougher  ss << ']';
91e69aac119c4660c567d5159729b9875c3330e4bbplougher  ss << '}';
921f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  return ss.str();
93e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher}
94e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher
951f413c84d736495fd61ff05ebe52c3a01a4d95c2ploughernamespace internal {
96e69aac119c4660c567d5159729b9875c3330e4bbploughernamespace {
97e69aac119c4660c567d5159729b9875c3330e4bbplougher
981f413c84d736495fd61ff05ebe52c3a01a4d95c2plougherVideoCodec CreateDecoderVideoCodec(const VideoReceiveStream::Decoder& decoder) {
991f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  VideoCodec codec;
1001f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  memset(&codec, 0, sizeof(codec));
1011f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
1021f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  codec.plType = decoder.payload_type;
1031f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  strcpy(codec.plName, decoder.payload_name.c_str());
1041f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  if (decoder.payload_name == "VP8") {
10506a19d326d8a13f8ef000d9197af9bb584c3f922plougher    codec.codecType = kVideoCodecVP8;
1061f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  } else if (decoder.payload_name == "H264") {
1071f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    codec.codecType = kVideoCodecH264;
1081f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  } else {
1091f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    codec.codecType = kVideoCodecGeneric;
1101f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  }
1111f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
1121f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  if (codec.codecType == kVideoCodecVP8) {
1131b899fc316f7eba7a31da12dc0c9b69ada441059plougher    codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings();
1141b899fc316f7eba7a31da12dc0c9b69ada441059plougher  } else if (codec.codecType == kVideoCodecH264) {
1151b899fc316f7eba7a31da12dc0c9b69ada441059plougher    codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings();
1161b899fc316f7eba7a31da12dc0c9b69ada441059plougher  }
1171b899fc316f7eba7a31da12dc0c9b69ada441059plougher
1181b899fc316f7eba7a31da12dc0c9b69ada441059plougher  codec.width = 320;
1191b899fc316f7eba7a31da12dc0c9b69ada441059plougher  codec.height = 180;
1201b899fc316f7eba7a31da12dc0c9b69ada441059plougher  codec.startBitrate = codec.minBitrate = codec.maxBitrate =
1211f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher      Call::Config::kDefaultStartBitrateBps / 1000;
1221f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
123df70c3e920ad82bcc5f5f33d5b7c313be6c2ea4fplougher  return codec;
1241f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
1251f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}  // namespace
1261f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
127e69aac119c4660c567d5159729b9875c3330e4bbplougherVideoReceiveStream::VideoReceiveStream(int num_cpu_cores,
128e69aac119c4660c567d5159729b9875c3330e4bbplougher                                       int base_channel_id,
129e69aac119c4660c567d5159729b9875c3330e4bbplougher                                       ChannelGroup* channel_group,
1301f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher                                       int channel_id,
1311f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher                                       const VideoReceiveStream::Config& config,
132e69aac119c4660c567d5159729b9875c3330e4bbplougher                                       newapi::Transport* transport,
133e69aac119c4660c567d5159729b9875c3330e4bbplougher                                       webrtc::VoiceEngine* voice_engine)
1341f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    : transport_adapter_(transport),
1351f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher      encoded_frame_proxy_(config.pre_decode_callback),
136e69aac119c4660c567d5159729b9875c3330e4bbplougher      config_(config),
137e69aac119c4660c567d5159729b9875c3330e4bbplougher      clock_(Clock::GetRealTimeClock()),
138e69aac119c4660c567d5159729b9875c3330e4bbplougher      channel_group_(channel_group),
139e69aac119c4660c567d5159729b9875c3330e4bbplougher      channel_id_(channel_id) {
140e69aac119c4660c567d5159729b9875c3330e4bbplougher  CHECK(channel_group_->CreateReceiveChannel(channel_id_, 0, base_channel_id,
141e69aac119c4660c567d5159729b9875c3330e4bbplougher                                             &transport_adapter_, num_cpu_cores,
1424c9b090b96c10193f33f9985a5a5c11eb1d23ae3plougher                                             true));
143e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher
144e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher  vie_channel_ = channel_group_->GetChannel(channel_id_);
145e69aac119c4660c567d5159729b9875c3330e4bbplougher
1461f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  // TODO(pbos): This is not fine grained enough...
1471f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  vie_channel_->SetProtectionMode(config_.rtp.nack.rtp_history_ms > 0, false,
1481f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher                                  -1, -1);
1494c9b090b96c10193f33f9985a5a5c11eb1d23ae3plougher  vie_channel_->SetKeyFrameRequestMethod(kKeyFrameReqPliRtcp);
1501f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  SetRtcpMode(config_.rtp.rtcp_mode);
1511f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
1521f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  DCHECK(config_.rtp.remote_ssrc != 0);
153e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher  // TODO(pbos): What's an appropriate local_ssrc for receive-only streams?
154e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher  DCHECK(config_.rtp.local_ssrc != 0);
155e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher  DCHECK(config_.rtp.remote_ssrc != config_.rtp.local_ssrc);
156e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher
1571f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  vie_channel_->SetSSRC(config_.rtp.local_ssrc, kViEStreamTypeNormal, 0);
1581f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  // TODO(pbos): Support multiple RTX, per video payload.
1591f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  Config::Rtp::RtxMap::const_iterator it = config_.rtp.rtx.begin();
1601f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  for (; it != config_.rtp.rtx.end(); ++it) {
1611f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    DCHECK(it->second.ssrc != 0);
1621f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    DCHECK(it->second.payload_type != 0);
16361343797593e92ad2cf75b221398c138e1fee058plougher
16461343797593e92ad2cf75b221398c138e1fee058plougher    vie_channel_->SetRemoteSSRCType(kViEStreamTypeRtx, it->second.ssrc);
1651f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    vie_channel_->SetRtxReceivePayloadType(it->second.payload_type, it->first);
16661343797593e92ad2cf75b221398c138e1fee058plougher  }
16761343797593e92ad2cf75b221398c138e1fee058plougher
1681f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  // TODO(pbos): Remove channel_group_ usage from VideoReceiveStream. This
1691f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  // should be configured in call.cc.
17061343797593e92ad2cf75b221398c138e1fee058plougher  channel_group_->SetChannelRembStatus(false, config_.rtp.remb, vie_channel_);
17161343797593e92ad2cf75b221398c138e1fee058plougher
1721f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) {
1731f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    const std::string& extension = config_.rtp.extensions[i].name;
1741b899fc316f7eba7a31da12dc0c9b69ada441059plougher    int id = config_.rtp.extensions[i].id;
1751b899fc316f7eba7a31da12dc0c9b69ada441059plougher    // One-byte-extension local identifiers are in the range 1-14 inclusive.
1761f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    DCHECK_GE(id, 1);
1771f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    DCHECK_LE(id, 14);
17861343797593e92ad2cf75b221398c138e1fee058plougher    if (extension == RtpExtension::kTOffset) {
17961343797593e92ad2cf75b221398c138e1fee058plougher      CHECK_EQ(0, vie_channel_->SetReceiveTimestampOffsetStatus(true, id));
1801f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    } else if (extension == RtpExtension::kAbsSendTime) {
181e69aac119c4660c567d5159729b9875c3330e4bbplougher      CHECK_EQ(0, vie_channel_->SetReceiveAbsoluteSendTimeStatus(true, id));
182e69aac119c4660c567d5159729b9875c3330e4bbplougher    } else if (extension == RtpExtension::kVideoRotation) {
183e69aac119c4660c567d5159729b9875c3330e4bbplougher      CHECK_EQ(0, vie_channel_->SetReceiveVideoRotationStatus(true, id));
1841b899fc316f7eba7a31da12dc0c9b69ada441059plougher    } else {
1851b899fc316f7eba7a31da12dc0c9b69ada441059plougher      RTC_NOTREACHED() << "Unsupported RTP extension.";
1861b899fc316f7eba7a31da12dc0c9b69ada441059plougher    }
1871b899fc316f7eba7a31da12dc0c9b69ada441059plougher  }
1881f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
1891f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  if (config_.rtp.fec.ulpfec_payload_type != -1) {
190e69aac119c4660c567d5159729b9875c3330e4bbplougher    // ULPFEC without RED doesn't make sense.
191e69aac119c4660c567d5159729b9875c3330e4bbplougher    DCHECK(config_.rtp.fec.red_payload_type != -1);
192e69aac119c4660c567d5159729b9875c3330e4bbplougher    VideoCodec codec;
193e69aac119c4660c567d5159729b9875c3330e4bbplougher    memset(&codec, 0, sizeof(codec));
194e69aac119c4660c567d5159729b9875c3330e4bbplougher    codec.codecType = kVideoCodecULPFEC;
195e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher    strcpy(codec.plName, "ulpfec");
196e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher    codec.plType = config_.rtp.fec.ulpfec_payload_type;
197e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher    CHECK_EQ(0, vie_channel_->SetReceiveCodec(codec));
1984c9b090b96c10193f33f9985a5a5c11eb1d23ae3plougher  }
1991a35122f8bd26beb614ccb9b9113677b198436a1plougher  if (config_.rtp.fec.red_payload_type != -1) {
2001a35122f8bd26beb614ccb9b9113677b198436a1plougher    VideoCodec codec;
201058eae41952c33345bd0ef290aea8eef37f3ca92plougher    memset(&codec, 0, sizeof(codec));
2021f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    codec.codecType = kVideoCodecRED;
203e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher    strcpy(codec.plName, "red");
204e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher    codec.plType = config_.rtp.fec.red_payload_type;
205e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher    CHECK_EQ(0, vie_channel_->SetReceiveCodec(codec));
2061f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    if (config_.rtp.fec.red_rtx_payload_type != -1) {
207e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher      vie_channel_->SetRtxReceivePayloadType(
208e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher          config_.rtp.fec.red_rtx_payload_type,
209e69aac119c4660c567d5159729b9875c3330e4bbplougher          config_.rtp.fec.red_payload_type);
210e69aac119c4660c567d5159729b9875c3330e4bbplougher    }
211e69aac119c4660c567d5159729b9875c3330e4bbplougher  }
212058eae41952c33345bd0ef290aea8eef37f3ca92plougher
213058eae41952c33345bd0ef290aea8eef37f3ca92plougher  if (config.rtp.rtcp_xr.receiver_reference_time_report)
214058eae41952c33345bd0ef290aea8eef37f3ca92plougher    vie_channel_->SetRtcpXrRrtrStatus(true);
2151f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
21661343797593e92ad2cf75b221398c138e1fee058plougher  stats_proxy_.reset(
21761343797593e92ad2cf75b221398c138e1fee058plougher      new ReceiveStatisticsProxy(config_.rtp.remote_ssrc, clock_));
2181f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
2191f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  vie_channel_->RegisterReceiveChannelRtcpStatisticsCallback(
2201f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher      stats_proxy_.get());
2211f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  vie_channel_->RegisterReceiveChannelRtpStatisticsCallback(stats_proxy_.get());
2221f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  vie_channel_->RegisterRtcpPacketTypeCounterObserver(stats_proxy_.get());
223e69aac119c4660c567d5159729b9875c3330e4bbplougher  vie_channel_->RegisterCodecObserver(stats_proxy_.get());
224e69aac119c4660c567d5159729b9875c3330e4bbplougher
225e69aac119c4660c567d5159729b9875c3330e4bbplougher  vie_channel_->RegisterReceiveStatisticsProxy(stats_proxy_.get());
2261f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
227e69aac119c4660c567d5159729b9875c3330e4bbplougher  DCHECK(!config_.decoders.empty());
228e69aac119c4660c567d5159729b9875c3330e4bbplougher  for (size_t i = 0; i < config_.decoders.size(); ++i) {
229e69aac119c4660c567d5159729b9875c3330e4bbplougher    const Decoder& decoder = config_.decoders[i];
2301f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    CHECK_EQ(0, vie_channel_->RegisterExternalDecoder(
2311f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher                    decoder.payload_type, decoder.decoder, decoder.is_renderer,
2321f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher                    decoder.is_renderer ? decoder.expected_delay_ms
233058eae41952c33345bd0ef290aea8eef37f3ca92plougher                                        : config.render_delay_ms));
234058eae41952c33345bd0ef290aea8eef37f3ca92plougher
235058eae41952c33345bd0ef290aea8eef37f3ca92plougher    VideoCodec codec = CreateDecoderVideoCodec(decoder);
236058eae41952c33345bd0ef290aea8eef37f3ca92plougher
237058eae41952c33345bd0ef290aea8eef37f3ca92plougher    CHECK_EQ(0, vie_channel_->SetReceiveCodec(codec));
2381a35122f8bd26beb614ccb9b9113677b198436a1plougher  }
2391a35122f8bd26beb614ccb9b9113677b198436a1plougher
240058eae41952c33345bd0ef290aea8eef37f3ca92plougher  incoming_video_stream_.reset(new IncomingVideoStream(0));
241058eae41952c33345bd0ef290aea8eef37f3ca92plougher  incoming_video_stream_->SetExpectedRenderDelay(config.render_delay_ms);
24261343797593e92ad2cf75b221398c138e1fee058plougher  incoming_video_stream_->SetExternalCallback(this);
24361343797593e92ad2cf75b221398c138e1fee058plougher  vie_channel_->SetIncomingVideoStream(incoming_video_stream_.get());
244058eae41952c33345bd0ef290aea8eef37f3ca92plougher
245e69aac119c4660c567d5159729b9875c3330e4bbplougher  if (config.pre_decode_callback)
246e69aac119c4660c567d5159729b9875c3330e4bbplougher    vie_channel_->RegisterPreDecodeImageCallback(&encoded_frame_proxy_);
247e69aac119c4660c567d5159729b9875c3330e4bbplougher  vie_channel_->RegisterPreRenderCallback(this);
248e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher}
249e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher
250e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougherVideoReceiveStream::~VideoReceiveStream() {
251e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher  incoming_video_stream_->Stop();
252058eae41952c33345bd0ef290aea8eef37f3ca92plougher  vie_channel_->RegisterPreRenderCallback(nullptr);
253058eae41952c33345bd0ef290aea8eef37f3ca92plougher  vie_channel_->RegisterPreDecodeImageCallback(nullptr);
254058eae41952c33345bd0ef290aea8eef37f3ca92plougher
255e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher  for (size_t i = 0; i < config_.decoders.size(); ++i)
256e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher    vie_channel_->DeRegisterExternalDecoder(config_.decoders[i].payload_type);
257e69aac119c4660c567d5159729b9875c3330e4bbplougher
258f1cdb557030f345c6cc1f68b52ab89589f2fed81plougher  vie_channel_->RegisterCodecObserver(nullptr);
259e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher  vie_channel_->RegisterReceiveChannelRtpStatisticsCallback(nullptr);
260e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher  vie_channel_->RegisterReceiveChannelRtcpStatisticsCallback(nullptr);
261e69aac119c4660c567d5159729b9875c3330e4bbplougher  vie_channel_->RegisterRtcpPacketTypeCounterObserver(nullptr);
262e69aac119c4660c567d5159729b9875c3330e4bbplougher  channel_group_->DeleteChannel(channel_id_);
263e69aac119c4660c567d5159729b9875c3330e4bbplougher}
264058eae41952c33345bd0ef290aea8eef37f3ca92plougher
265058eae41952c33345bd0ef290aea8eef37f3ca92ploughervoid VideoReceiveStream::Start() {
266058eae41952c33345bd0ef290aea8eef37f3ca92plougher  transport_adapter_.Enable();
267f1cdb557030f345c6cc1f68b52ab89589f2fed81plougher  incoming_video_stream_->Start();
26861343797593e92ad2cf75b221398c138e1fee058plougher  vie_channel_->StartReceive();
26961343797593e92ad2cf75b221398c138e1fee058plougher}
270058eae41952c33345bd0ef290aea8eef37f3ca92plougher
271058eae41952c33345bd0ef290aea8eef37f3ca92ploughervoid VideoReceiveStream::Stop() {
272058eae41952c33345bd0ef290aea8eef37f3ca92plougher  incoming_video_stream_->Stop();
273058eae41952c33345bd0ef290aea8eef37f3ca92plougher  vie_channel_->StopReceive();
274058eae41952c33345bd0ef290aea8eef37f3ca92plougher  transport_adapter_.Disable();
275e69aac119c4660c567d5159729b9875c3330e4bbplougher}
276e69aac119c4660c567d5159729b9875c3330e4bbplougher
277e69aac119c4660c567d5159729b9875c3330e4bbploughervoid VideoReceiveStream::SetSyncChannel(VoiceEngine* voice_engine,
278058eae41952c33345bd0ef290aea8eef37f3ca92plougher                                        int audio_channel_id) {
279e69aac119c4660c567d5159729b9875c3330e4bbplougher  if (voice_engine != nullptr && audio_channel_id != -1) {
280e69aac119c4660c567d5159729b9875c3330e4bbplougher    VoEVideoSync* voe_sync_interface = VoEVideoSync::GetInterface(voice_engine);
281e69aac119c4660c567d5159729b9875c3330e4bbplougher    vie_channel_->SetVoiceChannel(audio_channel_id, voe_sync_interface);
282058eae41952c33345bd0ef290aea8eef37f3ca92plougher    voe_sync_interface->Release();
283058eae41952c33345bd0ef290aea8eef37f3ca92plougher  } else {
284058eae41952c33345bd0ef290aea8eef37f3ca92plougher    vie_channel_->SetVoiceChannel(-1, nullptr);
2851f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  }
2861f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
2871f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
28861343797593e92ad2cf75b221398c138e1fee058plougherVideoReceiveStream::Stats VideoReceiveStream::GetStats() const {
28961343797593e92ad2cf75b221398c138e1fee058plougher  return stats_proxy_->GetStats();
29061343797593e92ad2cf75b221398c138e1fee058plougher}
2911f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
2921f413c84d736495fd61ff05ebe52c3a01a4d95c2plougherbool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
2931f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  return vie_channel_->ReceivedRTCPPacket(packet, length) == 0;
2941f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
2951f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
2961f413c84d736495fd61ff05ebe52c3a01a4d95c2plougherbool VideoReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) {
2971f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  return vie_channel_->ReceivedRTPPacket(packet, length, PacketTime()) == 0;
29861343797593e92ad2cf75b221398c138e1fee058plougher}
29961343797593e92ad2cf75b221398c138e1fee058plougher
3001f413c84d736495fd61ff05ebe52c3a01a4d95c2ploughervoid VideoReceiveStream::FrameCallback(VideoFrame* video_frame) {
301e69aac119c4660c567d5159729b9875c3330e4bbplougher  stats_proxy_->OnDecodedFrame();
302e69aac119c4660c567d5159729b9875c3330e4bbplougher
3031f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  // Post processing is not supported if the frame is backed by a texture.
3041f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  if (video_frame->native_handle() == NULL) {
3051f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    if (config_.pre_render_callback)
3061f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher      config_.pre_render_callback->FrameCallback(video_frame);
3071f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  }
3081f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
3091f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
3101f413c84d736495fd61ff05ebe52c3a01a4d95c2plougherint VideoReceiveStream::RenderFrame(const uint32_t /*stream_id*/,
31161343797593e92ad2cf75b221398c138e1fee058plougher                                    const VideoFrame& video_frame) {
31261343797593e92ad2cf75b221398c138e1fee058plougher  // TODO(pbos): Wire up config_.render->IsTextureSupported() and convert if not
3131f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  // supported. Or provide methods for converting a texture frame in
314e69aac119c4660c567d5159729b9875c3330e4bbplougher  // VideoFrame.
315e69aac119c4660c567d5159729b9875c3330e4bbplougher
3161f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  if (config_.renderer != nullptr)
3171f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    config_.renderer->RenderFrame(
3181f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher        video_frame,
3191f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher        video_frame.render_time_ms() - clock_->TimeInMilliseconds());
32061343797593e92ad2cf75b221398c138e1fee058plougher
32161343797593e92ad2cf75b221398c138e1fee058plougher  stats_proxy_->OnRenderedFrame(video_frame.width(), video_frame.height());
32261343797593e92ad2cf75b221398c138e1fee058plougher
323e69aac119c4660c567d5159729b9875c3330e4bbplougher  return 0;
324e69aac119c4660c567d5159729b9875c3330e4bbplougher}
3251f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
3261f413c84d736495fd61ff05ebe52c3a01a4d95c2ploughervoid VideoReceiveStream::SignalNetworkState(NetworkState state) {
3271f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  if (state == kNetworkUp)
3281f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    SetRtcpMode(config_.rtp.rtcp_mode);
3291f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  if (state == kNetworkDown)
3301f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    vie_channel_->SetRTCPMode(kRtcpOff);
3311f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
3321f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher
3331f413c84d736495fd61ff05ebe52c3a01a4d95c2ploughervoid VideoReceiveStream::SetRtcpMode(newapi::RtcpMode mode) {
3341f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  switch (mode) {
3351f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    case newapi::kRtcpCompound:
3361f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher      vie_channel_->SetRTCPMode(kRtcpCompound);
3371f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher      break;
3381f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher    case newapi::kRtcpReducedSize:
3391f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher      vie_channel_->SetRTCPMode(kRtcpNonCompound);
3401f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher      break;
3411f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher  }
3421f413c84d736495fd61ff05ebe52c3a01a4d95c2plougher}
343e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher}  // namespace internal
344e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher}  // namespace webrtc
345e6d6143d60f8f71167f8bb3e4d21a43188dd95fbplougher