Improve AV-sync when initial delay is set and NetEq has long buffer.

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3883 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/neteq/packet_buffer.c b/webrtc/modules/audio_coding/neteq/packet_buffer.c
index 39f40ef..83079d7 100644
--- a/webrtc/modules/audio_coding/neteq/packet_buffer.c
+++ b/webrtc/modules/audio_coding/neteq/packet_buffer.c
@@ -12,12 +12,15 @@
  * Implementation of the actual packet buffer data structure.
  */
 
+#include <assert.h>
 #include "packet_buffer.h"
 
 #include <string.h> /* to define NULL */
 
 #include "signal_processing_library.h"
 
+#include "mcu_dsp_common.h"
+
 #include "neteq_error_codes.h"
 
 #ifdef NETEQ_DELAY_LOGGING
@@ -140,7 +143,7 @@
 
 
 int WebRtcNetEQ_PacketBufferInsert(PacketBuf_t *bufferInst, const RTPPacket_t *RTPpacket,
-                                   int16_t *flushed)
+                                   int16_t *flushed, int av_sync)
 {
     int nextPos;
     int i;
@@ -169,6 +172,43 @@
         return (-1);
     }
 
+    /* If we are in AV-sync mode, there is a risk that we have inserted a sync
+     * packet but now received the real version of it. Or because of some timing
+     * we might be overwriting a true payload with sync (I'm not sure why this
+     * should happen in regular case, but in some FEC enabled case happens).
+     * Go through packets and delete the sync version of the packet in hand. Or
+     * if this is sync packet and the regular version of it exists in the buffer
+     * refrain from inserting.
+     *
+     * TODO(turajs): Could we get this for free if we had set the RCU-counter of
+     * the sync packet to a number larger than 2?
+     */
+    if (av_sync) {
+      for (i = 0; i < bufferInst->maxInsertPositions; ++i) {
+        /* Check if sequence numbers match and the payload actually exists. */
+        if (bufferInst->seqNumber[i] == RTPpacket->seqNumber &&
+            bufferInst->payloadLengthBytes[i] > 0) {
+          if (WebRtcNetEQ_IsSyncPayload(RTPpacket->payload,
+                                        RTPpacket->payloadLen)) {
+            return 0;
+          }
+
+          if (WebRtcNetEQ_IsSyncPayload(bufferInst->payloadLocation[i],
+                                        bufferInst->payloadLengthBytes[i])) {
+            /* Clear the position in the buffer. */
+            bufferInst->payloadType[i] = -1;
+            bufferInst->payloadLengthBytes[i] = 0;
+
+            /* Reduce packet counter by one. */
+            bufferInst->numPacketsInBuffer--;
+            /* TODO(turajs) if this is the latest packet better we rewind
+             * insertPosition and related variables. */
+            break;  /* There should be only one match. */
+          }
+        }
+      }
+    }
+
     /* Find a position in the buffer for this packet */
     if (bufferInst->numPacketsInBuffer != 0)
     {
@@ -406,7 +446,6 @@
   int32_t new_diff;
   int i;
   int16_t rcu_payload_cntr;
-
   if (buffer_inst->startPayloadMemory == NULL) {
     /* Packet buffer has not been initialized. */
     return PBUFFER_NOT_INITIALIZED;
@@ -493,10 +532,19 @@
 int WebRtcNetEQ_PacketBufferGetPacketSize(const PacketBuf_t* buffer_inst,
                                           int buffer_pos,
                                           const CodecDbInst_t* codec_database,
-                                          int codec_pos, int last_duration) {
+                                          int codec_pos, int last_duration,
+                                          int av_sync) {
   if (codec_database->funcDurationEst[codec_pos] == NULL) {
     return last_duration;
   }
+
+  if (av_sync != 0 &&
+      WebRtcNetEQ_IsSyncPayload(buffer_inst->payloadLocation[buffer_pos],
+                                buffer_inst->payloadLengthBytes[buffer_pos])) {
+    // In AV-sync and sync payload, report |last_duration| as current duration.
+    return last_duration;
+  }
+
   return (*codec_database->funcDurationEst[codec_pos])(
     codec_database->codec_state[codec_pos],
     (const uint8_t *)buffer_inst->payloadLocation[buffer_pos],
@@ -504,7 +552,8 @@
 }
 
 int32_t WebRtcNetEQ_PacketBufferGetSize(const PacketBuf_t* buffer_inst,
-                                        const CodecDbInst_t* codec_database) {
+                                        const CodecDbInst_t* codec_database,
+                                        int av_sync) {
   int i, count;
   int last_duration;
   int last_codec_pos;
@@ -546,9 +595,12 @@
          * last_duration to compute a changing duration, we would have to
          * iterate through the packets in chronological order by timestamp.
          */
-         last_duration = WebRtcNetEQ_PacketBufferGetPacketSize(
-           buffer_inst, i, codec_database, codec_pos,
-           last_duration);
+        /* Check for error before setting. */
+        int temp_last_duration = WebRtcNetEQ_PacketBufferGetPacketSize(
+            buffer_inst, i, codec_database, codec_pos,
+            last_duration, av_sync);
+        if (temp_last_duration >= 0)
+          last_duration = temp_last_duration;
       }
       /* Add in the size of this packet. */
       size_samples += last_duration;
@@ -560,7 +612,6 @@
   if (size_samples < 0) {
     size_samples = 0;
   }
-
   return size_samples;
 }