1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
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
11 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h"
12
13 #include <assert.h>
14 #include <math.h>
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
19 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
20 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
21 #include "webrtc/system_wrappers/interface/logging.h"
22
23 namespace webrtc {
24
25 using RtpUtility::GetCurrentRTP;
26 using RtpUtility::Payload;
27 using RtpUtility::StringCompare;
28
CreateVideoReceiver(int id,Clock * clock,RtpData * incoming_payload_callback,RtpFeedback * incoming_messages_callback,RTPPayloadRegistry * rtp_payload_registry)29 RtpReceiver* RtpReceiver::CreateVideoReceiver(
30 int id, Clock* clock,
31 RtpData* incoming_payload_callback,
32 RtpFeedback* incoming_messages_callback,
33 RTPPayloadRegistry* rtp_payload_registry) {
34 if (!incoming_payload_callback)
35 incoming_payload_callback = NullObjectRtpData();
36 if (!incoming_messages_callback)
37 incoming_messages_callback = NullObjectRtpFeedback();
38 return new RtpReceiverImpl(
39 id, clock, NullObjectRtpAudioFeedback(), incoming_messages_callback,
40 rtp_payload_registry,
41 RTPReceiverStrategy::CreateVideoStrategy(incoming_payload_callback));
42 }
43
CreateAudioReceiver(int id,Clock * clock,RtpAudioFeedback * incoming_audio_feedback,RtpData * incoming_payload_callback,RtpFeedback * incoming_messages_callback,RTPPayloadRegistry * rtp_payload_registry)44 RtpReceiver* RtpReceiver::CreateAudioReceiver(
45 int id, Clock* clock,
46 RtpAudioFeedback* incoming_audio_feedback,
47 RtpData* incoming_payload_callback,
48 RtpFeedback* incoming_messages_callback,
49 RTPPayloadRegistry* rtp_payload_registry) {
50 if (!incoming_audio_feedback)
51 incoming_audio_feedback = NullObjectRtpAudioFeedback();
52 if (!incoming_payload_callback)
53 incoming_payload_callback = NullObjectRtpData();
54 if (!incoming_messages_callback)
55 incoming_messages_callback = NullObjectRtpFeedback();
56 return new RtpReceiverImpl(
57 id, clock, incoming_audio_feedback, incoming_messages_callback,
58 rtp_payload_registry,
59 RTPReceiverStrategy::CreateAudioStrategy(id, incoming_payload_callback,
60 incoming_audio_feedback));
61 }
62
RtpReceiverImpl(int32_t id,Clock * clock,RtpAudioFeedback * incoming_audio_messages_callback,RtpFeedback * incoming_messages_callback,RTPPayloadRegistry * rtp_payload_registry,RTPReceiverStrategy * rtp_media_receiver)63 RtpReceiverImpl::RtpReceiverImpl(int32_t id,
64 Clock* clock,
65 RtpAudioFeedback* incoming_audio_messages_callback,
66 RtpFeedback* incoming_messages_callback,
67 RTPPayloadRegistry* rtp_payload_registry,
68 RTPReceiverStrategy* rtp_media_receiver)
69 : clock_(clock),
70 rtp_payload_registry_(rtp_payload_registry),
71 rtp_media_receiver_(rtp_media_receiver),
72 id_(id),
73 cb_rtp_feedback_(incoming_messages_callback),
74 critical_section_rtp_receiver_(
75 CriticalSectionWrapper::CreateCriticalSection()),
76 last_receive_time_(0),
77 last_received_payload_length_(0),
78 ssrc_(0),
79 num_csrcs_(0),
80 current_remote_csrc_(),
81 last_received_timestamp_(0),
82 last_received_frame_time_ms_(-1),
83 last_received_sequence_number_(0),
84 nack_method_(kNackOff) {
85 assert(incoming_audio_messages_callback);
86 assert(incoming_messages_callback);
87
88 memset(current_remote_csrc_, 0, sizeof(current_remote_csrc_));
89 }
90
~RtpReceiverImpl()91 RtpReceiverImpl::~RtpReceiverImpl() {
92 for (int i = 0; i < num_csrcs_; ++i) {
93 cb_rtp_feedback_->OnIncomingCSRCChanged(id_, current_remote_csrc_[i],
94 false);
95 }
96 }
97
RegisterReceivePayload(const char payload_name[RTP_PAYLOAD_NAME_SIZE],const int8_t payload_type,const uint32_t frequency,const uint8_t channels,const uint32_t rate)98 int32_t RtpReceiverImpl::RegisterReceivePayload(
99 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
100 const int8_t payload_type,
101 const uint32_t frequency,
102 const uint8_t channels,
103 const uint32_t rate) {
104 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
105
106 // TODO(phoglund): Try to streamline handling of the RED codec and some other
107 // cases which makes it necessary to keep track of whether we created a
108 // payload or not.
109 bool created_new_payload = false;
110 int32_t result = rtp_payload_registry_->RegisterReceivePayload(
111 payload_name, payload_type, frequency, channels, rate,
112 &created_new_payload);
113 if (created_new_payload) {
114 if (rtp_media_receiver_->OnNewPayloadTypeCreated(payload_name, payload_type,
115 frequency) != 0) {
116 LOG(LS_ERROR) << "Failed to register payload: " << payload_name << "/"
117 << payload_type;
118 return -1;
119 }
120 }
121 return result;
122 }
123
DeRegisterReceivePayload(const int8_t payload_type)124 int32_t RtpReceiverImpl::DeRegisterReceivePayload(
125 const int8_t payload_type) {
126 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
127 return rtp_payload_registry_->DeRegisterReceivePayload(payload_type);
128 }
129
NACK() const130 NACKMethod RtpReceiverImpl::NACK() const {
131 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
132 return nack_method_;
133 }
134
135 // Turn negative acknowledgment requests on/off.
SetNACKStatus(const NACKMethod method)136 void RtpReceiverImpl::SetNACKStatus(const NACKMethod method) {
137 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
138 nack_method_ = method;
139 }
140
SSRC() const141 uint32_t RtpReceiverImpl::SSRC() const {
142 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
143 return ssrc_;
144 }
145
146 // Get remote CSRC.
CSRCs(uint32_t array_of_csrcs[kRtpCsrcSize]) const147 int32_t RtpReceiverImpl::CSRCs(uint32_t array_of_csrcs[kRtpCsrcSize]) const {
148 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
149
150 assert(num_csrcs_ <= kRtpCsrcSize);
151
152 if (num_csrcs_ > 0) {
153 memcpy(array_of_csrcs, current_remote_csrc_, sizeof(uint32_t)*num_csrcs_);
154 }
155 return num_csrcs_;
156 }
157
Energy(uint8_t array_of_energy[kRtpCsrcSize]) const158 int32_t RtpReceiverImpl::Energy(
159 uint8_t array_of_energy[kRtpCsrcSize]) const {
160 return rtp_media_receiver_->Energy(array_of_energy);
161 }
162
IncomingRtpPacket(const RTPHeader & rtp_header,const uint8_t * payload,int payload_length,PayloadUnion payload_specific,bool in_order)163 bool RtpReceiverImpl::IncomingRtpPacket(
164 const RTPHeader& rtp_header,
165 const uint8_t* payload,
166 int payload_length,
167 PayloadUnion payload_specific,
168 bool in_order) {
169 // Sanity check.
170 assert(payload_length >= 0);
171
172 // Trigger our callbacks.
173 CheckSSRCChanged(rtp_header);
174
175 int8_t first_payload_byte = payload_length > 0 ? payload[0] : 0;
176 bool is_red = false;
177 bool should_reset_statistics = false;
178
179 if (CheckPayloadChanged(rtp_header,
180 first_payload_byte,
181 is_red,
182 &payload_specific,
183 &should_reset_statistics) == -1) {
184 if (payload_length == 0) {
185 // OK, keep-alive packet.
186 return true;
187 }
188 LOG(LS_WARNING) << "Receiving invalid payload type.";
189 return false;
190 }
191
192 if (should_reset_statistics) {
193 cb_rtp_feedback_->ResetStatistics(ssrc_);
194 }
195
196 WebRtcRTPHeader webrtc_rtp_header;
197 memset(&webrtc_rtp_header, 0, sizeof(webrtc_rtp_header));
198 webrtc_rtp_header.header = rtp_header;
199 CheckCSRC(webrtc_rtp_header);
200
201 uint16_t payload_data_length = payload_length - rtp_header.paddingLength;
202
203 bool is_first_packet_in_frame = false;
204 {
205 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
206 if (HaveReceivedFrame()) {
207 is_first_packet_in_frame =
208 last_received_sequence_number_ + 1 == rtp_header.sequenceNumber &&
209 last_received_timestamp_ != rtp_header.timestamp;
210 } else {
211 is_first_packet_in_frame = true;
212 }
213 }
214
215 int32_t ret_val = rtp_media_receiver_->ParseRtpPacket(
216 &webrtc_rtp_header, payload_specific, is_red, payload, payload_length,
217 clock_->TimeInMilliseconds(), is_first_packet_in_frame);
218
219 if (ret_val < 0) {
220 return false;
221 }
222
223 {
224 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
225
226 last_receive_time_ = clock_->TimeInMilliseconds();
227 last_received_payload_length_ = payload_data_length;
228
229 if (in_order) {
230 if (last_received_timestamp_ != rtp_header.timestamp) {
231 last_received_timestamp_ = rtp_header.timestamp;
232 last_received_frame_time_ms_ = clock_->TimeInMilliseconds();
233 }
234 last_received_sequence_number_ = rtp_header.sequenceNumber;
235 }
236 }
237 return true;
238 }
239
GetTelephoneEventHandler()240 TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() {
241 return rtp_media_receiver_->GetTelephoneEventHandler();
242 }
243
Timestamp(uint32_t * timestamp) const244 bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const {
245 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
246 if (!HaveReceivedFrame())
247 return false;
248 *timestamp = last_received_timestamp_;
249 return true;
250 }
251
LastReceivedTimeMs(int64_t * receive_time_ms) const252 bool RtpReceiverImpl::LastReceivedTimeMs(int64_t* receive_time_ms) const {
253 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
254 if (!HaveReceivedFrame())
255 return false;
256 *receive_time_ms = last_received_frame_time_ms_;
257 return true;
258 }
259
HaveReceivedFrame() const260 bool RtpReceiverImpl::HaveReceivedFrame() const {
261 return last_received_frame_time_ms_ >= 0;
262 }
263
264 // Implementation note: must not hold critsect when called.
CheckSSRCChanged(const RTPHeader & rtp_header)265 void RtpReceiverImpl::CheckSSRCChanged(const RTPHeader& rtp_header) {
266 bool new_ssrc = false;
267 bool re_initialize_decoder = false;
268 char payload_name[RTP_PAYLOAD_NAME_SIZE];
269 uint8_t channels = 1;
270 uint32_t rate = 0;
271
272 {
273 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
274
275 int8_t last_received_payload_type =
276 rtp_payload_registry_->last_received_payload_type();
277 if (ssrc_ != rtp_header.ssrc ||
278 (last_received_payload_type == -1 && ssrc_ == 0)) {
279 // We need the payload_type_ to make the call if the remote SSRC is 0.
280 new_ssrc = true;
281
282 cb_rtp_feedback_->ResetStatistics(ssrc_);
283
284 last_received_timestamp_ = 0;
285 last_received_sequence_number_ = 0;
286 last_received_frame_time_ms_ = -1;
287
288 // Do we have a SSRC? Then the stream is restarted.
289 if (ssrc_ != 0) {
290 // Do we have the same codec? Then re-initialize coder.
291 if (rtp_header.payloadType == last_received_payload_type) {
292 re_initialize_decoder = true;
293
294 Payload* payload;
295 if (!rtp_payload_registry_->PayloadTypeToPayload(
296 rtp_header.payloadType, payload)) {
297 return;
298 }
299 assert(payload);
300 payload_name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
301 strncpy(payload_name, payload->name, RTP_PAYLOAD_NAME_SIZE - 1);
302 if (payload->audio) {
303 channels = payload->typeSpecific.Audio.channels;
304 rate = payload->typeSpecific.Audio.rate;
305 }
306 }
307 }
308 ssrc_ = rtp_header.ssrc;
309 }
310 }
311
312 if (new_ssrc) {
313 // We need to get this to our RTCP sender and receiver.
314 // We need to do this outside critical section.
315 cb_rtp_feedback_->OnIncomingSSRCChanged(id_, rtp_header.ssrc);
316 }
317
318 if (re_initialize_decoder) {
319 if (-1 == cb_rtp_feedback_->OnInitializeDecoder(
320 id_, rtp_header.payloadType, payload_name,
321 rtp_header.payload_type_frequency, channels, rate)) {
322 // New stream, same codec.
323 LOG(LS_ERROR) << "Failed to create decoder for payload type: "
324 << rtp_header.payloadType;
325 }
326 }
327 }
328
329 // Implementation note: must not hold critsect when called.
330 // TODO(phoglund): Move as much as possible of this code path into the media
331 // specific receivers. Basically this method goes through a lot of trouble to
332 // compute something which is only used by the media specific parts later. If
333 // this code path moves we can get rid of some of the rtp_receiver ->
334 // media_specific interface (such as CheckPayloadChange, possibly get/set
335 // last known payload).
CheckPayloadChanged(const RTPHeader & rtp_header,const int8_t first_payload_byte,bool & is_red,PayloadUnion * specific_payload,bool * should_reset_statistics)336 int32_t RtpReceiverImpl::CheckPayloadChanged(
337 const RTPHeader& rtp_header,
338 const int8_t first_payload_byte,
339 bool& is_red,
340 PayloadUnion* specific_payload,
341 bool* should_reset_statistics) {
342 bool re_initialize_decoder = false;
343
344 char payload_name[RTP_PAYLOAD_NAME_SIZE];
345 int8_t payload_type = rtp_header.payloadType;
346
347 {
348 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
349
350 int8_t last_received_payload_type =
351 rtp_payload_registry_->last_received_payload_type();
352 // TODO(holmer): Remove this code when RED parsing has been broken out from
353 // RtpReceiverAudio.
354 if (payload_type != last_received_payload_type) {
355 if (rtp_payload_registry_->red_payload_type() == payload_type) {
356 // Get the real codec payload type.
357 payload_type = first_payload_byte & 0x7f;
358 is_red = true;
359
360 if (rtp_payload_registry_->red_payload_type() == payload_type) {
361 // Invalid payload type, traced by caller. If we proceeded here,
362 // this would be set as |_last_received_payload_type|, and we would no
363 // longer catch corrupt packets at this level.
364 return -1;
365 }
366
367 // When we receive RED we need to check the real payload type.
368 if (payload_type == last_received_payload_type) {
369 rtp_media_receiver_->GetLastMediaSpecificPayload(specific_payload);
370 return 0;
371 }
372 }
373 *should_reset_statistics = false;
374 bool should_discard_changes = false;
375
376 rtp_media_receiver_->CheckPayloadChanged(
377 payload_type, specific_payload, should_reset_statistics,
378 &should_discard_changes);
379
380 if (should_discard_changes) {
381 is_red = false;
382 return 0;
383 }
384
385 Payload* payload;
386 if (!rtp_payload_registry_->PayloadTypeToPayload(payload_type, payload)) {
387 // Not a registered payload type.
388 return -1;
389 }
390 assert(payload);
391 payload_name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
392 strncpy(payload_name, payload->name, RTP_PAYLOAD_NAME_SIZE - 1);
393
394 rtp_payload_registry_->set_last_received_payload_type(payload_type);
395
396 re_initialize_decoder = true;
397
398 rtp_media_receiver_->SetLastMediaSpecificPayload(payload->typeSpecific);
399 rtp_media_receiver_->GetLastMediaSpecificPayload(specific_payload);
400
401 if (!payload->audio) {
402 bool media_type_unchanged =
403 rtp_payload_registry_->ReportMediaPayloadType(payload_type);
404 if (media_type_unchanged) {
405 // Only reset the decoder if the media codec type has changed.
406 re_initialize_decoder = false;
407 }
408 }
409 if (re_initialize_decoder) {
410 *should_reset_statistics = true;
411 }
412 } else {
413 rtp_media_receiver_->GetLastMediaSpecificPayload(specific_payload);
414 is_red = false;
415 }
416 } // End critsect.
417
418 if (re_initialize_decoder) {
419 if (-1 == rtp_media_receiver_->InvokeOnInitializeDecoder(
420 cb_rtp_feedback_, id_, payload_type, payload_name,
421 *specific_payload)) {
422 return -1; // Wrong payload type.
423 }
424 }
425 return 0;
426 }
427
428 // Implementation note: must not hold critsect when called.
CheckCSRC(const WebRtcRTPHeader & rtp_header)429 void RtpReceiverImpl::CheckCSRC(const WebRtcRTPHeader& rtp_header) {
430 int32_t num_csrcs_diff = 0;
431 uint32_t old_remote_csrc[kRtpCsrcSize];
432 uint8_t old_num_csrcs = 0;
433
434 {
435 CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
436
437 if (!rtp_media_receiver_->ShouldReportCsrcChanges(
438 rtp_header.header.payloadType)) {
439 return;
440 }
441 old_num_csrcs = num_csrcs_;
442 if (old_num_csrcs > 0) {
443 // Make a copy of old.
444 memcpy(old_remote_csrc, current_remote_csrc_,
445 num_csrcs_ * sizeof(uint32_t));
446 }
447 const uint8_t num_csrcs = rtp_header.header.numCSRCs;
448 if ((num_csrcs > 0) && (num_csrcs <= kRtpCsrcSize)) {
449 // Copy new.
450 memcpy(current_remote_csrc_,
451 rtp_header.header.arrOfCSRCs,
452 num_csrcs * sizeof(uint32_t));
453 }
454 if (num_csrcs > 0 || old_num_csrcs > 0) {
455 num_csrcs_diff = num_csrcs - old_num_csrcs;
456 num_csrcs_ = num_csrcs; // Update stored CSRCs.
457 } else {
458 // No change.
459 return;
460 }
461 } // End critsect.
462
463 bool have_called_callback = false;
464 // Search for new CSRC in old array.
465 for (uint8_t i = 0; i < rtp_header.header.numCSRCs; ++i) {
466 const uint32_t csrc = rtp_header.header.arrOfCSRCs[i];
467
468 bool found_match = false;
469 for (uint8_t j = 0; j < old_num_csrcs; ++j) {
470 if (csrc == old_remote_csrc[j]) { // old list
471 found_match = true;
472 break;
473 }
474 }
475 if (!found_match && csrc) {
476 // Didn't find it, report it as new.
477 have_called_callback = true;
478 cb_rtp_feedback_->OnIncomingCSRCChanged(id_, csrc, true);
479 }
480 }
481 // Search for old CSRC in new array.
482 for (uint8_t i = 0; i < old_num_csrcs; ++i) {
483 const uint32_t csrc = old_remote_csrc[i];
484
485 bool found_match = false;
486 for (uint8_t j = 0; j < rtp_header.header.numCSRCs; ++j) {
487 if (csrc == rtp_header.header.arrOfCSRCs[j]) {
488 found_match = true;
489 break;
490 }
491 }
492 if (!found_match && csrc) {
493 // Did not find it, report as removed.
494 have_called_callback = true;
495 cb_rtp_feedback_->OnIncomingCSRCChanged(id_, csrc, false);
496 }
497 }
498 if (!have_called_callback) {
499 // If the CSRC list contain non-unique entries we will end up here.
500 // Using CSRC 0 to signal this event, not interop safe, other
501 // implementations might have CSRC 0 as a valid value.
502 if (num_csrcs_diff > 0) {
503 cb_rtp_feedback_->OnIncomingCSRCChanged(id_, 0, true);
504 } else if (num_csrcs_diff < 0) {
505 cb_rtp_feedback_->OnIncomingCSRCChanged(id_, 0, false);
506 }
507 }
508 }
509
510 } // namespace webrtc
511