Movie.cpp revision b9c58ab617c257dbece105167b21e94faad67320
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" 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/Asset.h> 12b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/ResourceTypes.h> 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <netinet/in.h> 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project #define TRACE_BITMAP(code) code 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project #define TRACE_BITMAP(code) 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass gMovie_class; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID gMovie_constructorMethodID; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID gMovie_nativeInstanceID; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjobject create_jmovie(JNIEnv* env, SkMovie* moov) { 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (NULL == moov) { 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29cf6f7a0f006c0fcf59bb634cbe79f2a8500fd92aElliott Hughes return env->NewObject(gMovie_class, gMovie_constructorMethodID, 30cf6f7a0f006c0fcf59bb634cbe79f2a8500fd92aElliott Hughes static_cast<jint>(reinterpret_cast<uintptr_t>(moov))); 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic SkMovie* J2Movie(JNIEnv* env, jobject movie) { 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkASSERT(env); 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkASSERT(movie); 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkASSERT(env->IsInstanceOf(movie, gMovie_class)); 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkMovie* m = (SkMovie*)env->GetIntField(movie, gMovie_nativeInstanceID); 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkASSERT(m); 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return m; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int movie_width(JNIEnv* env, jobject movie) { 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, movie); 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return J2Movie(env, movie)->width(); 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int movie_height(JNIEnv* env, jobject movie) { 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, movie); 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return J2Movie(env, movie)->height(); 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jboolean movie_isOpaque(JNIEnv* env, jobject movie) { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, movie); 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return J2Movie(env, movie)->isOpaque(); 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int movie_duration(JNIEnv* env, jobject movie) { 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, movie); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return J2Movie(env, movie)->duration(); 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jboolean movie_setTime(JNIEnv* env, jobject movie, int ms) { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, movie); 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return J2Movie(env, movie)->setTime(ms); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void movie_draw(JNIEnv* env, jobject movie, jobject canvas, 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfloat fx, jfloat fy, jobject jpaint) { 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_VOID(env, movie); 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_VOID(env, canvas); 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // its OK for paint to be null 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkMovie* m = J2Movie(env, movie); 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkCanvas* c = GraphicsJNI::getNativeCanvas(env, canvas); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkScalar sx = SkFloatToScalar(fx); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkScalar sy = SkFloatToScalar(fy); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const SkBitmap& b = m->bitmap(); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const SkPaint* p = jpaint ? GraphicsJNI::getNativePaint(env, jpaint) : NULL; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c->drawBitmap(b, sx, sy, p); 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 857315f1baee19476363235127bc1438e2a291fa15Leon Scroggins IIIstatic jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jint native_asset) { 867315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset); 877315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III if (asset == NULL) return NULL; 88b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III SkAutoTUnref<SkStreamRewindable> stream (new android::AssetStreamAdaptor(asset, 89b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III android::AssetStreamAdaptor::kNo_OwnAsset, 90b9c58ab617c257dbece105167b21e94faad67320Leon Scroggins III android::AssetStreamAdaptor::kNo_HasMemoryBase)); 917315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III SkMovie* moov = SkMovie::DecodeStream(stream.get()); 927315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III return create_jmovie(env, moov); 937315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III} 947315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) { 968451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, istream); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 997315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III jbyteArray byteArray = env->NewByteArray(16*1024); 1007315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III ScopedLocalRef<jbyteArray> scoper(env, byteArray); 1017315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (NULL == strm) { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1067315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III // Need to buffer enough input to be able to rewind as much as might be read by a decoder 1077315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III // trying to determine the stream's format. The only decoder for movies is GIF, which 1087315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III // will only read 6. 1097315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III // FIXME: Get this number from SkImageDecoder 1107315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6)); 1117315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III SkASSERT(bufferedStream.get() != NULL); 1127315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III 1137315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III SkMovie* moov = SkMovie::DecodeStream(bufferedStream); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strm->unref(); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return create_jmovie(env, moov); 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject movie_decodeByteArray(JNIEnv* env, jobject clazz, 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray byteArray, 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int offset, int length) { 1218451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, byteArray); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int totalLength = env->GetArrayLength(byteArray); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((offset | length) < 0 || offset + length > totalLength) { 1268451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes doThrowAIOOBE(env); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AutoJavaByteArray ar(env, byteArray); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkMovie* moov = SkMovie::DecodeMemory(ar.ptr() + offset, length); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return create_jmovie(env, moov); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13508d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusakastatic void movie_destructor(JNIEnv* env, jobject, SkMovie* movie) { 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 }, 1517315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III { "nativeDecodeAsset", "(I)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 }, 15508d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka { "nativeDestructor","(I)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 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gMovie_constructorMethodID = env->GetMethodID(gMovie_class, "<init>", "(I)V"); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RETURN_ERR_IF_NULL(gMovie_constructorMethodID); 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gMovie_nativeInstanceID = env->GetFieldID(gMovie_class, "mNativeMovie", "I"); 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