Merge "AmrInputStream refresh: eliminate the dependency upon OpenCore's code" into gingerbread
This commit is contained in:
@@ -11,7 +11,8 @@ LOCAL_SRC_FILES:= \
|
|||||||
android_media_MediaScanner.cpp \
|
android_media_MediaScanner.cpp \
|
||||||
android_media_MediaMetadataRetriever.cpp \
|
android_media_MediaMetadataRetriever.cpp \
|
||||||
android_media_ResampleInputStream.cpp \
|
android_media_ResampleInputStream.cpp \
|
||||||
android_media_MediaProfiles.cpp
|
android_media_MediaProfiles.cpp \
|
||||||
|
android_media_AmrInputStream.cpp
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
libandroid_runtime \
|
libandroid_runtime \
|
||||||
@@ -27,12 +28,8 @@ LOCAL_SHARED_LIBRARIES := \
|
|||||||
|
|
||||||
ifneq ($(BUILD_WITHOUT_PV),true)
|
ifneq ($(BUILD_WITHOUT_PV),true)
|
||||||
|
|
||||||
LOCAL_SRC_FILES += \
|
|
||||||
android_media_AmrInputStream.cpp
|
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES += \
|
LOCAL_SHARED_LIBRARIES += \
|
||||||
libopencore_player \
|
libopencore_player
|
||||||
libomx_amrenc_sharedlibrary
|
|
||||||
else
|
else
|
||||||
LOCAL_CFLAGS += -DNO_OPENCORE
|
LOCAL_CFLAGS += -DNO_OPENCORE
|
||||||
endif
|
endif
|
||||||
@@ -52,6 +49,9 @@ LOCAL_C_INCLUDES += \
|
|||||||
external/tremor/Tremor \
|
external/tremor/Tremor \
|
||||||
frameworks/base/core/jni \
|
frameworks/base/core/jni \
|
||||||
frameworks/base/media/libmedia \
|
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) \
|
$(PV_INCLUDES) \
|
||||||
$(JNI_H_INCLUDE) \
|
$(JNI_H_INCLUDE) \
|
||||||
$(call include-path-for, corecg graphics)
|
$(call include-path-for, corecg graphics)
|
||||||
|
|||||||
@@ -18,36 +18,43 @@
|
|||||||
#define LOG_TAG "AmrInputStream"
|
#define LOG_TAG "AmrInputStream"
|
||||||
#include "utils/Log.h"
|
#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 "jni.h"
|
||||||
#include "JNIHelp.h"
|
#include "JNIHelp.h"
|
||||||
#include "android_runtime/AndroidRuntime.h"
|
#include "android_runtime/AndroidRuntime.h"
|
||||||
#include "gsmamr_encoder_wrapper.h"
|
#include "gsmamr_enc.h"
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
using namespace android;
|
using namespace android;
|
||||||
|
|
||||||
// Corresponds to max bit rate of 12.2 kbps.
|
// 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);
|
||||||
|
|
||||||
static const int SAMPLES_PER_FRAME = 8000 * 20 / 1000;
|
struct GsmAmrEncoderState {
|
||||||
|
GsmAmrEncoderState()
|
||||||
|
: mEncState(NULL),
|
||||||
|
mSidState(NULL),
|
||||||
|
mLastModeUsed(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~GsmAmrEncoderState() {}
|
||||||
|
|
||||||
|
void* mEncState;
|
||||||
|
void* mSidState;
|
||||||
|
int32_t mLastModeUsed;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// helper function to throw an exception
|
// helper function to throw an exception
|
||||||
//
|
//
|
||||||
static void throwException(JNIEnv *env, const char* ex, const char* fmt, int data) {
|
static void throwException(JNIEnv *env, const char* ex, const char* fmt, int data) {
|
||||||
if (jclass cls = env->FindClass(ex)) {
|
if (jclass cls = env->FindClass(ex)) {
|
||||||
char msg[1000];
|
char msg[128];
|
||||||
sprintf(msg, fmt, data);
|
sprintf(msg, fmt, data);
|
||||||
env->ThrowNew(cls, msg);
|
env->ThrowNew(cls, msg);
|
||||||
env->DeleteLocalRef(cls);
|
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
|
static jint android_media_AmrInputStream_GsmAmrEncoderNew
|
||||||
(JNIEnv *env, jclass clazz) {
|
(JNIEnv *env, jclass clazz) {
|
||||||
CPvGsmAmrEncoder* gae = new CPvGsmAmrEncoder();
|
GsmAmrEncoderState* gae = new GsmAmrEncoderState();
|
||||||
if (gae == NULL) {
|
if (gae == NULL) {
|
||||||
throwException(env, "java/lang/IllegalStateException",
|
throwException(env, "java/lang/RuntimeException",
|
||||||
"new CPvGsmAmrEncoder() failed", 0);
|
"Out of memory", 0);
|
||||||
}
|
}
|
||||||
return (jint)gae;
|
return (jint)gae;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void android_media_AmrInputStream_GsmAmrEncoderInitialize
|
static void android_media_AmrInputStream_GsmAmrEncoderInitialize
|
||||||
(JNIEnv *env, jclass clazz, jint gae) {
|
(JNIEnv *env, jclass clazz, jint gae) {
|
||||||
// set input parameters
|
GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
|
||||||
TEncodeProperties encodeProps;
|
int32_t nResult = AMREncodeInit(&state->mEncState, &state->mSidState, false);
|
||||||
encodeProps.iInBitsPerSample = 16;
|
if (nResult != OK) {
|
||||||
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)) {
|
|
||||||
throwException(env, "java/lang/IllegalArgumentException",
|
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,
|
(JNIEnv *env, jclass clazz,
|
||||||
jint gae, jbyteArray pcm, jint pcmOffset, jbyteArray amr, jint amrOffset) {
|
jint gae, jbyteArray pcm, jint pcmOffset, jbyteArray amr, jint amrOffset) {
|
||||||
|
|
||||||
// set up input stream
|
jbyte inBuf[BYTES_PER_FRAME];
|
||||||
jbyte inBuf[SAMPLES_PER_FRAME*2];
|
jbyte outBuf[MAX_OUTPUT_BUFFER_SIZE];
|
||||||
TInputAudioStream in;
|
|
||||||
in.iSampleBuffer = (uint8*)inBuf;
|
|
||||||
env->GetByteArrayRegion(pcm, pcmOffset, sizeof(inBuf), inBuf);
|
env->GetByteArrayRegion(pcm, pcmOffset, sizeof(inBuf), inBuf);
|
||||||
in.iSampleLength = sizeof(inBuf);
|
GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
|
||||||
in.iMode = CPvGsmAmrEncoder::GSM_AMR_12_2;
|
int32_t length = AMREncode(state->mEncState, state->mSidState,
|
||||||
in.iStartTime = 0;
|
(Mode) MR122,
|
||||||
in.iStopTime = 0;
|
(int16_t *) inBuf,
|
||||||
|
(unsigned char *) outBuf,
|
||||||
// set up output stream
|
(Frame_Type_3GPP*) &state->mLastModeUsed,
|
||||||
jbyte outBuf[aMaxOutputBufferSize];
|
AMR_TX_WMF);
|
||||||
int32 sampleFrameSize[1] = { 0 };
|
if (length < 0) {
|
||||||
TOutputAudioStream out;
|
throwException(env, "java/io/IOException",
|
||||||
out.iBitStreamBuffer = (uint8*)outBuf;
|
"Failed to encode a frame with error code: %d", length);
|
||||||
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate one-frame assumption
|
|
||||||
if (out.iNumSampleFrames != 1) {
|
|
||||||
throwException(env, "java/io/IOException",
|
|
||||||
"CPvGsmAmrEncoder::Encode more than one frame returned %d", out.iNumSampleFrames);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy result
|
|
||||||
int length = out.iSampleFrameSize[0];
|
|
||||||
|
|
||||||
// The 1st byte of PV AMR frames are WMF (Wireless Multimedia Forum)
|
// The 1st byte of PV AMR frames are WMF (Wireless Multimedia Forum)
|
||||||
// bitpacked, i.e.;
|
// bitpacked, i.e.;
|
||||||
// [P(4) + FT(4)]. Q=1 for good frame, P=padding bit, 0
|
// [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
|
static void android_media_AmrInputStream_GsmAmrEncoderCleanup
|
||||||
(JNIEnv *env, jclass clazz, jint gae) {
|
(JNIEnv *env, jclass clazz, jint gae) {
|
||||||
if (int rtn = ((CPvGsmAmrEncoder*)gae)->CleanupEncoder()) {
|
GsmAmrEncoderState *state = (GsmAmrEncoderState *)gae;
|
||||||
throwException(env, "java/lang/IllegalStateException",
|
AMREncodeExit(&state->mEncState, &state->mSidState);
|
||||||
"CPvGsmAmrEncoder::CleanupEncoder failed %d", rtn);
|
state->mEncState = NULL;
|
||||||
}
|
state->mSidState = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void android_media_AmrInputStream_GsmAmrEncoderDelete
|
static void android_media_AmrInputStream_GsmAmrEncoderDelete
|
||||||
(JNIEnv *env, jclass clazz, jint gae) {
|
(JNIEnv *env, jclass clazz, jint gae) {
|
||||||
delete (CPvGsmAmrEncoder*)gae;
|
delete (GsmAmrEncoderState*)gae;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user