Move FlacJni to FlacDecoderJni

If/when we add the ability to query version information,
such methods will go into FlacLibrary for consistency with
the other extensions. The difference for Flac is that
since the decoder JNI is used by the extractor too, it
needs splitting into a separate from from FlacDecoder.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=132904665
This commit is contained in:
olly 2016-09-12 12:31:21 -07:00 committed by Oliver Woodman
parent de67fa5017
commit f2229d920b
5 changed files with 49 additions and 53 deletions

View file

@ -30,7 +30,7 @@ import java.util.List;
SimpleDecoder<DecoderInputBuffer, SimpleOutputBuffer, FlacDecoderException> {
private final int maxOutputBufferSize;
private final FlacJni decoder;
private final FlacDecoderJni decoderJni;
/**
* Creates a Flac decoder.
@ -47,11 +47,11 @@ import java.util.List;
if (initializationData.size() != 1) {
throw new FlacDecoderException("Initialization data must be of length 1");
}
decoder = new FlacJni();
decoder.setData(ByteBuffer.wrap(initializationData.get(0)));
decoderJni = new FlacDecoderJni();
decoderJni.setData(ByteBuffer.wrap(initializationData.get(0)));
FlacStreamInfo streamInfo;
try {
streamInfo = decoder.decodeMetadata();
streamInfo = decoderJni.decodeMetadata();
} catch (IOException | InterruptedException e) {
// Never happens.
throw new IllegalStateException(e);
@ -83,13 +83,13 @@ import java.util.List;
public FlacDecoderException decode(DecoderInputBuffer inputBuffer,
SimpleOutputBuffer outputBuffer, boolean reset) {
if (reset) {
decoder.flush();
decoderJni.flush();
}
decoder.setData(inputBuffer.data);
decoderJni.setData(inputBuffer.data);
ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, maxOutputBufferSize);
int result;
try {
result = decoder.decodeSample(outputData);
result = decoderJni.decodeSample(outputData);
} catch (IOException | InterruptedException e) {
// Never happens.
throw new IllegalStateException(e);
@ -105,7 +105,7 @@ import java.util.List;
@Override
public void release() {
super.release();
decoder.release();
decoderJni.release();
}
}

View file

@ -24,7 +24,7 @@ import java.nio.ByteBuffer;
/**
* JNI wrapper for the libflac Flac decoder.
*/
/* package */ final class FlacJni {
/* package */ final class FlacDecoderJni {
private static final int TEMP_BUFFER_SIZE = 8192; // The same buffer size which libflac has
@ -35,7 +35,7 @@ import java.nio.ByteBuffer;
private boolean endOfExtractorInput;
private byte[] tempBuffer;
public FlacJni() throws FlacDecoderException {
public FlacDecoderJni() throws FlacDecoderException {
if (!FlacLibrary.isAvailable()) {
throw new FlacDecoderException("Failed to load decoder native libraries.");
}

View file

@ -57,7 +57,7 @@ public final class FlacExtractor implements Extractor {
private ExtractorOutput extractorOutput;
private TrackOutput trackOutput;
private FlacJni decoder;
private FlacDecoderJni decoderJni;
private boolean metadataParsed;
@ -70,7 +70,7 @@ public final class FlacExtractor implements Extractor {
trackOutput = extractorOutput.track(0);
extractorOutput.endTracks();
try {
decoder = new FlacJni();
decoderJni = new FlacDecoderJni();
} catch (FlacDecoderException e) {
throw new RuntimeException(e);
}
@ -86,24 +86,24 @@ public final class FlacExtractor implements Extractor {
@Override
public int read(final ExtractorInput input, PositionHolder seekPosition)
throws IOException, InterruptedException {
decoder.setData(input);
decoderJni.setData(input);
if (!metadataParsed) {
final FlacStreamInfo streamInfo;
try {
streamInfo = decoder.decodeMetadata();
streamInfo = decoderJni.decodeMetadata();
if (streamInfo == null) {
throw new IOException("Metadata decoding failed");
}
} catch (IOException e){
decoder.reset(0);
decoderJni.reset(0);
input.setRetryPosition(0, e);
throw e; // never executes
}
metadataParsed = true;
extractorOutput.seekMap(new SeekMap() {
final boolean isSeekable = decoder.getSeekPosition(0) != -1;
final boolean isSeekable = decoderJni.getSeekPosition(0) != -1;
final long durationUs = streamInfo.durationUs();
@Override
@ -113,7 +113,7 @@ public final class FlacExtractor implements Extractor {
@Override
public long getPosition(long timeUs) {
return isSeekable ? decoder.getSeekPosition(timeUs) : 0;
return isSeekable ? decoderJni.getSeekPosition(timeUs) : 0;
}
@Override
@ -133,13 +133,13 @@ public final class FlacExtractor implements Extractor {
}
outputBuffer.reset();
long lastDecodePosition = decoder.getDecodePosition();
long lastDecodePosition = decoderJni.getDecodePosition();
int size;
try {
size = decoder.decodeSample(outputByteBuffer);
size = decoderJni.decodeSample(outputByteBuffer);
} catch (IOException e){
if (lastDecodePosition >= 0) {
decoder.reset(lastDecodePosition);
decoderJni.reset(lastDecodePosition);
input.setRetryPosition(lastDecodePosition, e);
}
throw e;
@ -148,11 +148,10 @@ public final class FlacExtractor implements Extractor {
return RESULT_END_OF_INPUT;
}
trackOutput.sampleData(outputBuffer, size);
trackOutput.sampleMetadata(decoderJni.getLastSampleTimestamp(), C.BUFFER_FLAG_KEY_FRAME, size,
0, null);
trackOutput.sampleMetadata(decoder.getLastSampleTimestamp(), C.BUFFER_FLAG_KEY_FRAME, size, 0,
null);
return decoder.isEndOfData() ? RESULT_END_OF_INPUT : RESULT_CONTINUE;
return decoderJni.isEndOfData() ? RESULT_END_OF_INPUT : RESULT_CONTINUE;
}
@Override
@ -160,13 +159,13 @@ public final class FlacExtractor implements Extractor {
if (position == 0) {
metadataParsed = false;
}
decoder.reset(position);
decoderJni.reset(position);
}
@Override
public void release() {
decoder.release();
decoder = null;
decoderJni.release();
decoderJni = null;
}
}

View file

@ -15,11 +15,8 @@
*/
#include <jni.h>
#include <android/log.h>
#include <cstdlib>
#include "include/flac_parser.h"
#define LOG_TAG "flac_jni"
@ -28,23 +25,23 @@
#define ALOGV(...) \
((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
#define FUNC(RETURN_TYPE, NAME, ...) \
#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_flac_FlacJni_##NAME( \
Java_com_google_android_exoplayer2_ext_flac_FlacDecoderJni_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__); \
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_flac_FlacJni_##NAME( \
Java_com_google_android_exoplayer2_ext_flac_FlacDecoderJni_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__)
class JavaDataSource : public DataSource {
public:
void setFlacJni(JNIEnv *env, jobject flacJni) {
void setFlacDecoderJni(JNIEnv *env, jobject flacDecoderJni) {
this->env = env;
this->flacJni = flacJni;
this->flacDecoderJni = flacDecoderJni;
if (mid == NULL) {
jclass cls = env->GetObjectClass(flacJni);
jclass cls = env->GetObjectClass(flacDecoderJni);
mid = env->GetMethodID(cls, "read", "(Ljava/nio/ByteBuffer;)I");
env->DeleteLocalRef(cls);
}
@ -52,7 +49,7 @@ class JavaDataSource : public DataSource {
ssize_t readAt(off64_t offset, void *const data, size_t size) {
jobject byteBuffer = env->NewDirectByteBuffer(data, size);
int result = env->CallIntMethod(flacJni, mid, byteBuffer);
int result = env->CallIntMethod(flacDecoderJni, mid, byteBuffer);
if (env->ExceptionOccurred()) {
result = -1;
}
@ -62,7 +59,7 @@ class JavaDataSource : public DataSource {
private:
JNIEnv *env;
jobject flacJni;
jobject flacDecoderJni;
jmethodID mid;
};
@ -81,7 +78,7 @@ struct Context {
}
};
FUNC(jlong, flacInit) {
DECODER_FUNC(jlong, flacInit) {
Context *context = new Context;
if (!context->parser->init()) {
delete context;
@ -90,9 +87,9 @@ FUNC(jlong, flacInit) {
return reinterpret_cast<intptr_t>(context);
}
FUNC(jobject, flacDecodeMetadata, jlong jContext) {
DECODER_FUNC(jobject, flacDecodeMetadata, jlong jContext) {
Context *context = reinterpret_cast<Context *>(jContext);
context->source->setFlacJni(env, thiz);
context->source->setFlacDecoderJni(env, thiz);
if (!context->parser->decodeMetadata()) {
return NULL;
}
@ -112,17 +109,17 @@ FUNC(jobject, flacDecodeMetadata, jlong jContext) {
streamInfo.total_samples);
}
FUNC(jint, flacDecodeToBuffer, jlong jContext, jobject jOutputBuffer) {
DECODER_FUNC(jint, flacDecodeToBuffer, jlong jContext, jobject jOutputBuffer) {
Context *context = reinterpret_cast<Context *>(jContext);
context->source->setFlacJni(env, thiz);
context->source->setFlacDecoderJni(env, thiz);
void *outputBuffer = env->GetDirectBufferAddress(jOutputBuffer);
jint outputSize = env->GetDirectBufferCapacity(jOutputBuffer);
return context->parser->readBuffer(outputBuffer, outputSize);
}
FUNC(jint, flacDecodeToArray, jlong jContext, jbyteArray jOutputArray) {
DECODER_FUNC(jint, flacDecodeToArray, jlong jContext, jbyteArray jOutputArray) {
Context *context = reinterpret_cast<Context *>(jContext);
context->source->setFlacJni(env, thiz);
context->source->setFlacDecoderJni(env, thiz);
jbyte *outputBuffer = env->GetByteArrayElements(jOutputArray, NULL);
jint outputSize = env->GetArrayLength(jOutputArray);
int count = context->parser->readBuffer(outputBuffer, outputSize);
@ -130,38 +127,38 @@ FUNC(jint, flacDecodeToArray, jlong jContext, jbyteArray jOutputArray) {
return count;
}
FUNC(jlong, flacGetDecodePosition, jlong jContext) {
DECODER_FUNC(jlong, flacGetDecodePosition, jlong jContext) {
Context *context = reinterpret_cast<Context *>(jContext);
return context->parser->getDecodePosition();
}
FUNC(jlong, flacGetLastTimestamp, jlong jContext) {
DECODER_FUNC(jlong, flacGetLastTimestamp, jlong jContext) {
Context *context = reinterpret_cast<Context *>(jContext);
return context->parser->getLastTimestamp();
}
FUNC(jlong, flacGetSeekPosition, jlong jContext, jlong timeUs) {
DECODER_FUNC(jlong, flacGetSeekPosition, jlong jContext, jlong timeUs) {
Context *context = reinterpret_cast<Context *>(jContext);
return context->parser->getSeekPosition(timeUs);
}
FUNC(jstring, flacGetStateString, jlong jContext) {
DECODER_FUNC(jstring, flacGetStateString, jlong jContext) {
Context *context = reinterpret_cast<Context *>(jContext);
const char *str = context->parser->getDecoderStateString();
return env->NewStringUTF(str);
}
FUNC(void, flacFlush, jlong jContext) {
DECODER_FUNC(void, flacFlush, jlong jContext) {
Context *context = reinterpret_cast<Context *>(jContext);
context->parser->flush();
}
FUNC(void, flacReset, jlong jContext, jlong newPosition) {
DECODER_FUNC(void, flacReset, jlong jContext, jlong newPosition) {
Context *context = reinterpret_cast<Context *>(jContext);
context->parser->reset(newPosition);
}
FUNC(void, flacRelease, jlong jContext) {
DECODER_FUNC(void, flacRelease, jlong jContext) {
Context *context = reinterpret_cast<Context *>(jContext);
delete context;
}

View file

@ -6,6 +6,6 @@
}
# Some members of this class are being accessed from native methods. Keep them unobfuscated.
-keep class com.google.android.exoplayer2.ext.flac.FlacJni {
-keep class com.google.android.exoplayer2.ext.flac.FlacDecoderJni {
*;
}