video_receive_stream.cc revision cd6702282a49448adda470934f4bd9e6181cab22
129d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org/*
229d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
329d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org *
429d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org *  Use of this source code is governed by a BSD-style license
529d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org *  that can be found in the LICENSE file in the root of the source
629d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org *  tree. An additional intellectual property rights grant can be found
729d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org *  in the file PATENTS.  All contributing project authors may
829d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
929d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org */
1029d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
1116e03b7bd8b88ba569987e20a7f29061f91a3d0dpbos@webrtc.org#include "webrtc/video/video_receive_stream.h"
1229d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
1312dc1a38ca54a000e4fecfbc6d41138b895c9ca5pbos@webrtc.org#include <stdlib.h>
1429d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
15b429e516a98d2dee0c57d3263f6d21633939b564mflodman@webrtc.org#include <string>
16b429e516a98d2dee0c57d3263f6d21633939b564mflodman@webrtc.org
170d852d5c27a759fe7aadc500bd7b3cadfae3deb8pbos@webrtc.org#include "webrtc/base/checks.h"
1829d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
1929d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org#include "webrtc/system_wrappers/interface/clock.h"
202a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org#include "webrtc/system_wrappers/interface/logging.h"
2109315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org#include "webrtc/video/receive_statistics_proxy.h"
22776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org#include "webrtc/video_encoder.h"
2316e03b7bd8b88ba569987e20a7f29061f91a3d0dpbos@webrtc.org#include "webrtc/video_receive_stream.h"
2429d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
2529d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.orgnamespace webrtc {
2632e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.orgstd::string VideoReceiveStream::Decoder::ToString() const {
2732e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  std::stringstream ss;
282b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org  ss << "{decoder: " << (decoder != nullptr ? "(VideoDecoder)" : "nullptr");
2932e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", payload_type: " << payload_type;
3032e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", payload_name: " << payload_name;
3132e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", is_renderer: " << (is_renderer ? "yes" : "no");
3232e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", expected_delay_ms: " << expected_delay_ms;
3332e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << '}';
3432e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org
3532e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  return ss.str();
3632e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org}
3732e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org
3832e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.orgstd::string VideoReceiveStream::Config::ToString() const {
3932e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  std::stringstream ss;
4032e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << "{decoders: [";
4132e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  for (size_t i = 0; i < decoders.size(); ++i) {
4232e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org    ss << decoders[i].ToString();
4332e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org    if (i != decoders.size() - 1)
4432e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org      ss << ", ";
4532e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  }
4632e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ']';
4732e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", rtp: " << rtp.ToString();
482b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org  ss << ", renderer: " << (renderer != nullptr ? "(renderer)" : "nullptr");
4932e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", render_delay_ms: " << render_delay_ms;
508fc7fa798f7a36955f1b933980401afad2aff592pbos  if (!sync_group.empty())
518fc7fa798f7a36955f1b933980401afad2aff592pbos    ss << ", sync_group: " << sync_group;
5232e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", pre_decode_callback: "
532b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org     << (pre_decode_callback != nullptr ? "(EncodedFrameObserver)" : "nullptr");
5432e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", pre_render_callback: "
552b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org     << (pre_render_callback != nullptr ? "(I420FrameCallback)" : "nullptr");
5632e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", target_delay_ms: " << target_delay_ms;
5732e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << '}';
5832e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org
5932e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  return ss.str();
6032e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org}
6132e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org
6232e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.orgstd::string VideoReceiveStream::Config::Rtp::ToString() const {
6332e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  std::stringstream ss;
6432e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << "{remote_ssrc: " << remote_ssrc;
6532e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", local_ssrc: " << local_ssrc;
6632e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", rtcp_mode: " << (rtcp_mode == newapi::kRtcpCompound
6732e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org                                ? "kRtcpCompound"
6832e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org                                : "kRtcpReducedSize");
6932e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", rtcp_xr: ";
7032e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << "{receiver_reference_time_report: "
7132e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org     << (rtcp_xr.receiver_reference_time_report ? "on" : "off");
7232e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << '}';
7332e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", remb: " << (remb ? "on" : "off");
7432e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}';
7532e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", fec: " << fec.ToString();
7632e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", rtx: {";
7732e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  for (auto& kv : rtx) {
7832e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org    ss << kv.first << " -> ";
7932e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org    ss << "{ssrc: " << kv.second.ssrc;
8032e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org    ss << ", payload_type: " << kv.second.payload_type;
8132e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org    ss << '}';
8232e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  }
8332e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << '}';
8432e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ", extensions: [";
8532e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
8632e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org    ss << extensions[i].ToString();
8732e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org    if (i != extensions.size() - 1)
8832e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org      ss << ", ";
8932e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  }
9032e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << ']';
9132e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  ss << '}';
9232e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org  return ss.str();
9332e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org}
9432e852858101c3565cfc79cdda9310a3336d95a0pbos@webrtc.org
9529d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.orgnamespace internal {
96776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.orgnamespace {
979e4e524f3894c7eeee8a53bd3cbf21d27b5efc8cpbos@webrtc.org
98776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.orgVideoCodec CreateDecoderVideoCodec(const VideoReceiveStream::Decoder& decoder) {
99776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  VideoCodec codec;
100776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  memset(&codec, 0, sizeof(codec));
101776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
102776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  codec.plType = decoder.payload_type;
103776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  strcpy(codec.plName, decoder.payload_name.c_str());
104776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  if (decoder.payload_name == "VP8") {
105776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    codec.codecType = kVideoCodecVP8;
106776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  } else if (decoder.payload_name == "H264") {
107776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    codec.codecType = kVideoCodecH264;
108776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  } else {
109776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    codec.codecType = kVideoCodecGeneric;
110776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  }
111776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
112776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  if (codec.codecType == kVideoCodecVP8) {
113776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings();
114776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  } else if (codec.codecType == kVideoCodecH264) {
115776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings();
116776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  }
117776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
118776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  codec.width = 320;
119776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  codec.height = 180;
120776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  codec.startBitrate = codec.minBitrate = codec.maxBitrate =
121776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org      Call::Config::kDefaultStartBitrateBps / 1000;
122776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
123776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  return codec;
124776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org}
125776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org}  // namespace
12629d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
12745553aefacb797818da83ccef1c3679a8aa0fc7fPeter BoströmVideoReceiveStream::VideoReceiveStream(int num_cpu_cores,
12845553aefacb797818da83ccef1c3679a8aa0fc7fPeter Boström                                       int base_channel_id,
12976c53d36bc455fe89ca1f860d5171633198fe907Peter Boström                                       ChannelGroup* channel_group,
13045553aefacb797818da83ccef1c3679a8aa0fc7fPeter Boström                                       int channel_id,
1310181b5f8dd719f7b1f938d12875a96e59fef44f5pbos@webrtc.org                                       const VideoReceiveStream::Config& config,
132b082ade3db118113bba284d0f8fd32901371a2a0stefan@webrtc.org                                       newapi::Transport* transport,
13345553aefacb797818da83ccef1c3679a8aa0fc7fPeter Boström                                       webrtc::VoiceEngine* voice_engine)
1344070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.org    : transport_adapter_(transport),
1354070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.org      encoded_frame_proxy_(config.pre_decode_callback),
1364070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.org      config_(config),
13709315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org      clock_(Clock::GetRealTimeClock()),
13876c53d36bc455fe89ca1f860d5171633198fe907Peter Boström      channel_group_(channel_group),
1398fc7fa798f7a36955f1b933980401afad2aff592pbos      channel_id_(channel_id) {
14045553aefacb797818da83ccef1c3679a8aa0fc7fPeter Boström  CHECK(channel_group_->CreateReceiveChannel(channel_id_, 0, base_channel_id,
1412251d6e17438e1a085ff4f88ad19de513214bec1Peter Boström                                             &transport_adapter_, num_cpu_cores,
1422251d6e17438e1a085ff4f88ad19de513214bec1Peter Boström                                             true));
14329d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
14445553aefacb797818da83ccef1c3679a8aa0fc7fPeter Boström  vie_channel_ = channel_group_->GetChannel(channel_id_);
14529d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
146bbb07e69e55761ca43b38f929f3e39f4bba70ef1pbos@webrtc.org  // TODO(pbos): This is not fine grained enough...
147ba8c15b857c0f341d9c1e02d41b6ccd56f9f1030pbos  vie_channel_->SetProtectionMode(config_.rtp.nack.rtp_history_ms > 0, false,
148ba8c15b857c0f341d9c1e02d41b6ccd56f9f1030pbos                                  -1, -1);
14976c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->SetKeyFrameRequestMethod(kKeyFrameReqPliRtcp);
15026c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org  SetRtcpMode(config_.rtp.rtcp_mode);
151bbb07e69e55761ca43b38f929f3e39f4bba70ef1pbos@webrtc.org
1522b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org  DCHECK(config_.rtp.remote_ssrc != 0);
153c279a5d72c885b1a1737018ee26dc7c0475a38bfpbos@webrtc.org  // TODO(pbos): What's an appropriate local_ssrc for receive-only streams?
1542b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org  DCHECK(config_.rtp.local_ssrc != 0);
1552b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org  DCHECK(config_.rtp.remote_ssrc != config_.rtp.local_ssrc);
156b613b5ab2b03041942f04fd892e2ad5a4f9de027pbos@webrtc.org
15776c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->SetSSRC(config_.rtp.local_ssrc, kViEStreamTypeNormal, 0);
158c279a5d72c885b1a1737018ee26dc7c0475a38bfpbos@webrtc.org  // TODO(pbos): Support multiple RTX, per video payload.
159c279a5d72c885b1a1737018ee26dc7c0475a38bfpbos@webrtc.org  Config::Rtp::RtxMap::const_iterator it = config_.rtp.rtx.begin();
160e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  for (; it != config_.rtp.rtx.end(); ++it) {
1612b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org    DCHECK(it->second.ssrc != 0);
1622b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org    DCHECK(it->second.payload_type != 0);
163c279a5d72c885b1a1737018ee26dc7c0475a38bfpbos@webrtc.org
16476c53d36bc455fe89ca1f860d5171633198fe907Peter Boström    vie_channel_->SetRemoteSSRCType(kViEStreamTypeRtx, it->second.ssrc);
165e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    vie_channel_->SetRtxReceivePayloadType(it->second.payload_type, it->first);
166c279a5d72c885b1a1737018ee26dc7c0475a38bfpbos@webrtc.org  }
167c279a5d72c885b1a1737018ee26dc7c0475a38bfpbos@webrtc.org
16876c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  // TODO(pbos): Remove channel_group_ usage from VideoReceiveStream. This
16976c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  // should be configured in call.cc.
17076c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  channel_group_->SetChannelRembStatus(false, config_.rtp.remb, vie_channel_);
17129d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
1725ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org  for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) {
1735ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org    const std::string& extension = config_.rtp.extensions[i].name;
1745ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org    int id = config_.rtp.extensions[i].id;
17523914fe756903353eae13fffc868d2c84f51f06fPeter Boström    // One-byte-extension local identifiers are in the range 1-14 inclusive.
17623914fe756903353eae13fffc868d2c84f51f06fPeter Boström    DCHECK_GE(id, 1);
17723914fe756903353eae13fffc868d2c84f51f06fPeter Boström    DCHECK_LE(id, 14);
1785ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org    if (extension == RtpExtension::kTOffset) {
17976c53d36bc455fe89ca1f860d5171633198fe907Peter Boström      CHECK_EQ(0, vie_channel_->SetReceiveTimestampOffsetStatus(true, id));
1805ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org    } else if (extension == RtpExtension::kAbsSendTime) {
18176c53d36bc455fe89ca1f860d5171633198fe907Peter Boström      CHECK_EQ(0, vie_channel_->SetReceiveAbsoluteSendTimeStatus(true, id));
182fdd10579496123c9a7fdc0bf185e2a26a12ed340guoweis@webrtc.org    } else if (extension == RtpExtension::kVideoRotation) {
18376c53d36bc455fe89ca1f860d5171633198fe907Peter Boström      CHECK_EQ(0, vie_channel_->SetReceiveVideoRotationStatus(true, id));
1845ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org    } else {
1852b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org      RTC_NOTREACHED() << "Unsupported RTP extension.";
1865ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org    }
1875ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org  }
1885ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org
1892a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org  if (config_.rtp.fec.ulpfec_payload_type != -1) {
1902a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org    // ULPFEC without RED doesn't make sense.
1912b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org    DCHECK(config_.rtp.fec.red_payload_type != -1);
1922a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org    VideoCodec codec;
1932a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org    memset(&codec, 0, sizeof(codec));
1942a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org    codec.codecType = kVideoCodecULPFEC;
1952a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org    strcpy(codec.plName, "ulpfec");
1962a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org    codec.plType = config_.rtp.fec.ulpfec_payload_type;
19776c53d36bc455fe89ca1f860d5171633198fe907Peter Boström    CHECK_EQ(0, vie_channel_->SetReceiveCodec(codec));
1982a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org  }
1992a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org  if (config_.rtp.fec.red_payload_type != -1) {
2002a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org    VideoCodec codec;
2012a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org    memset(&codec, 0, sizeof(codec));
2022a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org    codec.codecType = kVideoCodecRED;
2032a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org    strcpy(codec.plName, "red");
2042a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org    codec.plType = config_.rtp.fec.red_payload_type;
20576c53d36bc455fe89ca1f860d5171633198fe907Peter Boström    CHECK_EQ(0, vie_channel_->SetReceiveCodec(codec));
206e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (config_.rtp.fec.red_rtx_payload_type != -1) {
207e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin      vie_channel_->SetRtxReceivePayloadType(
208e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin          config_.rtp.fec.red_rtx_payload_type,
209e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin          config_.rtp.fec.red_payload_type);
210e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    }
2112a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org  }
2122a034988257074183615615f0cc7f59f3411a21cpbos@webrtc.org
21376c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  if (config.rtp.rtcp_xr.receiver_reference_time_report)
21476c53d36bc455fe89ca1f860d5171633198fe907Peter Boström    vie_channel_->SetRtcpXrRrtrStatus(true);
21576c53d36bc455fe89ca1f860d5171633198fe907Peter Boström
21655707692105a4765f8f321ec7c30a1034d03d23apbos@webrtc.org  stats_proxy_.reset(
2171d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org      new ReceiveStatisticsProxy(config_.rtp.remote_ssrc, clock_));
21809315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org
21976c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterReceiveChannelRtcpStatisticsCallback(
22076c53d36bc455fe89ca1f860d5171633198fe907Peter Boström      stats_proxy_.get());
22176c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterReceiveChannelRtpStatisticsCallback(stats_proxy_.get());
22276c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterRtcpPacketTypeCounterObserver(stats_proxy_.get());
22376c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterCodecObserver(stats_proxy_.get());
224ce4e9a356200170abcdd44ff2af95f87a6781b8epbos@webrtc.org
22576c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterReceiveStatisticsProxy(stats_proxy_.get());
22609315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org
2272b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org  DCHECK(!config_.decoders.empty());
228776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  for (size_t i = 0; i < config_.decoders.size(); ++i) {
229776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    const Decoder& decoder = config_.decoders[i];
23076c53d36bc455fe89ca1f860d5171633198fe907Peter Boström    CHECK_EQ(0, vie_channel_->RegisterExternalDecoder(
23176c53d36bc455fe89ca1f860d5171633198fe907Peter Boström                    decoder.payload_type, decoder.decoder, decoder.is_renderer,
232def39883f00c25525dfd34c3cee92b428e54b9e5Peter Boström                    decoder.is_renderer ? decoder.expected_delay_ms
233def39883f00c25525dfd34c3cee92b428e54b9e5Peter Boström                                        : config.render_delay_ms));
234776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
235776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    VideoCodec codec = CreateDecoderVideoCodec(decoder);
236776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
23776c53d36bc455fe89ca1f860d5171633198fe907Peter Boström    CHECK_EQ(0, vie_channel_->SetReceiveCodec(codec));
2380181b5f8dd719f7b1f938d12875a96e59fef44f5pbos@webrtc.org  }
2390181b5f8dd719f7b1f938d12875a96e59fef44f5pbos@webrtc.org
24045553aefacb797818da83ccef1c3679a8aa0fc7fPeter Boström  incoming_video_stream_.reset(new IncomingVideoStream(0));
241c4188fd3c74688264621393fc622cb81c042c1acPeter Boström  incoming_video_stream_->SetExpectedRenderDelay(config.render_delay_ms);
242c4188fd3c74688264621393fc622cb81c042c1acPeter Boström  incoming_video_stream_->SetExternalCallback(this);
243c4188fd3c74688264621393fc622cb81c042c1acPeter Boström  vie_channel_->SetIncomingVideoStream(incoming_video_stream_.get());
244fe1ef935e7d35b465bd00744cc188f08198265b6pbos@webrtc.org
24576c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  if (config.pre_decode_callback)
24676c53d36bc455fe89ca1f860d5171633198fe907Peter Boström    vie_channel_->RegisterPreDecodeImageCallback(&encoded_frame_proxy_);
24776c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterPreRenderCallback(this);
24829d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org}
24929d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
25029d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.orgVideoReceiveStream::~VideoReceiveStream() {
25152ef9d77386e8d3e40c8d3d07b93f06950aede72Peter Boström  incoming_video_stream_->Stop();
25276c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterPreRenderCallback(nullptr);
25376c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterPreDecodeImageCallback(nullptr);
254fe1ef935e7d35b465bd00744cc188f08198265b6pbos@webrtc.org
25576c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  for (size_t i = 0; i < config_.decoders.size(); ++i)
25676c53d36bc455fe89ca1f860d5171633198fe907Peter Boström    vie_channel_->DeRegisterExternalDecoder(config_.decoders[i].payload_type);
257fe1ef935e7d35b465bd00744cc188f08198265b6pbos@webrtc.org
25876c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterCodecObserver(nullptr);
25976c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterReceiveChannelRtpStatisticsCallback(nullptr);
26076c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterReceiveChannelRtcpStatisticsCallback(nullptr);
26176c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->RegisterRtcpPacketTypeCounterObserver(nullptr);
26245553aefacb797818da83ccef1c3679a8aa0fc7fPeter Boström  channel_group_->DeleteChannel(channel_id_);
26329d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org}
26429d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
265a5c8d2c9b39a2d20fead2147e60ed0cd6d62019cpbos@webrtc.orgvoid VideoReceiveStream::Start() {
266d9b9560ee50c236efcb690ee479021b415f7dfd4sprang@webrtc.org  transport_adapter_.Enable();
267c4188fd3c74688264621393fc622cb81c042c1acPeter Boström  incoming_video_stream_->Start();
26876c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->StartReceive();
26929d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org}
27029d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
271a5c8d2c9b39a2d20fead2147e60ed0cd6d62019cpbos@webrtc.orgvoid VideoReceiveStream::Stop() {
272c4188fd3c74688264621393fc622cb81c042c1acPeter Boström  incoming_video_stream_->Stop();
27376c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  vie_channel_->StopReceive();
274d9b9560ee50c236efcb690ee479021b415f7dfd4sprang@webrtc.org  transport_adapter_.Disable();
27529d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org}
27629d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
2778fc7fa798f7a36955f1b933980401afad2aff592pbosvoid VideoReceiveStream::SetSyncChannel(VoiceEngine* voice_engine,
2788fc7fa798f7a36955f1b933980401afad2aff592pbos                                        int audio_channel_id) {
2798fc7fa798f7a36955f1b933980401afad2aff592pbos  if (voice_engine != nullptr && audio_channel_id != -1) {
2808fc7fa798f7a36955f1b933980401afad2aff592pbos    VoEVideoSync* voe_sync_interface = VoEVideoSync::GetInterface(voice_engine);
2818fc7fa798f7a36955f1b933980401afad2aff592pbos    vie_channel_->SetVoiceChannel(audio_channel_id, voe_sync_interface);
2828fc7fa798f7a36955f1b933980401afad2aff592pbos    voe_sync_interface->Release();
2838fc7fa798f7a36955f1b933980401afad2aff592pbos  } else {
2848fc7fa798f7a36955f1b933980401afad2aff592pbos    vie_channel_->SetVoiceChannel(-1, nullptr);
2858fc7fa798f7a36955f1b933980401afad2aff592pbos  }
2868fc7fa798f7a36955f1b933980401afad2aff592pbos}
2878fc7fa798f7a36955f1b933980401afad2aff592pbos
2889510e53cc06b0aa5be2be78fbab375216067eea2sprang@webrtc.orgVideoReceiveStream::Stats VideoReceiveStream::GetStats() const {
28909315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org  return stats_proxy_->GetStats();
29009315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org}
29109315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org
292bbb07e69e55761ca43b38f929f3e39f4bba70ef1pbos@webrtc.orgbool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
29376c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  return vie_channel_->ReceivedRTCPPacket(packet, length) == 0;
29429d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org}
29529d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
296bbb07e69e55761ca43b38f929f3e39f4bba70ef1pbos@webrtc.orgbool VideoReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) {
29776c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  return vie_channel_->ReceivedRTPPacket(packet, length, PacketTime()) == 0;
29829d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org}
29929d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
3004765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchezvoid VideoReceiveStream::FrameCallback(VideoFrame* video_frame) {
30109315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org  stats_proxy_->OnDecodedFrame();
30209315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org
3031aff095b6cc39d843a3d85d09de599cfcff0e35eÅsa Persson  // Post processing is not supported if the frame is backed by a texture.
3041aff095b6cc39d843a3d85d09de599cfcff0e35eÅsa Persson  if (video_frame->native_handle() == NULL) {
3051aff095b6cc39d843a3d85d09de599cfcff0e35eÅsa Persson    if (config_.pre_render_callback)
3061aff095b6cc39d843a3d85d09de599cfcff0e35eÅsa Persson      config_.pre_render_callback->FrameCallback(video_frame);
3071aff095b6cc39d843a3d85d09de599cfcff0e35eÅsa Persson  }
30809315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org}
30909315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org
310c4188fd3c74688264621393fc622cb81c042c1acPeter Boströmint VideoReceiveStream::RenderFrame(const uint32_t /*stream_id*/,
3114765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez                                    const VideoFrame& video_frame) {
312c4188fd3c74688264621393fc622cb81c042c1acPeter Boström  // TODO(pbos): Wire up config_.render->IsTextureSupported() and convert if not
313c4188fd3c74688264621393fc622cb81c042c1acPeter Boström  // supported. Or provide methods for converting a texture frame in
3144765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez  // VideoFrame.
3150d852d5c27a759fe7aadc500bd7b3cadfae3deb8pbos@webrtc.org
3162b4ce3a501b8d679f84c1ad10317dea5c78fa595pbos@webrtc.org  if (config_.renderer != nullptr)
31709315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org    config_.renderer->RenderFrame(
318f4c10d24dc8f1c3ce6859644077d7df6fb678dcdpbos@webrtc.org        video_frame,
319f4c10d24dc8f1c3ce6859644077d7df6fb678dcdpbos@webrtc.org        video_frame.render_time_ms() - clock_->TimeInMilliseconds());
32009315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org
32109315705b9caf3bff455e3515b9bd99492a7c3e3sprang@webrtc.org  stats_proxy_->OnRenderedFrame();
32229d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org
32329d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org  return 0;
32429d5839233b19743286a89676bd748a6bd8623d6pbos@webrtc.org}
32526c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org
326cd6702282a49448adda470934f4bd9e6181cab22Jelena Marusicvoid VideoReceiveStream::SignalNetworkState(NetworkState state) {
327cd6702282a49448adda470934f4bd9e6181cab22Jelena Marusic  if (state == kNetworkUp)
32826c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org    SetRtcpMode(config_.rtp.rtcp_mode);
329cd6702282a49448adda470934f4bd9e6181cab22Jelena Marusic  if (state == kNetworkDown)
33076c53d36bc455fe89ca1f860d5171633198fe907Peter Boström    vie_channel_->SetRTCPMode(kRtcpOff);
33126c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org}
33226c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org
33326c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.orgvoid VideoReceiveStream::SetRtcpMode(newapi::RtcpMode mode) {
33426c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org  switch (mode) {
33526c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org    case newapi::kRtcpCompound:
33676c53d36bc455fe89ca1f860d5171633198fe907Peter Boström      vie_channel_->SetRTCPMode(kRtcpCompound);
33726c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org      break;
33826c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org    case newapi::kRtcpReducedSize:
33976c53d36bc455fe89ca1f860d5171633198fe907Peter Boström      vie_channel_->SetRTCPMode(kRtcpNonCompound);
34026c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org      break;
34126c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org  }
34226c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org}
343f3973e81d5aa7e4f1d6b5abdfe3a6dc53a32840cmflodman@webrtc.org}  // namespace internal
344f3973e81d5aa7e4f1d6b5abdfe3a6dc53a32840cmflodman@webrtc.org}  // namespace webrtc
345