am 1c2eab2d: am 955ab37c: Merge "RTP: Enable GSM-EFR codec." into gingerbread

Merge commit '1c2eab2d86faa9c647a9893f761a50cfa28d9d57'

* commit '1c2eab2d86faa9c647a9893f761a50cfa28d9d57':
  RTP: Enable GSM-EFR codec.
diff --git a/voip/java/android/net/rtp/AudioCodec.java b/voip/java/android/net/rtp/AudioCodec.java
index dfa6841..f171806 100644
--- a/voip/java/android/net/rtp/AudioCodec.java
+++ b/voip/java/android/net/rtp/AudioCodec.java
@@ -81,7 +81,7 @@
     public static final AudioCodec AMR = new AudioCodec(97, "AMR/8000", null);
 
     // TODO: add rest of the codecs when the native part is done.
-    private static final AudioCodec[] sCodecs = {GSM, PCMU, PCMA};
+    private static final AudioCodec[] sCodecs = {GSM_EFR, GSM, PCMU, PCMA};
 
     private AudioCodec(int type, String rtpmap, String fmtp) {
         this.type = type;
diff --git a/voip/jni/rtp/AmrCodec.cpp b/voip/jni/rtp/AmrCodec.cpp
new file mode 100644
index 0000000..9a2227d
--- /dev/null
+++ b/voip/jni/rtp/AmrCodec.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyrightm (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AudioCodec.h"
+
+#include "gsmamr_dec.h"
+#include "gsmamr_enc.h"
+
+namespace {
+
+class GsmEfrCodec : public AudioCodec
+{
+public:
+    GsmEfrCodec() {
+        if (AMREncodeInit(&mEncoder, &mSidSync, false)) {
+            mEncoder = NULL;
+        }
+        if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) {
+            mDecoder = NULL;
+        }
+    }
+
+    ~GsmEfrCodec() {
+        if (mEncoder) {
+            AMREncodeExit(&mEncoder, &mSidSync);
+        }
+        if (mDecoder) {
+            GSMDecodeFrameExit(&mDecoder);
+        }
+    }
+
+    int set(int sampleRate, const char *fmtp) {
+        return (sampleRate == 8000 && mEncoder && mDecoder) ? 160 : -1;
+    }
+
+    int encode(void *payload, int16_t *samples);
+    int decode(int16_t *samples, void *payload, int length);
+
+private:
+    void *mEncoder;
+    void *mSidSync;
+    void *mDecoder;
+};
+
+int GsmEfrCodec::encode(void *payload, int16_t *samples)
+{
+    unsigned char *bytes = (unsigned char *)payload;
+    Frame_Type_3GPP type;
+
+    int length = AMREncode(mEncoder, mSidSync, MR122,
+        samples, bytes, &type, AMR_TX_WMF);
+
+    if (type == AMR_122 && length == 32) {
+        bytes[0] = 0xC0 | (bytes[1] >> 4);
+        for (int i = 1; i < 31; ++i) {
+            bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4);
+        }
+        return 31;
+    }
+    return -1;
+}
+
+int GsmEfrCodec::decode(int16_t *samples, void *payload, int length)
+{
+    unsigned char *bytes = (unsigned char *)payload;
+    if (length == 31 && (bytes[0] >> 4) == 0x0C) {
+        for (int i = 0; i < 30; ++i) {
+            bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4);
+        }
+        bytes[30] <<= 4;
+
+        if (AMRDecode(mDecoder, AMR_122, bytes, samples, MIME_IETF) == 31) {
+            return 160;
+        }
+    }
+    return -1;
+}
+
+} // namespace
+
+AudioCodec *newGsmEfrCodec()
+{
+    return new GsmEfrCodec;
+}
diff --git a/voip/jni/rtp/Android.mk b/voip/jni/rtp/Android.mk
index 29683bd..5909c0d 100644
--- a/voip/jni/rtp/Android.mk
+++ b/voip/jni/rtp/Android.mk
@@ -27,6 +27,7 @@
 	rtp_jni.cpp
 
 LOCAL_SRC_FILES += \
+	AmrCodec.cpp \
 	G711Codec.cpp \
 	GsmCodec.cpp
 
@@ -34,13 +35,20 @@
 	libnativehelper \
 	libcutils \
 	libutils \
-	libmedia
+	libmedia \
+	libstagefright
 
 LOCAL_STATIC_LIBRARIES := libgsm
 
 LOCAL_C_INCLUDES += \
 	$(JNI_H_INCLUDE) \
-	external/libgsm/inc
+	external/libgsm/inc \
+	frameworks/base/media/libstagefright/codecs/amrnb/common/include \
+	frameworks/base/media/libstagefright/codecs/amrnb/common/ \
+	frameworks/base/media/libstagefright/codecs/amrnb/enc/include \
+	frameworks/base/media/libstagefright/codecs/amrnb/enc/src \
+	frameworks/base/media/libstagefright/codecs/amrnb/dec/include \
+	frameworks/base/media/libstagefright/codecs/amrnb/dec/src
 
 LOCAL_CFLAGS += -fvisibility=hidden
 
diff --git a/voip/jni/rtp/AudioCodec.cpp b/voip/jni/rtp/AudioCodec.cpp
index fc33ef2..afc193c 100644
--- a/voip/jni/rtp/AudioCodec.cpp
+++ b/voip/jni/rtp/AudioCodec.cpp
@@ -21,6 +21,7 @@
 extern AudioCodec *newAlawCodec();
 extern AudioCodec *newUlawCodec();
 extern AudioCodec *newGsmCodec();
+extern AudioCodec *newGsmEfrCodec();
 
 struct AudioCodecType {
     const char *name;
@@ -29,6 +30,7 @@
     {"PCMA", newAlawCodec},
     {"PCMU", newUlawCodec},
     {"GSM", newGsmCodec},
+    {"GSM-EFR", newGsmEfrCodec},
     {NULL, NULL},
 };