From f4ae94229d736c7dbd3c5c36d484213d51545702 Mon Sep 17 00:00:00 2001 From: Chia-chi Yeh Date: Thu, 30 Sep 2010 03:04:06 +0800 Subject: RTP: Enable GSM-EFR codec. Change-Id: I9d84009e4557a0a82c1f9d7d543922741be97c77 --- voip/java/android/net/rtp/AudioCodec.java | 2 +- voip/jni/rtp/AmrCodec.cpp | 97 +++++++++++++++++++++++++++++++ voip/jni/rtp/Android.mk | 12 +++- voip/jni/rtp/AudioCodec.cpp | 2 + 4 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 voip/jni/rtp/AmrCodec.cpp 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 class AudioCodec { 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 @@ LOCAL_SRC_FILES := \ rtp_jni.cpp LOCAL_SRC_FILES += \ + AmrCodec.cpp \ G711Codec.cpp \ GsmCodec.cpp @@ -34,13 +35,20 @@ LOCAL_SHARED_LIBRARIES := \ 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 @@ struct AudioCodecType { {"PCMA", newAlawCodec}, {"PCMU", newUlawCodec}, {"GSM", newGsmCodec}, + {"GSM-EFR", newGsmEfrCodec}, {NULL, NULL}, }; -- cgit v1.1