mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
4.1 KiB
C
155 lines
4.1 KiB
C
13 years ago
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
#include <jni.h>
|
||
|
#include <inc/voAAC.h>
|
||
|
#include <inc/cmnMemory.h>
|
||
|
#include <android/log.h>
|
||
|
|
||
|
#define DEBUG 0
|
||
|
|
||
|
#if DEBUG
|
||
|
#define LOG(msg, args...) __android_log_print(ANDROID_LOG_ERROR, "aac-enc", msg, ## args)
|
||
|
#else
|
||
|
#define LOG(msg, args...)
|
||
|
#endif
|
||
|
|
||
|
/* utility functions */
|
||
|
|
||
|
void throwException(JNIEnv* env, const char *name, const char *msg)
|
||
|
{
|
||
|
jclass cls = (*env)->FindClass(env, name);
|
||
|
/* if cls is NULL, an exception has already been thrown */
|
||
|
if (cls != NULL) {
|
||
|
(*env)->ThrowNew(env, cls, msg);
|
||
|
}
|
||
|
/* free the local ref */
|
||
|
(*env)->DeleteLocalRef(env, cls);
|
||
|
}
|
||
|
|
||
|
/* internal storage */
|
||
|
|
||
|
FILE* outfile;
|
||
|
|
||
|
VO_AUDIO_CODECAPI codec_api;
|
||
|
VO_HANDLE handle = 0;
|
||
|
VO_AUDIO_CODECAPI codec_api = { 0 };
|
||
|
VO_MEM_OPERATOR mem_operator = { 0 };
|
||
|
VO_CODEC_INIT_USERDATA user_data;
|
||
|
AACENC_PARAM params = { 0 };
|
||
|
|
||
|
/* java native functions */
|
||
|
|
||
|
void
|
||
|
Java_com_todoroo_aacenc_AACEncoder_init( JNIEnv* env,
|
||
|
jobject thiz,
|
||
|
int bitrate,
|
||
|
int channels,
|
||
|
int sampleRate,
|
||
|
int bitsPerSample,
|
||
|
jstring outputFile)
|
||
|
{
|
||
|
|
||
|
if (bitsPerSample != 16) {
|
||
|
throwException(env, "java/lang/IllegalArgumentException",
|
||
|
"Unsupported sample depth. Only 16 bits per sample is supported");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
voGetAACEncAPI(&codec_api);
|
||
|
|
||
|
mem_operator.Alloc = cmnMemAlloc;
|
||
|
mem_operator.Copy = cmnMemCopy;
|
||
|
mem_operator.Free = cmnMemFree;
|
||
|
mem_operator.Set = cmnMemSet;
|
||
|
mem_operator.Check = cmnMemCheck;
|
||
|
user_data.memflag = VO_IMF_USERMEMOPERATOR;
|
||
|
user_data.memData = &mem_operator;
|
||
|
codec_api.Init(&handle, VO_AUDIO_CodingAAC, &user_data);
|
||
|
|
||
|
params.sampleRate = sampleRate;
|
||
|
params.bitRate = bitrate;
|
||
|
params.nChannels = channels;
|
||
|
params.adtsUsed = 1;
|
||
|
|
||
|
if (codec_api.SetParam(handle, VO_PID_AAC_ENCPARAM, ¶ms) != VO_ERR_NONE) {
|
||
|
throwException(env, "java/lang/IllegalArgumentException",
|
||
|
"Unable to set encoding parameters");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const char* output_file = (*env)->GetStringUTFChars(env, outputFile, (jboolean) 0);
|
||
|
outfile = fopen(output_file, "wb");
|
||
|
LOG("writing to %s", output_file);
|
||
|
(*env)->ReleaseStringUTFChars(env, outputFile, output_file);
|
||
|
|
||
|
LOG("initialized handle: %x", handle);
|
||
|
|
||
|
}
|
||
|
|
||
|
void
|
||
|
Java_com_todoroo_aacenc_AACEncoder_encode( JNIEnv* env,
|
||
|
jobject thiz,
|
||
|
jbyteArray inputArray)
|
||
|
{
|
||
|
|
||
|
LOG("writing to handle: %x", handle);
|
||
|
|
||
|
jbyte* buffer = (*env)->GetByteArrayElements(env, inputArray, (jboolean) 0);
|
||
|
int inputSize = (*env)->GetArrayLength(env, inputArray);
|
||
|
|
||
|
VO_CODECBUFFER input = { 0 }, output = { 0 };
|
||
|
VO_AUDIO_OUTPUTINFO output_info = { 0 };
|
||
|
|
||
|
int readSize = params.nChannels * 2 * 1024;
|
||
|
uint16_t* outbuf = (uint16_t*) malloc(readSize * 2);
|
||
|
|
||
|
LOG("input buffer: %d", inputSize);
|
||
|
|
||
|
/* GET OUTPUT DATA */
|
||
|
int i;
|
||
|
for(i = 0; i < inputSize; i += readSize) {
|
||
|
|
||
|
input.Buffer = buffer + i;
|
||
|
input.Length = readSize;
|
||
|
codec_api.SetInputData(handle, &input);
|
||
|
|
||
|
output.Buffer = outbuf;
|
||
|
output.Length = readSize * 2;
|
||
|
|
||
|
int status = codec_api.GetOutputData(handle, &output, &output_info);
|
||
|
if (status == VO_ERR_INPUT_BUFFER_SMALL)
|
||
|
break;
|
||
|
|
||
|
if (status == VO_ERR_OUTPUT_BUFFER_SMALL) {
|
||
|
LOG("output buffer was too small, read %d", output_info.InputUsed);
|
||
|
} else if (status != VO_ERR_NONE) {
|
||
|
char message[100];
|
||
|
sprintf(message, "Unable to encode frame: %x", status);
|
||
|
throwException(env, "java/lang/RuntimeException", message);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
fwrite(outbuf, 1, output.Length, outfile);
|
||
|
}
|
||
|
|
||
|
LOG("finished output");
|
||
|
(*env)->ReleaseByteArrayElements(env, inputArray, buffer, JNI_ABORT);
|
||
|
free(outbuf);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
Java_com_todoroo_aacenc_AACEncoder_uninit( JNIEnv* env,
|
||
|
jobject thiz)
|
||
|
{
|
||
|
|
||
|
fclose(outfile);
|
||
|
codec_api.Uninit(handle);
|
||
|
|
||
|
}
|
||
|
|
||
|
JNIEXPORT jint JNICALL
|
||
|
JNI_OnLoad (JavaVM * vm, void * reserved)
|
||
|
{
|
||
|
return JNI_VERSION_1_6;
|
||
|
}
|