Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f4ae9422 authored by Chia-chi Yeh's avatar Chia-chi Yeh
Browse files

RTP: Enable GSM-EFR codec.

Change-Id: I9d84009e4557a0a82c1f9d7d543922741be97c77
parent fe529899
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
+97 −0
Original line number Diff line number Diff line
/*
 * 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;
}
+10 −2
Original line number Diff line number Diff line
@@ -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

+2 −0
Original line number Diff line number Diff line
@@ -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},
};