summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Craik <ccraik@android.com>2015-04-02 22:25:47 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-04-02 22:25:48 +0000
commitd90222baefb107ddc08d024b02d664d18f50f44f (patch)
tree83290b350f7b0e75a256d64d50a331b36b42f991
parent46ca918db82c1fca3f370ec6a9b936bf7268aa85 (diff)
parent6a61141137c7a46d747aa611c9caf62436bc119f (diff)
downloadandroid_frameworks_ex-d90222baefb107ddc08d024b02d664d18f50f44f.tar.gz
android_frameworks_ex-d90222baefb107ddc08d024b02d664d18f50f44f.tar.bz2
android_frameworks_ex-d90222baefb107ddc08d024b02d664d18f50f44f.zip
Merge "Adding Bytebuffer support to rastermill library"
-rw-r--r--framesequence/Android.mk2
-rw-r--r--framesequence/jni/FrameSequence.h1
-rw-r--r--framesequence/jni/FrameSequenceJNI.cpp25
-rw-r--r--framesequence/jni/FrameSequence_gif.cpp5
-rw-r--r--framesequence/jni/FrameSequence_gif.h4
-rw-r--r--framesequence/jni/FrameSequence_webp.cpp47
-rw-r--r--framesequence/jni/FrameSequence_webp.h5
-rw-r--r--framesequence/jni/Registry.cpp27
-rw-r--r--framesequence/jni/Registry.h4
-rw-r--r--framesequence/jni/Stream.cpp28
-rw-r--r--framesequence/jni/Stream.h16
-rw-r--r--framesequence/src/android/support/rastermill/FrameSequence.java15
12 files changed, 149 insertions, 30 deletions
diff --git a/framesequence/Android.mk b/framesequence/Android.mk
index cc2c16c..1b3cf2d 100644
--- a/framesequence/Android.mk
+++ b/framesequence/Android.mk
@@ -21,6 +21,8 @@ LOCAL_MODULE := android-common-framesequence
LOCAL_SDK_VERSION := 8
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
include $(BUILD_STATIC_JAVA_LIBRARY)
include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/framesequence/jni/FrameSequence.h b/framesequence/jni/FrameSequence.h
index 6667cdd..134c81a 100644
--- a/framesequence/jni/FrameSequence.h
+++ b/framesequence/jni/FrameSequence.h
@@ -49,6 +49,7 @@ public:
virtual bool isOpaque() const = 0;
virtual int getFrameCount() const = 0;
virtual int getDefaultLoopCount() const = 0;
+ virtual jobject getRawByteBuffer() const = 0;
virtual FrameSequenceState* createState() const = 0;
};
diff --git a/framesequence/jni/FrameSequenceJNI.cpp b/framesequence/jni/FrameSequenceJNI.cpp
index 08a73bc..dfc51ec 100644
--- a/framesequence/jni/FrameSequenceJNI.cpp
+++ b/framesequence/jni/FrameSequenceJNI.cpp
@@ -53,12 +53,27 @@ static jobject nativeDecodeByteArray(JNIEnv* env, jobject clazz,
"couldn't read array bytes");
return NULL;
}
- MemoryStream stream(bytes + offset, length);
+ MemoryStream stream(bytes + offset, length, NULL);
FrameSequence* frameSequence = FrameSequence::create(&stream);
env->ReleasePrimitiveArrayCritical(byteArray, bytes, 0);
return createJavaFrameSequence(env, frameSequence);
}
+static jobject nativeDecodeByteBuffer(JNIEnv* env, jobject clazz,
+ jobject buf, jint offset, jint limit) {
+ jobject globalBuf = env->NewGlobalRef(buf);
+ JavaVM* vm;
+ env->GetJavaVM(&vm);
+ MemoryStream stream(
+ (reinterpret_cast<uint8_t*>(
+ env->GetDirectBufferAddress(globalBuf))) + offset,
+ limit,
+ globalBuf);
+ FrameSequence* frameSequence = FrameSequence::create(&stream);
+ jobject finalSequence = createJavaFrameSequence(env, frameSequence);
+ return finalSequence;
+}
+
static jobject nativeDecodeStream(JNIEnv* env, jobject clazz,
jobject istream, jbyteArray byteArray) {
JavaInputStream stream(env, istream, byteArray);
@@ -69,6 +84,10 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz,
static void nativeDestroyFrameSequence(JNIEnv* env, jobject clazz,
jlong frameSequenceLong) {
FrameSequence* frameSequence = reinterpret_cast<FrameSequence*>(frameSequenceLong);
+ jobject buf = frameSequence->getRawByteBuffer();
+ if (buf != NULL) {
+ env->DeleteGlobalRef(buf);
+ }
delete frameSequence;
}
@@ -123,6 +142,10 @@ static JNINativeMethod gMethods[] = {
"([BII)L" JNI_PACKAGE "/FrameSequence;",
(void*) nativeDecodeByteArray
},
+ { "nativeDecodeByteBuffer",
+ "(Ljava/nio/ByteBuffer;II)L" JNI_PACKAGE "/FrameSequence;",
+ (void*) nativeDecodeByteBuffer
+ },
{ "nativeDecodeStream",
"(Ljava/io/InputStream;[B)L" JNI_PACKAGE "/FrameSequence;",
(void*) nativeDecodeStream
diff --git a/framesequence/jni/FrameSequence_gif.cpp b/framesequence/jni/FrameSequence_gif.cpp
index f3e94df..2188c53 100644
--- a/framesequence/jni/FrameSequence_gif.cpp
+++ b/framesequence/jni/FrameSequence_gif.cpp
@@ -352,6 +352,10 @@ static bool isGif(void* header, int header_size) {
|| !memcmp(GIF89_STAMP, header, GIF_STAMP_LEN);
}
+static bool acceptsBuffers() {
+ return false;
+}
+
static FrameSequence* createFramesequence(Stream* stream) {
return new FrameSequence_gif(stream);
}
@@ -361,6 +365,7 @@ static RegistryEntry gEntry = {
isGif,
createFramesequence,
NULL,
+ acceptsBuffers,
};
static Registry gRegister(gEntry);
diff --git a/framesequence/jni/FrameSequence_gif.h b/framesequence/jni/FrameSequence_gif.h
index 8bf57b6..563f5b8 100644
--- a/framesequence/jni/FrameSequence_gif.h
+++ b/framesequence/jni/FrameSequence_gif.h
@@ -49,6 +49,10 @@ public:
return mLoopCount;
}
+ virtual jobject getRawByteBuffer() const {
+ return NULL;
+ }
+
virtual FrameSequenceState* createState() const;
GifFileType* getGif() const { return mGif; }
diff --git a/framesequence/jni/FrameSequence_webp.cpp b/framesequence/jni/FrameSequence_webp.cpp
index 602feb7..c33a7e2 100644
--- a/framesequence/jni/FrameSequence_webp.cpp
+++ b/framesequence/jni/FrameSequence_webp.cpp
@@ -85,22 +85,28 @@ void FrameSequence_webp::constructDependencyChain() {
}
FrameSequence_webp::FrameSequence_webp(Stream* stream) {
- // Read RIFF header to get file size.
- uint8_t riff_header[RIFF_HEADER_SIZE];
- if (stream->read(riff_header, RIFF_HEADER_SIZE) != RIFF_HEADER_SIZE) {
- ALOGE("WebP header load failed");
- return;
- }
- mData.size = CHUNK_HEADER_SIZE + GetLE32(riff_header + TAG_SIZE);
- mData.bytes = new uint8_t[mData.size];
- memcpy((void*)mData.bytes, riff_header, RIFF_HEADER_SIZE);
-
- // Read rest of the bytes.
- void* remaining_bytes = (void*)(mData.bytes + RIFF_HEADER_SIZE);
- size_t remaining_size = mData.size - RIFF_HEADER_SIZE;
- if (stream->read(remaining_bytes, remaining_size) != remaining_size) {
- ALOGE("WebP full load failed");
- return;
+ if (stream->getRawBuffer() != NULL) {
+ mData.size = stream->getRawBufferSize();
+ mData.bytes = stream->getRawBufferAddr();
+ mRawByteBuffer = stream->getRawBuffer();
+ } else {
+ // Read RIFF header to get file size.
+ uint8_t riff_header[RIFF_HEADER_SIZE];
+ if (stream->read(riff_header, RIFF_HEADER_SIZE) != RIFF_HEADER_SIZE) {
+ ALOGE("WebP header load failed");
+ return;
+ }
+ mData.size = CHUNK_HEADER_SIZE + GetLE32(riff_header + TAG_SIZE);
+ mData.bytes = new uint8_t[mData.size];
+ memcpy((void*)mData.bytes, riff_header, RIFF_HEADER_SIZE);
+
+ // Read rest of the bytes.
+ void* remaining_bytes = (void*)(mData.bytes + RIFF_HEADER_SIZE);
+ size_t remaining_size = mData.size - RIFF_HEADER_SIZE;
+ if (stream->read(remaining_bytes, remaining_size) != remaining_size) {
+ ALOGE("WebP full load failed");
+ return;
+ }
}
// Construct demux.
@@ -120,8 +126,10 @@ FrameSequence_webp::FrameSequence_webp(Stream* stream) {
FrameSequence_webp::~FrameSequence_webp() {
WebPDemuxDelete(mDemux);
- delete[] mData.bytes;
delete[] mIsKeyFrame;
+ if (mRawByteBuffer == NULL) {
+ delete[] mData.bytes;
+ }
}
FrameSequenceState* FrameSequence_webp::createState() const {
@@ -366,6 +374,10 @@ static bool isWebP(void* header, int header_size) {
!memcmp("WEBP", header_str + 8, 4);
}
+static bool acceptsWebPBuffer() {
+ return true;
+}
+
static FrameSequence* createFramesequence(Stream* stream) {
return new FrameSequence_webp(stream);
}
@@ -375,6 +387,7 @@ static RegistryEntry gEntry = {
isWebP,
createFramesequence,
NULL,
+ acceptsWebPBuffer,
};
static Registry gRegister(gEntry);
diff --git a/framesequence/jni/FrameSequence_webp.h b/framesequence/jni/FrameSequence_webp.h
index f4fbec0..94dcc3b 100644
--- a/framesequence/jni/FrameSequence_webp.h
+++ b/framesequence/jni/FrameSequence_webp.h
@@ -51,6 +51,10 @@ public:
return mLoopCount;
}
+ virtual jobject getRawByteBuffer() const {
+ return mRawByteBuffer;
+ }
+
virtual FrameSequenceState* createState() const;
WebPDemuxer* getDemuxer() const { return mDemux; }
@@ -66,6 +70,7 @@ private:
uint32_t mFormatFlags;
// mIsKeyFrame[i] is true if ith canvas can be constructed without decoding any prior frames.
bool* mIsKeyFrame;
+ jobject mRawByteBuffer;
};
// Produces frames of a possibly-animated WebP file for display.
diff --git a/framesequence/jni/Registry.cpp b/framesequence/jni/Registry.cpp
index 125ac66..e632bb2 100644
--- a/framesequence/jni/Registry.cpp
+++ b/framesequence/jni/Registry.cpp
@@ -34,15 +34,26 @@ Registry::Registry(const RegistryEntry& entry) {
const RegistryEntry* Registry::Find(Stream* stream) {
Registry* registry = gHead;
- int headerSize = gHeaderBytesRequired;
- char header[headerSize];
- headerSize = stream->peek(header, headerSize);
- while (registry) {
- if (headerSize >= registry->mImpl.requiredHeaderBytes
- && registry->mImpl.checkHeader(header, headerSize)) {
- return &(registry->mImpl);
+
+ if (stream->getRawBuffer() != NULL) {
+ while (registry) {
+ if (registry->mImpl.acceptsBuffer()) {
+ return &(registry->mImpl);
+ }
+ registry = registry->mNext;
+ }
+ } else {
+ int headerSize = gHeaderBytesRequired;
+ char header[headerSize];
+ headerSize = stream->peek(header, headerSize);
+ while (registry) {
+ if (headerSize >= registry->mImpl.requiredHeaderBytes
+ && registry->mImpl.checkHeader(header, headerSize)) {
+ return &(registry->mImpl);
+ }
+ registry = registry->mNext;
}
- registry = registry->mNext;
}
return 0;
}
+
diff --git a/framesequence/jni/Registry.h b/framesequence/jni/Registry.h
index 571c611..8db43cf 100644
--- a/framesequence/jni/Registry.h
+++ b/framesequence/jni/Registry.h
@@ -17,6 +17,9 @@
#ifndef RASTERMILL_REGISTRY_H
#define RASTERMILL_REGISTRY_H
+#include "jni.h"
+#include <stdint.h>
+
class FrameSequence;
class Decoder;
class Stream;
@@ -26,6 +29,7 @@ struct RegistryEntry {
bool (*checkHeader)(void* header, int header_size);
FrameSequence* (*createFrameSequence)(Stream* stream);
Decoder* (*createDecoder)(Stream* stream);
+ bool (*acceptsBuffer)();
};
/**
diff --git a/framesequence/jni/Stream.cpp b/framesequence/jni/Stream.cpp
index b2e0c39..a576e66 100644
--- a/framesequence/jni/Stream.cpp
+++ b/framesequence/jni/Stream.cpp
@@ -79,6 +79,34 @@ size_t Stream::read(void* buffer, size_t size) {
return bytes_read;
}
+uint8_t* Stream::getRawBufferAddr() {
+ return NULL;
+}
+
+jobject Stream::getRawBuffer() {
+ return NULL;
+}
+
+int Stream::getRawBufferSize() {
+ return 0;
+}
+
+uint8_t* MemoryStream::getRawBufferAddr() {
+ return mBuffer;
+}
+
+jobject MemoryStream::getRawBuffer() {
+ return mRawBuffer;
+}
+
+int MemoryStream::getRawBufferSize() {
+ if (mRawBuffer != NULL) {
+ return mRemaining;
+ } else {
+ return 0;
+ }
+}
+
size_t MemoryStream::doRead(void* buffer, size_t size) {
size = min(size, mRemaining);
memcpy(buffer, mBuffer, size);
diff --git a/framesequence/jni/Stream.h b/framesequence/jni/Stream.h
index f8f2427..f0f3895 100644
--- a/framesequence/jni/Stream.h
+++ b/framesequence/jni/Stream.h
@@ -28,6 +28,9 @@ public:
size_t peek(void* buffer, size_t size);
size_t read(void* buffer, size_t size);
+ virtual uint8_t* getRawBufferAddr();
+ virtual jobject getRawBuffer();
+ virtual int getRawBufferSize();
protected:
virtual size_t doRead(void* buffer, size_t size) = 0;
@@ -40,16 +43,21 @@ private:
class MemoryStream : public Stream {
public:
- MemoryStream(void* buffer, size_t size) :
- mBuffer((char*)buffer),
- mRemaining(size) {}
+ MemoryStream(void* buffer, size_t size, jobject buf) :
+ mBuffer((uint8_t*)buffer),
+ mRemaining(size),
+ mRawBuffer(buf) {}
+ virtual uint8_t* getRawBufferAddr();
+ virtual jobject getRawBuffer();
+ virtual int getRawBufferSize();
protected:
virtual size_t doRead(void* buffer, size_t size);
private:
- char* mBuffer;
+ uint8_t* mBuffer;
size_t mRemaining;
+ jobject mRawBuffer;
};
class FileStream : public Stream {
diff --git a/framesequence/src/android/support/rastermill/FrameSequence.java b/framesequence/src/android/support/rastermill/FrameSequence.java
index d2bd128..8ff241f 100644
--- a/framesequence/src/android/support/rastermill/FrameSequence.java
+++ b/framesequence/src/android/support/rastermill/FrameSequence.java
@@ -17,6 +17,7 @@
package android.support.rastermill;
import android.graphics.Bitmap;
+import java.nio.ByteBuffer;
import java.io.InputStream;
@@ -40,6 +41,7 @@ public class FrameSequence {
private static native FrameSequence nativeDecodeByteArray(byte[] data, int offset, int length);
private static native FrameSequence nativeDecodeStream(InputStream is, byte[] tempStorage);
+ private static native FrameSequence nativeDecodeByteBuffer(ByteBuffer buffer, int offset, int capacity);
private static native void nativeDestroyFrameSequence(long nativeFrameSequence);
private static native long nativeCreateState(long nativeFrameSequence);
private static native void nativeDestroyState(long nativeState);
@@ -69,6 +71,19 @@ public class FrameSequence {
return nativeDecodeByteArray(data, offset, length);
}
+ public static FrameSequence decodeByteBuffer(ByteBuffer buffer) {
+ if (buffer == null) throw new IllegalArgumentException();
+ if (!buffer.isDirect()) {
+ if (buffer.hasArray()) {
+ byte[] byteArray = buffer.array();
+ return decodeByteArray(byteArray, buffer.position(), buffer.remaining());
+ } else {
+ throw new IllegalArgumentException("Cannot have non-direct ByteBuffer with no byte array");
+ }
+ }
+ return nativeDecodeByteBuffer(buffer, buffer.position(), buffer.remaining());
+ }
+
public static FrameSequence decodeStream(InputStream stream) {
if (stream == null) throw new IllegalArgumentException();
byte[] tempStorage = new byte[16 * 1024]; // TODO: use buffer pool