From 91744a1f148ef6d8dbaaf74ae3b331b1faf34b6b Mon Sep 17 00:00:00 2001
From: Lyubomir Marinov <lyubomir.marinov@jitsi.org>
Date: Wed, 4 Jun 2014 20:23:18 +0300
Subject: [PATCH] Fixes a false reporting of SSRC audio levels when such are
 negotiated but not sent.

---
 src/org/jitsi/impl/neomedia/RawPacket.java    | 63 +++++++++++++------
 .../transform/csrc/SsrcTransformEngine.java   |  2 +-
 2 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/src/org/jitsi/impl/neomedia/RawPacket.java b/src/org/jitsi/impl/neomedia/RawPacket.java
index b2929221..c4f4805b 100644
--- a/src/org/jitsi/impl/neomedia/RawPacket.java
+++ b/src/org/jitsi/impl/neomedia/RawPacket.java
@@ -240,7 +240,14 @@ public long[] extractCsrcAudioLevels(byte csrcExtID)
             int csrcLevelsIndex = 2 * i;
 
             csrcLevels[csrcLevelsIndex] = 0xFFFFFFFFL & readInt(csrcStartIndex);
-            csrcLevels[csrcLevelsIndex + 1] = getCsrcAudioLevel(csrcExtID, i);
+            /*
+             * The audio levels generated by Jitsi are not in accord with the
+             * respective specification, they are backwards with respect to the
+             * value domain. Which means that the audio level generated from a
+             * muted audio source is 0/zero.
+             */
+            csrcLevels[csrcLevelsIndex + 1]
+                = getCsrcAudioLevel(csrcExtID, i, (byte) 0);
         }
 
         return csrcLevels;
@@ -267,13 +274,29 @@ public long[] extractCsrcList()
         return csrcList;
     }
 
+    /**
+     * Extracts the source audio level reported by the remote party which sent
+     * this packet and carried in this packet.
+     *
+     * @param ssrcExtID the ID of the extension that's transporting ssrc audio
+     * levels in the session that this <tt>RawPacket</tt> belongs to
+     * @return the source audio level reported by the remote party which sent
+     * this packet and carried in this packet or a negative value if this packet
+     * contains no extension such as the specified by <tt>ssrcExtID</tt>
+     */
     public byte extractSsrcAudioLevel(byte ssrcExtID)
     {
         /*
          * The method getCsrcAudioLevel(byte, int) is implemented with the
          * awareness that there may be a flag bit V with a value other than 0.
          */
-        return getCsrcAudioLevel(ssrcExtID, 0);
+        /*
+         * The audio levels sent by Google Chrome are in accord with the
+         * specification i.e. the audio level generated from a muted audio
+         * source is 127 and the values are non-negative. If there is no source
+         * audio level in this packet, return a negative value.
+         */
+        return getCsrcAudioLevel(ssrcExtID, 0, Byte.MIN_VALUE);
     }
 
     /**
@@ -375,26 +398,30 @@ public byte[] getBuffer()
      * @return the CSRC audio level at the specified index of the csrc audio
      * level option or <tt>0</tt> if there was no level at that index.
      */
-    private byte getCsrcAudioLevel(byte csrcExtID, int index)
+    private byte getCsrcAudioLevel(byte csrcExtID, int index, byte defaultValue)
     {
-        if( !getExtensionBit() || getExtensionLength() == 0)
-            return 0;
-
-        int levelsStart = findExtension(csrcExtID);
+        byte level = defaultValue;
 
-        if(levelsStart == -1)
-            return 0;
-
-        int levelsCount = getLengthForExtension(levelsStart);
-
-        if(levelsCount < index)
+        if (getExtensionBit() && getExtensionLength() != 0)
         {
-            //apparently the remote side sent more CSRCs than levels.
-            // ... yeah remote sides do that now and then ...
-            return 0;
-        }
+            int levelsStart = findExtension(csrcExtID);
 
-        return (byte) (0x7F & buffer[levelsStart + index]);
+            if (levelsStart != -1)
+            {
+                int levelsCount = getLengthForExtension(levelsStart);
+
+                if (levelsCount < index)
+                {
+                    //apparently the remote side sent more CSRCs than levels.
+                    // ... yeah remote sides do that now and then ...
+                }
+                else
+                {
+                    level = (byte) (0x7F & buffer[levelsStart + index]);
+                }
+            }
+        }
+        return level;
     }
 
     /**
diff --git a/src/org/jitsi/impl/neomedia/transform/csrc/SsrcTransformEngine.java b/src/org/jitsi/impl/neomedia/transform/csrc/SsrcTransformEngine.java
index d940ea44..17ce4251 100644
--- a/src/org/jitsi/impl/neomedia/transform/csrc/SsrcTransformEngine.java
+++ b/src/org/jitsi/impl/neomedia/transform/csrc/SsrcTransformEngine.java
@@ -239,7 +239,7 @@ public RawPacket reverseTransform(RawPacket pkt)
              * Notify the AudioMediaStream associated with this instance about
              * the received audio level.
              */
-            if (!dropPkt && (csrcAudioLevelDispatcher != null))
+            if (!dropPkt && (csrcAudioLevelDispatcher != null) && (level >= 0))
             {
                 long[] levels = new long[2];
 
-- 
GitLab