1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* Original code copied from NDK Native-media sample code */
18
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "NativeMedia"
21 #include <log/log.h>
22
23 #include <assert.h>
24 #include <jni.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 #include "media/NdkMediaExtractor.h"
30 #include "media/NdkMediaCrypto.h"
31 #include "media/NdkMediaDataSource.h"
32 #include "media/NdkMediaFormat.h"
33
Java_android_media_misc_cts_NativeDecoderTest_testFormatNative(JNIEnv *,jclass)34 extern "C" jboolean Java_android_media_misc_cts_NativeDecoderTest_testFormatNative(JNIEnv * /*env*/,
35 jclass /*clazz*/) {
36 AMediaFormat* format = AMediaFormat_new();
37 if (!format) {
38 return false;
39 }
40
41 AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, 8000);
42 int32_t bitrate = 0;
43 if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &bitrate) || bitrate != 8000) {
44 ALOGE("AMediaFormat_getInt32 fail: %d", bitrate);
45 return false;
46 }
47
48 AMediaFormat_setInt64(format, AMEDIAFORMAT_KEY_DURATION, 123456789123456789LL);
49 int64_t duration = 0;
50 if (!AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &duration)
51 || duration != 123456789123456789LL) {
52 ALOGE("AMediaFormat_getInt64 fail: %lld", (long long) duration);
53 return false;
54 }
55
56 AMediaFormat_setFloat(format, AMEDIAFORMAT_KEY_FRAME_RATE, 25.0f);
57 float framerate = 0.0f;
58 if (!AMediaFormat_getFloat(format, AMEDIAFORMAT_KEY_FRAME_RATE, &framerate)
59 || framerate != 25.0f) {
60 ALOGE("AMediaFormat_getFloat fail: %f", framerate);
61 return false;
62 }
63
64 const char* value = "audio/mpeg";
65 AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, value);
66 const char* readback = NULL;
67 if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &readback)
68 || strcmp(value, readback) || value == readback) {
69 ALOGE("AMediaFormat_getString fail");
70 return false;
71 }
72
73 uint32_t foo = 0xdeadbeef;
74 AMediaFormat_setBuffer(format, "csd-0", &foo, sizeof(foo));
75 foo = 0xabadcafe;
76 void *bytes;
77 size_t bytesize = 0;
78 if(!AMediaFormat_getBuffer(format, "csd-0", &bytes, &bytesize)
79 || bytesize != sizeof(foo) || *((uint32_t*)bytes) != 0xdeadbeef) {
80 ALOGE("AMediaFormat_getBuffer fail");
81 return false;
82 }
83
84 return true;
85 }
86
87
Java_android_media_misc_cts_NativeDecoderTest_testPsshNative(JNIEnv *,jclass,int fd,jlong offset,jlong size)88 extern "C" jboolean Java_android_media_misc_cts_NativeDecoderTest_testPsshNative(JNIEnv * /*env*/,
89 jclass /*clazz*/, int fd, jlong offset, jlong size) {
90
91 AMediaExtractor *ex = AMediaExtractor_new();
92 int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
93 if (err != 0) {
94 ALOGE("setDataSource error: %d", err);
95 return false;
96 }
97
98 PsshInfo* info = AMediaExtractor_getPsshInfo(ex);
99 if (info == NULL) {
100 ALOGI("null pssh");
101 return false;
102 }
103
104 ALOGI("pssh has %zd entries", info->numentries);
105 if (info->numentries != 2) {
106 return false;
107 }
108
109 for (size_t i = 0; i < info->numentries; i++) {
110 PsshEntry *entry = &info->entries[i];
111 ALOGI("entry uuid %02x%02x..%02x%02x, data size %zd",
112 entry->uuid[0],
113 entry->uuid[1],
114 entry->uuid[14],
115 entry->uuid[15],
116 entry->datalen);
117
118 AMediaCrypto *crypto = AMediaCrypto_new(entry->uuid, entry->data, entry->datalen);
119 if (crypto) {
120 ALOGI("got crypto");
121 AMediaCrypto_delete(crypto);
122 } else {
123 ALOGI("no crypto");
124 }
125 }
126 return true;
127 }
128
Java_android_media_misc_cts_NativeDecoderTest_testCryptoInfoNative(JNIEnv *,jclass)129 extern "C" jboolean Java_android_media_misc_cts_NativeDecoderTest_testCryptoInfoNative(JNIEnv * /*env*/,
130 jclass /*clazz*/) {
131
132 size_t numsubsamples = 4;
133 uint8_t key[16] = { 1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4 };
134 uint8_t iv[16] = { 4,3,2,1,4,3,2,1,4,3,2,1,4,3,2,1 };
135 size_t clearbytes[4] = { 5, 6, 7, 8 };
136 size_t encryptedbytes[4] = { 8, 7, 6, 5 };
137
138 AMediaCodecCryptoInfo *ci =
139 AMediaCodecCryptoInfo_new(numsubsamples, key, iv, AMEDIACODECRYPTOINFO_MODE_CLEAR, clearbytes, encryptedbytes);
140
141 if (AMediaCodecCryptoInfo_getNumSubSamples(ci) != 4) {
142 ALOGE("numsubsamples mismatch");
143 return false;
144 }
145 uint8_t bytes[16];
146 AMediaCodecCryptoInfo_getKey(ci, bytes);
147 if (memcmp(key, bytes, 16) != 0) {
148 ALOGE("key mismatch");
149 return false;
150 }
151 AMediaCodecCryptoInfo_getIV(ci, bytes);
152 if (memcmp(iv, bytes, 16) != 0) {
153 ALOGE("IV mismatch");
154 return false;
155 }
156 if (AMediaCodecCryptoInfo_getMode(ci) != AMEDIACODECRYPTOINFO_MODE_CLEAR) {
157 ALOGE("mode mismatch");
158 return false;
159 }
160 size_t sizes[numsubsamples];
161 AMediaCodecCryptoInfo_getClearBytes(ci, sizes);
162 if (memcmp(clearbytes, sizes, sizeof(size_t) * numsubsamples)) {
163 ALOGE("clear size mismatch");
164 return false;
165 }
166 AMediaCodecCryptoInfo_getEncryptedBytes(ci, sizes);
167 if (memcmp(encryptedbytes, sizes, sizeof(size_t) * numsubsamples)) {
168 ALOGE("encrypted size mismatch");
169 return false;
170 }
171 return true;
172 }
173
Java_android_media_misc_cts_NativeDecoderTest_createAMediaExtractor(JNIEnv *,jclass)174 extern "C" jlong Java_android_media_misc_cts_NativeDecoderTest_createAMediaExtractor(JNIEnv * /*env*/,
175 jclass /*clazz*/) {
176 AMediaExtractor *ex = AMediaExtractor_new();
177 return reinterpret_cast<jlong>(ex);
178 }
179
Java_android_media_misc_cts_NativeDecoderTest_createAMediaDataSource(JNIEnv * env,jclass,jstring jurl)180 extern "C" jlong Java_android_media_misc_cts_NativeDecoderTest_createAMediaDataSource(JNIEnv * env,
181 jclass /*clazz*/, jstring jurl) {
182 const char *url = env->GetStringUTFChars(jurl, NULL);
183 if (url == NULL) {
184 ALOGE("GetStringUTFChars error");
185 return 0;
186 }
187
188 AMediaDataSource *ds = AMediaDataSource_newUri(url, 0, NULL);
189 env->ReleaseStringUTFChars(jurl, url);
190 return reinterpret_cast<jlong>(ds);
191 }
192
Java_android_media_misc_cts_NativeDecoderTest_setAMediaExtractorDataSource(JNIEnv *,jclass,jlong jex,jlong jds)193 extern "C" jint Java_android_media_misc_cts_NativeDecoderTest_setAMediaExtractorDataSource(JNIEnv * /*env*/,
194 jclass /*clazz*/, jlong jex, jlong jds) {
195 AMediaExtractor *ex = reinterpret_cast<AMediaExtractor *>(jex);
196 AMediaDataSource *ds = reinterpret_cast<AMediaDataSource *>(jds);
197 return AMediaExtractor_setDataSourceCustom(ex, ds);
198 }
199
Java_android_media_misc_cts_NativeDecoderTest_closeAMediaDataSource(JNIEnv *,jclass,jlong ds)200 extern "C" void Java_android_media_misc_cts_NativeDecoderTest_closeAMediaDataSource(
201 JNIEnv * /*env*/, jclass /*clazz*/, jlong ds) {
202 AMediaDataSource_close(reinterpret_cast<AMediaDataSource *>(ds));
203 }
204
Java_android_media_misc_cts_NativeDecoderTest_deleteAMediaExtractor(JNIEnv *,jclass,jlong ex)205 extern "C" void Java_android_media_misc_cts_NativeDecoderTest_deleteAMediaExtractor(
206 JNIEnv * /*env*/, jclass /*clazz*/, jlong ex) {
207 AMediaExtractor_delete(reinterpret_cast<AMediaExtractor *>(ex));
208 }
209
Java_android_media_misc_cts_NativeDecoderTest_deleteAMediaDataSource(JNIEnv *,jclass,jlong ds)210 extern "C" void Java_android_media_misc_cts_NativeDecoderTest_deleteAMediaDataSource(
211 JNIEnv * /*env*/, jclass /*clazz*/, jlong ds) {
212 AMediaDataSource_delete(reinterpret_cast<AMediaDataSource *>(ds));
213 }
214
Java_android_media_misc_cts_NativeDecoderTest_testMediaFormatNative(JNIEnv *,jclass)215 extern "C" jboolean Java_android_media_misc_cts_NativeDecoderTest_testMediaFormatNative(
216 JNIEnv * /*env*/, jclass /*clazz*/) {
217
218 AMediaFormat *original = AMediaFormat_new();
219 AMediaFormat *copy = AMediaFormat_new();
220 jboolean ret = false;
221 while (true) {
222 AMediaFormat_setInt64(original, AMEDIAFORMAT_KEY_DURATION, 1234ll);
223 int64_t value = 0;
224 if (!AMediaFormat_getInt64(original, AMEDIAFORMAT_KEY_DURATION, &value) || value != 1234) {
225 ALOGE("format missing expected entry");
226 break;
227 }
228 AMediaFormat_copy(copy, original);
229 value = 0;
230 if (!AMediaFormat_getInt64(copy, AMEDIAFORMAT_KEY_DURATION, &value) || value != 1234) {
231 ALOGE("copied format missing expected entry");
232 break;
233 }
234 AMediaFormat_clear(original);
235 if (AMediaFormat_getInt64(original, AMEDIAFORMAT_KEY_DURATION, &value)) {
236 ALOGE("format still has entry after clear");
237 break;
238 }
239 value = 0;
240 if (!AMediaFormat_getInt64(copy, AMEDIAFORMAT_KEY_DURATION, &value) || value != 1234) {
241 ALOGE("copied format missing expected entry");
242 break;
243 }
244 ret = true;
245 break;
246 }
247 AMediaFormat_delete(original);
248 AMediaFormat_delete(copy);
249 return ret;
250 }
251