10a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia/* 20a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Copyright 2017, The Android Open Source Project 30a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 40a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Licensed under the Apache License, Version 2.0 (the "License"); 50a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * you may not use this file except in compliance with the License. 60a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * You may obtain a copy of the License at 70a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 80a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * http://www.apache.org/licenses/LICENSE-2.0 90a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * 100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * Unless required by applicable law or agreed to in writing, software 110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * distributed under the License is distributed on an "AS IS" BASIS, 120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * See the License for the specific language governing permissions and 140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia * limitations under the License. 150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia */ 160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia//#define LOG_NDEBUG 0 180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia#define LOG_TAG "JMedia2DataSource-JNI" 190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia#include <utils/Log.h> 200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia#include "android_media_Media2DataSource.h" 220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia#include "android_runtime/AndroidRuntime.h" 240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia#include "android_runtime/Log.h" 250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia#include "jni.h" 260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia#include <nativehelper/JNIHelp.h> 270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia#include <drm/drm_framework_common.h> 290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia#include <media/stagefright/foundation/ADebug.h> 300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia#include <nativehelper/ScopedLocalRef.h> 310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jianamespace android { 330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiastatic const size_t kBufferSize = 64 * 1024; 350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 360a8a8f0b26634395ce64123e2a385670d6b07c00Wei JiaJMedia2DataSource::JMedia2DataSource(JNIEnv* env, jobject source) 370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia : mJavaObjStatus(OK), 380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSizeIsCached(false), 390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mCachedSize(0) { 400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mMedia2DataSourceObj = env->NewGlobalRef(source); 410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia CHECK(mMedia2DataSourceObj != NULL); 420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ScopedLocalRef<jclass> media2DataSourceClass(env, env->GetObjectClass(mMedia2DataSourceObj)); 440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia CHECK(media2DataSourceClass.get() != NULL); 450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mReadAtMethod = env->GetMethodID(media2DataSourceClass.get(), "readAt", "(J[BII)I"); 470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia CHECK(mReadAtMethod != NULL); 480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mGetSizeMethod = env->GetMethodID(media2DataSourceClass.get(), "getSize", "()J"); 490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia CHECK(mGetSizeMethod != NULL); 500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mCloseMethod = env->GetMethodID(media2DataSourceClass.get(), "close", "()V"); 510a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia CHECK(mCloseMethod != NULL); 520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ScopedLocalRef<jbyteArray> tmp(env, env->NewByteArray(kBufferSize)); 540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mByteArrayObj = (jbyteArray)env->NewGlobalRef(tmp.get()); 550a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia CHECK(mByteArrayObj != NULL); 560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia} 570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 580a8a8f0b26634395ce64123e2a385670d6b07c00Wei JiaJMedia2DataSource::~JMedia2DataSource() { 590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia JNIEnv* env = AndroidRuntime::getJNIEnv(); 600a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia env->DeleteGlobalRef(mMedia2DataSourceObj); 610a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia env->DeleteGlobalRef(mByteArrayObj); 620a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia} 630a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 640a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiastatus_t JMedia2DataSource::initCheck() const { 650a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return OK; 660a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia} 670a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 680a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiassize_t JMedia2DataSource::readAt(off64_t offset, void *data, size_t size) { 690a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Mutex::Autolock lock(mLock); 700a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 710a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mJavaObjStatus != OK) { 720a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return -1; 730a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 740a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (size > kBufferSize) { 750a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia size = kBufferSize; 760a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 770a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 780a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia JNIEnv* env = AndroidRuntime::getJNIEnv(); 790a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia jint numread = env->CallIntMethod(mMedia2DataSourceObj, mReadAtMethod, 800a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia (jlong)offset, mByteArrayObj, (jint)0, (jint)size); 810a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (env->ExceptionCheck()) { 820a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ALOGW("An exception occurred in readAt()"); 830a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia LOGW_EX(env); 840a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia env->ExceptionClear(); 850a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mJavaObjStatus = UNKNOWN_ERROR; 860a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return -1; 870a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 880a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (numread < 0) { 890a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (numread != -1) { 900a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ALOGW("An error occurred in readAt()"); 910a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mJavaObjStatus = UNKNOWN_ERROR; 920a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return -1; 930a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } else { 940a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // numread == -1 indicates EOF 950a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return 0; 960a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 970a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 980a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if ((size_t)numread > size) { 990a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ALOGE("readAt read too many bytes."); 1000a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mJavaObjStatus = UNKNOWN_ERROR; 1010a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return -1; 1020a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 1030a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1040a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ALOGV("readAt %lld / %zu => %d.", (long long)offset, size, numread); 1050a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia env->GetByteArrayRegion(mByteArrayObj, 0, numread, (jbyte*)data); 1060a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return numread; 1070a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia} 1080a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1090a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiastatus_t JMedia2DataSource::getSize(off64_t* size) { 1100a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Mutex::Autolock lock(mLock); 1110a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1120a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mJavaObjStatus != OK) { 1130a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return UNKNOWN_ERROR; 1140a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 1150a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (mSizeIsCached) { 1160a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia *size = mCachedSize; 1170a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return OK; 1180a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 1190a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1200a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia JNIEnv* env = AndroidRuntime::getJNIEnv(); 1210a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia *size = env->CallLongMethod(mMedia2DataSourceObj, mGetSizeMethod); 1220a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (env->ExceptionCheck()) { 1230a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia ALOGW("An exception occurred in getSize()"); 1240a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia LOGW_EX(env); 1250a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia env->ExceptionClear(); 1260a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // After returning an error, size shouldn't be used by callers. 1270a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia *size = UNKNOWN_ERROR; 1280a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mJavaObjStatus = UNKNOWN_ERROR; 1290a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return UNKNOWN_ERROR; 1300a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 1310a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1320a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // The minimum size should be -1, which indicates unknown size. 1330a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia if (*size < 0) { 1340a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia *size = -1; 1350a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia } 1360a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1370a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mCachedSize = *size; 1380a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mSizeIsCached = true; 1390a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return OK; 1400a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia} 1410a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1420a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jiavoid JMedia2DataSource::close() { 1430a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia Mutex::Autolock lock(mLock); 1440a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1450a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia JNIEnv* env = AndroidRuntime::getJNIEnv(); 1460a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia env->CallVoidMethod(mMedia2DataSourceObj, mCloseMethod); 1470a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia // The closed state is effectively the same as an error state. 1480a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia mJavaObjStatus = UNKNOWN_ERROR; 1490a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia} 1500a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1510a8a8f0b26634395ce64123e2a385670d6b07c00Wei JiaString8 JMedia2DataSource::toString() { 1520a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return String8::format("JMedia2DataSource(pid %d, uid %d)", getpid(), getuid()); 1530a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia} 1540a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1550a8a8f0b26634395ce64123e2a385670d6b07c00Wei JiaString8 JMedia2DataSource::getMIMEType() const { 1560a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia return String8("application/octet-stream"); 1570a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia} 1580a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia 1590a8a8f0b26634395ce64123e2a385670d6b07c00Wei Jia} // namespace android 160