From 061fa5b828fbeb30f1e9a79be73df1ad7675c76c Mon Sep 17 00:00:00 2001
From: "pwestin@webrtc.org"
 <pwestin@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>
Date: Tue, 20 Dec 2011 15:56:17 +0000
Subject: [PATCH] Changed handling of padding data. Review URL:
 http://webrtc-codereview.appspot.com/331008

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1252 4adac7df-926f-26a2-2b94-8c16560cd09d
---
 src/modules/rtp_rtcp/source/rtp_receiver.cc   | 26 ++++---
 .../rtp_rtcp/source/rtp_receiver_video.cc     | 30 +++++--
 .../rtp_rtcp/source/rtp_sender_video.cc       | 78 ++++++++++---------
 .../rtp_rtcp/source/rtp_sender_video.h        |  5 +-
 4 files changed, 82 insertions(+), 57 deletions(-)

diff --git a/src/modules/rtp_rtcp/source/rtp_receiver.cc b/src/modules/rtp_rtcp/source/rtp_receiver.cc
index 18e6c9850..a864b9d6c 100644
--- a/src/modules/rtp_rtcp/source/rtp_receiver.cc
+++ b/src/modules/rtp_rtcp/source/rtp_receiver.cc
@@ -804,12 +804,6 @@ RTPReceiver::IncomingRTPPacket(WebRtcRTPHeader* rtpHeader,
             }
         }
     }
-    if(length - rtpHeader->header.headerLength == 0)
-    {
-        // ok keepalive packet
-        return 0;
-    }
-
     WebRtc_Word8 firstPayloadByte = 0;
     if(length > 0)
     {
@@ -829,9 +823,23 @@ RTPReceiver::IncomingRTPPacket(WebRtcRTPHeader* rtpHeader,
     audioSpecific.channels = 0;
     audioSpecific.frequency = 0;
 
-    if(CheckPayloadChanged(rtpHeader, firstPayloadByte, isRED, audioSpecific, videoSpecific) == -1)
+    if (CheckPayloadChanged(rtpHeader,
+                            firstPayloadByte,
+                            isRED,
+                            audioSpecific,
+                            videoSpecific) == -1)
     {
-        WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s received invalid payloadtype", __FUNCTION__);
+        if (length - rtpHeader->header.headerLength == 0)
+        {
+            // ok keepalive packet
+            WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
+                 "%s received keepalive",
+                  __FUNCTION__);
+            return 0;
+        }
+        WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
+             "%s received invalid payloadtype",
+              __FUNCTION__);
         return -1;
     }
     CheckCSRC(rtpHeader);
@@ -847,7 +855,7 @@ RTPReceiver::IncomingRTPPacket(WebRtcRTPHeader* rtpHeader,
                                          payloadDataLength,
                                          audioSpecific,
                                          isRED);
-    }else
+    } else
     {
         retVal = ParseVideoCodecSpecific(rtpHeader,
                                          payloadData,
diff --git a/src/modules/rtp_rtcp/source/rtp_receiver_video.cc b/src/modules/rtp_rtcp/source/rtp_receiver_video.cc
index 82c664de7..4bf418a11 100644
--- a/src/modules/rtp_rtcp/source/rtp_receiver_video.cc
+++ b/src/modules/rtp_rtcp/source/rtp_receiver_video.cc
@@ -231,7 +231,8 @@ RTPReceiverVideo::ParseVideoCodecSpecific(WebRtcRTPHeader* rtpHeader,
 
     _criticalSectionReceiverVideo->Enter();
 
-    _videoBitRate.Update(payloadDataLength, nowMS);
+    _videoBitRate.Update(payloadDataLength + rtpHeader->header.paddingLength,
+                         nowMS);
 
     // Add headers, ideally we would like to include for instance
     // Ethernet header here as well.
@@ -647,14 +648,21 @@ RTPReceiverVideo::ReceiveVp8Codec(WebRtcRTPHeader* rtpHeader,
                                   const WebRtc_UWord8* payloadData,
                                   const WebRtc_UWord16 payloadDataLength)
 {
-    ModuleRTPUtility::RTPPayloadParser rtpPayloadParser(kRtpVp8Video,
-                                                        payloadData,
-                                                        payloadDataLength,
-                                                        _id);
-
+    bool success;
     ModuleRTPUtility::RTPPayload parsedPacket;
-    const bool success = rtpPayloadParser.Parse(parsedPacket);
-
+    if (payloadDataLength == 0)
+    {
+        success = true;
+        parsedPacket.info.VP8.dataLength = 0;
+    } else
+    {
+        ModuleRTPUtility::RTPPayloadParser rtpPayloadParser(kRtpVp8Video,
+                                                            payloadData,
+                                                            payloadDataLength,
+                                                           _id);
+ 
+        success = rtpPayloadParser.Parse(parsedPacket);
+    }
     // from here down we only work on local data
     _criticalSectionReceiverVideo->Leave();
 
@@ -665,6 +673,12 @@ RTPReceiverVideo::ReceiveVp8Codec(WebRtcRTPHeader* rtpHeader,
     if (parsedPacket.info.VP8.dataLength == 0)
     {
         // we have an "empty" VP8 packet, it's ok, could be one way video
+        // Inform the jitter buffer about this packet.
+        rtpHeader->frameType = kFrameEmpty;
+        if (CallbackOfReceivedPayloadData(NULL, 0, rtpHeader) != 0)
+        {
+            return -1;
+        }
         return 0;
     }
     rtpHeader->frameType = (parsedPacket.frameType == ModuleRTPUtility::kIFrame) ? kVideoFrameKey : kVideoFrameDelta;
diff --git a/src/modules/rtp_rtcp/source/rtp_sender_video.cc b/src/modules/rtp_rtcp/source/rtp_sender_video.cc
index 5a8896312..c675e0a2f 100644
--- a/src/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/src/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -545,50 +545,52 @@ RTPSenderVideo::SendGeneric(const WebRtc_Word8 payloadType,
     return 0;
 }
 
-WebRtc_Word32
-RTPSenderVideo::SendPadData(const WebRtcRTPHeader* rtpHeader,
-                            const WebRtc_UWord32 bytes)
-{
-    const WebRtc_UWord16 rtpHeaderLength = _rtpSender.RTPHeaderLength();
-    WebRtc_UWord32 maxLength = _rtpSender.MaxPayloadLength() -
-        FECPacketOverhead() - rtpHeaderLength;
-    WebRtc_UWord8 dataBuffer[IP_PACKET_SIZE];
+void RTPSenderVideo::SendPadData(WebRtc_Word8 payload_type,
+                                 WebRtc_UWord32 capture_timestamp,
+                                 WebRtc_Word32 bytes) {
+  // Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP.
+  int max_length = 224;
+  WebRtc_UWord8 data_buffer[IP_PACKET_SIZE];
 
-    if(bytes<maxLength)
+  for (; bytes > 0; bytes -= max_length) {
+    WebRtc_Word32 header_length;
     {
-        // For a small packet don't spend too much time
-        maxLength = bytes;
+      CriticalSectionScoped cs(_sendVideoCritsect);
+
+      // Correct seq num, timestamp and payload type.
+      header_length = _rtpSender.BuildRTPheader(
+          data_buffer,
+          payload_type,
+          false,  // No markerbit.
+          capture_timestamp,
+          true,  // Timestamp provided.
+          true);  // Increment sequence number.
+
     }
+    data_buffer[0] |= 0x20;  // Set padding bit.
+    WebRtc_Word32* data =
+        reinterpret_cast<WebRtc_Word32*>(&(data_buffer[header_length]));
 
-    {
-        CriticalSectionScoped cs(_sendVideoCritsect);
-
-        // Send paded data
-        // Correct seq num, time stamp and payloadtype
-        // We reuse the last seq number
-        _rtpSender.BuildRTPheader(dataBuffer, rtpHeader->header.payloadType,
-                                  false, 0, false, false);
-
-        // Version 0 to be compatible with old ViE
-        dataBuffer[0] &= !0x80;
-
-        // Set relay SSRC
-        ModuleRTPUtility::AssignUWord32ToBuffer(dataBuffer+8,
-                                                rtpHeader->header.ssrc);
-        // Start at 12
-        WebRtc_Word32* data = (WebRtc_Word32*)&(dataBuffer[12]);
-
-        // Build data buffer
-        for(WebRtc_UWord32 j = 0; j < ((maxLength>>2)-4) && j < (bytes>>4); j++)
-        {
-            data[j] = rand();
-        }
+    int padding_bytes_in_packet = max_length;
+    if (bytes < max_length) {
+      padding_bytes_in_packet = (bytes + 16) & 0xffe0;  // Keep our modulus 32.
     }
-    // Min
-    WebRtc_UWord16 length = (WebRtc_UWord16)(bytes<maxLength?bytes:maxLength);
-
+    if (padding_bytes_in_packet < 32) {
+       // Sanity don't send empty packets.
+       return;
+    }
+    // Fill data buffer with random data.
+    for(int j = 0; j < (padding_bytes_in_packet >> 2); j++) {
+      data[j] = rand();
+    }
+    // Set number of padding bytes in the last byte of the packet.
+    data_buffer[header_length + padding_bytes_in_packet - 1] =
+        padding_bytes_in_packet;
     // Send the packet
-    return _rtpSender.SendToNetwork(dataBuffer, length, rtpHeaderLength, true);
+    _rtpSender.SendToNetwork(data_buffer,
+                             padding_bytes_in_packet,
+                             header_length);
+  }
 }
 
 WebRtc_Word32
diff --git a/src/modules/rtp_rtcp/source/rtp_sender_video.h b/src/modules/rtp_rtcp/source/rtp_sender_video.h
index 989205ff7..9b8e02d78 100644
--- a/src/modules/rtp_rtcp/source/rtp_sender_video.h
+++ b/src/modules/rtp_rtcp/source/rtp_sender_video.h
@@ -68,8 +68,9 @@ public:
 
     WebRtc_UWord32 MaxConfiguredBitrateVideo() const;
 
-    WebRtc_Word32 SendPadData(const WebRtcRTPHeader* rtpHeader,
-                              const WebRtc_UWord32 bytes);
+    void SendPadData(WebRtc_Word8 payload_type,
+                     WebRtc_UWord32 capture_timestamp,
+                     WebRtc_Word32 bytes);
 
     // FEC
     WebRtc_Word32 SetGenericFECStatus(const bool enable,