blob: 43aa5661640ad4e1315cc10e96e64081471fa3c7 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
leozwang@webrtc.org39e96592012-03-01 18:22:48 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
mflodman@webrtc.org1b1cd782012-06-28 06:34:08 +000011#include "video_engine/vie_receiver.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
mflodman@webrtc.org4fd55272013-02-06 17:46:39 +000013#include <vector>
14
stefan@webrtc.org976a7e62012-09-21 13:20:21 +000015#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
mflodman@webrtc.org1b1cd782012-06-28 06:34:08 +000016#include "modules/rtp_rtcp/interface/rtp_rtcp.h"
17#include "modules/utility/interface/rtp_dump.h"
18#include "modules/video_coding/main/interface/video_coding.h"
19#include "system_wrappers/interface/critical_section_wrapper.h"
stefan@webrtc.org976a7e62012-09-21 13:20:21 +000020#include "system_wrappers/interface/tick_util.h"
mflodman@webrtc.org1b1cd782012-06-28 06:34:08 +000021#include "system_wrappers/interface/trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000022
23namespace webrtc {
24
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +000025ViEReceiver::ViEReceiver(const int32_t channel_id,
stefan@webrtc.org976a7e62012-09-21 13:20:21 +000026 VideoCodingModule* module_vcm,
27 RemoteBitrateEstimator* remote_bitrate_estimator)
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +000028 : receive_cs_(CriticalSectionWrapper::CreateCriticalSection()),
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000029 channel_id_(channel_id),
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +000030 rtp_rtcp_(NULL),
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000031 vcm_(module_vcm),
stefan@webrtc.org976a7e62012-09-21 13:20:21 +000032 remote_bitrate_estimator_(remote_bitrate_estimator),
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000033 external_decryption_(NULL),
34 decryption_buffer_(NULL),
35 rtp_dump_(NULL),
36 receiving_(false) {
stefan@webrtc.org976a7e62012-09-21 13:20:21 +000037 assert(remote_bitrate_estimator);
niklase@google.com470e71d2011-07-07 08:21:25 +000038}
39
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000040ViEReceiver::~ViEReceiver() {
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000041 if (decryption_buffer_) {
42 delete[] decryption_buffer_;
43 decryption_buffer_ = NULL;
44 }
45 if (rtp_dump_) {
46 rtp_dump_->Stop();
47 RtpDump::DestroyRtpDump(rtp_dump_);
48 rtp_dump_ = NULL;
49 }
niklase@google.com470e71d2011-07-07 08:21:25 +000050}
51
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000052int ViEReceiver::RegisterExternalDecryption(Encryption* decryption) {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +000053 CriticalSectionScoped cs(receive_cs_.get());
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000054 if (external_decryption_) {
55 return -1;
56 }
57 decryption_buffer_ = new WebRtc_UWord8[kViEMaxMtu];
58 if (decryption_buffer_ == NULL) {
59 return -1;
60 }
61 external_decryption_ = decryption;
62 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000063}
64
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000065int ViEReceiver::DeregisterExternalDecryption() {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +000066 CriticalSectionScoped cs(receive_cs_.get());
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000067 if (external_decryption_ == NULL) {
68 return -1;
69 }
70 external_decryption_ = NULL;
71 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000072}
73
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +000074void ViEReceiver::SetRtpRtcpModule(RtpRtcp* module) {
75 rtp_rtcp_ = module;
76}
77
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +000078void ViEReceiver::RegisterSimulcastRtpRtcpModules(
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000079 const std::list<RtpRtcp*>& rtp_modules) {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +000080 CriticalSectionScoped cs(receive_cs_.get());
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000081 rtp_rtcp_simulcast_.clear();
82
83 if (!rtp_modules.empty()) {
84 rtp_rtcp_simulcast_.insert(rtp_rtcp_simulcast_.begin(),
85 rtp_modules.begin(),
86 rtp_modules.end());
87 }
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +000088}
89
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000090void ViEReceiver::IncomingRTPPacket(const WebRtc_Word8* rtp_packet,
91 const WebRtc_Word32 rtp_packet_length,
leozwang@webrtc.org39e96592012-03-01 18:22:48 +000092 const char* from_ip,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000093 const WebRtc_UWord16 from_port) {
94 InsertRTPPacket(rtp_packet, rtp_packet_length);
95}
niklase@google.com470e71d2011-07-07 08:21:25 +000096
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +000097void ViEReceiver::IncomingRTCPPacket(const WebRtc_Word8* rtcp_packet,
98 const WebRtc_Word32 rtcp_packet_length,
leozwang@webrtc.org39e96592012-03-01 18:22:48 +000099 const char* from_ip,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000100 const WebRtc_UWord16 from_port) {
101 InsertRTCPPacket(rtcp_packet, rtcp_packet_length);
102}
niklase@google.com470e71d2011-07-07 08:21:25 +0000103
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000104int ViEReceiver::ReceivedRTPPacket(const void* rtp_packet,
105 int rtp_packet_length) {
106 if (!receiving_) {
107 return -1;
108 }
109 return InsertRTPPacket((const WebRtc_Word8*) rtp_packet, rtp_packet_length);
110}
111
112int ViEReceiver::ReceivedRTCPPacket(const void* rtcp_packet,
113 int rtcp_packet_length) {
114 if (!receiving_) {
115 return -1;
116 }
117 return InsertRTCPPacket((const WebRtc_Word8*) rtcp_packet,
118 rtcp_packet_length);
119}
120
121WebRtc_Word32 ViEReceiver::OnReceivedPayloadData(
122 const WebRtc_UWord8* payload_data, const WebRtc_UWord16 payload_size,
123 const WebRtcRTPHeader* rtp_header) {
124 if (rtp_header == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000125 return 0;
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000126 }
127
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000128 // TODO(holmer): Make sure packets reconstructed using FEC are not passed to
129 // the bandwidth estimator.
stefan@webrtc.org1a2a6dd2012-10-31 12:21:13 +0000130 const int packet_size = payload_size + rtp_header->header.paddingLength;
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000131 uint32_t compensated_timestamp = rtp_header->header.timestamp +
132 rtp_header->extension.transmissionTimeOffset;
phoglund@webrtc.org4cebe6c2012-11-07 13:37:19 +0000133 remote_bitrate_estimator_->IncomingPacket(
134 rtp_header->header.ssrc, packet_size,
135 TickTime::MillisecondTimestamp(), compensated_timestamp);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000136 if (vcm_->IncomingPacket(payload_data, payload_size, *rtp_header) != 0) {
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000137 // Check this...
138 return -1;
139 }
140 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000141}
142
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000143void ViEReceiver::OnSendReportReceived(const WebRtc_Word32 id,
144 const WebRtc_UWord32 senderSSRC,
145 uint32_t ntp_secs,
146 uint32_t ntp_frac,
147 uint32_t timestamp) {
148 remote_bitrate_estimator_->IncomingRtcp(senderSSRC, ntp_secs, ntp_frac,
149 timestamp);
150}
151
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000152int ViEReceiver::InsertRTPPacket(const WebRtc_Word8* rtp_packet,
153 int rtp_packet_length) {
154 // TODO(mflodman) Change decrypt to get rid of this cast.
155 WebRtc_Word8* tmp_ptr = const_cast<WebRtc_Word8*>(rtp_packet);
156 unsigned char* received_packet = reinterpret_cast<unsigned char*>(tmp_ptr);
157 int received_packet_length = rtp_packet_length;
niklase@google.com470e71d2011-07-07 08:21:25 +0000158
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000159 {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000160 CriticalSectionScoped cs(receive_cs_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000161
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000162 if (external_decryption_) {
mflodman@webrtc.org34e83b82012-10-17 11:05:54 +0000163 int decrypted_length = kViEMaxMtu;
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000164 external_decryption_->decrypt(channel_id_, received_packet,
165 decryption_buffer_, received_packet_length,
166 &decrypted_length);
167 if (decrypted_length <= 0) {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000168 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
169 "RTP decryption failed");
niklase@google.com470e71d2011-07-07 08:21:25 +0000170 return -1;
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000171 } else if (decrypted_length > kViEMaxMtu) {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000172 WEBRTC_TRACE(webrtc::kTraceCritical, webrtc::kTraceVideo, channel_id_,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000173 "InsertRTPPacket: %d bytes is allocated as RTP decrytption"
174 " output, external decryption used %d bytes. => memory is "
175 " now corrupted", kViEMaxMtu, decrypted_length);
176 return -1;
177 }
178 received_packet = decryption_buffer_;
179 received_packet_length = decrypted_length;
niklase@google.com470e71d2011-07-07 08:21:25 +0000180 }
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000181
182 if (rtp_dump_) {
183 rtp_dump_->DumpPacket(received_packet,
184 static_cast<WebRtc_UWord16>(received_packet_length));
185 }
186 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000187 assert(rtp_rtcp_); // Should be set by owner at construction time.
188 return rtp_rtcp_->IncomingPacket(received_packet, received_packet_length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000189}
190
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000191int ViEReceiver::InsertRTCPPacket(const WebRtc_Word8* rtcp_packet,
192 int rtcp_packet_length) {
193 // TODO(mflodman) Change decrypt to get rid of this cast.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000194 WebRtc_Word8* tmp_ptr = const_cast<WebRtc_Word8*>(rtcp_packet);
195 unsigned char* received_packet = reinterpret_cast<unsigned char*>(tmp_ptr);
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000196 int received_packet_length = rtcp_packet_length;
197 {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000198 CriticalSectionScoped cs(receive_cs_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000199
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000200 if (external_decryption_) {
mflodman@webrtc.org34e83b82012-10-17 11:05:54 +0000201 int decrypted_length = kViEMaxMtu;
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000202 external_decryption_->decrypt_rtcp(channel_id_, received_packet,
203 decryption_buffer_,
204 received_packet_length,
205 &decrypted_length);
206 if (decrypted_length <= 0) {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000207 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
208 "RTP decryption failed");
niklase@google.com470e71d2011-07-07 08:21:25 +0000209 return -1;
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000210 } else if (decrypted_length > kViEMaxMtu) {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000211 WEBRTC_TRACE(webrtc::kTraceCritical, webrtc::kTraceVideo, channel_id_,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000212 "InsertRTCPPacket: %d bytes is allocated as RTP "
213 " decrytption output, external decryption used %d bytes. "
214 " => memory is now corrupted",
215 kViEMaxMtu, decrypted_length);
216 return -1;
217 }
218 received_packet = decryption_buffer_;
219 received_packet_length = decrypted_length;
niklase@google.com470e71d2011-07-07 08:21:25 +0000220 }
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000221
222 if (rtp_dump_) {
223 rtp_dump_->DumpPacket(
224 received_packet, static_cast<WebRtc_UWord16>(received_packet_length));
225 }
226 }
227 {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000228 CriticalSectionScoped cs(receive_cs_.get());
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000229 std::list<RtpRtcp*>::iterator it = rtp_rtcp_simulcast_.begin();
230 while (it != rtp_rtcp_simulcast_.end()) {
231 RtpRtcp* rtp_rtcp = *it++;
232 rtp_rtcp->IncomingPacket(received_packet, received_packet_length);
233 }
234 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000235 assert(rtp_rtcp_); // Should be set by owner at construction time.
236 return rtp_rtcp_->IncomingPacket(received_packet, received_packet_length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000237}
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000238
239void ViEReceiver::StartReceive() {
240 receiving_ = true;
241}
242
243void ViEReceiver::StopReceive() {
244 receiving_ = false;
245}
246
247int ViEReceiver::StartRTPDump(const char file_nameUTF8[1024]) {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000248 CriticalSectionScoped cs(receive_cs_.get());
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000249 if (rtp_dump_) {
250 // Restart it if it already exists and is started
251 rtp_dump_->Stop();
252 } else {
253 rtp_dump_ = RtpDump::CreateRtpDump();
254 if (rtp_dump_ == NULL) {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000255 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000256 "StartRTPDump: Failed to create RTP dump");
257 return -1;
258 }
259 }
260 if (rtp_dump_->Start(file_nameUTF8) != 0) {
261 RtpDump::DestroyRtpDump(rtp_dump_);
262 rtp_dump_ = NULL;
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000263 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000264 "StartRTPDump: Failed to start RTP dump");
265 return -1;
266 }
267 return 0;
268}
269
270int ViEReceiver::StopRTPDump() {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000271 CriticalSectionScoped cs(receive_cs_.get());
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000272 if (rtp_dump_) {
273 if (rtp_dump_->IsActive()) {
274 rtp_dump_->Stop();
275 } else {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000276 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000277 "StopRTPDump: Dump not active");
278 }
279 RtpDump::DestroyRtpDump(rtp_dump_);
280 rtp_dump_ = NULL;
281 } else {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000282 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, channel_id_,
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000283 "StopRTPDump: RTP dump not started");
284 return -1;
285 }
286 return 0;
287}
288
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000289// TODO(holmer): To be moved to ViEChannelGroup.
mflodman@webrtc.org4fd55272013-02-06 17:46:39 +0000290void ViEReceiver::EstimatedReceiveBandwidth(
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000291 unsigned int* available_bandwidth) const {
292 std::vector<unsigned int> ssrcs;
mflodman@webrtc.org4fd55272013-02-06 17:46:39 +0000293
294 // LatestEstimate returns an error if there is no valid bitrate estimate, but
295 // ViEReceiver instead returns a zero estimate.
296 remote_bitrate_estimator_->LatestEstimate(&ssrcs, available_bandwidth);
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000297 if (!ssrcs.empty()) {
298 *available_bandwidth /= ssrcs.size();
mflodman@webrtc.org4fd55272013-02-06 17:46:39 +0000299 } else {
300 *available_bandwidth = 0;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000301 }
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000302}
303
mflodman@webrtc.orgad4ee362011-11-28 22:39:24 +0000304} // namespace webrtc