Loading api/current.txt +13 −1 Original line number Diff line number Diff line Loading @@ -10960,7 +10960,7 @@ package android.media { method public java.nio.ByteBuffer[] getOutputBuffers(); method public final java.util.Map<java.lang.String, java.lang.Object> getOutputFormat(); method public final void queueInputBuffer(int, int, int, long, int); method public final void queueSecureInputBuffer(int, int, int[], int[], int, byte[], byte[], int, long, int); method public final void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int); method public final void release(); method public final void releaseOutputBuffer(int, boolean); method public final void start(); Loading @@ -10985,6 +10985,17 @@ package android.media { field public int size; } public static final class MediaCodec.CryptoInfo { ctor public MediaCodec.CryptoInfo(); method public void set(int, int[], int[], byte[], byte[], int); field public byte[] iv; field public byte[] key; field public int mode; field public int[] numBytesOfClearData; field public int[] numBytesOfEncryptedData; field public int numSubSamples; } public final class MediaCodecList { method public static final int countCodecs(); method public static final android.media.MediaCodecList.CodecCapabilities getCodecCapabilities(int, java.lang.String); Loading Loading @@ -11016,6 +11027,7 @@ package android.media { ctor public MediaExtractor(); method public boolean advance(); method public int countTracks(); method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo); method public int getSampleFlags(); method public long getSampleTime(); method public int getSampleTrackIndex(); media/java/android/media/MediaCodec.java +43 −22 Original line number Diff line number Diff line Loading @@ -309,36 +309,57 @@ final public class MediaCodec { int index, int offset, int size, long presentationTimeUs, int flags); /** Metadata describing the structure of a (at least partially) encrypted * input sample. * A buffer's data is considered to be partitioned into "subSamples", * each subSample starts with a (potentially empty) run of plain, * unencrypted bytes followed by a (also potentially empty) run of * encrypted bytes. * numBytesOfClearData can be null to indicate that all data is encrypted. */ public final static class CryptoInfo { public void set( int newNumSubSamples, int[] newNumBytesOfClearData, int[] newNumBytesOfEncryptedData, byte[] newKey, byte[] newIV, int newMode) { numSubSamples = newNumSubSamples; numBytesOfClearData = newNumBytesOfClearData; numBytesOfEncryptedData = newNumBytesOfEncryptedData; key = newKey; iv = newIV; mode = newMode; } /** The number of subSamples that make up the buffer's contents. */ public int numSubSamples; /** The number of leading unencrypted bytes in each subSample. */ public int[] numBytesOfClearData; /** The number of trailing encrypted bytes in each subSample. */ public int[] numBytesOfEncryptedData; /** A 16-byte opaque key */ public byte[] key; /** A 16-byte initialization vector */ public byte[] iv; /** The type of encryption that has been applied */ public int mode; }; /** Similar to {@link #queueInputBuffer} but submits a buffer that is * potentially encrypted. The buffer's data is considered to be * partitioned into "subSamples", each subSample starts with a * (potentially empty) run of plain, unencrypted bytes followed * by a (also potentially empty) run of encrypted bytes. * potentially encrypted. * @param index The index of a client-owned input buffer previously returned * in a call to {@link #dequeueInputBuffer}. * @param offset The byte offset into the input buffer at which the data starts. * @param numBytesOfClearData The number of leading unencrypted bytes in * each subSample. * @param numBytesOfEncryptedData The number of trailing encrypted bytes * in each subSample. * @param numSubSamples The number of subSamples that make up the * buffer's contents. * @param key A 16-byte opaque key * @param iv A 16-byte initialization vector * @param mode The type of encryption that has been applied * * Either numBytesOfClearData or numBytesOfEncryptedData (but not both) * can be null to indicate that all respective sizes are 0. * @param presentationTimeUs The time at which this buffer should be rendered. * @param flags A bitmask of flags {@link #FLAG_SYNCFRAME}, * {@link #FLAG_CODECCONFIG} or {@link #FLAG_EOS}. */ public native final void queueSecureInputBuffer( int index, int offset, int[] numBytesOfClearData, int[] numBytesOfEncryptedData, int numSubSamples, byte[] key, byte[] iv, int mode, CryptoInfo info, long presentationTimeUs, int flags); Loading media/java/android/media/MediaExtractor.java +10 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.media; import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.media.MediaCodec; import android.net.Uri; import java.io.FileDescriptor; import java.io.IOException; Loading Loading @@ -235,6 +236,15 @@ final public class MediaExtractor { /** Returns the current sample's flags. */ public native int getSampleFlags(); /** If the sample flags indicate that the current sample is at least * partially encrypted, this call returns relevant information about * the structure of the sample data required for decryption. * @param info The android.media.MediaCodec.CryptoInfo structure * to be filled in. * @return true iff the sample flags contain {@link #SAMPLE_FLAG_ENCRYPTED} */ public native boolean getSampleCryptoInfo(MediaCodec.CryptoInfo info); private static native final void native_init(); private native final void native_setup(); private native final void native_finalize(); Loading media/jni/android_media_MediaCodec.cpp +52 −7 Original line number Diff line number Diff line Loading @@ -49,6 +49,13 @@ enum { struct fields_t { jfieldID context; jfieldID cryptoInfoNumSubSamplesID; jfieldID cryptoInfoNumBytesOfClearDataID; jfieldID cryptoInfoNumBytesOfEncryptedDataID; jfieldID cryptoInfoKeyID; jfieldID cryptoInfoIVID; jfieldID cryptoInfoModeID; }; static fields_t gFields; Loading Loading @@ -387,12 +394,7 @@ static void android_media_MediaCodec_queueSecureInputBuffer( jobject thiz, jint index, jint offset, jintArray numBytesOfClearDataObj, jintArray numBytesOfEncryptedDataObj, jint numSubSamples, jbyteArray keyObj, jbyteArray ivObj, jint mode, jobject cryptoInfoObj, jlong timestampUs, jint flags) { ALOGV("android_media_MediaCodec_queueSecureInputBuffer"); Loading @@ -404,6 +406,25 @@ static void android_media_MediaCodec_queueSecureInputBuffer( return; } jint numSubSamples = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID); jintArray numBytesOfClearDataObj = (jintArray)env->GetObjectField( cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID); jintArray numBytesOfEncryptedDataObj = (jintArray)env->GetObjectField( cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID); jbyteArray keyObj = (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID); jbyteArray ivObj = (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID); jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID); status_t err = OK; CryptoPlugin::SubSample *subSamples = NULL; Loading Loading @@ -612,6 +633,30 @@ static void android_media_MediaCodec_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.cryptoInfoNumSubSamplesID = env->GetFieldID(clazz, "numSubSamples", "I"); CHECK(gFields.cryptoInfoNumSubSamplesID != NULL); gFields.cryptoInfoNumBytesOfClearDataID = env->GetFieldID(clazz, "numBytesOfClearData", "[I"); CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL); gFields.cryptoInfoNumBytesOfEncryptedDataID = env->GetFieldID(clazz, "numBytesOfEncryptedData", "[I"); CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL); gFields.cryptoInfoKeyID = env->GetFieldID(clazz, "key", "[B"); CHECK(gFields.cryptoInfoKeyID != NULL); gFields.cryptoInfoIVID = env->GetFieldID(clazz, "iv", "[B"); CHECK(gFields.cryptoInfoIVID != NULL); gFields.cryptoInfoModeID = env->GetFieldID(clazz, "mode", "I"); CHECK(gFields.cryptoInfoModeID != NULL); } static void android_media_MediaCodec_native_setup( Loading Loading @@ -666,7 +711,7 @@ static JNINativeMethod gMethods[] = { { "queueInputBuffer", "(IIIJI)V", (void *)android_media_MediaCodec_queueInputBuffer }, { "queueSecureInputBuffer", "(II[I[II[B[BIJI)V", { "queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V", (void *)android_media_MediaCodec_queueSecureInputBuffer }, { "dequeueInputBuffer", "(J)I", Loading media/jni/android_media_MediaExtractor.cpp +142 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); Loading @@ -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(); } Loading Loading @@ -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", Loading Loading
api/current.txt +13 −1 Original line number Diff line number Diff line Loading @@ -10960,7 +10960,7 @@ package android.media { method public java.nio.ByteBuffer[] getOutputBuffers(); method public final java.util.Map<java.lang.String, java.lang.Object> getOutputFormat(); method public final void queueInputBuffer(int, int, int, long, int); method public final void queueSecureInputBuffer(int, int, int[], int[], int, byte[], byte[], int, long, int); method public final void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int); method public final void release(); method public final void releaseOutputBuffer(int, boolean); method public final void start(); Loading @@ -10985,6 +10985,17 @@ package android.media { field public int size; } public static final class MediaCodec.CryptoInfo { ctor public MediaCodec.CryptoInfo(); method public void set(int, int[], int[], byte[], byte[], int); field public byte[] iv; field public byte[] key; field public int mode; field public int[] numBytesOfClearData; field public int[] numBytesOfEncryptedData; field public int numSubSamples; } public final class MediaCodecList { method public static final int countCodecs(); method public static final android.media.MediaCodecList.CodecCapabilities getCodecCapabilities(int, java.lang.String); Loading Loading @@ -11016,6 +11027,7 @@ package android.media { ctor public MediaExtractor(); method public boolean advance(); method public int countTracks(); method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo); method public int getSampleFlags(); method public long getSampleTime(); method public int getSampleTrackIndex();
media/java/android/media/MediaCodec.java +43 −22 Original line number Diff line number Diff line Loading @@ -309,36 +309,57 @@ final public class MediaCodec { int index, int offset, int size, long presentationTimeUs, int flags); /** Metadata describing the structure of a (at least partially) encrypted * input sample. * A buffer's data is considered to be partitioned into "subSamples", * each subSample starts with a (potentially empty) run of plain, * unencrypted bytes followed by a (also potentially empty) run of * encrypted bytes. * numBytesOfClearData can be null to indicate that all data is encrypted. */ public final static class CryptoInfo { public void set( int newNumSubSamples, int[] newNumBytesOfClearData, int[] newNumBytesOfEncryptedData, byte[] newKey, byte[] newIV, int newMode) { numSubSamples = newNumSubSamples; numBytesOfClearData = newNumBytesOfClearData; numBytesOfEncryptedData = newNumBytesOfEncryptedData; key = newKey; iv = newIV; mode = newMode; } /** The number of subSamples that make up the buffer's contents. */ public int numSubSamples; /** The number of leading unencrypted bytes in each subSample. */ public int[] numBytesOfClearData; /** The number of trailing encrypted bytes in each subSample. */ public int[] numBytesOfEncryptedData; /** A 16-byte opaque key */ public byte[] key; /** A 16-byte initialization vector */ public byte[] iv; /** The type of encryption that has been applied */ public int mode; }; /** Similar to {@link #queueInputBuffer} but submits a buffer that is * potentially encrypted. The buffer's data is considered to be * partitioned into "subSamples", each subSample starts with a * (potentially empty) run of plain, unencrypted bytes followed * by a (also potentially empty) run of encrypted bytes. * potentially encrypted. * @param index The index of a client-owned input buffer previously returned * in a call to {@link #dequeueInputBuffer}. * @param offset The byte offset into the input buffer at which the data starts. * @param numBytesOfClearData The number of leading unencrypted bytes in * each subSample. * @param numBytesOfEncryptedData The number of trailing encrypted bytes * in each subSample. * @param numSubSamples The number of subSamples that make up the * buffer's contents. * @param key A 16-byte opaque key * @param iv A 16-byte initialization vector * @param mode The type of encryption that has been applied * * Either numBytesOfClearData or numBytesOfEncryptedData (but not both) * can be null to indicate that all respective sizes are 0. * @param presentationTimeUs The time at which this buffer should be rendered. * @param flags A bitmask of flags {@link #FLAG_SYNCFRAME}, * {@link #FLAG_CODECCONFIG} or {@link #FLAG_EOS}. */ public native final void queueSecureInputBuffer( int index, int offset, int[] numBytesOfClearData, int[] numBytesOfEncryptedData, int numSubSamples, byte[] key, byte[] iv, int mode, CryptoInfo info, long presentationTimeUs, int flags); Loading
media/java/android/media/MediaExtractor.java +10 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.media; import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.media.MediaCodec; import android.net.Uri; import java.io.FileDescriptor; import java.io.IOException; Loading Loading @@ -235,6 +236,15 @@ final public class MediaExtractor { /** Returns the current sample's flags. */ public native int getSampleFlags(); /** If the sample flags indicate that the current sample is at least * partially encrypted, this call returns relevant information about * the structure of the sample data required for decryption. * @param info The android.media.MediaCodec.CryptoInfo structure * to be filled in. * @return true iff the sample flags contain {@link #SAMPLE_FLAG_ENCRYPTED} */ public native boolean getSampleCryptoInfo(MediaCodec.CryptoInfo info); private static native final void native_init(); private native final void native_setup(); private native final void native_finalize(); Loading
media/jni/android_media_MediaCodec.cpp +52 −7 Original line number Diff line number Diff line Loading @@ -49,6 +49,13 @@ enum { struct fields_t { jfieldID context; jfieldID cryptoInfoNumSubSamplesID; jfieldID cryptoInfoNumBytesOfClearDataID; jfieldID cryptoInfoNumBytesOfEncryptedDataID; jfieldID cryptoInfoKeyID; jfieldID cryptoInfoIVID; jfieldID cryptoInfoModeID; }; static fields_t gFields; Loading Loading @@ -387,12 +394,7 @@ static void android_media_MediaCodec_queueSecureInputBuffer( jobject thiz, jint index, jint offset, jintArray numBytesOfClearDataObj, jintArray numBytesOfEncryptedDataObj, jint numSubSamples, jbyteArray keyObj, jbyteArray ivObj, jint mode, jobject cryptoInfoObj, jlong timestampUs, jint flags) { ALOGV("android_media_MediaCodec_queueSecureInputBuffer"); Loading @@ -404,6 +406,25 @@ static void android_media_MediaCodec_queueSecureInputBuffer( return; } jint numSubSamples = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID); jintArray numBytesOfClearDataObj = (jintArray)env->GetObjectField( cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID); jintArray numBytesOfEncryptedDataObj = (jintArray)env->GetObjectField( cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID); jbyteArray keyObj = (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID); jbyteArray ivObj = (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID); jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID); status_t err = OK; CryptoPlugin::SubSample *subSamples = NULL; Loading Loading @@ -612,6 +633,30 @@ static void android_media_MediaCodec_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.cryptoInfoNumSubSamplesID = env->GetFieldID(clazz, "numSubSamples", "I"); CHECK(gFields.cryptoInfoNumSubSamplesID != NULL); gFields.cryptoInfoNumBytesOfClearDataID = env->GetFieldID(clazz, "numBytesOfClearData", "[I"); CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL); gFields.cryptoInfoNumBytesOfEncryptedDataID = env->GetFieldID(clazz, "numBytesOfEncryptedData", "[I"); CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL); gFields.cryptoInfoKeyID = env->GetFieldID(clazz, "key", "[B"); CHECK(gFields.cryptoInfoKeyID != NULL); gFields.cryptoInfoIVID = env->GetFieldID(clazz, "iv", "[B"); CHECK(gFields.cryptoInfoIVID != NULL); gFields.cryptoInfoModeID = env->GetFieldID(clazz, "mode", "I"); CHECK(gFields.cryptoInfoModeID != NULL); } static void android_media_MediaCodec_native_setup( Loading Loading @@ -666,7 +711,7 @@ static JNINativeMethod gMethods[] = { { "queueInputBuffer", "(IIIJI)V", (void *)android_media_MediaCodec_queueInputBuffer }, { "queueSecureInputBuffer", "(II[I[II[B[BIJI)V", { "queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V", (void *)android_media_MediaCodec_queueSecureInputBuffer }, { "dequeueInputBuffer", "(J)I", Loading
media/jni/android_media_MediaExtractor.cpp +142 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); Loading @@ -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(); } Loading Loading @@ -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", Loading