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