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