diff options
author | Andreas Huber <andih@google.com> | 2012-04-18 12:19:51 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2012-04-18 12:19:51 -0700 |
commit | 91befdc0c4710234840cdfd853e7d30e8f9de62c (patch) | |
tree | e37fa5820ab6348549d7a59a342ad3ee70e7e55c /media/jni/android_media_MediaExtractor.cpp | |
parent | 26fbf27ad1e9f9c26a82097fe306f07ec36e8410 (diff) |
Information required to decrypt buffers is now packaged into MediaCodec.CryptoInfo
New API on MediaExtractor to retrieve a CryptoInfo structure where applicable.
Change-Id: I18edfc9ac56a4544c8f17cba24401b96dacbff7d
related-to-bug: 6275919
Diffstat (limited to 'media/jni/android_media_MediaExtractor.cpp')
-rw-r--r-- | media/jni/android_media_MediaExtractor.cpp | 143 |
1 files changed, 142 insertions, 1 deletions
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp index e2cdbca38add..adf0e666488d 100644 --- a/media/jni/android_media_MediaExtractor.cpp +++ b/media/jni/android_media_MediaExtractor.cpp @@ -30,12 +30,15 @@ #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/DataSource.h> #include <media/stagefright/MediaErrors.h> +#include <media/stagefright/MetaData.h> #include <media/stagefright/NuMediaExtractor.h> namespace android { struct fields_t { jfieldID context; + + jmethodID cryptoInfoSetID; }; static fields_t gFields; @@ -166,7 +169,32 @@ status_t JMediaExtractor::getSampleTime(int64_t *sampleTimeUs) { } status_t JMediaExtractor::getSampleFlags(uint32_t *sampleFlags) { - return mImpl->getSampleFlags(sampleFlags); + *sampleFlags = 0; + + sp<MetaData> meta; + status_t err = mImpl->getSampleMeta(&meta); + + if (err != OK) { + return err; + } + + int32_t val; + if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) { + (*sampleFlags) |= NuMediaExtractor::SAMPLE_FLAG_SYNC; + } + + uint32_t type; + const void *data; + size_t size; + if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) { + (*sampleFlags) |= NuMediaExtractor::SAMPLE_FLAG_ENCRYPTED; + } + + return OK; +} + +status_t JMediaExtractor::getSampleMeta(sp<MetaData> *sampleMeta) { + return mImpl->getSampleMeta(sampleMeta); } } // namespace android @@ -369,6 +397,110 @@ static jint android_media_MediaExtractor_getSampleFlags( return sampleFlags; } +static jboolean android_media_MediaExtractor_getSampleCryptoInfo( + JNIEnv *env, jobject thiz, jobject cryptoInfoObj) { + sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); + + if (extractor == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", NULL); + return -1ll; + } + + sp<MetaData> meta; + status_t err = extractor->getSampleMeta(&meta); + + if (err != OK) { + return false; + } + + uint32_t type; + const void *data; + size_t size; + if (!meta->findData(kKeyEncryptedSizes, &type, &data, &size)) { + return false; + } + + size_t numSubSamples = size / sizeof(size_t); + + if (numSubSamples == 0) { + return false; + } + + jintArray numBytesOfEncryptedDataObj = env->NewIntArray(numSubSamples); + jboolean isCopy; + jint *dst = env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy); + for (size_t i = 0; i < numSubSamples; ++i) { + dst[i] = ((const size_t *)data)[i]; + } + env->ReleaseIntArrayElements(numBytesOfEncryptedDataObj, dst, 0); + dst = NULL; + + size_t encSize = size; + jintArray numBytesOfPlainDataObj = NULL; + if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) { + if (size != encSize) { + // The two must be of the same length. + return false; + } + + numBytesOfPlainDataObj = env->NewIntArray(numSubSamples); + jboolean isCopy; + jint *dst = env->GetIntArrayElements(numBytesOfPlainDataObj, &isCopy); + for (size_t i = 0; i < numSubSamples; ++i) { + dst[i] = ((const size_t *)data)[i]; + } + env->ReleaseIntArrayElements(numBytesOfPlainDataObj, dst, 0); + dst = NULL; + } + + jbyteArray keyObj = NULL; + if (meta->findData(kKeyCryptoKey, &type, &data, &size)) { + if (size != 16) { + // Keys must be 16 bytes in length. + return false; + } + + keyObj = env->NewByteArray(size); + jboolean isCopy; + jbyte *dst = env->GetByteArrayElements(keyObj, &isCopy); + memcpy(dst, data, size); + env->ReleaseByteArrayElements(keyObj, dst, 0); + dst = NULL; + } + + jbyteArray ivObj = NULL; + if (meta->findData(kKeyCryptoIV, &type, &data, &size)) { + if (size != 16) { + // IVs must be 16 bytes in length. + return false; + } + + ivObj = env->NewByteArray(size); + jboolean isCopy; + jbyte *dst = env->GetByteArrayElements(ivObj, &isCopy); + memcpy(dst, data, size); + env->ReleaseByteArrayElements(ivObj, dst, 0); + dst = NULL; + } + + int32_t mode; + if (!meta->findInt32(kKeyCryptoMode, &mode)) { + mode = 0; + } + + env->CallVoidMethod( + cryptoInfoObj, + gFields.cryptoInfoSetID, + numSubSamples, + numBytesOfPlainDataObj, + numBytesOfEncryptedDataObj, + keyObj, + ivObj, + mode); + + return true; +} + static void android_media_MediaExtractor_native_init(JNIEnv *env) { jclass clazz = env->FindClass("android/media/MediaExtractor"); CHECK(clazz != NULL); @@ -376,6 +508,12 @@ static void android_media_MediaExtractor_native_init(JNIEnv *env) { gFields.context = env->GetFieldID(clazz, "mNativeContext", "I"); CHECK(gFields.context != NULL); + clazz = env->FindClass("android/media/MediaCodec$CryptoInfo"); + CHECK(clazz != NULL); + + gFields.cryptoInfoSetID = + env->GetMethodID(clazz, "set", "(I[I[I[B[BI)V"); + DataSource::RegisterDefaultSniffers(); } @@ -485,6 +623,9 @@ static JNINativeMethod gMethods[] = { { "getSampleFlags", "()I", (void *)android_media_MediaExtractor_getSampleFlags }, + { "getSampleCryptoInfo", "(Landroid/media/MediaCodec$CryptoInfo;)Z", + (void *)android_media_MediaExtractor_getSampleCryptoInfo }, + { "native_init", "()V", (void *)android_media_MediaExtractor_native_init }, { "native_setup", "()V", |