Movie.cpp revision 6ba30b85ddfbe37c338ee8dde3dd33322eb38d47
1ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "ScopedLocalRef.h"
27315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III#include "SkFrontBufferedStream.h"
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkMovie.h"
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkStream.h"
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "GraphicsJNI.h"
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkTemplates.h"
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkUtils.h"
8ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "Utils.h"
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "CreateJavaOutputStreamAdaptor.h"
106ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod#include "Paint.h"
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/Asset.h>
13b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/ResourceTypes.h>
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <netinet/in.h>
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #define TRACE_BITMAP(code)  code
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #define TRACE_BITMAP(code)
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass       gMovie_class;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID    gMovie_constructorMethodID;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID     gMovie_nativeInstanceID;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjobject create_jmovie(JNIEnv* env, SkMovie* moov) {
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (NULL == moov) {
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
30cf6f7a0f006c0fcf59bb634cbe79f2a8500fd92aElliott Hughes    return env->NewObject(gMovie_class, gMovie_constructorMethodID,
31dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat            static_cast<jlong>(reinterpret_cast<uintptr_t>(moov)));
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic SkMovie* J2Movie(JNIEnv* env, jobject movie) {
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(env);
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(movie);
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(env->IsInstanceOf(movie, gMovie_class));
38dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    SkMovie* m = (SkMovie*)env->GetLongField(movie, gMovie_nativeInstanceID);
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(m);
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return m;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
45dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jint movie_width(JNIEnv* env, jobject movie) {
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
47dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    return static_cast<jint>(J2Movie(env, movie)->width());
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
50dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jint movie_height(JNIEnv* env, jobject movie) {
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
52dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    return static_cast<jint>(J2Movie(env, movie)->height());
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jboolean movie_isOpaque(JNIEnv* env, jobject movie) {
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
57dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    return J2Movie(env, movie)->isOpaque() ? JNI_TRUE : JNI_FALSE;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
60dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jint movie_duration(JNIEnv* env, jobject movie) {
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
62dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    return static_cast<jint>(J2Movie(env, movie)->duration());
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
65dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jboolean movie_setTime(JNIEnv* env, jobject movie, jint ms) {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
67dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    return J2Movie(env, movie)->setTime(ms) ? JNI_TRUE : JNI_FALSE;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void movie_draw(JNIEnv* env, jobject movie, jobject canvas,
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       jfloat fx, jfloat fy, jobject jpaint) {
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_VOID(env, movie);
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_VOID(env, canvas);
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // its OK for paint to be null
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkMovie* m = J2Movie(env, movie);
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkCanvas* c = GraphicsJNI::getNativeCanvas(env, canvas);
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const SkBitmap& b = m->bitmap();
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const SkPaint* p = jpaint ? GraphicsJNI::getNativePaint(env, jpaint) : NULL;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
812e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III    c->drawBitmap(b, fx, fy, p);
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
84dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jlong native_asset) {
857315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset);
867315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    if (asset == NULL) return NULL;
87b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III    SkAutoTUnref<SkStreamRewindable> stream (new android::AssetStreamAdaptor(asset,
88b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III            android::AssetStreamAdaptor::kNo_OwnAsset,
89b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III            android::AssetStreamAdaptor::kNo_HasMemoryBase));
907315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    SkMovie* moov = SkMovie::DecodeStream(stream.get());
917315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    return create_jmovie(env, moov);
927315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III}
937315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) {
958451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, istream);
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
987315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    jbyteArray byteArray = env->NewByteArray(16*1024);
997315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    ScopedLocalRef<jbyteArray> scoper(env, byteArray);
1007315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray);
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (NULL == strm) {
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1057315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    // Need to buffer enough input to be able to rewind as much as might be read by a decoder
1067315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    // trying to determine the stream's format. The only decoder for movies is GIF, which
1077315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    // will only read 6.
1087315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    // FIXME: Get this number from SkImageDecoder
1097315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6));
1107315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    SkASSERT(bufferedStream.get() != NULL);
1117315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III
1127315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    SkMovie* moov = SkMovie::DecodeStream(bufferedStream);
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    strm->unref();
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return create_jmovie(env, moov);
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject movie_decodeByteArray(JNIEnv* env, jobject clazz,
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                     jbyteArray byteArray,
119dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat                                     jint offset, jint length) {
1208451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, byteArray);
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int totalLength = env->GetArrayLength(byteArray);
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((offset | length) < 0 || offset + length > totalLength) {
1258451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowAIOOBE(env);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoJavaByteArray   ar(env, byteArray);
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkMovie* moov = SkMovie::DecodeMemory(ar.ptr() + offset, length);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return create_jmovie(env, moov);
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
134dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic void movie_destructor(JNIEnv* env, jobject, jlong movieHandle) {
135dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    SkMovie* movie = (SkMovie*) movieHandle;
13608d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka    delete movie;
13708d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka}
13808d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//////////////////////////////////////////////////////////////////////////////////////////////
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h>
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = {
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "width",    "()I",  (void*)movie_width  },
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "height",   "()I",  (void*)movie_height  },
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "isOpaque", "()Z",  (void*)movie_isOpaque  },
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "duration", "()I",  (void*)movie_duration  },
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "setTime",  "(I)Z", (void*)movie_setTime  },
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "draw",     "(Landroid/graphics/Canvas;FFLandroid/graphics/Paint;)V",
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (void*)movie_draw  },
151dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    { "nativeDecodeAsset", "(J)Landroid/graphics/Movie;",
1527315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III                            (void*)movie_decodeAsset },
1537315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    { "nativeDecodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;",
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (void*)movie_decodeStream },
155dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    { "nativeDestructor","(J)V", (void*)movie_destructor },
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "decodeByteArray", "([BII)Landroid/graphics/Movie;",
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (void*)movie_decodeByteArray },
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define kClassPathName  "android/graphics/Movie"
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define RETURN_ERR_IF_NULL(value)   do { if (!(value)) { assert(0); return -1; } } while (false)
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_graphics_Movie(JNIEnv* env)
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    gMovie_class = env->FindClass(kClassPathName);
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RETURN_ERR_IF_NULL(gMovie_class);
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    gMovie_class = (jclass)env->NewGlobalRef(gMovie_class);
1698451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
170dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    gMovie_constructorMethodID = env->GetMethodID(gMovie_class, "<init>", "(J)V");
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RETURN_ERR_IF_NULL(gMovie_constructorMethodID);
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
173dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    gMovie_nativeInstanceID = env->GetFieldID(gMovie_class, "mNativeMovie", "J");
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RETURN_ERR_IF_NULL(gMovie_nativeInstanceID);
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                       gMethods, SK_ARRAY_COUNT(gMethods));
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
179