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 TAG "NativeMedia" 21 #include <log/log.h> 22 23 #include <assert.h> 24 #include <jni.h> 25 #include <pthread.h> 26 #include <stdio.h> 27 #include <string.h> 28 #include <unistd.h> 29 #include <semaphore.h> 30 31 #include <android/native_window_jni.h> 32 33 #include "media/NdkMediaExtractor.h" 34 #include "media/NdkMediaCodec.h" 35 #include "media/NdkMediaCrypto.h" 36 #include "media/NdkMediaFormat.h" 37 #include "media/NdkMediaMuxer.h" 38 39 template <class T> 40 class simplevector { 41 T *storage; 42 int capacity; 43 int numfilled; 44 public: 45 simplevector() { 46 capacity = 16; 47 numfilled = 0; 48 storage = new T[capacity]; 49 } 50 ~simplevector() { 51 delete[] storage; 52 } 53 54 void add(T item) { 55 if (numfilled == capacity) { 56 T *old = storage; 57 capacity *= 2; 58 storage = new T[capacity]; 59 for (int i = 0; i < numfilled; i++) { 60 storage[i] = old[i]; 61 } 62 delete[] old; 63 } 64 storage[numfilled] = item; 65 numfilled++; 66 } 67 68 int size() { 69 return numfilled; 70 } 71 72 T* data() { 73 return storage; 74 } 75 }; 76 77 78 79 jobject testExtractor(AMediaExtractor *ex, JNIEnv *env) { 80 81 simplevector<int> sizes; 82 int numtracks = AMediaExtractor_getTrackCount(ex); 83 sizes.add(numtracks); 84 for (int i = 0; i < numtracks; i++) { 85 AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i); 86 const char *s = AMediaFormat_toString(format); 87 ALOGI("track %d format: %s", i, s); 88 const char *mime; 89 if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) { 90 ALOGE("no mime type"); 91 return NULL; 92 } else if (!strncmp(mime, "audio/", 6)) { 93 sizes.add(0); 94 int32_t val32; 95 int64_t val64; 96 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &val32); 97 sizes.add(val32); 98 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &val32); 99 sizes.add(val32); 100 AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &val64); 101 sizes.add(val64); 102 } else if (!strncmp(mime, "video/", 6)) { 103 sizes.add(1); 104 int32_t val32; 105 int64_t val64; 106 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &val32); 107 sizes.add(val32); 108 AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &val32); 109 sizes.add(val32); 110 AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &val64); 111 sizes.add(val64); 112 } else { 113 ALOGE("expected audio or video mime type, got %s", mime); 114 } 115 AMediaFormat_delete(format); 116 AMediaExtractor_selectTrack(ex, i); 117 } 118 int bufsize = 1024*1024; 119 uint8_t *buf = new uint8_t[bufsize]; 120 while(true) { 121 int n = AMediaExtractor_readSampleData(ex, buf, bufsize); 122 if (n < 0) { 123 break; 124 } 125 sizes.add(n); 126 sizes.add(AMediaExtractor_getSampleTrackIndex(ex)); 127 sizes.add(AMediaExtractor_getSampleFlags(ex)); 128 sizes.add(AMediaExtractor_getSampleTime(ex)); 129 AMediaExtractor_advance(ex); 130 } 131 132 // allocate java int array for result and return it 133 int *data = sizes.data(); 134 int numsamples = sizes.size(); 135 jintArray ret = env->NewIntArray(numsamples); 136 jboolean isCopy; 137 jint *dst = env->GetIntArrayElements(ret, &isCopy); 138 for (int i = 0; i < numsamples; ++i) { 139 dst[i] = data[i]; 140 } 141 env->ReleaseIntArrayElements(ret, dst, 0); 142 143 delete[] buf; 144 AMediaExtractor_delete(ex); 145 return ret; 146 } 147 148 149 // get the sample sizes for the file 150 extern "C" jobject Java_android_media_cts_NativeDecoderTest_getSampleSizesNative(JNIEnv *env, 151 jclass /*clazz*/, int fd, jlong offset, jlong size) 152 { 153 AMediaExtractor *ex = AMediaExtractor_new(); 154 int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size); 155 if (err != 0) { 156 ALOGE("setDataSource error: %d", err); 157 return NULL; 158 } 159 return testExtractor(ex, env); 160 } 161 162 // get the sample sizes for the path 163 extern "C" jobject Java_android_media_cts_NativeDecoderTest_getSampleSizesNativePath(JNIEnv *env, 164 jclass /*clazz*/, jstring jpath) 165 { 166 AMediaExtractor *ex = AMediaExtractor_new(); 167 168 const char *tmp = env->GetStringUTFChars(jpath, NULL); 169 if (tmp == NULL) { // Out of memory 170 return NULL; 171 } 172 173 int err = AMediaExtractor_setDataSource(ex, tmp); 174 175 env->ReleaseStringUTFChars(jpath, tmp); 176 177 if (err != 0) { 178 ALOGE("setDataSource error: %d", err); 179 return NULL; 180 } 181 return testExtractor(ex, env); 182 } 183 184 static int adler32(const uint8_t *input, int len) { 185 186 int a = 1; 187 int b = 0; 188 for (int i = 0; i < len; i++) { 189 a += input[i]; 190 b += a; 191 } 192 a = a % 65521; 193 b = b % 65521; 194 int ret = b * 65536 + a; 195 ALOGV("adler %d/%d", len, ret); 196 return ret; 197 } 198 199 static int checksum(const uint8_t *in, int len, AMediaFormat *format) { 200 int width, stride, height; 201 if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width)) { 202 width = len; 203 } 204 if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_STRIDE, &stride)) { 205 stride = width; 206 } 207 if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height)) { 208 height = 1; 209 } 210 uint8_t *bb = new uint8_t[width * height]; 211 for (int i = 0; i < height; i++) { 212 memcpy(bb + i * width, in + i * stride, width); 213 } 214 // bb is filled with data 215 int sum = adler32(bb, width * height); 216 delete[] bb; 217 return sum; 218 } 219 220 extern "C" jobject Java_android_media_cts_NativeDecoderTest_getDecodedDataNative(JNIEnv *env, 221 jclass /*clazz*/, int fd, jlong offset, jlong size) { 222 ALOGV("getDecodedDataNative"); 223 224 AMediaExtractor *ex = AMediaExtractor_new(); 225 int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size); 226 if (err != 0) { 227 ALOGE("setDataSource error: %d", err); 228 return NULL; 229 } 230 231 int numtracks = AMediaExtractor_getTrackCount(ex); 232 233 AMediaCodec **codec = new AMediaCodec*[numtracks]; 234 AMediaFormat **format = new AMediaFormat*[numtracks]; 235 bool *sawInputEOS = new bool[numtracks]; 236 bool *sawOutputEOS = new bool[numtracks]; 237 simplevector<int> *sizes = new simplevector<int>[numtracks]; 238 239 ALOGV("input has %d tracks", numtracks); 240 for (int i = 0; i < numtracks; i++) { 241 AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i); 242 const char *s = AMediaFormat_toString(format); 243 ALOGI("track %d format: %s", i, s); 244 const char *mime; 245 if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) { 246 ALOGE("no mime type"); 247 return NULL; 248 } else if (!strncmp(mime, "audio/", 6) || !strncmp(mime, "video/", 6)) { 249 codec[i] = AMediaCodec_createDecoderByType(mime); 250 AMediaCodec_configure(codec[i], format, NULL /* surface */, NULL /* crypto */, 0); 251 AMediaCodec_start(codec[i]); 252 sawInputEOS[i] = false; 253 sawOutputEOS[i] = false; 254 } else { 255 ALOGE("expected audio or video mime type, got %s", mime); 256 return NULL; 257 } 258 AMediaFormat_delete(format); 259 AMediaExtractor_selectTrack(ex, i); 260 } 261 int eosCount = 0; 262 while(eosCount < numtracks) { 263 int t = AMediaExtractor_getSampleTrackIndex(ex); 264 if (t >=0) { 265 ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec[t], 5000); 266 ALOGV("track %d, input buffer %zd", t, bufidx); 267 if (bufidx >= 0) { 268 size_t bufsize; 269 uint8_t *buf = AMediaCodec_getInputBuffer(codec[t], bufidx, &bufsize); 270 int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize); 271 ALOGV("read %d", sampleSize); 272 if (sampleSize < 0) { 273 sampleSize = 0; 274 sawInputEOS[t] = true; 275 ALOGV("EOS"); 276 //break; 277 } 278 int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex); 279 280 AMediaCodec_queueInputBuffer(codec[t], bufidx, 0, sampleSize, presentationTimeUs, 281 sawInputEOS[t] ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0); 282 AMediaExtractor_advance(ex); 283 } 284 } else { 285 ALOGV("@@@@ no more input samples"); 286 for (int tt = 0; tt < numtracks; tt++) { 287 if (!sawInputEOS[tt]) { 288 // we ran out of samples without ever signaling EOS to the codec, 289 // so do that now 290 int bufidx = AMediaCodec_dequeueInputBuffer(codec[tt], 5000); 291 if (bufidx >= 0) { 292 AMediaCodec_queueInputBuffer(codec[tt], bufidx, 0, 0, 0, 293 AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM); 294 sawInputEOS[tt] = true; 295 } 296 } 297 } 298 } 299 300 // check all codecs for available data 301 AMediaCodecBufferInfo info; 302 for (int tt = 0; tt < numtracks; tt++) { 303 if (!sawOutputEOS[tt]) { 304 int status = AMediaCodec_dequeueOutputBuffer(codec[tt], &info, 1); 305 ALOGV("dequeueoutput on track %d: %d", tt, status); 306 if (status >= 0) { 307 if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) { 308 ALOGV("EOS on track %d", tt); 309 sawOutputEOS[tt] = true; 310 eosCount++; 311 } 312 ALOGV("got decoded buffer for track %d, size %d", tt, info.size); 313 if (info.size > 0) { 314 size_t bufsize; 315 uint8_t *buf = AMediaCodec_getOutputBuffer(codec[tt], status, &bufsize); 316 int adler = checksum(buf, info.size, format[tt]); 317 sizes[tt].add(adler); 318 } 319 AMediaCodec_releaseOutputBuffer(codec[tt], status, false); 320 } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) { 321 ALOGV("output buffers changed for track %d", tt); 322 } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) { 323 format[tt] = AMediaCodec_getOutputFormat(codec[tt]); 324 ALOGV("format changed for track %d: %s", tt, AMediaFormat_toString(format[tt])); 325 } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) { 326 ALOGV("no output buffer right now for track %d", tt); 327 } else { 328 ALOGV("unexpected info code for track %d : %d", tt, status); 329 } 330 } else { 331 ALOGV("already at EOS on track %d", tt); 332 } 333 } 334 } 335 ALOGV("decoding loop done"); 336 337 // allocate java int array for result and return it 338 int numsamples = 0; 339 for (int i = 0; i < numtracks; i++) { 340 numsamples += sizes[i].size(); 341 } 342 ALOGV("checksums: %d", numsamples); 343 jintArray ret = env->NewIntArray(numsamples); 344 jboolean isCopy; 345 jint *org = env->GetIntArrayElements(ret, &isCopy); 346 jint *dst = org; 347 for (int i = 0; i < numtracks; i++) { 348 int *data = sizes[i].data(); 349 int len = sizes[i].size(); 350 ALOGV("copying %d", len); 351 for (int j = 0; j < len; j++) { 352 *dst++ = data[j]; 353 } 354 } 355 env->ReleaseIntArrayElements(ret, org, 0); 356 357 delete[] sizes; 358 delete[] sawOutputEOS; 359 delete[] sawInputEOS; 360 for (int i = 0; i < numtracks; i++) { 361 AMediaFormat_delete(format[i]); 362 AMediaCodec_stop(codec[i]); 363 AMediaCodec_delete(codec[i]); 364 } 365 delete[] format; 366 delete[] codec; 367 AMediaExtractor_delete(ex); 368 return ret; 369 } 370 371 extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testPlaybackNative(JNIEnv *env, 372 jclass /*clazz*/, jobject surface, int fd, jlong offset, jlong size) { 373 374 ANativeWindow *window = ANativeWindow_fromSurface(env, surface); 375 ALOGI("@@@@ native window: %p", window); 376 377 AMediaExtractor *ex = AMediaExtractor_new(); 378 int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size); 379 if (err != 0) { 380 ALOGE("setDataSource error: %d", err); 381 return false; 382 } 383 384 int numtracks = AMediaExtractor_getTrackCount(ex); 385 386 AMediaCodec *codec = NULL; 387 AMediaFormat *format = NULL; 388 bool sawInputEOS = false; 389 bool sawOutputEOS = false; 390 391 ALOGV("input has %d tracks", numtracks); 392 for (int i = 0; i < numtracks; i++) { 393 AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i); 394 const char *s = AMediaFormat_toString(format); 395 ALOGI("track %d format: %s", i, s); 396 const char *mime; 397 if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) { 398 ALOGE("no mime type"); 399 return false; 400 } else if (!strncmp(mime, "video/", 6)) { 401 codec = AMediaCodec_createDecoderByType(mime); 402 AMediaCodec_configure(codec, format, window, NULL, 0); 403 AMediaCodec_start(codec); 404 AMediaExtractor_selectTrack(ex, i); 405 } 406 AMediaFormat_delete(format); 407 } 408 409 while (!sawOutputEOS) { 410 ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec, 5000); 411 ALOGV("input buffer %zd", bufidx); 412 if (bufidx >= 0) { 413 size_t bufsize; 414 uint8_t *buf = AMediaCodec_getInputBuffer(codec, bufidx, &bufsize); 415 int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize); 416 ALOGV("read %d", sampleSize); 417 if (sampleSize < 0) { 418 sampleSize = 0; 419 sawInputEOS = true; 420 ALOGV("EOS"); 421 } 422 int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex); 423 424 AMediaCodec_queueInputBuffer(codec, bufidx, 0, sampleSize, presentationTimeUs, 425 sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0); 426 AMediaExtractor_advance(ex); 427 } 428 429 AMediaCodecBufferInfo info; 430 int status = AMediaCodec_dequeueOutputBuffer(codec, &info, 1); 431 ALOGV("dequeueoutput returned: %d", status); 432 if (status >= 0) { 433 if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) { 434 ALOGV("output EOS"); 435 sawOutputEOS = true; 436 } 437 ALOGV("got decoded buffer size %d", info.size); 438 AMediaCodec_releaseOutputBuffer(codec, status, true); 439 usleep(20000); 440 } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) { 441 ALOGV("output buffers changed"); 442 } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) { 443 format = AMediaCodec_getOutputFormat(codec); 444 ALOGV("format changed to: %s", AMediaFormat_toString(format)); 445 } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) { 446 ALOGV("no output buffer right now"); 447 } else { 448 ALOGV("unexpected info code: %d", status); 449 } 450 } 451 452 AMediaCodec_stop(codec); 453 AMediaCodec_delete(codec); 454 AMediaExtractor_delete(ex); 455 return true; 456 } 457 458 extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testMuxerNative(JNIEnv */*env*/, 459 jclass /*clazz*/, int infd, jlong inoffset, jlong insize, int outfd, jboolean webm) { 460 461 462 AMediaMuxer *muxer = AMediaMuxer_new(outfd, 463 webm ? AMEDIAMUXER_OUTPUT_FORMAT_WEBM : AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4); 464 465 AMediaExtractor *ex = AMediaExtractor_new(); 466 int err = AMediaExtractor_setDataSourceFd(ex, infd, inoffset, insize); 467 if (err != 0) { 468 ALOGE("setDataSource error: %d", err); 469 return false; 470 } 471 472 int numtracks = AMediaExtractor_getTrackCount(ex); 473 ALOGI("input tracks: %d", numtracks); 474 for (int i = 0; i < numtracks; i++) { 475 AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i); 476 const char *s = AMediaFormat_toString(format); 477 ALOGI("track %d format: %s", i, s); 478 const char *mime; 479 if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) { 480 ALOGE("no mime type"); 481 return false; 482 } else if (!strncmp(mime, "audio/", 6) || !strncmp(mime, "video/", 6)) { 483 ssize_t tidx = AMediaMuxer_addTrack(muxer, format); 484 ALOGI("track %d -> %zd format %s", i, tidx, s); 485 AMediaExtractor_selectTrack(ex, i); 486 } else { 487 ALOGE("expected audio or video mime type, got %s", mime); 488 return false; 489 } 490 AMediaFormat_delete(format); 491 AMediaExtractor_selectTrack(ex, i); 492 } 493 AMediaMuxer_start(muxer); 494 495 int bufsize = 1024*1024; 496 uint8_t *buf = new uint8_t[bufsize]; 497 AMediaCodecBufferInfo info; 498 while(true) { 499 int n = AMediaExtractor_readSampleData(ex, buf, bufsize); 500 if (n < 0) { 501 break; 502 } 503 info.offset = 0; 504 info.size = n; 505 info.presentationTimeUs = AMediaExtractor_getSampleTime(ex); 506 info.flags = AMediaExtractor_getSampleFlags(ex); 507 508 size_t idx = (size_t) AMediaExtractor_getSampleTrackIndex(ex); 509 AMediaMuxer_writeSampleData(muxer, idx, buf, &info); 510 511 AMediaExtractor_advance(ex); 512 } 513 514 AMediaExtractor_delete(ex); 515 AMediaMuxer_stop(muxer); 516 AMediaMuxer_delete(muxer); 517 return true; 518 519 } 520 521 extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testFormatNative(JNIEnv * /*env*/, 522 jclass /*clazz*/) { 523 AMediaFormat* format = AMediaFormat_new(); 524 if (!format) { 525 return false; 526 } 527 528 AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, 8000); 529 int32_t bitrate = 0; 530 if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &bitrate) || bitrate != 8000) { 531 ALOGE("AMediaFormat_getInt32 fail: %d", bitrate); 532 return false; 533 } 534 535 AMediaFormat_setInt64(format, AMEDIAFORMAT_KEY_DURATION, 123456789123456789ll); 536 int64_t duration = 0; 537 if (!AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &duration) 538 || duration != 123456789123456789ll) { 539 ALOGE("AMediaFormat_getInt64 fail: %lld", (long long) duration); 540 return false; 541 } 542 543 AMediaFormat_setFloat(format, AMEDIAFORMAT_KEY_FRAME_RATE, 25.0f); 544 float framerate = 0.0f; 545 if (!AMediaFormat_getFloat(format, AMEDIAFORMAT_KEY_FRAME_RATE, &framerate) 546 || framerate != 25.0f) { 547 ALOGE("AMediaFormat_getFloat fail: %f", framerate); 548 return false; 549 } 550 551 const char* value = "audio/mpeg"; 552 AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, value); 553 const char* readback = NULL; 554 if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &readback) 555 || strcmp(value, readback) || value == readback) { 556 ALOGE("AMediaFormat_getString fail"); 557 return false; 558 } 559 560 uint32_t foo = 0xdeadbeef; 561 AMediaFormat_setBuffer(format, "csd-0", &foo, sizeof(foo)); 562 foo = 0xabadcafe; 563 void *bytes; 564 size_t bytesize = 0; 565 if(!AMediaFormat_getBuffer(format, "csd-0", &bytes, &bytesize) 566 || bytesize != sizeof(foo) || *((uint32_t*)bytes) != 0xdeadbeef) { 567 ALOGE("AMediaFormat_getBuffer fail"); 568 return false; 569 } 570 571 return true; 572 } 573 574 575 extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testPsshNative(JNIEnv * /*env*/, 576 jclass /*clazz*/, int fd, jlong offset, jlong size) { 577 578 AMediaExtractor *ex = AMediaExtractor_new(); 579 int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size); 580 if (err != 0) { 581 ALOGE("setDataSource error: %d", err); 582 return false; 583 } 584 585 PsshInfo* info = AMediaExtractor_getPsshInfo(ex); 586 if (info == NULL) { 587 ALOGI("null pssh"); 588 return false; 589 } 590 591 ALOGI("pssh has %zd entries", info->numentries); 592 if (info->numentries != 2) { 593 return false; 594 } 595 596 for (size_t i = 0; i < info->numentries; i++) { 597 PsshEntry *entry = &info->entries[i]; 598 ALOGI("entry uuid %02x%02x..%02x%02x, data size %zd", 599 entry->uuid[0], 600 entry->uuid[1], 601 entry->uuid[14], 602 entry->uuid[15], 603 entry->datalen); 604 605 AMediaCrypto *crypto = AMediaCrypto_new(entry->uuid, entry->data, entry->datalen); 606 if (crypto) { 607 ALOGI("got crypto"); 608 AMediaCrypto_delete(crypto); 609 } else { 610 ALOGI("no crypto"); 611 } 612 } 613 return true; 614 } 615 616 extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testCryptoInfoNative(JNIEnv * /*env*/, 617 jclass /*clazz*/) { 618 619 size_t numsubsamples = 4; 620 uint8_t key[16] = { 1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4 }; 621 uint8_t iv[16] = { 4,3,2,1,4,3,2,1,4,3,2,1,4,3,2,1 }; 622 size_t clearbytes[4] = { 5, 6, 7, 8 }; 623 size_t encryptedbytes[4] = { 8, 7, 6, 5 }; 624 625 AMediaCodecCryptoInfo *ci = 626 AMediaCodecCryptoInfo_new(numsubsamples, key, iv, AMEDIACODECRYPTOINFO_MODE_CLEAR, clearbytes, encryptedbytes); 627 628 if (AMediaCodecCryptoInfo_getNumSubSamples(ci) != 4) { 629 ALOGE("numsubsamples mismatch"); 630 return false; 631 } 632 uint8_t bytes[16]; 633 AMediaCodecCryptoInfo_getKey(ci, bytes); 634 if (memcmp(key, bytes, 16) != 0) { 635 ALOGE("key mismatch"); 636 return false; 637 } 638 AMediaCodecCryptoInfo_getIV(ci, bytes); 639 if (memcmp(iv, bytes, 16) != 0) { 640 ALOGE("IV mismatch"); 641 return false; 642 } 643 if (AMediaCodecCryptoInfo_getMode(ci) != AMEDIACODECRYPTOINFO_MODE_CLEAR) { 644 ALOGE("mode mismatch"); 645 return false; 646 } 647 size_t sizes[numsubsamples]; 648 AMediaCodecCryptoInfo_getClearBytes(ci, sizes); 649 if (memcmp(clearbytes, sizes, sizeof(size_t) * numsubsamples)) { 650 ALOGE("clear size mismatch"); 651 return false; 652 } 653 AMediaCodecCryptoInfo_getEncryptedBytes(ci, sizes); 654 if (memcmp(encryptedbytes, sizes, sizeof(size_t) * numsubsamples)) { 655 ALOGE("encrypted size mismatch"); 656 return false; 657 } 658 return true; 659 } 660 661