diff --git a/build_jni.sh b/build_jni.sh old mode 100644 new mode 100755 diff --git a/jni/libvorbis-jni/org_xiph_vorbis_decoder_VorbisDecoder.c b/jni/libvorbis-jni/org_xiph_vorbis_decoder_VorbisDecoder.c index c701f18..e98f918 100644 --- a/jni/libvorbis-jni/org_xiph_vorbis_decoder_VorbisDecoder.c +++ b/jni/libvorbis-jni/org_xiph_vorbis_decoder_VorbisDecoder.c @@ -13,6 +13,8 @@ to end. */ #define PREMATURE_END_OF_FILE -26 #define SUCCESS 0 +#define BUFFER_LENGTH 4096 + extern void _VDBG_dump(void); //Stops the vorbis data feed @@ -40,48 +42,39 @@ void throwDecodeException(JNIEnv *env, const int code, jobject* vorbisDataFeed, } //Reads raw vorbis data from the jni callback -int readVorbisDataFromVorbisDataFeed(JNIEnv *env, jobject* vorbisDataFeed, jmethodID* readVorbisDataMethodId, char* buffer, int length) { +int readVorbisDataFromVorbisDataFeed(JNIEnv *env, jobject* vorbisDataFeed, jmethodID* readVorbisDataMethodId, char* buffer, jbyteArray* jByteArrayReadBuffer) { + //Call the read method + int readByteCount = (*env)->CallIntMethod(env, (*vorbisDataFeed), (*readVorbisDataMethodId), (*jByteArrayReadBuffer), BUFFER_LENGTH); - //create a new java byte array to pass to the vorbis data feed method - jbyteArray jByteArray = (*env)->NewByteArray(env, length); - int readByteCount = (*env)->CallIntMethod(env, (*vorbisDataFeed), (*readVorbisDataMethodId), jByteArray, length); - - //Don't bother copying, just delete the reference and return 0 + //Don't bother copying, just return 0 if(readByteCount == 0) { - (*env)->DeleteLocalRef(env, jByteArray); return 0; } - - + //Gets the bytes from the java array and copies them to the vorbis buffer - jbyte* readBytes = (*env)->GetByteArrayElements(env, jByteArray, NULL); + jbyte* readBytes = (*env)->GetByteArrayElements(env, (*jByteArrayReadBuffer), NULL); memcpy(buffer, readBytes, readByteCount); //Clean up memory and return how much data was read - (*env)->ReleaseByteArrayElements(env, jByteArray, readBytes, JNI_ABORT); - (*env)->DeleteLocalRef(env, jByteArray); + (*env)->ReleaseByteArrayElements(env, (*jByteArrayReadBuffer), readBytes, JNI_ABORT); + + //Return the amount actually read return readByteCount; - } //Writes the pcm data to the Java layer -void writePCMDataFromVorbisDataFeed(JNIEnv *env, jobject* vorbisDataFeed, jmethodID* writePCMDataMethodId, ogg_int16_t* buffer, int bytes) { +void writePCMDataFromVorbisDataFeed(JNIEnv *env, jobject* vorbisDataFeed, jmethodID* writePCMDataMethodId, ogg_int16_t* buffer, int bytes, jshortArray* jShortArrayWriteBuffer) { //No data to read, just exit if(bytes == 0) { return; } - //Create and copy the contents of what we're writing to the java short array - jshortArray jShortArray = (*env)->NewShortArray(env, bytes); - (*env)->SetShortArrayRegion(env, jShortArray, 0, bytes, (jshort *)buffer); + //Copy the contents of what we're writing to the java short array + (*env)->SetShortArrayRegion(env, (*jShortArrayWriteBuffer), 0, bytes, (jshort *)buffer); //Call the write pcm data method - (*env)->CallVoidMethod(env, (*vorbisDataFeed), (*writePCMDataMethodId), jShortArray, bytes); - - //cleanup - (*env)->DeleteLocalRef(env, jShortArray); - + (*env)->CallVoidMethod(env, (*vorbisDataFeed), (*writePCMDataMethodId), (*jShortArrayWriteBuffer), bytes); } //Starts the decode feed with the necessary information about sample rates, channels, etc about the stream @@ -119,6 +112,12 @@ void startReadingHeader(JNIEnv *env, jobject *vorbisDataFeed, jmethodID* startRe JNIEXPORT int JNICALL Java_org_xiph_vorbis_decoder_VorbisDecoder_startDecoding (JNIEnv *env, jclass cls, jobject vorbisDataFeed) { + //Create a new java byte array to pass to the vorbis data feed method + jbyteArray jByteArrayReadBuffer = (*env)->NewByteArray(env, BUFFER_LENGTH); + + //Create our write buffer + jshortArray jShortArrayWriteBuffer = (*env)->NewShortArray(env, BUFFER_LENGTH*2); + //Find our java classes we'll be calling jclass vorbisDataFeedClass = (*env)->FindClass(env, "org/xiph/vorbis/decoder/DecodeFeed"); @@ -129,8 +128,8 @@ JNIEXPORT int JNICALL Java_org_xiph_vorbis_decoder_VorbisDecoder_startDecoding jmethodID startReadingHeaderMethodId = (*env)->GetMethodID(env, vorbisDataFeedClass, "startReadingHeader", "()V"); jmethodID stopMethodId = (*env)->GetMethodID(env, vorbisDataFeedClass, "stop", "()V"); - ogg_int16_t convbuffer[4096]; /* take 8k out of the data segment, not the stack */ - int convsize=4096; + ogg_int16_t convbuffer[BUFFER_LENGTH]; /* take 8k out of the data segment, not the stack */ + int convsize=BUFFER_LENGTH; ogg_sync_state oy; /* sync and verify incoming physical bitstream */ ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ @@ -164,15 +163,15 @@ JNIEXPORT int JNICALL Java_org_xiph_vorbis_decoder_VorbisDecoder_startDecoding /* submit a 4k block to libvorbis' Ogg layer */ __android_log_print(ANDROID_LOG_INFO, "VorbisDecoder", "Submitting 4k block to libvorbis' Ogg layer"); - buffer=ogg_sync_buffer(&oy,4096); - bytes=readVorbisDataFromVorbisDataFeed(env, &vorbisDataFeed, &readVorbisDataMethodId, buffer, 4096); + buffer=ogg_sync_buffer(&oy,BUFFER_LENGTH); + bytes=readVorbisDataFromVorbisDataFeed(env, &vorbisDataFeed, &readVorbisDataMethodId, buffer, &jByteArrayReadBuffer); ogg_sync_wrote(&oy,bytes); /* Get the first page. */ __android_log_print(ANDROID_LOG_DEBUG, "VorbisDecoder", "Getting the first page, read (%d) bytes", bytes); if(ogg_sync_pageout(&oy,&og)!=1){ /* have we simply run out of data? If so, we're done. */ - if(bytes<4096)break; + if(bytesPCM decoder. */ @@ -365,7 +364,7 @@ JNIEXPORT int JNICALL Java_org_xiph_vorbis_decoder_VorbisDecoder_startDecoding __android_log_print(ANDROID_LOG_INFO, "VorbisDecoder", "Clipping in frame %ld\n",(long)(vd.sequence)); } - writePCMDataFromVorbisDataFeed(env, &vorbisDataFeed, &writePCMDataMethodId, &convbuffer[0], bout*vi.channels); + writePCMDataFromVorbisDataFeed(env, &vorbisDataFeed, &writePCMDataMethodId, &convbuffer[0], bout*vi.channels, &jShortArrayWriteBuffer); vorbis_synthesis_read(&vd,bout); /* tell libvorbis how many samples we actually consumed */ } @@ -376,8 +375,8 @@ JNIEXPORT int JNICALL Java_org_xiph_vorbis_decoder_VorbisDecoder_startDecoding } if(!eos){ - buffer=ogg_sync_buffer(&oy,4096); - bytes=readVorbisDataFromVorbisDataFeed(env, &vorbisDataFeed, &readVorbisDataMethodId, buffer, 4096); + buffer=ogg_sync_buffer(&oy,BUFFER_LENGTH); + bytes=readVorbisDataFromVorbisDataFeed(env, &vorbisDataFeed, &readVorbisDataMethodId, buffer, &jByteArrayReadBuffer); ogg_sync_wrote(&oy,bytes); if(bytes==0) { eos=1; @@ -406,6 +405,13 @@ JNIEXPORT int JNICALL Java_org_xiph_vorbis_decoder_VorbisDecoder_startDecoding /* OK, clean up the framer */ ogg_sync_clear(&oy); + + stopDecodeFeed(env, &vorbisDataFeed, &stopMethodId); + + //Clean up our buffers + (*env)->DeleteLocalRef(env, jByteArrayReadBuffer); + (*env)->DeleteLocalRef(env, jShortArrayWriteBuffer); + return SUCCESS; } \ No newline at end of file diff --git a/jni/libvorbis-jni/org_xiph_vorbis_decoder_VorbisDecoder.h b/jni/libvorbis-jni/org_xiph_vorbis_decoder_VorbisDecoder.h index cb24d86..ca07f1c 100644 --- a/jni/libvorbis-jni/org_xiph_vorbis_decoder_VorbisDecoder.h +++ b/jni/libvorbis-jni/org_xiph_vorbis_decoder_VorbisDecoder.h @@ -23,10 +23,10 @@ void stopDecodeFeed(JNIEnv *env, jobject* vorbisDataFeed, jmethodID* stopMethodI void throwDecodeException(JNIEnv *env, const int code, jobject* vorbisDataFeed, jmethodID* stopMethodId); //Reads raw vorbis data from the jni callback -int readVorbisDataFromVorbisDataFeed(JNIEnv *env, jobject* vorbisDataFeed, jmethodID* readVorbisDataMethodId, char* buffer, int length); +int readVorbisDataFromVorbisDataFeed(JNIEnv *env, jobject* vorbisDataFeed, jmethodID* readVorbisDataMethodId, char* buffer, jbyteArray* jByteArrayReadBuffer); //Writes the pcm data to the Java layer -void writePCMDataFromVorbisDataFeed(JNIEnv *env, jobject* vorbisDataFeed, jmethodID* writePCMDataMethodId, ogg_int16_t* buffer, int bytes); +void writePCMDataFromVorbisDataFeed(JNIEnv *env, jobject* vorbisDataFeed, jmethodID* writePCMDataMethodId, ogg_int16_t* buffer, int bytes, jshortArray* jShortArrayWriteBuffer); //Starts the decode feed with the necessary information about sample rates, channels, etc about the stream void start(JNIEnv *env, jobject *vorbisDataFeed, jmethodID* startMethodId, long sampleRate, long channels, char* vendor); diff --git a/jni/libvorbis-jni/org_xiph_vorbis_encoder_VorbisEncoder.c b/jni/libvorbis-jni/org_xiph_vorbis_encoder_VorbisEncoder.c index 4012eac..ab0cc42 100644 --- a/jni/libvorbis-jni/org_xiph_vorbis_encoder_VorbisEncoder.c +++ b/jni/libvorbis-jni/org_xiph_vorbis_encoder_VorbisEncoder.c @@ -40,31 +40,27 @@ void stopEncodeFeed(JNIEnv *env, jobject* vorbisDataFeed, jmethodID* stopMethodI } //Reads pcm data from the jni callback -long readPCMDataFromEncoderDataFeed(JNIEnv *env, jobject* encoderDataFeed, jmethodID* readPCMDataMethodId, char* buffer, int length) { - - //create a new java byte array to pass to the data feed method - jbyteArray jByteArray = (*env)->NewByteArray(env, length); - long readByteCount = (*env)->CallLongMethod(env, (*encoderDataFeed), (*readPCMDataMethodId), jByteArray, length); +long readPCMDataFromEncoderDataFeed(JNIEnv *env, jobject* encoderDataFeed, jmethodID* readPCMDataMethodId, char* buffer, int length, jbyteArray* jByteArrayBuffer) { + long readByteCount = (*env)->CallLongMethod(env, (*encoderDataFeed), (*readPCMDataMethodId), (*jByteArrayBuffer), length); //Don't bother copying, just delete the reference and return 0 if(readByteCount == 0) { - (*env)->DeleteLocalRef(env, jByteArray); + (*env)->DeleteLocalRef(env, (*jByteArrayBuffer)); return 0; } //Gets the bytes from the java array and copies them to the pcm buffer - jbyte* readBytes = (*env)->GetByteArrayElements(env, jByteArray, NULL); + jbyte* readBytes = (*env)->GetByteArrayElements(env, (*jByteArrayBuffer), NULL); memcpy(buffer, readBytes, readByteCount); //Clean up memory and return how much data was read - (*env)->ReleaseByteArrayElements(env, jByteArray, readBytes, JNI_ABORT); - (*env)->DeleteLocalRef(env, jByteArray); + (*env)->ReleaseByteArrayElements(env, (*jByteArrayBuffer), readBytes, JNI_ABORT); return readByteCount; } //Writes the vorbis data to the Java layer -int writeVorbisDataToEncoderDataFeed(JNIEnv *env, jobject* encoderDataFeed, jmethodID* writeVorbisDataMethodId, char* buffer, int bytes) { +int writeVorbisDataToEncoderDataFeed(JNIEnv *env, jobject* encoderDataFeed, jmethodID* writeVorbisDataMethodId, char* buffer, int bytes, jbyteArray* jByteArrayWriteBuffer) { //No data to write, just exit if(bytes == 0) { @@ -73,14 +69,12 @@ int writeVorbisDataToEncoderDataFeed(JNIEnv *env, jobject* encoderDataFeed, jmet //Create and copy the contents of what we're writing to the java byte array jbyteArray jByteArray = (*env)->NewByteArray(env, bytes); - (*env)->SetByteArrayRegion(env, jByteArray, 0, bytes, (jbyte *)buffer); + (*env)->SetByteArrayRegion(env, (*jByteArrayWriteBuffer), 0, bytes, (jbyte *)buffer); //Call the write vorbis data method - int amountWritten = (*env)->CallIntMethod(env, (*encoderDataFeed), (*writeVorbisDataMethodId), jByteArray, bytes); - - //cleanup - (*env)->DeleteLocalRef(env, jByteArray); + int amountWritten = (*env)->CallIntMethod(env, (*encoderDataFeed), (*writeVorbisDataMethodId), (*jByteArrayWriteBuffer), bytes); + //Return the amount that was actually written return amountWritten; } @@ -90,6 +84,12 @@ JNIEXPORT int JNICALL Java_org_xiph_vorbis_encoder_VorbisEncoder_startEncoding //Create our PCM data buffer signed char readbuffer[READ*4+44]; + //Create a new java byte array to pass to the data feed method + jbyteArray jByteArrayBuffer = (*env)->NewByteArray(env, READ*4); + + //Create a new java byte buffer to write to + jbyteArray jByteArrayWriteBuffer = (*env)->NewByteArray(env, READ*8); + //Find our java classes we'll be calling jclass encoderDataFeedClass = (*env)->FindClass(env, "org/xiph/vorbis/encoder/EncodeFeed"); @@ -201,8 +201,8 @@ JNIEXPORT int JNICALL Java_org_xiph_vorbis_encoder_VorbisEncoder_startEncoding while(!eos){ int result=ogg_stream_flush(&os,&og); if(result==0)break; - writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.header, og.header_len); - writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.body, og.body_len); + writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.header, og.header_len, &jByteArrayWriteBuffer); + writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.body, og.body_len, &jByteArrayWriteBuffer); } } @@ -210,7 +210,7 @@ JNIEXPORT int JNICALL Java_org_xiph_vorbis_encoder_VorbisEncoder_startEncoding __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Starting to read from pcm callback"); while(!eos){ long i; - long bytes = readPCMDataFromEncoderDataFeed(env, &encoderDataFeed, &readPCMDataMethodId, readbuffer, READ*4); + long bytes = readPCMDataFromEncoderDataFeed(env, &encoderDataFeed, &readPCMDataMethodId, readbuffer, READ*4, &jByteArrayBuffer); if(bytes==0){ /* end of file. this can be done implicitly in the mainline, @@ -257,8 +257,8 @@ JNIEXPORT int JNICALL Java_org_xiph_vorbis_encoder_VorbisEncoder_startEncoding while(!eos){ int result=ogg_stream_pageout(&os,&og); if(result==0)break; - writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.header, og.header_len); - writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.body, og.body_len); + writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.header, og.header_len, &jByteArrayWriteBuffer); + writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.body, og.body_len, &jByteArrayWriteBuffer); /* this could be set above, but for illustrative purposes, I do it here (to show that vorbis does know where the stream ends) */ @@ -281,5 +281,10 @@ JNIEXPORT int JNICALL Java_org_xiph_vorbis_encoder_VorbisEncoder_startEncoding libvorbis. They're never freed or manipulated directly */ __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Completed encoding."); stopEncodeFeed(env, &encoderDataFeed, &stopMethodId); + + //Clean up encode buffers + (*env)->DeleteLocalRef(env, jByteArrayBuffer); + (*env)->DeleteLocalRef(env, jByteArrayWriteBuffer); + return SUCCESS; } diff --git a/jni/libvorbis-jni/org_xiph_vorbis_encoder_VorbisEncoder.h b/jni/libvorbis-jni/org_xiph_vorbis_encoder_VorbisEncoder.h index c423933..ecd927c 100644 --- a/jni/libvorbis-jni/org_xiph_vorbis_encoder_VorbisEncoder.h +++ b/jni/libvorbis-jni/org_xiph_vorbis_encoder_VorbisEncoder.h @@ -23,10 +23,10 @@ void startEncodeFeed(JNIEnv *env, jobject *vorbisDataFeed, jmethodID* startMetho void stopEncodeFeed(JNIEnv *env, jobject* vorbisDataFeed, jmethodID* stopMethodId); //Reads pcm data from the jni callback -long readPCMDataFromEncoderDataFeed(JNIEnv *env, jobject* encoderDataFeed, jmethodID* readPCMDataMethodId, char* buffer, int length); +long readPCMDataFromEncoderDataFeed(JNIEnv *env, jobject* encoderDataFeed, jmethodID* readPCMDataMethodId, char* buffer, int length, jbyteArray* jByteArrayBuffer); //Writes the vorbis data to the Java layer -int writeVorbisDataToEncoderDataFeed(JNIEnv *env, jobject* encoderDataFeed, jmethodID* writeVorbisDataMethodId, char* buffer, int bytes); +int writeVorbisDataToEncoderDataFeed(JNIEnv *env, jobject* encoderDataFeed, jmethodID* writeVorbisDataMethodId, char* buffer, int bytes, jbyteArray* jByteArrayWriteBuffer); JNIEXPORT int JNICALL Java_org_xiph_vorbis_encoder_VorbisEncoder_startEncoding (JNIEnv *env, jclass cls, jlong sampleRate, jlong channels, jfloat quality, jobject encoderDataFeed); diff --git a/libs/armeabi/libvorbis-jni.so b/libs/armeabi/libvorbis-jni.so index 135cff9..12df41d 100755 Binary files a/libs/armeabi/libvorbis-jni.so and b/libs/armeabi/libvorbis-jni.so differ