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

Commit 875500b4 authored by James Dong's avatar James Dong Committed by Android (Google) Code Review
Browse files

Merge "AmrInputStream refresh: eliminate the dependency upon OpenCore's code" into gingerbread

parents ef8f96a7 49b6fbae
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -11,7 +11,8 @@ LOCAL_SRC_FILES:= \
    android_media_MediaScanner.cpp \
    android_media_MediaMetadataRetriever.cpp \
    android_media_ResampleInputStream.cpp \
    android_media_MediaProfiles.cpp
    android_media_MediaProfiles.cpp \
    android_media_AmrInputStream.cpp

LOCAL_SHARED_LIBRARIES := \
    libandroid_runtime \
@@ -27,12 +28,8 @@ LOCAL_SHARED_LIBRARIES := \

ifneq ($(BUILD_WITHOUT_PV),true)

LOCAL_SRC_FILES += \
    android_media_AmrInputStream.cpp

LOCAL_SHARED_LIBRARIES += \
    libopencore_player          \
    libomx_amrenc_sharedlibrary
    libopencore_player
else
    LOCAL_CFLAGS += -DNO_OPENCORE
endif
@@ -52,6 +49,9 @@ LOCAL_C_INCLUDES += \
    external/tremor/Tremor \
    frameworks/base/core/jni \
    frameworks/base/media/libmedia \
    frameworks/base/media/libstagefright/codecs/amrnb/enc/src \
    frameworks/base/media/libstagefright/codecs/amrnb/common \
    frameworks/base/media/libstagefright/codecs/amrnb/common/include \
    $(PV_INCLUDES) \
    $(JNI_H_INCLUDE) \
    $(call include-path-for, corecg graphics)
+45 −70
Original line number Diff line number Diff line
@@ -18,36 +18,43 @@
#define LOG_TAG "AmrInputStream"
#include "utils/Log.h"

#include <media/mediarecorder.h>
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <utils/threads.h>

#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include "gsmamr_encoder_wrapper.h"

#include "gsmamr_enc.h"

// ----------------------------------------------------------------------------

using namespace android;

// Corresponds to max bit rate of 12.2 kbps.
static const int aMaxOutputBufferSize = 32;
static const int MAX_OUTPUT_BUFFER_SIZE = 32;
static const int FRAME_DURATION_MS = 20;
static const int SAMPLING_RATE_HZ = 8000;
static const int SAMPLES_PER_FRAME = ((SAMPLING_RATE_HZ * FRAME_DURATION_MS) / 1000);
static const int BYTES_PER_SAMPLE = 2;  // Assume 16-bit PCM samples
static const int BYTES_PER_FRAME = (SAMPLES_PER_FRAME * BYTES_PER_SAMPLE);

struct GsmAmrEncoderState {
    GsmAmrEncoderState()
        : mEncState(NULL),
          mSidState(NULL),
          mLastModeUsed(0) {
    }

static const int SAMPLES_PER_FRAME = 8000 * 20 / 1000;
    ~GsmAmrEncoderState() {}

    void*   mEncState;
    void*   mSidState;
    int32_t mLastModeUsed;
};

//
// helper function to throw an exception
//
static void throwException(JNIEnv *env, const char* ex, const char* fmt, int data) {
    if (jclass cls = env->FindClass(ex)) {
        char msg[1000];
        char msg[128];
        sprintf(msg, fmt, data);
        env->ThrowNew(cls, msg);
        env->DeleteLocalRef(cls);
@@ -56,34 +63,21 @@ static void throwException(JNIEnv *env, const char* ex, const char* fmt, int dat

static jint android_media_AmrInputStream_GsmAmrEncoderNew
        (JNIEnv *env, jclass clazz) {
    CPvGsmAmrEncoder* gae = new CPvGsmAmrEncoder();
    GsmAmrEncoderState* gae = new GsmAmrEncoderState();
    if (gae == NULL) {
        throwException(env, "java/lang/IllegalStateException",
                "new CPvGsmAmrEncoder() failed", 0);
        throwException(env, "java/lang/RuntimeException",
                "Out of memory", 0);
    }
    return (jint)gae;
}

static void android_media_AmrInputStream_GsmAmrEncoderInitialize
        (JNIEnv *env, jclass clazz, jint gae) {
    // set input parameters
    TEncodeProperties encodeProps;
    encodeProps.iInBitsPerSample = 16;
    encodeProps.iInSamplingRate = 8000;
    encodeProps.iInClockRate = 1000;
    encodeProps.iInNumChannels = 1;
    encodeProps.iInInterleaveMode = TEncodeProperties::EINTERLEAVE_LR;
    encodeProps.iMode = CPvGsmAmrEncoder::GSM_AMR_12_2;
    encodeProps.iBitStreamFormat = false;
    encodeProps.iAudioObjectType = 0;
    encodeProps.iOutSamplingRate = encodeProps.iInSamplingRate;
    encodeProps.iOutNumChannels = encodeProps.iInNumChannels;
    encodeProps.iOutClockRate = encodeProps.iInClockRate;

    if (int rtn = ((CPvGsmAmrEncoder*)gae)->
            InitializeEncoder(aMaxOutputBufferSize, &encodeProps)) {
    GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
    int32_t nResult = AMREncodeInit(&state->mEncState, &state->mSidState, false);
    if (nResult != OK) {
        throwException(env, "java/lang/IllegalArgumentException",
                "CPvGsmAmrEncoder::InitializeEncoder failed %d", rtn);
                "GsmAmrEncoder initialization failed %d", nResult);
    }
}

@@ -91,42 +85,23 @@ static jint android_media_AmrInputStream_GsmAmrEncoderEncode
        (JNIEnv *env, jclass clazz,
         jint gae, jbyteArray pcm, jint pcmOffset, jbyteArray amr, jint amrOffset) {

    // set up input stream
    jbyte inBuf[SAMPLES_PER_FRAME*2];
    TInputAudioStream in;
    in.iSampleBuffer = (uint8*)inBuf;
    env->GetByteArrayRegion(pcm, pcmOffset, sizeof(inBuf), inBuf);
    in.iSampleLength = sizeof(inBuf);
    in.iMode = CPvGsmAmrEncoder::GSM_AMR_12_2;
    in.iStartTime = 0;
    in.iStopTime = 0;

    // set up output stream
    jbyte outBuf[aMaxOutputBufferSize];
    int32 sampleFrameSize[1] = { 0 };
    TOutputAudioStream out;
    out.iBitStreamBuffer = (uint8*)outBuf;
    out.iNumSampleFrames = 0;
    out.iSampleFrameSize = sampleFrameSize;
    out.iStartTime = 0;
    out.iStopTime = 0;

    // encode
    if (int rtn = ((CPvGsmAmrEncoder*)gae)->Encode(in, out)) {
        throwException(env, "java/io/IOException", "CPvGsmAmrEncoder::Encode failed %d", rtn);
        return -1;
    }
    jbyte inBuf[BYTES_PER_FRAME];
    jbyte outBuf[MAX_OUTPUT_BUFFER_SIZE];

    // validate one-frame assumption
    if (out.iNumSampleFrames != 1) {
    env->GetByteArrayRegion(pcm, pcmOffset, sizeof(inBuf), inBuf);
    GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
    int32_t length = AMREncode(state->mEncState, state->mSidState,
                                (Mode) MR122,
                                (int16_t *) inBuf,
                                (unsigned char *) outBuf,
                                (Frame_Type_3GPP*) &state->mLastModeUsed,
                                AMR_TX_WMF);
    if (length < 0) {
        throwException(env, "java/io/IOException",
                "CPvGsmAmrEncoder::Encode more than one frame returned %d", out.iNumSampleFrames);
        return 0;
                "Failed to encode a frame with error code: %d", length);
        return -1;
    }

    // copy result
    int length = out.iSampleFrameSize[0];

    // The 1st byte of PV AMR frames are WMF (Wireless Multimedia Forum)
    // bitpacked, i.e.;
    //    [P(4) + FT(4)]. Q=1 for good frame, P=padding bit, 0
@@ -144,15 +119,15 @@ static jint android_media_AmrInputStream_GsmAmrEncoderEncode

static void android_media_AmrInputStream_GsmAmrEncoderCleanup
        (JNIEnv *env, jclass clazz, jint gae) {
    if (int rtn = ((CPvGsmAmrEncoder*)gae)->CleanupEncoder()) {
        throwException(env, "java/lang/IllegalStateException",
                "CPvGsmAmrEncoder::CleanupEncoder failed %d", rtn);
    }
    GsmAmrEncoderState *state = (GsmAmrEncoderState *)gae;
    AMREncodeExit(&state->mEncState, &state->mSidState);
    state->mEncState = NULL;
    state->mSidState = NULL;
}

static void android_media_AmrInputStream_GsmAmrEncoderDelete
        (JNIEnv *env, jclass clazz, jint gae) {
    delete (CPvGsmAmrEncoder*)gae;
    delete (GsmAmrEncoderState*)gae;
}

// ----------------------------------------------------------------------------