android_media_MediaCodec.cpp revision b12a5390694e8525ac61d7377e266e31d124c815
1/* 2 * Copyright 2012, 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//#define LOG_NDEBUG 0 18#define LOG_TAG "MediaCodec-JNI" 19#include <utils/Log.h> 20 21#include "android_media_MediaCodec.h" 22 23#include "android_media_MediaCrypto.h" 24#include "android_media_Utils.h" 25#include "android_runtime/AndroidRuntime.h" 26#include "android_runtime/android_view_Surface.h" 27#include "jni.h" 28#include "JNIHelp.h" 29 30#include <gui/Surface.h> 31#include <gui/SurfaceTextureClient.h> 32 33#include <media/ICrypto.h> 34#include <media/stagefright/MediaCodec.h> 35#include <media/stagefright/foundation/ABuffer.h> 36#include <media/stagefright/foundation/ADebug.h> 37#include <media/stagefright/foundation/ALooper.h> 38#include <media/stagefright/foundation/AMessage.h> 39#include <media/stagefright/foundation/AString.h> 40#include <media/stagefright/MediaErrors.h> 41 42#include <system/window.h> 43 44namespace android { 45 46// Keep these in sync with their equivalents in MediaCodec.java !!! 47enum { 48 DEQUEUE_INFO_TRY_AGAIN_LATER = -1, 49 DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED = -2, 50 DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED = -3, 51}; 52 53struct fields_t { 54 jfieldID context; 55 56 jfieldID cryptoInfoNumSubSamplesID; 57 jfieldID cryptoInfoNumBytesOfClearDataID; 58 jfieldID cryptoInfoNumBytesOfEncryptedDataID; 59 jfieldID cryptoInfoKeyID; 60 jfieldID cryptoInfoIVID; 61 jfieldID cryptoInfoModeID; 62}; 63 64static fields_t gFields; 65 66//////////////////////////////////////////////////////////////////////////////// 67 68JMediaCodec::JMediaCodec( 69 JNIEnv *env, jobject thiz, 70 const char *name, bool nameIsType, bool encoder) 71 : mClass(NULL), 72 mObject(NULL) { 73 jclass clazz = env->GetObjectClass(thiz); 74 CHECK(clazz != NULL); 75 76 mClass = (jclass)env->NewGlobalRef(clazz); 77 mObject = env->NewWeakGlobalRef(thiz); 78 79 mLooper = new ALooper; 80 mLooper->setName("MediaCodec_looper"); 81 82 mLooper->start( 83 false, // runOnCallingThread 84 false, // canCallJava 85 PRIORITY_DEFAULT); 86 87 if (nameIsType) { 88 mCodec = MediaCodec::CreateByType(mLooper, name, encoder); 89 } else { 90 mCodec = MediaCodec::CreateByComponentName(mLooper, name); 91 } 92} 93 94status_t JMediaCodec::initCheck() const { 95 return mCodec != NULL ? OK : NO_INIT; 96} 97 98JMediaCodec::~JMediaCodec() { 99 mCodec->release(); 100 101 JNIEnv *env = AndroidRuntime::getJNIEnv(); 102 103 env->DeleteWeakGlobalRef(mObject); 104 mObject = NULL; 105 env->DeleteGlobalRef(mClass); 106 mClass = NULL; 107} 108 109status_t JMediaCodec::configure( 110 const sp<AMessage> &format, 111 const sp<ISurfaceTexture> &surfaceTexture, 112 const sp<ICrypto> &crypto, 113 int flags) { 114 sp<SurfaceTextureClient> client; 115 if (surfaceTexture != NULL) { 116 mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture); 117 } else { 118 mSurfaceTextureClient.clear(); 119 } 120 121 return mCodec->configure(format, mSurfaceTextureClient, crypto, flags); 122} 123 124status_t JMediaCodec::start() { 125 return mCodec->start(); 126} 127 128status_t JMediaCodec::stop() { 129 mSurfaceTextureClient.clear(); 130 131 return mCodec->stop(); 132} 133 134status_t JMediaCodec::flush() { 135 return mCodec->flush(); 136} 137 138status_t JMediaCodec::queueInputBuffer( 139 size_t index, 140 size_t offset, size_t size, int64_t timeUs, uint32_t flags, 141 AString *errorDetailMsg) { 142 return mCodec->queueInputBuffer( 143 index, offset, size, timeUs, flags, errorDetailMsg); 144} 145 146status_t JMediaCodec::queueSecureInputBuffer( 147 size_t index, 148 size_t offset, 149 const CryptoPlugin::SubSample *subSamples, 150 size_t numSubSamples, 151 const uint8_t key[16], 152 const uint8_t iv[16], 153 CryptoPlugin::Mode mode, 154 int64_t presentationTimeUs, 155 uint32_t flags, 156 AString *errorDetailMsg) { 157 return mCodec->queueSecureInputBuffer( 158 index, offset, subSamples, numSubSamples, key, iv, mode, 159 presentationTimeUs, flags, errorDetailMsg); 160} 161 162status_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { 163 return mCodec->dequeueInputBuffer(index, timeoutUs); 164} 165 166status_t JMediaCodec::dequeueOutputBuffer( 167 JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) { 168 size_t size, offset; 169 int64_t timeUs; 170 uint32_t flags; 171 status_t err; 172 if ((err = mCodec->dequeueOutputBuffer( 173 index, &offset, &size, &timeUs, &flags, timeoutUs)) != OK) { 174 return err; 175 } 176 177 jclass clazz = env->FindClass("android/media/MediaCodec$BufferInfo"); 178 179 jmethodID method = env->GetMethodID(clazz, "set", "(IIJI)V"); 180 env->CallVoidMethod(bufferInfo, method, offset, size, timeUs, flags); 181 182 return OK; 183} 184 185status_t JMediaCodec::releaseOutputBuffer(size_t index, bool render) { 186 return render 187 ? mCodec->renderOutputBufferAndRelease(index) 188 : mCodec->releaseOutputBuffer(index); 189} 190 191status_t JMediaCodec::getOutputFormat(JNIEnv *env, jobject *format) const { 192 sp<AMessage> msg; 193 status_t err; 194 if ((err = mCodec->getOutputFormat(&msg)) != OK) { 195 return err; 196 } 197 198 return ConvertMessageToMap(env, msg, format); 199} 200 201status_t JMediaCodec::getBuffers( 202 JNIEnv *env, bool input, jobjectArray *bufArray) const { 203 Vector<sp<ABuffer> > buffers; 204 205 status_t err = 206 input 207 ? mCodec->getInputBuffers(&buffers) 208 : mCodec->getOutputBuffers(&buffers); 209 210 if (err != OK) { 211 return err; 212 } 213 214 jclass byteBufferClass = env->FindClass("java/nio/ByteBuffer"); 215 216 *bufArray = (jobjectArray)env->NewObjectArray( 217 buffers.size(), byteBufferClass, NULL); 218 219 for (size_t i = 0; i < buffers.size(); ++i) { 220 const sp<ABuffer> &buffer = buffers.itemAt(i); 221 222 jobject byteBuffer = 223 env->NewDirectByteBuffer( 224 buffer->base(), 225 buffer->capacity()); 226 227 env->SetObjectArrayElement( 228 *bufArray, i, byteBuffer); 229 230 env->DeleteLocalRef(byteBuffer); 231 byteBuffer = NULL; 232 } 233 234 return OK; 235} 236 237void JMediaCodec::setVideoScalingMode(int mode) { 238 if (mSurfaceTextureClient != NULL) { 239 native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode); 240 } 241} 242 243} // namespace android 244 245//////////////////////////////////////////////////////////////////////////////// 246 247using namespace android; 248 249static sp<JMediaCodec> setMediaCodec( 250 JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) { 251 sp<JMediaCodec> old = (JMediaCodec *)env->GetIntField(thiz, gFields.context); 252 if (codec != NULL) { 253 codec->incStrong(thiz); 254 } 255 if (old != NULL) { 256 old->decStrong(thiz); 257 } 258 env->SetIntField(thiz, gFields.context, (int)codec.get()); 259 260 return old; 261} 262 263static sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) { 264 return (JMediaCodec *)env->GetIntField(thiz, gFields.context); 265} 266 267static void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) { 268 setMediaCodec(env, thiz, NULL); 269} 270 271static void throwCryptoException(JNIEnv *env, status_t err, const char *msg) { 272 jclass clazz = env->FindClass("android/media/MediaCodec$CryptoException"); 273 CHECK(clazz != NULL); 274 275 jmethodID constructID = 276 env->GetMethodID(clazz, "<init>", "(ILjava/lang/String;)V"); 277 CHECK(constructID != NULL); 278 279 jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error"); 280 281 jthrowable exception = 282 (jthrowable)env->NewObject(clazz, constructID, err, msgObj); 283 284 env->Throw(exception); 285} 286 287static jint throwExceptionAsNecessary( 288 JNIEnv *env, status_t err, const char *msg = NULL) { 289 if (err >= ERROR_DRM_WV_VENDOR_MIN && err <= ERROR_DRM_WV_VENDOR_MAX) { 290 // We'll throw our custom MediaCodec.CryptoException 291 292 throwCryptoException(env, err, msg); 293 return 0; 294 } 295 296 switch (err) { 297 case OK: 298 return 0; 299 300 case -EAGAIN: 301 return DEQUEUE_INFO_TRY_AGAIN_LATER; 302 303 case INFO_FORMAT_CHANGED: 304 return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED; 305 306 case INFO_OUTPUT_BUFFERS_CHANGED: 307 return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED; 308 309 default: 310 { 311 jniThrowException(env, "java/lang/IllegalStateException", NULL); 312 break; 313 } 314 } 315 316 return 0; 317} 318 319static void android_media_MediaCodec_native_configure( 320 JNIEnv *env, 321 jobject thiz, 322 jobjectArray keys, jobjectArray values, 323 jobject jsurface, 324 jobject jcrypto, 325 jint flags) { 326 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 327 328 if (codec == NULL) { 329 jniThrowException(env, "java/lang/IllegalStateException", NULL); 330 return; 331 } 332 333 sp<AMessage> format; 334 status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format); 335 336 if (err != OK) { 337 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 338 return; 339 } 340 341 sp<ISurfaceTexture> surfaceTexture; 342 if (jsurface != NULL) { 343 sp<Surface> surface(Surface_getSurface(env, jsurface)); 344 if (surface != NULL) { 345 surfaceTexture = surface->getSurfaceTexture(); 346 } else { 347 jniThrowException( 348 env, 349 "java/lang/IllegalArgumentException", 350 "The surface has been released"); 351 return; 352 } 353 } 354 355 sp<ICrypto> crypto; 356 if (jcrypto != NULL) { 357 crypto = JCrypto::GetCrypto(env, jcrypto); 358 } 359 360 err = codec->configure(format, surfaceTexture, crypto, flags); 361 362 throwExceptionAsNecessary(env, err); 363} 364 365static void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) { 366 ALOGV("android_media_MediaCodec_start"); 367 368 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 369 370 if (codec == NULL) { 371 jniThrowException(env, "java/lang/IllegalStateException", NULL); 372 return; 373 } 374 375 status_t err = codec->start(); 376 377 throwExceptionAsNecessary(env, err); 378} 379 380static void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) { 381 ALOGV("android_media_MediaCodec_stop"); 382 383 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 384 385 if (codec == NULL) { 386 jniThrowException(env, "java/lang/IllegalStateException", NULL); 387 return; 388 } 389 390 status_t err = codec->stop(); 391 392 throwExceptionAsNecessary(env, err); 393} 394 395static void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) { 396 ALOGV("android_media_MediaCodec_flush"); 397 398 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 399 400 if (codec == NULL) { 401 jniThrowException(env, "java/lang/IllegalStateException", NULL); 402 return; 403 } 404 405 status_t err = codec->flush(); 406 407 throwExceptionAsNecessary(env, err); 408} 409 410static void android_media_MediaCodec_queueInputBuffer( 411 JNIEnv *env, 412 jobject thiz, 413 jint index, 414 jint offset, 415 jint size, 416 jlong timestampUs, 417 jint flags) { 418 ALOGV("android_media_MediaCodec_queueInputBuffer"); 419 420 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 421 422 if (codec == NULL) { 423 jniThrowException(env, "java/lang/IllegalStateException", NULL); 424 return; 425 } 426 427 AString errorDetailMsg; 428 429 status_t err = codec->queueInputBuffer( 430 index, offset, size, timestampUs, flags, &errorDetailMsg); 431 432 throwExceptionAsNecessary( 433 env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str()); 434} 435 436static void android_media_MediaCodec_queueSecureInputBuffer( 437 JNIEnv *env, 438 jobject thiz, 439 jint index, 440 jint offset, 441 jobject cryptoInfoObj, 442 jlong timestampUs, 443 jint flags) { 444 ALOGV("android_media_MediaCodec_queueSecureInputBuffer"); 445 446 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 447 448 if (codec == NULL) { 449 jniThrowException(env, "java/lang/IllegalStateException", NULL); 450 return; 451 } 452 453 jint numSubSamples = 454 env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID); 455 456 jintArray numBytesOfClearDataObj = 457 (jintArray)env->GetObjectField( 458 cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID); 459 460 jintArray numBytesOfEncryptedDataObj = 461 (jintArray)env->GetObjectField( 462 cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID); 463 464 jbyteArray keyObj = 465 (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID); 466 467 jbyteArray ivObj = 468 (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID); 469 470 jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID); 471 472 status_t err = OK; 473 474 CryptoPlugin::SubSample *subSamples = NULL; 475 jbyte *key = NULL; 476 jbyte *iv = NULL; 477 478 if (numSubSamples <= 0) { 479 err = -EINVAL; 480 } else if (numBytesOfClearDataObj == NULL 481 && numBytesOfEncryptedDataObj == NULL) { 482 err = -EINVAL; 483 } else if (numBytesOfEncryptedDataObj != NULL 484 && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) { 485 err = -ERANGE; 486 } else if (numBytesOfClearDataObj != NULL 487 && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) { 488 err = -ERANGE; 489 } else { 490 jboolean isCopy; 491 492 jint *numBytesOfClearData = 493 (numBytesOfClearDataObj == NULL) 494 ? NULL 495 : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy); 496 497 jint *numBytesOfEncryptedData = 498 (numBytesOfEncryptedDataObj == NULL) 499 ? NULL 500 : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy); 501 502 subSamples = new CryptoPlugin::SubSample[numSubSamples]; 503 504 for (jint i = 0; i < numSubSamples; ++i) { 505 subSamples[i].mNumBytesOfClearData = 506 (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i]; 507 508 subSamples[i].mNumBytesOfEncryptedData = 509 (numBytesOfEncryptedData == NULL) 510 ? 0 : numBytesOfEncryptedData[i]; 511 } 512 513 if (numBytesOfEncryptedData != NULL) { 514 env->ReleaseIntArrayElements( 515 numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0); 516 numBytesOfEncryptedData = NULL; 517 } 518 519 if (numBytesOfClearData != NULL) { 520 env->ReleaseIntArrayElements( 521 numBytesOfClearDataObj, numBytesOfClearData, 0); 522 numBytesOfClearData = NULL; 523 } 524 } 525 526 if (err == OK && keyObj != NULL) { 527 if (env->GetArrayLength(keyObj) != 16) { 528 err = -EINVAL; 529 } else { 530 jboolean isCopy; 531 key = env->GetByteArrayElements(keyObj, &isCopy); 532 } 533 } 534 535 if (err == OK && ivObj != NULL) { 536 if (env->GetArrayLength(ivObj) != 16) { 537 err = -EINVAL; 538 } else { 539 jboolean isCopy; 540 iv = env->GetByteArrayElements(ivObj, &isCopy); 541 } 542 } 543 544 AString errorDetailMsg; 545 546 if (err == OK) { 547 err = codec->queueSecureInputBuffer( 548 index, offset, 549 subSamples, numSubSamples, 550 (const uint8_t *)key, (const uint8_t *)iv, 551 (CryptoPlugin::Mode)mode, 552 timestampUs, 553 flags, 554 &errorDetailMsg); 555 } 556 557 if (iv != NULL) { 558 env->ReleaseByteArrayElements(ivObj, iv, 0); 559 iv = NULL; 560 } 561 562 if (key != NULL) { 563 env->ReleaseByteArrayElements(keyObj, key, 0); 564 key = NULL; 565 } 566 567 delete[] subSamples; 568 subSamples = NULL; 569 570 throwExceptionAsNecessary( 571 env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str()); 572} 573 574static jint android_media_MediaCodec_dequeueInputBuffer( 575 JNIEnv *env, jobject thiz, jlong timeoutUs) { 576 ALOGV("android_media_MediaCodec_dequeueInputBuffer"); 577 578 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 579 580 if (codec == NULL) { 581 jniThrowException(env, "java/lang/IllegalStateException", NULL); 582 return -1; 583 } 584 585 size_t index; 586 status_t err = codec->dequeueInputBuffer(&index, timeoutUs); 587 588 if (err == OK) { 589 return index; 590 } 591 592 return throwExceptionAsNecessary(env, err); 593} 594 595static jint android_media_MediaCodec_dequeueOutputBuffer( 596 JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) { 597 ALOGV("android_media_MediaCodec_dequeueOutputBuffer"); 598 599 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 600 601 if (codec == NULL) { 602 jniThrowException(env, "java/lang/IllegalStateException", NULL); 603 return 0; 604 } 605 606 size_t index; 607 status_t err = codec->dequeueOutputBuffer( 608 env, bufferInfo, &index, timeoutUs); 609 610 if (err == OK) { 611 return index; 612 } 613 614 return throwExceptionAsNecessary(env, err); 615} 616 617static void android_media_MediaCodec_releaseOutputBuffer( 618 JNIEnv *env, jobject thiz, jint index, jboolean render) { 619 ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease"); 620 621 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 622 623 if (codec == NULL) { 624 jniThrowException(env, "java/lang/IllegalStateException", NULL); 625 return; 626 } 627 628 status_t err = codec->releaseOutputBuffer(index, render); 629 630 throwExceptionAsNecessary(env, err); 631} 632 633static jobject android_media_MediaCodec_getOutputFormat( 634 JNIEnv *env, jobject thiz) { 635 ALOGV("android_media_MediaCodec_getOutputFormat"); 636 637 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 638 639 if (codec == NULL) { 640 jniThrowException(env, "java/lang/IllegalStateException", NULL); 641 return NULL; 642 } 643 644 jobject format; 645 status_t err = codec->getOutputFormat(env, &format); 646 647 if (err == OK) { 648 return format; 649 } 650 651 throwExceptionAsNecessary(env, err); 652 653 return NULL; 654} 655 656static jobjectArray android_media_MediaCodec_getBuffers( 657 JNIEnv *env, jobject thiz, jboolean input) { 658 ALOGV("android_media_MediaCodec_getBuffers"); 659 660 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 661 662 if (codec == NULL) { 663 jniThrowException(env, "java/lang/IllegalStateException", NULL); 664 return NULL; 665 } 666 667 jobjectArray buffers; 668 status_t err = codec->getBuffers(env, input, &buffers); 669 670 if (err == OK) { 671 return buffers; 672 } 673 674 throwExceptionAsNecessary(env, err); 675 676 return NULL; 677} 678 679static void android_media_MediaCodec_setVideoScalingMode( 680 JNIEnv *env, jobject thiz, jint mode) { 681 sp<JMediaCodec> codec = getMediaCodec(env, thiz); 682 683 if (codec == NULL) { 684 jniThrowException(env, "java/lang/IllegalStateException", NULL); 685 return; 686 } 687 688 if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW 689 && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) { 690 jniThrowException(env, "java/lang/InvalidArgumentException", NULL); 691 return; 692 } 693 694 codec->setVideoScalingMode(mode); 695} 696 697static void android_media_MediaCodec_native_init(JNIEnv *env) { 698 jclass clazz = env->FindClass("android/media/MediaCodec"); 699 CHECK(clazz != NULL); 700 701 gFields.context = env->GetFieldID(clazz, "mNativeContext", "I"); 702 CHECK(gFields.context != NULL); 703 704 clazz = env->FindClass("android/media/MediaCodec$CryptoInfo"); 705 CHECK(clazz != NULL); 706 707 gFields.cryptoInfoNumSubSamplesID = 708 env->GetFieldID(clazz, "numSubSamples", "I"); 709 CHECK(gFields.cryptoInfoNumSubSamplesID != NULL); 710 711 gFields.cryptoInfoNumBytesOfClearDataID = 712 env->GetFieldID(clazz, "numBytesOfClearData", "[I"); 713 CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL); 714 715 gFields.cryptoInfoNumBytesOfEncryptedDataID = 716 env->GetFieldID(clazz, "numBytesOfEncryptedData", "[I"); 717 CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL); 718 719 gFields.cryptoInfoKeyID = env->GetFieldID(clazz, "key", "[B"); 720 CHECK(gFields.cryptoInfoKeyID != NULL); 721 722 gFields.cryptoInfoIVID = env->GetFieldID(clazz, "iv", "[B"); 723 CHECK(gFields.cryptoInfoIVID != NULL); 724 725 gFields.cryptoInfoModeID = env->GetFieldID(clazz, "mode", "I"); 726 CHECK(gFields.cryptoInfoModeID != NULL); 727} 728 729static void android_media_MediaCodec_native_setup( 730 JNIEnv *env, jobject thiz, 731 jstring name, jboolean nameIsType, jboolean encoder) { 732 if (name == NULL) { 733 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 734 return; 735 } 736 737 const char *tmp = env->GetStringUTFChars(name, NULL); 738 739 if (tmp == NULL) { 740 return; 741 } 742 743 sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder); 744 745 status_t err = codec->initCheck(); 746 747 env->ReleaseStringUTFChars(name, tmp); 748 tmp = NULL; 749 750 if (err != OK) { 751 jniThrowException( 752 env, 753 "java/io/IOException", 754 "Failed to allocate component instance"); 755 return; 756 } 757 758 setMediaCodec(env,thiz, codec); 759} 760 761static void android_media_MediaCodec_native_finalize( 762 JNIEnv *env, jobject thiz) { 763 android_media_MediaCodec_release(env, thiz); 764} 765 766static JNINativeMethod gMethods[] = { 767 { "release", "()V", (void *)android_media_MediaCodec_release }, 768 769 { "native_configure", 770 "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;" 771 "Landroid/media/MediaCrypto;I)V", 772 (void *)android_media_MediaCodec_native_configure }, 773 774 { "start", "()V", (void *)android_media_MediaCodec_start }, 775 { "stop", "()V", (void *)android_media_MediaCodec_stop }, 776 { "flush", "()V", (void *)android_media_MediaCodec_flush }, 777 778 { "queueInputBuffer", "(IIIJI)V", 779 (void *)android_media_MediaCodec_queueInputBuffer }, 780 781 { "queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V", 782 (void *)android_media_MediaCodec_queueSecureInputBuffer }, 783 784 { "dequeueInputBuffer", "(J)I", 785 (void *)android_media_MediaCodec_dequeueInputBuffer }, 786 787 { "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I", 788 (void *)android_media_MediaCodec_dequeueOutputBuffer }, 789 790 { "releaseOutputBuffer", "(IZ)V", 791 (void *)android_media_MediaCodec_releaseOutputBuffer }, 792 793 { "getOutputFormat", "()Ljava/util/Map;", 794 (void *)android_media_MediaCodec_getOutputFormat }, 795 796 { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;", 797 (void *)android_media_MediaCodec_getBuffers }, 798 799 { "setVideoScalingMode", "(I)V", 800 (void *)android_media_MediaCodec_setVideoScalingMode }, 801 802 { "native_init", "()V", (void *)android_media_MediaCodec_native_init }, 803 804 { "native_setup", "(Ljava/lang/String;ZZ)V", 805 (void *)android_media_MediaCodec_native_setup }, 806 807 { "native_finalize", "()V", 808 (void *)android_media_MediaCodec_native_finalize }, 809}; 810 811int register_android_media_MediaCodec(JNIEnv *env) { 812 return AndroidRuntime::registerNativeMethods(env, 813 "android/media/MediaCodec", gMethods, NELEM(gMethods)); 814} 815