LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/rtp_rtcp/source - rtp_receiver_impl.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 233 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 20 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13