Fix issues with sequence number wrap-around in jitter statistics

Wrap-arounds in sequence numbers (and in timestamps) were not always
treated correctly. This is fixed by introducing two helper functions
for correct comparisons, and by casting to the right word size.

Also added a new member variable to AutomodeInst_t. The new member keeps
track of when the first packet has been registered in the automode code.
This was previously done implicitly (and not very good) using the fact
that the lastSeqNo and lastTimestamp members were initialized to zero.

Two new unit tests were added as part of this CL.
NetEqDecodingTest.SequenceNumberWrap was failing before the fixes were
made; now it is ok.

BUG=2654
R=tina.legrand@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/4139004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5150 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/neteq/automode.c b/webrtc/modules/audio_coding/neteq/automode.c
index a922448..4dbd81e 100644
--- a/webrtc/modules/audio_coding/neteq/automode.c
+++ b/webrtc/modules/audio_coding/neteq/automode.c
@@ -28,6 +28,17 @@
 extern FILE *delay_fid2; /* file pointer to delay log file */
 #endif /* NETEQ_DELAY_LOGGING */
 
+// These two functions are copied from module_common_types.h, but adapted for C.
+int WebRtcNetEQ_IsNewerSequenceNumber(uint16_t sequence_number,
+                                      uint16_t prev_sequence_number) {
+  return sequence_number != prev_sequence_number &&
+         ((uint16_t) (sequence_number - prev_sequence_number)) < 0x8000;
+}
+
+int WebRtcNetEQ_IsNewerTimestamp(uint32_t timestamp, uint32_t prev_timestamp) {
+  return timestamp != prev_timestamp &&
+         ((uint32_t) (timestamp - prev_timestamp)) < 0x80000000;
+}
 
 int WebRtcNetEQ_UpdateIatStatistics(AutomodeInst_t *inst, int maxBufLen,
                                     uint16_t seqNumber, uint32_t timeStamp,
@@ -55,7 +66,8 @@
     /****************************/
 
     /* Try calculating packet length from current and previous timestamps */
-    if ((timeStamp <= inst->lastTimeStamp) || (seqNumber <= inst->lastSeqNo))
+    if (!WebRtcNetEQ_IsNewerTimestamp(timeStamp, inst->lastTimeStamp) ||
+        !WebRtcNetEQ_IsNewerSequenceNumber(seqNumber, inst->lastSeqNo))
     {
         /* Wrong timestamp or sequence order; revert to backup plan */
         packetLenSamp = inst->packetSpeechLenSamp; /* use stored value */
@@ -68,7 +80,7 @@
     }
 
     /* Check that the packet size is positive; if not, the statistics cannot be updated. */
-    if (packetLenSamp > 0)
+    if (inst->firstPacketReceived && packetLenSamp > 0)
     { /* packet size ok */
 
         /* calculate inter-arrival time in integer packets (rounding down) */
@@ -113,19 +125,19 @@
         } /* end of streaming mode */
 
         /* check for discontinuous packet sequence and re-ordering */
-        if (seqNumber > inst->lastSeqNo + 1)
+        if (WebRtcNetEQ_IsNewerSequenceNumber(seqNumber, inst->lastSeqNo + 1))
         {
             /* Compensate for gap in the sequence numbers.
              * Reduce IAT with expected extra time due to lost packets, but ensure that
              * the IAT is not negative.
              */
             timeIat -= WEBRTC_SPL_MIN(timeIat,
-                (uint32_t) (seqNumber - inst->lastSeqNo - 1));
+                (uint16_t) (seqNumber - (uint16_t) (inst->lastSeqNo + 1)));
         }
-        else if (seqNumber < inst->lastSeqNo)
+        else if (!WebRtcNetEQ_IsNewerSequenceNumber(seqNumber, inst->lastSeqNo))
         {
             /* compensate for re-ordering */
-            timeIat += (uint32_t) (inst->lastSeqNo + 1 - seqNumber);
+            timeIat += (uint16_t) (inst->lastSeqNo + 1 - seqNumber);
         }
 
         /* saturate IAT at maximum value */
@@ -316,6 +328,8 @@
 
     inst->lastTimeStamp = timeStamp; /* remember current timestamp */
 
+    inst->firstPacketReceived = 1;
+
     return retval;
 }