Bug 981680: Upstream webrtc patch for avsync (r5102) rs=jesup
authorRandell Jesup <rjesup@jesup.org>
Tue, 11 Mar 2014 00:36:12 -0400
changeset 190110 bf9adc1ce324ded8a2f931c7322181e7b67c9240
parent 190109 c234a1aeaeabbef07895cddb858059594db11626
child 190111 9ea150674ac04abd9f7ae03f89aa2fe8a0a6b88e
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs981680
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 981680: Upstream webrtc patch for avsync (r5102) rs=jesup
media/webrtc/trunk/webrtc/modules/rtp_rtcp/interface/rtp_receiver.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/test/testAPI/test_api_audio.cc
media/webrtc/trunk/webrtc/video_engine/vie_receiver.cc
media/webrtc/trunk/webrtc/video_engine/vie_receiver.h
media/webrtc/trunk/webrtc/video_engine/vie_sync_module.cc
media/webrtc/trunk/webrtc/voice_engine/channel.cc
media/webrtc/trunk/webrtc/voice_engine/channel.h
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/interface/rtp_receiver.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/interface/rtp_receiver.h
@@ -77,20 +77,22 @@ class RtpReceiver {
                                  bool in_order) = 0;
 
   // Returns the currently configured NACK method.
   virtual NACKMethod NACK() const = 0;
 
   // Turn negative acknowledgement (NACK) requests on/off.
   virtual void SetNACKStatus(const NACKMethod method) = 0;
 
-  // Returns the last received timestamp.
-  virtual uint32_t Timestamp() const = 0;
-  // Returns the time in milliseconds when the last timestamp was received.
-  virtual int32_t LastReceivedTimeMs() const = 0;
+  // Gets the last received timestamp. Returns true if a packet has been
+  // received, false otherwise.
+  virtual bool Timestamp(uint32_t* timestamp) const = 0;
+  // Gets the time in milliseconds when the last timestamp was received.
+  // Returns true if a packet has been received, false otherwise.
+  virtual bool LastReceivedTimeMs(int64_t* receive_time_ms) const = 0;
 
   // Returns the remote SSRC of the currently received RTP stream.
   virtual uint32_t SSRC() const = 0;
 
   // Returns the current remote CSRCs.
   virtual int32_t CSRCs(uint32_t array_of_csrc[kRtpCsrcSize]) const = 0;
 
   // Returns the current energy of the RTP stream received.
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc
@@ -75,17 +75,17 @@ RtpReceiverImpl::RtpReceiverImpl(int32_t
       critical_section_rtp_receiver_(
         CriticalSectionWrapper::CreateCriticalSection()),
       last_receive_time_(0),
       last_received_payload_length_(0),
       ssrc_(0),
       num_csrcs_(0),
       current_remote_csrc_(),
       last_received_timestamp_(0),
-      last_received_frame_time_ms_(0),
+      last_received_frame_time_ms_(-1),
       last_received_sequence_number_(0),
       nack_method_(kNackOff) {
   assert(incoming_audio_messages_callback);
   assert(incoming_messages_callback);
 
   memset(current_remote_csrc_, 0, sizeof(current_remote_csrc_));
 
   WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
@@ -223,28 +223,30 @@ bool RtpReceiverImpl::IncomingRtpPacket(
   WebRtcRTPHeader webrtc_rtp_header;
   memset(&webrtc_rtp_header, 0, sizeof(webrtc_rtp_header));
   webrtc_rtp_header.header = rtp_header;
   CheckCSRC(webrtc_rtp_header);
 
   uint16_t payload_data_length = payload_length - rtp_header.paddingLength;
 
   bool is_first_packet_in_frame = false;
-  bool is_first_packet = false;
   {
     CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
-    is_first_packet_in_frame =
+    if (HaveReceivedFrame()) {
+      is_first_packet_in_frame =
           last_received_sequence_number_ + 1 == rtp_header.sequenceNumber &&
-          Timestamp() != rtp_header.timestamp;
-    is_first_packet = is_first_packet_in_frame || last_receive_time_ == 0;
+          last_received_timestamp_ != rtp_header.timestamp;
+    } else {
+      is_first_packet_in_frame = true;
+    }
   }
 
   int32_t ret_val = rtp_media_receiver_->ParseRtpPacket(
       &webrtc_rtp_header, payload_specific, is_red, payload, payload_length,
-      clock_->TimeInMilliseconds(), is_first_packet);
+      clock_->TimeInMilliseconds(), is_first_packet_in_frame);
 
   if (ret_val < 0) {
     return false;
   }
 
   {
     CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
 
@@ -261,24 +263,34 @@ bool RtpReceiverImpl::IncomingRtpPacket(
   }
   return true;
 }
 
 TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() {
   return rtp_media_receiver_->GetTelephoneEventHandler();
 }
 
-uint32_t RtpReceiverImpl::Timestamp() const {
+bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const {
   CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
-  return last_received_timestamp_;
+  if (!HaveReceivedFrame())
+    return false;
+  *timestamp = last_received_timestamp_;
+  return true;
 }
 
-int32_t RtpReceiverImpl::LastReceivedTimeMs() const {
+bool RtpReceiverImpl::LastReceivedTimeMs(int64_t* receive_time_ms) const {
   CriticalSectionScoped lock(critical_section_rtp_receiver_.get());
-  return last_received_frame_time_ms_;
+  if (!HaveReceivedFrame())
+    return false;
+  *receive_time_ms = last_received_frame_time_ms_;
+  return true;
+}
+
+bool RtpReceiverImpl::HaveReceivedFrame() const {
+  return last_received_frame_time_ms_ >= 0;
 }
 
 // Implementation note: must not hold critsect when called.
 void RtpReceiverImpl::CheckSSRCChanged(const RTPHeader& rtp_header) {
   bool new_ssrc = false;
   bool re_initialize_decoder = false;
   char payload_name[RTP_PAYLOAD_NAME_SIZE];
   uint8_t channels = 1;
@@ -293,17 +305,17 @@ void RtpReceiverImpl::CheckSSRCChanged(c
         (last_received_payload_type == -1 && ssrc_ == 0)) {
       // We need the payload_type_ to make the call if the remote SSRC is 0.
       new_ssrc = true;
 
       cb_rtp_feedback_->ResetStatistics(ssrc_);
 
       last_received_timestamp_ = 0;
       last_received_sequence_number_ = 0;
-      last_received_frame_time_ms_ = 0;
+      last_received_frame_time_ms_ = -1;
 
       // Do we have a SSRC? Then the stream is restarted.
       if (ssrc_ != 0) {
         // Do we have the same codec? Then re-initialize coder.
         if (rtp_header.payloadType == last_received_payload_type) {
           re_initialize_decoder = true;
 
           Payload* payload;
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h
@@ -53,18 +53,18 @@ class RtpReceiverImpl : public RtpReceiv
       bool in_order);
 
   NACKMethod NACK() const;
 
   // Turn negative acknowledgement requests on/off.
   void SetNACKStatus(const NACKMethod method);
 
   // Returns the last received timestamp.
-  virtual uint32_t Timestamp() const;
-  int32_t LastReceivedTimeMs() const;
+  bool Timestamp(uint32_t* timestamp) const;
+  bool LastReceivedTimeMs(int64_t* receive_time_ms) const;
 
   uint32_t SSRC() const;
 
   int32_t CSRCs(uint32_t array_of_csrc[kRtpCsrcSize]) const;
 
   int32_t Energy(uint8_t array_of_energy[kRtpCsrcSize]) const;
 
   // RTX.
@@ -72,16 +72,18 @@ class RtpReceiverImpl : public RtpReceiv
 
   void RTXStatus(bool* enable, uint32_t* ssrc, int* payload_type) const;
 
   void SetRtxPayloadType(int payload_type);
 
   TelephoneEventHandler* GetTelephoneEventHandler();
 
  private:
+  bool HaveReceivedFrame() const;
+
   RtpVideoCodecTypes VideoCodecType() const;
 
   void CheckSSRCChanged(const RTPHeader& rtp_header);
   void CheckCSRC(const WebRtcRTPHeader& rtp_header);
   int32_t CheckPayloadChanged(const RTPHeader& rtp_header,
                               const int8_t first_payload_byte,
                               bool& is_red,
                               PayloadUnion* payload,
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/test/testAPI/test_api_audio.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/test/testAPI/test_api_audio.cc
@@ -227,17 +227,19 @@ TEST_F(RtpRtcpAudioTest, Basic) {
       (voice_codec.rate < 0) ? 0 : voice_codec.rate));
   printf("4\n");
 
   const uint8_t test[5] = "test";
   EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
                                          0, -1, test, 4));
 
   EXPECT_EQ(test_ssrc, rtp_receiver2_->SSRC());
-  EXPECT_EQ(test_timestamp, rtp_receiver2_->Timestamp());
+  uint32_t timestamp;
+  EXPECT_TRUE(rtp_receiver2_->Timestamp(&timestamp));
+  EXPECT_EQ(test_timestamp, timestamp);
 }
 
 TEST_F(RtpRtcpAudioTest, RED) {
   CodecInst voice_codec;
   memset(&voice_codec, 0, sizeof(voice_codec));
   voice_codec.pltype = 96;
   voice_codec.plfreq = 8000;
   memcpy(voice_codec.plname, "PCMU", 5);
--- a/media/webrtc/trunk/webrtc/video_engine/vie_receiver.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_receiver.cc
@@ -256,21 +256,22 @@ int ViEReceiver::InsertRTPPacket(const i
                  "Incoming packet: Invalid RTP header");
     return -1;
   }
   int payload_length = received_packet_length - header.headerLength;
   remote_bitrate_estimator_->IncomingPacket(TickTime::MillisecondTimestamp(),
                                             payload_length, header);
   header.payload_type_frequency = kVideoPayloadTypeFrequency;
 
+  bool in_order = IsPacketInOrder(header);
   rtp_receive_statistics_->IncomingPacket(header, received_packet_length,
-                                          IsPacketRetransmitted(header));
+      IsPacketRetransmitted(header, in_order));
   rtp_payload_registry_->SetIncomingPayloadType(header);
   return ReceivePacket(received_packet, received_packet_length, header,
-                       IsPacketInOrder(header)) ? 0 : -1;
+                       in_order) ? 0 : -1;
 }
 
 bool ViEReceiver::ReceivePacket(const uint8_t* packet,
                                 int packet_length,
                                 const RTPHeader& header,
                                 bool in_order) {
   if (rtp_payload_registry_->IsEncapsulated(header)) {
     return ParseAndHandleEncapsulatingHeader(packet, packet_length, header);
@@ -463,23 +464,24 @@ ReceiveStatistics* ViEReceiver::GetRecei
 bool ViEReceiver::IsPacketInOrder(const RTPHeader& header) const {
   StreamStatistician* statistician =
       rtp_receive_statistics_->GetStatistician(header.ssrc);
   if (!statistician)
     return false;
   return statistician->IsPacketInOrder(header.sequenceNumber);
 }
 
-bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header) const {
+bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header,
+                                        bool in_order) const {
   // Retransmissions are handled separately if RTX is enabled.
   if (rtp_payload_registry_->RtxEnabled())
     return false;
   StreamStatistician* statistician =
       rtp_receive_statistics_->GetStatistician(header.ssrc);
   if (!statistician)
     return false;
   // Check if this is a retransmission.
   uint16_t min_rtt = 0;
   rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
-  return !IsPacketInOrder(header) &&
+  return !in_order &&
       statistician->IsRetransmitOfOldPacket(header, min_rtt);
 }
 }  // namespace webrtc
--- a/media/webrtc/trunk/webrtc/video_engine/vie_receiver.h
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_receiver.h
@@ -94,17 +94,17 @@ class ViEReceiver : public RtpData {
                      const RTPHeader& header, bool in_order);
   // Parses and handles for instance RTX and RED headers.
   // This function assumes that it's being called from only one thread.
   bool ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
                                          int packet_length,
                                          const RTPHeader& header);
   int InsertRTCPPacket(const int8_t* rtcp_packet, int rtcp_packet_length);
   bool IsPacketInOrder(const RTPHeader& header) const;
-  bool IsPacketRetransmitted(const RTPHeader& header) const;
+  bool IsPacketRetransmitted(const RTPHeader& header, bool in_order) const;
 
   scoped_ptr<CriticalSectionWrapper> receive_cs_;
   const int32_t channel_id_;
   scoped_ptr<RtpHeaderParser> rtp_header_parser_;
   scoped_ptr<RTPPayloadRegistry> rtp_payload_registry_;
   scoped_ptr<RtpReceiver> rtp_receiver_;
   scoped_ptr<ReceiveStatistics> rtp_receive_statistics_;
   scoped_ptr<FecReceiver> fec_receiver_;
--- a/media/webrtc/trunk/webrtc/video_engine/vie_sync_module.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_sync_module.cc
@@ -21,18 +21,20 @@
 #include "webrtc/voice_engine/include/voe_video_sync.h"
 
 namespace webrtc {
 
 enum { kSyncInterval = 1000};
 
 int UpdateMeasurements(StreamSynchronization::Measurements* stream,
                        const RtpRtcp& rtp_rtcp, const RtpReceiver& receiver) {
-  stream->latest_timestamp = receiver.Timestamp();
-  stream->latest_receive_time_ms = receiver.LastReceivedTimeMs();
+  if (!receiver.Timestamp(&stream->latest_timestamp))
+    return -1;
+  if (!receiver.LastReceivedTimeMs(&stream->latest_receive_time_ms))
+    return -1;
   synchronization::RtcpMeasurement measurement;
   if (0 != rtp_rtcp.RemoteNTP(&measurement.ntp_secs,
                               &measurement.ntp_frac,
                               NULL,
                               NULL,
                               &measurement.rtp_timestamp)) {
     return -1;
   }
--- a/media/webrtc/trunk/webrtc/voice_engine/channel.cc
+++ b/media/webrtc/trunk/webrtc/voice_engine/channel.cc
@@ -2190,21 +2190,21 @@ int32_t Channel::ReceivedRTPPacket(const
     WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
                  "Incoming packet: invalid RTP header");
     return -1;
   }
   header.payload_type_frequency =
       rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
   if (header.payload_type_frequency < 0)
     return -1;
+  bool in_order = IsPacketInOrder(header);
   rtp_receive_statistics_->IncomingPacket(header, length,
-                                          IsPacketRetransmitted(header));
+      IsPacketRetransmitted(header, in_order));
   rtp_payload_registry_->SetIncomingPayloadType(header);
-  return ReceivePacket(received_packet, length, header,
-                       IsPacketInOrder(header)) ? 0 : -1;
+  return ReceivePacket(received_packet, length, header, in_order) ? 0 : -1;
 }
 
 bool Channel::ReceivePacket(const uint8_t* packet,
                             int packet_length,
                             const RTPHeader& header,
                             bool in_order) {
   if (rtp_payload_registry_->IsEncapsulated(header)) {
     return HandleEncapsulation(packet, packet_length, header);
@@ -2254,28 +2254,29 @@ bool Channel::HandleEncapsulation(const 
 bool Channel::IsPacketInOrder(const RTPHeader& header) const {
   StreamStatistician* statistician =
       rtp_receive_statistics_->GetStatistician(header.ssrc);
   if (!statistician)
     return false;
   return statistician->IsPacketInOrder(header.sequenceNumber);
 }
 
-bool Channel::IsPacketRetransmitted(const RTPHeader& header) const {
+bool Channel::IsPacketRetransmitted(const RTPHeader& header,
+                                    bool in_order) const {
   // Retransmissions are handled separately if RTX is enabled.
   if (rtp_payload_registry_->RtxEnabled())
     return false;
   StreamStatistician* statistician =
       rtp_receive_statistics_->GetStatistician(header.ssrc);
   if (!statistician)
     return false;
   // Check if this is a retransmission.
   uint16_t min_rtt = 0;
   _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
-  return !IsPacketInOrder(header) &&
+  return !in_order &&
       statistician->IsRetransmitOfOldPacket(header, min_rtt);
 }
 
 int32_t Channel::ReceivedRTCPPacket(const int8_t* data, int32_t length) {
   WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
                "Channel::ReceivedRTCPPacket()");
   // Store playout timestamp for the received RTCP packet
   UpdatePlayoutTimestamp(true);
--- a/media/webrtc/trunk/webrtc/voice_engine/channel.h
+++ b/media/webrtc/trunk/webrtc/voice_engine/channel.h
@@ -431,17 +431,17 @@ public:
 
 private:
     bool ReceivePacket(const uint8_t* packet, int packet_length,
                        const RTPHeader& header, bool in_order);
     bool HandleEncapsulation(const uint8_t* packet,
                              int packet_length,
                              const RTPHeader& header);
     bool IsPacketInOrder(const RTPHeader& header) const;
-    bool IsPacketRetransmitted(const RTPHeader& header) const;
+    bool IsPacketRetransmitted(const RTPHeader& header, bool in_order) const;
     int ResendPackets(const uint16_t* sequence_numbers, int length);
     int InsertInbandDtmfTone();
     int32_t MixOrReplaceAudioWithFile(int mixingFrequency);
     int32_t MixAudioWithFile(AudioFrame& audioFrame, int mixingFrequency);
     void UpdateDeadOrAliveCounters(bool alive);
     int32_t SendPacketRaw(const void *data, int len, bool RTCP);
     void UpdatePacketDelay(uint32_t timestamp,
                            uint16_t sequenceNumber);