From 1fbe62c662ca271eb5715dd6049644adbe8ddd19 Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 30 Aug 2016 03:42:27 -0700 Subject: [PATCH] Update Opus decoder, move init ouput buffer to native code ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=131692317 --- .../exoplayer2/ext/opus/OpusDecoder.java | 16 +++----- extensions/opus/src/main/jni/opus_jni.cc | 40 ++++++++++++------- extensions/opus/src/main/proguard.cfg | 5 +++ 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java b/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java index e8f637a34f..c18bb3448a 100644 --- a/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java +++ b/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java @@ -156,16 +156,12 @@ import java.util.List; skipSamples = (inputBuffer.timeUs == 0) ? headerSkipSamples : headerSeekPreRollSamples; } ByteBuffer inputData = inputBuffer.data; - int inputSize = inputData.limit(); - int outputSize = opusGetRequiredOutputBufferSize(inputData, inputSize, SAMPLE_RATE); - if (outputSize < 0) { - return new OpusDecoderException("Error when computing required output buffer size."); - } - ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, outputSize); - int result = opusDecode(nativeDecoderContext, inputData, inputSize, outputData, outputSize); + int result = opusDecode(nativeDecoderContext, inputBuffer.timeUs, inputData, inputData.limit(), + outputBuffer, SAMPLE_RATE); if (result < 0) { return new OpusDecoderException("Decode error: " + opusGetErrorMessage(result)); } + ByteBuffer outputData = outputBuffer.data; outputData.position(0); outputData.limit(result); if (skipSamples > 0) { @@ -191,10 +187,8 @@ import java.util.List; private native long opusInit(int sampleRate, int channelCount, int numStreams, int numCoupled, int gain, byte[] streamMap); - private native int opusDecode(long decoder, ByteBuffer inputBuffer, int inputSize, - ByteBuffer outputBuffer, int outputSize); - private native int opusGetRequiredOutputBufferSize( - ByteBuffer inputBuffer, int inputSize, int sampleRate); + private native int opusDecode(long decoder, long timeUs, ByteBuffer inputBuffer, int inputSize, + SimpleOutputBuffer outputBuffer, int sampleRate); private native void opusClose(long decoder); private native void opusReset(long decoder); private native String opusGetErrorMessage(int errorCode); diff --git a/extensions/opus/src/main/jni/opus_jni.cc b/extensions/opus/src/main/jni/opus_jni.cc index 8214d0e140..79b9792cc6 100644 --- a/extensions/opus/src/main/jni/opus_jni.cc +++ b/extensions/opus/src/main/jni/opus_jni.cc @@ -37,6 +37,9 @@ Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_ ## NAME \ (JNIEnv* env, jobject thiz, ##__VA_ARGS__)\ +// JNI references for SimpleOutputBuffer class. +static jmethodID outputBufferInit; + jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env; if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { @@ -66,30 +69,37 @@ FUNC(jlong, opusInit, jint sampleRate, jint channelCount, jint numStreams, LOGE("Failed to set Opus header gain; status=%s", opus_strerror(status)); return 0; } + + // Populate JNI References. + const jclass outputBufferClass = env->FindClass( + "com/google/android/exoplayer2/decoder/SimpleOutputBuffer"); + outputBufferInit = env->GetMethodID(outputBufferClass, "init", + "(JI)Ljava/nio/ByteBuffer;"); + return reinterpret_cast(decoder); } -FUNC(jint, opusDecode, jlong jDecoder, jobject jInputBuffer, jint inputSize, - jobject jOutputBuffer, jint outputSize) { +FUNC(jint, opusDecode, jlong jDecoder, jlong jTimeUs, jobject jInputBuffer, + jint inputSize, jobject jOutputBuffer, jint sampleRate) { OpusMSDecoder* decoder = reinterpret_cast(jDecoder); const uint8_t* inputBuffer = reinterpret_cast( env->GetDirectBufferAddress(jInputBuffer)); - int16_t* outputBuffer = reinterpret_cast( - env->GetDirectBufferAddress(jOutputBuffer)); - int sampleCount = opus_multistream_decode(decoder, inputBuffer, inputSize, - outputBuffer, outputSize, 0); - return (sampleCount < 0) ? sampleCount - : sampleCount * kBytesPerSample * channelCount; -} -FUNC(jint, opusGetRequiredOutputBufferSize, jobject jInputBuffer, - jint inputSize, jint sampleRate) { - const uint8_t* inputBuffer = reinterpret_cast( - env->GetDirectBufferAddress(jInputBuffer)); - const int32_t sampleCount = + const int32_t inputSampleCount = opus_packet_get_nb_samples(inputBuffer, inputSize, sampleRate); - return sampleCount * kBytesPerSample * channelCount; + const jint outputSize = inputSampleCount * kBytesPerSample * channelCount; + + env->CallObjectMethod(jOutputBuffer, outputBufferInit, jTimeUs, outputSize); + const jobject jOutputBufferData = env->CallObjectMethod(jOutputBuffer, + outputBufferInit, jTimeUs, outputSize); + + int16_t* outputBufferData = reinterpret_cast( + env->GetDirectBufferAddress(jOutputBufferData)); + int sampleCount = opus_multistream_decode(decoder, inputBuffer, inputSize, + outputBufferData, outputSize, 0); + return (sampleCount < 0) ? sampleCount + : sampleCount * kBytesPerSample * channelCount; } FUNC(void, opusClose, jlong jDecoder) { diff --git a/extensions/opus/src/main/proguard.cfg b/extensions/opus/src/main/proguard.cfg index 15e910b1e9..2a380e23dd 100644 --- a/extensions/opus/src/main/proguard.cfg +++ b/extensions/opus/src/main/proguard.cfg @@ -4,3 +4,8 @@ -keepclasseswithmembernames class * { native ; } + +# Some members of this class are being accessed from native methods. Keep them unobfuscated. +-keep class com.google.android.exoplayer2.decoder.SimpleOutputBuffer { + *; +}