Skip to content

Commit a3bd242

Browse files
theandi666Android (Google) Code Review
authored andcommitted
Merge "New JAVA API to support submitting encrypted buffers of input data."
2 parents 85d9e02 + 9e6bcce commit a3bd242

File tree

3 files changed

+186
-1
lines changed

3 files changed

+186
-1
lines changed

media/java/android/media/MediaCodec.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,16 @@ public void set(
4545
public int mFlags;
4646
};
4747

48+
// The follow flag constants MUST stay in sync with their equivalents
49+
// in MediaCodec.h !
4850
public static int FLAG_SYNCFRAME = 1;
4951
public static int FLAG_CODECCONFIG = 2;
5052
public static int FLAG_EOS = 4;
51-
public static int FLAG_ENCRYPTED = 8;
53+
54+
// The following mode constants MUST stay in sync with their equivalents
55+
// in media/hardware/CryptoAPI.h !
56+
public static int MODE_UNENCRYPTED = 0;
57+
public static int MODE_AES_CTR = 1;
5258

5359
/** Instantiate a codec component by mime type. For decoder components
5460
this is the mime type of media that this decoder should be able to
@@ -176,6 +182,36 @@ public native final void queueInputBuffer(
176182
int index,
177183
int offset, int size, long presentationTimeUs, int flags);
178184

185+
/** Similar to {@link queueInputBuffer} but submits a buffer that is
186+
* potentially encrypted. The buffer's data is considered to be
187+
* partitioned into "subSamples", each subSample starts with a
188+
* (potentially empty) run of plain, unencrypted bytes followed
189+
* by a (also potentially empty) run of encrypted bytes.
190+
* @param numBytesOfClearData The number of leading unencrypted bytes in
191+
* each subSample.
192+
* @param numBytesOfEncryptedData The number of trailing encrypted bytes
193+
* in each subSample.
194+
* @param numSubSamples The number of subSamples that make up the
195+
* buffer's contents.
196+
* @param key A 16-byte opaque key
197+
* @param iv A 16-byte initialization vector
198+
* @param mode The type of encryption that has been applied
199+
*
200+
* Either numBytesOfClearData or numBytesOfEncryptedData (but not both)
201+
* can be null to indicate that all respective sizes are 0.
202+
*/
203+
public native final void queueSecureInputBuffer(
204+
int index,
205+
int offset,
206+
int[] numBytesOfClearData,
207+
int[] numBytesOfEncryptedData,
208+
int numSubSamples,
209+
byte[] key,
210+
byte[] iv,
211+
int mode,
212+
long presentationTimeUs,
213+
int flags);
214+
179215
// Returns the index of an input buffer to be filled with valid data
180216
// or -1 if no such buffer is currently available.
181217
// This method will return immediately if timeoutUs == 0, wait indefinitely

media/jni/android_media_MediaCodec.cpp

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,21 @@ status_t JMediaCodec::queueInputBuffer(
126126
return mCodec->queueInputBuffer(index, offset, size, timeUs, flags);
127127
}
128128

129+
status_t JMediaCodec::queueSecureInputBuffer(
130+
size_t index,
131+
size_t offset,
132+
const CryptoPlugin::SubSample *subSamples,
133+
size_t numSubSamples,
134+
const uint8_t key[16],
135+
const uint8_t iv[16],
136+
CryptoPlugin::Mode mode,
137+
int64_t presentationTimeUs,
138+
uint32_t flags) {
139+
return mCodec->queueSecureInputBuffer(
140+
index, offset, subSamples, numSubSamples, key, iv, mode,
141+
presentationTimeUs, flags);
142+
}
143+
129144
status_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
130145
return mCodec->dequeueInputBuffer(index, timeoutUs);
131146
}
@@ -367,6 +382,125 @@ static void android_media_MediaCodec_queueInputBuffer(
367382
throwExceptionAsNecessary(env, err);
368383
}
369384

385+
static void android_media_MediaCodec_queueSecureInputBuffer(
386+
JNIEnv *env,
387+
jobject thiz,
388+
jint index,
389+
jint offset,
390+
jintArray numBytesOfClearDataObj,
391+
jintArray numBytesOfEncryptedDataObj,
392+
jint numSubSamples,
393+
jbyteArray keyObj,
394+
jbyteArray ivObj,
395+
jint mode,
396+
jlong timestampUs,
397+
jint flags) {
398+
ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
399+
400+
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
401+
402+
if (codec == NULL) {
403+
jniThrowException(env, "java/lang/IllegalStateException", NULL);
404+
return;
405+
}
406+
407+
status_t err = OK;
408+
409+
CryptoPlugin::SubSample *subSamples = NULL;
410+
jbyte *key = NULL;
411+
jbyte *iv = NULL;
412+
413+
if (numSubSamples <= 0) {
414+
err = -EINVAL;
415+
} else if (numBytesOfClearDataObj == NULL
416+
&& numBytesOfEncryptedDataObj == NULL) {
417+
err = -EINVAL;
418+
} else if (numBytesOfEncryptedDataObj != NULL
419+
&& env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
420+
err = -ERANGE;
421+
} else if (numBytesOfClearDataObj != NULL
422+
&& env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
423+
err = -ERANGE;
424+
} else {
425+
jboolean isCopy;
426+
427+
jint *numBytesOfClearData =
428+
(numBytesOfClearDataObj == NULL)
429+
? NULL
430+
: env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
431+
432+
jint *numBytesOfEncryptedData =
433+
(numBytesOfEncryptedDataObj == NULL)
434+
? NULL
435+
: env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
436+
437+
subSamples = new CryptoPlugin::SubSample[numSubSamples];
438+
439+
for (jint i = 0; i < numSubSamples; ++i) {
440+
subSamples[i].mNumBytesOfClearData =
441+
(numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
442+
443+
subSamples[i].mNumBytesOfEncryptedData =
444+
(numBytesOfEncryptedData == NULL)
445+
? 0 : numBytesOfEncryptedData[i];
446+
}
447+
448+
if (numBytesOfEncryptedData != NULL) {
449+
env->ReleaseIntArrayElements(
450+
numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
451+
numBytesOfEncryptedData = NULL;
452+
}
453+
454+
if (numBytesOfClearData != NULL) {
455+
env->ReleaseIntArrayElements(
456+
numBytesOfClearDataObj, numBytesOfClearData, 0);
457+
numBytesOfClearData = NULL;
458+
}
459+
}
460+
461+
if (err == OK && keyObj != NULL) {
462+
if (env->GetArrayLength(keyObj) != 16) {
463+
err = -EINVAL;
464+
} else {
465+
jboolean isCopy;
466+
key = env->GetByteArrayElements(keyObj, &isCopy);
467+
}
468+
}
469+
470+
if (err == OK && ivObj != NULL) {
471+
if (env->GetArrayLength(ivObj) != 16) {
472+
err = -EINVAL;
473+
} else {
474+
jboolean isCopy;
475+
iv = env->GetByteArrayElements(ivObj, &isCopy);
476+
}
477+
}
478+
479+
if (err == OK) {
480+
err = codec->queueSecureInputBuffer(
481+
index, offset,
482+
subSamples, numSubSamples,
483+
(const uint8_t *)key, (const uint8_t *)iv,
484+
(CryptoPlugin::Mode)mode,
485+
timestampUs, flags);
486+
}
487+
488+
if (iv != NULL) {
489+
env->ReleaseByteArrayElements(ivObj, iv, 0);
490+
iv = NULL;
491+
}
492+
493+
if (key != NULL) {
494+
env->ReleaseByteArrayElements(keyObj, key, 0);
495+
key = NULL;
496+
}
497+
498+
delete[] subSamples;
499+
subSamples = NULL;
500+
501+
throwExceptionAsNecessary(env, err);
502+
}
503+
370504
static jint android_media_MediaCodec_dequeueInputBuffer(
371505
JNIEnv *env, jobject thiz, jlong timeoutUs) {
372506
ALOGV("android_media_MediaCodec_dequeueInputBuffer");
@@ -532,6 +666,9 @@ static JNINativeMethod gMethods[] = {
532666
{ "queueInputBuffer", "(IIIJI)V",
533667
(void *)android_media_MediaCodec_queueInputBuffer },
534668

669+
{ "queueSecureInputBuffer", "(II[I[II[B[BIJI)V",
670+
(void *)android_media_MediaCodec_queueSecureInputBuffer },
671+
535672
{ "dequeueInputBuffer", "(J)I",
536673
(void *)android_media_MediaCodec_dequeueInputBuffer },
537674

media/jni/android_media_MediaCodec.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "jni.h"
2121

22+
#include <media/hardware/CryptoAPI.h>
2223
#include <media/stagefright/foundation/ABase.h>
2324
#include <utils/Errors.h>
2425
#include <utils/RefBase.h>
@@ -53,6 +54,17 @@ struct JMediaCodec : public RefBase {
5354
size_t index,
5455
size_t offset, size_t size, int64_t timeUs, uint32_t flags);
5556

57+
status_t queueSecureInputBuffer(
58+
size_t index,
59+
size_t offset,
60+
const CryptoPlugin::SubSample *subSamples,
61+
size_t numSubSamples,
62+
const uint8_t key[16],
63+
const uint8_t iv[16],
64+
CryptoPlugin::Mode mode,
65+
int64_t presentationTimeUs,
66+
uint32_t flags);
67+
5668
status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs);
5769

5870
status_t dequeueOutputBuffer(

0 commit comments

Comments
 (0)