Skip to content

Commit bbdb87a

Browse files
author
Tim Su
committed
A little logging, a little tweaking, and we have an AWESOME api!
1 parent a249e98 commit bbdb87a

File tree

7 files changed

+137
-65
lines changed

7 files changed

+137
-65
lines changed

AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
android:versionCode="1"
55
android:versionName="1.0" >
66

7+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
8+
79
<uses-sdk android:minSdkVersion="7" />
810

911
<application

jni/Android.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ endif
6363

6464
LOCAL_ARM_MODE := arm
6565

66+
LOCAL_LDLIBS := -llog
67+
6668
LOCAL_STATIC_LIBRARIES :=
6769
LOCAL_SHARED_LIBRARIES :=
6870

jni/aac-enc.c

Lines changed: 93 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
#include <string.h>
2+
#include <stdio.h>
23
#include <jni.h>
34
#include <inc/voAAC.h>
45
#include <inc/cmnMemory.h>
6+
#include <android/log.h>
7+
8+
#define DEBUG 1
9+
10+
#if DEBUG
11+
#define LOG(msg, args...) __android_log_print(ANDROID_LOG_ERROR, "aac-enc", msg, ## args)
12+
#else
13+
#define LOG(msg)
14+
#endif
15+
16+
/* utility functions */
517

618
void throwException(JNIEnv* env, const char *name, const char *msg)
719
{
@@ -14,32 +26,35 @@ void throwException(JNIEnv* env, const char *name, const char *msg)
1426
(*env)->DeleteLocalRef(env, cls);
1527
}
1628

17-
jbyteArray
18-
Java_com_todoroo_aacenc_AACEncoder_encode( JNIEnv* env,
19-
jobject thiz,
20-
int bitrate,
21-
int channels,
22-
int sampleRate,
23-
int bitsPerSample,
24-
jbyteArray inputArray)
25-
{
26-
int ch;
29+
/* internal storage */
30+
31+
FILE* outfile;
32+
33+
VO_AUDIO_CODECAPI codec_api;
34+
VO_HANDLE handle = 0;
35+
VO_AUDIO_CODECAPI codec_api = { 0 };
36+
VO_MEM_OPERATOR mem_operator = { 0 };
37+
VO_CODEC_INIT_USERDATA user_data;
38+
AACENC_PARAM params = { 0 };
2739

28-
VO_AUDIO_CODECAPI codec_api = { 0 };
29-
VO_HANDLE handle = 0;
30-
VO_MEM_OPERATOR mem_operator = { 0 };
31-
VO_CODEC_INIT_USERDATA user_data;
32-
AACENC_PARAM params = { 0 };
40+
/* java native functions */
41+
42+
void
43+
Java_com_todoroo_aacenc_AACEncoder_init( JNIEnv* env,
44+
jobject thiz,
45+
int bitrate,
46+
int channels,
47+
int sampleRate,
48+
int bitsPerSample,
49+
jstring outputFile)
50+
{
3351

3452
if (bitsPerSample != 16) {
3553
throwException(env, "java/lang/IllegalArgumentException",
36-
"Unsupported WAV sample depth. Only 16 bits per sample is supported");
37-
return NULL;
54+
"Unsupported sample depth. Only 16 bits per sample is supported");
55+
return;
3856
}
3957

40-
jbyte* buffer = (*env)->GetByteArrayElements(env, inputArray, (jboolean) 0);
41-
int inputSize = (*env)->GetArrayLength(env, inputArray);
42-
4358
voGetAACEncAPI(&codec_api);
4459

4560
mem_operator.Alloc = cmnMemAlloc;
@@ -58,37 +73,82 @@ Java_com_todoroo_aacenc_AACEncoder_encode( JNIEnv* env,
5873
if (codec_api.SetParam(handle, VO_PID_AAC_ENCPARAM, &params) != VO_ERR_NONE) {
5974
throwException(env, "java/lang/IllegalArgumentException",
6075
"Unable to set encoding parameters");
61-
return NULL;
76+
return;
6277
}
6378

79+
const char* output_file = (*env)->GetStringUTFChars(env, outputFile, (jboolean) 0);
80+
outfile = fopen(output_file, "wb");
81+
LOG("writing to %s", output_file);
82+
(*env)->ReleaseStringUTFChars(env, outputFile, output_file);
83+
84+
LOG("initialized handle: %x", handle);
85+
86+
}
87+
88+
void
89+
Java_com_todoroo_aacenc_AACEncoder_encode( JNIEnv* env,
90+
jobject thiz,
91+
jbyteArray inputArray)
92+
{
93+
94+
LOG("writing to handle: %x", handle);
95+
96+
jbyte* buffer = (*env)->GetByteArrayElements(env, inputArray, (jboolean) 0);
97+
int inputSize = (*env)->GetArrayLength(env, inputArray);
98+
6499
VO_CODECBUFFER input = { 0 }, output = { 0 };
65100
VO_AUDIO_OUTPUTINFO output_info = { 0 };
66-
int read, i;
67101

68-
unsigned char* outbuf = (unsigned char*) malloc(inputSize);
102+
unsigned char outbuf[20480];
69103

104+
LOG("input buffer: %d", inputSize);
105+
106+
/* SET INPUT DATA */
70107
input.Buffer = buffer;
71108
input.Length = inputSize;
72109
codec_api.SetInputData(handle, &input);
73110

74111
output.Buffer = outbuf;
75112
output.Length = sizeof(outbuf);
76113

77-
if (codec_api.GetOutputData(handle, &output, &output_info) != VO_ERR_NONE) {
78-
throwException(env, "java/lang/RuntimeException",
79-
"Unable to encode frame");
80-
return NULL;
114+
LOG("output data time");
115+
116+
/* GET OUTPUT DATA */
117+
int i;
118+
for (i = 0; i < 5; i++) {
119+
int status = codec_api.GetOutputData(handle, &output, &output_info);
120+
if (status == VO_ERR_INPUT_BUFFER_SMALL)
121+
break;
122+
123+
if (status != VO_ERR_NONE) {
124+
char message[100];
125+
sprintf(message, "Unable to encode frame: %x", status);
126+
throwException(env, "java/lang/RuntimeException", message);
127+
return;
128+
}
129+
130+
LOG("output length: %d (%d)", output.Length, i);
131+
132+
fwrite(outbuf, 1, output.Length, outfile);
133+
81134
}
82135

83-
jbyteArray result = (*env)->NewByteArray(env, output.Length);
84-
if (result == NULL)
85-
return NULL;
136+
LOG("finished output");
137+
(*env)->ReleaseByteArrayElements(env, inputArray, buffer, JNI_ABORT);
138+
}
86139

87-
(*env)->SetByteArrayRegion(env, result, 0, output.Length, outbuf);
140+
void
141+
Java_com_todoroo_aacenc_AACEncoder_uninit( JNIEnv* env,
142+
jobject thiz)
143+
{
88144

89-
free(outbuf);
145+
fclose(outfile);
90146
codec_api.Uninit(handle);
91147

92-
return result;
93148
}
94149

150+
JNIEXPORT jint JNICALL
151+
JNI_OnLoad (JavaVM * vm, void * reserved)
152+
{
153+
return JNI_VERSION_1_6;
154+
}

jni/utils/Log.h

Lines changed: 0 additions & 6 deletions
This file was deleted.

libs/armeabi/libaac-encoder.so

2.1 KB
Binary file not shown.

src/com/todoroo/aacenc/AACEncoder.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,23 @@
33
public class AACEncoder {
44

55
/**
6-
* Native JNI
6+
* Native JNI - initialize AAC encoder
77
*
88
*/
9-
public native byte[] encode(int bitrate, int channels,
10-
int sampleRate, int bitsPerSample, byte[] inputArray);
9+
public native void init(int bitrate, int channels,
10+
int sampleRate, int bitsPerSample, String outputFile);
11+
12+
/**
13+
* Native JNI - encode one or more frames
14+
*
15+
*/
16+
public native void encode(byte[] inputArray);
17+
18+
/**
19+
* Native JNI - uninitialize AAC encoder and flush file
20+
*
21+
*/
22+
public native void uninit();
1123

1224
static {
1325
System.loadLibrary("aac-encoder");

src/com/todoroo/aacenc/Main.java

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
package com.todoroo.aacenc;
22

3-
import java.io.FileOutputStream;
3+
import java.io.File;
44

55
import android.app.Activity;
66
import android.os.Bundle;
7-
import android.view.View;
8-
import android.view.View.OnClickListener;
9-
import android.widget.Button;
107
import android.widget.Toast;
118

129
public class Main extends Activity {
@@ -16,29 +13,34 @@ public void onCreate(Bundle savedInstanceState) {
1613
super.onCreate(savedInstanceState);
1714
setContentView(R.layout.main);
1815

19-
Button button = (Button) findViewById(R.id.button);
20-
button.setOnClickListener(new OnClickListener() {
21-
@Override
22-
public void onClick(View v) {
23-
AACEncoder encoder = new AACEncoder();
16+
try {
17+
File dir = getFilesDir();
18+
String output = dir.toString() + "/audio.aac";
2419

25-
byte[] input = new byte[1000];
26-
for(int i = 0; i < input.length; i++)
27-
input[i] = (byte) Math.round(255 * Math.sin(i * 1.0 / 100));
20+
AACEncoder encoder = new AACEncoder();
21+
encoder.init(64000, 1, 16000, 16, output);
2822

29-
byte[] output = encoder.encode(64000, 1, 16000, 16, input);
23+
byte[] input = new byte[16000];
24+
for(int i = 0; i < input.length; i++)
25+
input[i] = (byte) Math.round(255 * Math.sin(i * 1.0 / 10));
3026

31-
try {
32-
FileOutputStream fos = new FileOutputStream("/sdcard/output.aac");
33-
fos.write(output);
34-
fos.close();
27+
encoder.encode(input);
3528

36-
Toast.makeText(Main.this, "WE DID IT", Toast.LENGTH_LONG).show();
37-
} catch (Exception e) {
38-
throw new RuntimeException(e);
39-
}
40-
}
41-
});
29+
for(int i = 0; i < input.length; i++)
30+
input[i] = (byte) Math.round(255 * Math.sin(i * 1.0 / 100));
4231

32+
encoder.encode(input);
33+
34+
for(int i = 0; i < input.length; i++)
35+
input[i] = (byte) Math.round(255 * Math.sin(i * 1.0 / 200));
36+
37+
encoder.encode(input);
38+
39+
encoder.uninit();
40+
41+
Toast.makeText(Main.this, "WE DID IT", Toast.LENGTH_LONG).show();
42+
} catch (Exception e) {
43+
throw new RuntimeException(e);
44+
}
4345
}
4446
}

0 commit comments

Comments
 (0)