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