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