android_media_MediaExtractor.cpp revision e20a6d5c479909f37af748a81a6e5a5deb7b6e2c
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 "MediaExtractor-JNI" 19#include <utils/Log.h> 20 21#include "android_media_MediaExtractor.h" 22 23#include "android_media_Utils.h" 24#include "android_runtime/AndroidRuntime.h" 25#include "jni.h" 26#include "JNIHelp.h" 27 28#include <media/hardware/CryptoAPI.h> 29#include <media/stagefright/foundation/ABuffer.h> 30#include <media/stagefright/foundation/ADebug.h> 31#include <media/stagefright/foundation/AMessage.h> 32#include <media/stagefright/DataSource.h> 33#include <media/stagefright/MediaErrors.h> 34#include <media/stagefright/MetaData.h> 35#include <media/stagefright/NuMediaExtractor.h> 36 37namespace android { 38 39struct fields_t { 40 jfieldID context; 41 42 jmethodID cryptoInfoSetID; 43}; 44 45static fields_t gFields; 46 47class JavaDataSourceBridge : public DataSource { 48 jmethodID mReadMethod; 49 jmethodID mGetSizeMethod; 50 jmethodID mCloseMethod; 51 jobject mDataSource; 52 public: 53 JavaDataSourceBridge(JNIEnv *env, jobject source) { 54 mDataSource = env->NewGlobalRef(source); 55 56 jclass datasourceclass = env->GetObjectClass(mDataSource); 57 CHECK(datasourceclass != NULL); 58 59 mReadMethod = env->GetMethodID(datasourceclass, "readAt", "(J[BI)I"); 60 CHECK(mReadMethod != NULL); 61 62 mGetSizeMethod = env->GetMethodID(datasourceclass, "getSize", "()J"); 63 CHECK(mGetSizeMethod != NULL); 64 65 mCloseMethod = env->GetMethodID(datasourceclass, "close", "()V"); 66 CHECK(mCloseMethod != NULL); 67 } 68 69 ~JavaDataSourceBridge() { 70 JNIEnv *env = AndroidRuntime::getJNIEnv(); 71 env->CallVoidMethod(mDataSource, mCloseMethod); 72 env->DeleteGlobalRef(mDataSource); 73 } 74 75 virtual status_t initCheck() const { 76 return OK; 77 } 78 79 virtual ssize_t readAt(off64_t offset, void* buffer, size_t size) { 80 JNIEnv *env = AndroidRuntime::getJNIEnv(); 81 82 // XXX could optimize this by reusing the same array 83 jbyteArray byteArrayObj = env->NewByteArray(size); 84 env->DeleteLocalRef(env->GetObjectClass(mDataSource)); 85 env->DeleteLocalRef(env->GetObjectClass(byteArrayObj)); 86 ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, size); 87 env->GetByteArrayRegion(byteArrayObj, 0, size, (jbyte*) buffer); 88 env->DeleteLocalRef(byteArrayObj); 89 if (env->ExceptionCheck()) { 90 ALOGW("Exception occurred while reading %d at %lld", size, offset); 91 LOGW_EX(env); 92 env->ExceptionClear(); 93 return -1; 94 } 95 return numread; 96 } 97 98 virtual status_t getSize(off64_t *size) { 99 JNIEnv *env = AndroidRuntime::getJNIEnv(); 100 101 CHECK(size != NULL); 102 103 int64_t len = env->CallLongMethod(mDataSource, mGetSizeMethod); 104 if (len < 0) { 105 *size = ERROR_UNSUPPORTED; 106 } else { 107 *size = len; 108 } 109 return OK; 110 } 111}; 112 113//////////////////////////////////////////////////////////////////////////////// 114 115JMediaExtractor::JMediaExtractor(JNIEnv *env, jobject thiz) 116 : mClass(NULL), 117 mObject(NULL) { 118 jclass clazz = env->GetObjectClass(thiz); 119 CHECK(clazz != NULL); 120 121 mClass = (jclass)env->NewGlobalRef(clazz); 122 mObject = env->NewWeakGlobalRef(thiz); 123 124 mImpl = new NuMediaExtractor; 125} 126 127JMediaExtractor::~JMediaExtractor() { 128 JNIEnv *env = AndroidRuntime::getJNIEnv(); 129 130 env->DeleteWeakGlobalRef(mObject); 131 mObject = NULL; 132 env->DeleteGlobalRef(mClass); 133 mClass = NULL; 134} 135 136status_t JMediaExtractor::setDataSource( 137 const char *path, const KeyedVector<String8, String8> *headers) { 138 return mImpl->setDataSource(path, headers); 139} 140 141status_t JMediaExtractor::setDataSource(int fd, off64_t offset, off64_t size) { 142 return mImpl->setDataSource(fd, offset, size); 143} 144 145status_t JMediaExtractor::setDataSource(const sp<DataSource> &datasource) { 146 return mImpl->setDataSource(datasource); 147} 148 149size_t JMediaExtractor::countTracks() const { 150 return mImpl->countTracks(); 151} 152 153status_t JMediaExtractor::getTrackFormat(size_t index, jobject *format) const { 154 sp<AMessage> msg; 155 status_t err; 156 if ((err = mImpl->getTrackFormat(index, &msg)) != OK) { 157 return err; 158 } 159 160 JNIEnv *env = AndroidRuntime::getJNIEnv(); 161 162 return ConvertMessageToMap(env, msg, format); 163} 164 165status_t JMediaExtractor::getFileFormat(jobject *format) const { 166 sp<AMessage> msg; 167 status_t err; 168 if ((err = mImpl->getFileFormat(&msg)) != OK) { 169 return err; 170 } 171 172 JNIEnv *env = AndroidRuntime::getJNIEnv(); 173 174 return ConvertMessageToMap(env, msg, format); 175} 176 177status_t JMediaExtractor::selectTrack(size_t index) { 178 return mImpl->selectTrack(index); 179} 180 181status_t JMediaExtractor::unselectTrack(size_t index) { 182 return mImpl->unselectTrack(index); 183} 184 185status_t JMediaExtractor::seekTo( 186 int64_t timeUs, MediaSource::ReadOptions::SeekMode mode) { 187 return mImpl->seekTo(timeUs, mode); 188} 189 190status_t JMediaExtractor::advance() { 191 return mImpl->advance(); 192} 193 194status_t JMediaExtractor::readSampleData( 195 jobject byteBuf, size_t offset, size_t *sampleSize) { 196 JNIEnv *env = AndroidRuntime::getJNIEnv(); 197 198 void *dst = env->GetDirectBufferAddress(byteBuf); 199 200 jlong dstSize; 201 jbyteArray byteArray = NULL; 202 203 if (dst == NULL) { 204 jclass byteBufClass = env->FindClass("java/nio/ByteBuffer"); 205 CHECK(byteBufClass != NULL); 206 207 jmethodID arrayID = 208 env->GetMethodID(byteBufClass, "array", "()[B"); 209 CHECK(arrayID != NULL); 210 211 byteArray = 212 (jbyteArray)env->CallObjectMethod(byteBuf, arrayID); 213 214 if (byteArray == NULL) { 215 return INVALID_OPERATION; 216 } 217 218 jboolean isCopy; 219 dst = env->GetByteArrayElements(byteArray, &isCopy); 220 221 dstSize = env->GetArrayLength(byteArray); 222 } else { 223 dstSize = env->GetDirectBufferCapacity(byteBuf); 224 } 225 226 if (dstSize < offset) { 227 if (byteArray != NULL) { 228 env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0); 229 } 230 231 return -ERANGE; 232 } 233 234 sp<ABuffer> buffer = new ABuffer((char *)dst + offset, dstSize - offset); 235 236 status_t err = mImpl->readSampleData(buffer); 237 238 if (byteArray != NULL) { 239 env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0); 240 } 241 242 if (err != OK) { 243 return err; 244 } 245 246 *sampleSize = buffer->size(); 247 248 return OK; 249} 250 251status_t JMediaExtractor::getSampleTrackIndex(size_t *trackIndex) { 252 return mImpl->getSampleTrackIndex(trackIndex); 253} 254 255status_t JMediaExtractor::getSampleTime(int64_t *sampleTimeUs) { 256 return mImpl->getSampleTime(sampleTimeUs); 257} 258 259status_t JMediaExtractor::getSampleFlags(uint32_t *sampleFlags) { 260 *sampleFlags = 0; 261 262 sp<MetaData> meta; 263 status_t err = mImpl->getSampleMeta(&meta); 264 265 if (err != OK) { 266 return err; 267 } 268 269 int32_t val; 270 if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) { 271 (*sampleFlags) |= NuMediaExtractor::SAMPLE_FLAG_SYNC; 272 } 273 274 uint32_t type; 275 const void *data; 276 size_t size; 277 if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) { 278 (*sampleFlags) |= NuMediaExtractor::SAMPLE_FLAG_ENCRYPTED; 279 } 280 281 return OK; 282} 283 284status_t JMediaExtractor::getSampleMeta(sp<MetaData> *sampleMeta) { 285 return mImpl->getSampleMeta(sampleMeta); 286} 287 288bool JMediaExtractor::getCachedDuration(int64_t *durationUs, bool *eos) const { 289 return mImpl->getCachedDuration(durationUs, eos); 290} 291 292} // namespace android 293 294//////////////////////////////////////////////////////////////////////////////// 295 296using namespace android; 297 298static sp<JMediaExtractor> setMediaExtractor( 299 JNIEnv *env, jobject thiz, const sp<JMediaExtractor> &extractor) { 300 sp<JMediaExtractor> old = 301 (JMediaExtractor *)env->GetIntField(thiz, gFields.context); 302 303 if (extractor != NULL) { 304 extractor->incStrong(thiz); 305 } 306 if (old != NULL) { 307 old->decStrong(thiz); 308 } 309 env->SetIntField(thiz, gFields.context, (int)extractor.get()); 310 311 return old; 312} 313 314static sp<JMediaExtractor> getMediaExtractor(JNIEnv *env, jobject thiz) { 315 return (JMediaExtractor *)env->GetIntField(thiz, gFields.context); 316} 317 318static void android_media_MediaExtractor_release(JNIEnv *env, jobject thiz) { 319 setMediaExtractor(env, thiz, NULL); 320} 321 322static jint android_media_MediaExtractor_getTrackCount( 323 JNIEnv *env, jobject thiz) { 324 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 325 326 if (extractor == NULL) { 327 jniThrowException(env, "java/lang/IllegalStateException", NULL); 328 return -1; 329 } 330 331 return extractor->countTracks(); 332} 333 334static jobject android_media_MediaExtractor_getTrackFormatNative( 335 JNIEnv *env, jobject thiz, jint index) { 336 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 337 338 if (extractor == NULL) { 339 jniThrowException(env, "java/lang/IllegalStateException", NULL); 340 return NULL; 341 } 342 343 jobject format; 344 status_t err = extractor->getTrackFormat(index, &format); 345 346 if (err != OK) { 347 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 348 return NULL; 349 } 350 351 return format; 352} 353 354static jobject android_media_MediaExtractor_getFileFormatNative( 355 JNIEnv *env, jobject thiz) { 356 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 357 358 if (extractor == NULL) { 359 jniThrowException(env, "java/lang/IllegalStateException", NULL); 360 return NULL; 361 } 362 363 jobject format; 364 status_t err = extractor->getFileFormat(&format); 365 366 if (err != OK) { 367 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 368 return NULL; 369 } 370 371 return format; 372} 373 374static void android_media_MediaExtractor_selectTrack( 375 JNIEnv *env, jobject thiz, jint index) { 376 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 377 378 if (extractor == NULL) { 379 jniThrowException(env, "java/lang/IllegalStateException", NULL); 380 return; 381 } 382 383 status_t err = extractor->selectTrack(index); 384 385 if (err != OK) { 386 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 387 return; 388 } 389} 390 391static void android_media_MediaExtractor_unselectTrack( 392 JNIEnv *env, jobject thiz, jint index) { 393 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 394 395 if (extractor == NULL) { 396 jniThrowException(env, "java/lang/IllegalStateException", NULL); 397 return; 398 } 399 400 status_t err = extractor->unselectTrack(index); 401 402 if (err != OK) { 403 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 404 return; 405 } 406} 407 408static void android_media_MediaExtractor_seekTo( 409 JNIEnv *env, jobject thiz, jlong timeUs, jint mode) { 410 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 411 412 if (extractor == NULL) { 413 jniThrowException(env, "java/lang/IllegalStateException", NULL); 414 return; 415 } 416 417 if (mode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC 418 || mode >= MediaSource::ReadOptions::SEEK_CLOSEST) { 419 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 420 return; 421 } 422 423 extractor->seekTo(timeUs, (MediaSource::ReadOptions::SeekMode)mode); 424} 425 426static jboolean android_media_MediaExtractor_advance( 427 JNIEnv *env, jobject thiz) { 428 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 429 430 if (extractor == NULL) { 431 jniThrowException(env, "java/lang/IllegalStateException", NULL); 432 return false; 433 } 434 435 status_t err = extractor->advance(); 436 437 if (err == ERROR_END_OF_STREAM) { 438 return false; 439 } else if (err != OK) { 440 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 441 return false; 442 } 443 444 return true; 445} 446 447static jint android_media_MediaExtractor_readSampleData( 448 JNIEnv *env, jobject thiz, jobject byteBuf, jint offset) { 449 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 450 451 if (extractor == NULL) { 452 jniThrowException(env, "java/lang/IllegalStateException", NULL); 453 return -1; 454 } 455 456 size_t sampleSize; 457 status_t err = extractor->readSampleData(byteBuf, offset, &sampleSize); 458 459 if (err == ERROR_END_OF_STREAM) { 460 return -1; 461 } else if (err != OK) { 462 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 463 return false; 464 } 465 466 return sampleSize; 467} 468 469static jint android_media_MediaExtractor_getSampleTrackIndex( 470 JNIEnv *env, jobject thiz) { 471 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 472 473 if (extractor == NULL) { 474 jniThrowException(env, "java/lang/IllegalStateException", NULL); 475 return -1; 476 } 477 478 size_t trackIndex; 479 status_t err = extractor->getSampleTrackIndex(&trackIndex); 480 481 if (err == ERROR_END_OF_STREAM) { 482 return -1; 483 } else if (err != OK) { 484 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 485 return false; 486 } 487 488 return trackIndex; 489} 490 491static jlong android_media_MediaExtractor_getSampleTime( 492 JNIEnv *env, jobject thiz) { 493 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 494 495 if (extractor == NULL) { 496 jniThrowException(env, "java/lang/IllegalStateException", NULL); 497 return -1ll; 498 } 499 500 int64_t sampleTimeUs; 501 status_t err = extractor->getSampleTime(&sampleTimeUs); 502 503 if (err == ERROR_END_OF_STREAM) { 504 return -1ll; 505 } else if (err != OK) { 506 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 507 return false; 508 } 509 510 return sampleTimeUs; 511} 512 513static jint android_media_MediaExtractor_getSampleFlags( 514 JNIEnv *env, jobject thiz) { 515 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 516 517 if (extractor == NULL) { 518 jniThrowException(env, "java/lang/IllegalStateException", NULL); 519 return -1ll; 520 } 521 522 uint32_t sampleFlags; 523 status_t err = extractor->getSampleFlags(&sampleFlags); 524 525 if (err == ERROR_END_OF_STREAM) { 526 return -1ll; 527 } else if (err != OK) { 528 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 529 return false; 530 } 531 532 return sampleFlags; 533} 534 535static jboolean android_media_MediaExtractor_getSampleCryptoInfo( 536 JNIEnv *env, jobject thiz, jobject cryptoInfoObj) { 537 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 538 539 if (extractor == NULL) { 540 jniThrowException(env, "java/lang/IllegalStateException", NULL); 541 return -1ll; 542 } 543 544 sp<MetaData> meta; 545 status_t err = extractor->getSampleMeta(&meta); 546 547 if (err != OK) { 548 return false; 549 } 550 551 uint32_t type; 552 const void *data; 553 size_t size; 554 if (!meta->findData(kKeyEncryptedSizes, &type, &data, &size)) { 555 return false; 556 } 557 558 size_t numSubSamples = size / sizeof(size_t); 559 560 if (numSubSamples == 0) { 561 return false; 562 } 563 564 jintArray numBytesOfEncryptedDataObj = env->NewIntArray(numSubSamples); 565 jboolean isCopy; 566 jint *dst = env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy); 567 for (size_t i = 0; i < numSubSamples; ++i) { 568 dst[i] = ((const size_t *)data)[i]; 569 } 570 env->ReleaseIntArrayElements(numBytesOfEncryptedDataObj, dst, 0); 571 dst = NULL; 572 573 size_t encSize = size; 574 jintArray numBytesOfPlainDataObj = NULL; 575 if (meta->findData(kKeyPlainSizes, &type, &data, &size)) { 576 if (size != encSize) { 577 // The two must be of the same length. 578 return false; 579 } 580 581 numBytesOfPlainDataObj = env->NewIntArray(numSubSamples); 582 jboolean isCopy; 583 jint *dst = env->GetIntArrayElements(numBytesOfPlainDataObj, &isCopy); 584 for (size_t i = 0; i < numSubSamples; ++i) { 585 dst[i] = ((const size_t *)data)[i]; 586 } 587 env->ReleaseIntArrayElements(numBytesOfPlainDataObj, dst, 0); 588 dst = NULL; 589 } 590 591 jbyteArray keyObj = NULL; 592 if (meta->findData(kKeyCryptoKey, &type, &data, &size)) { 593 if (size != 16) { 594 // Keys must be 16 bytes in length. 595 return false; 596 } 597 598 keyObj = env->NewByteArray(size); 599 jboolean isCopy; 600 jbyte *dst = env->GetByteArrayElements(keyObj, &isCopy); 601 memcpy(dst, data, size); 602 env->ReleaseByteArrayElements(keyObj, dst, 0); 603 dst = NULL; 604 } 605 606 jbyteArray ivObj = NULL; 607 if (meta->findData(kKeyCryptoIV, &type, &data, &size)) { 608 if (size != 16) { 609 // IVs must be 16 bytes in length. 610 return false; 611 } 612 613 ivObj = env->NewByteArray(size); 614 jboolean isCopy; 615 jbyte *dst = env->GetByteArrayElements(ivObj, &isCopy); 616 memcpy(dst, data, size); 617 env->ReleaseByteArrayElements(ivObj, dst, 0); 618 dst = NULL; 619 } 620 621 int32_t mode; 622 if (!meta->findInt32(kKeyCryptoMode, &mode)) { 623 mode = CryptoPlugin::kMode_AES_CTR; 624 } 625 626 env->CallVoidMethod( 627 cryptoInfoObj, 628 gFields.cryptoInfoSetID, 629 numSubSamples, 630 numBytesOfPlainDataObj, 631 numBytesOfEncryptedDataObj, 632 keyObj, 633 ivObj, 634 mode); 635 636 return true; 637} 638 639static void android_media_MediaExtractor_native_init(JNIEnv *env) { 640 jclass clazz = env->FindClass("android/media/MediaExtractor"); 641 CHECK(clazz != NULL); 642 643 gFields.context = env->GetFieldID(clazz, "mNativeContext", "I"); 644 CHECK(gFields.context != NULL); 645 646 clazz = env->FindClass("android/media/MediaCodec$CryptoInfo"); 647 CHECK(clazz != NULL); 648 649 gFields.cryptoInfoSetID = 650 env->GetMethodID(clazz, "set", "(I[I[I[B[BI)V"); 651 652 DataSource::RegisterDefaultSniffers(); 653} 654 655static void android_media_MediaExtractor_native_setup( 656 JNIEnv *env, jobject thiz) { 657 sp<JMediaExtractor> extractor = new JMediaExtractor(env, thiz); 658 setMediaExtractor(env,thiz, extractor); 659} 660 661static void android_media_MediaExtractor_setDataSource( 662 JNIEnv *env, jobject thiz, 663 jstring pathObj, jobjectArray keysArray, jobjectArray valuesArray) { 664 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 665 666 if (extractor == NULL) { 667 jniThrowException(env, "java/lang/IllegalStateException", NULL); 668 return; 669 } 670 671 if (pathObj == NULL) { 672 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 673 return; 674 } 675 676 KeyedVector<String8, String8> headers; 677 if (!ConvertKeyValueArraysToKeyedVector( 678 env, keysArray, valuesArray, &headers)) { 679 return; 680 } 681 682 const char *path = env->GetStringUTFChars(pathObj, NULL); 683 684 if (path == NULL) { 685 return; 686 } 687 688 status_t err = extractor->setDataSource(path, &headers); 689 690 env->ReleaseStringUTFChars(pathObj, path); 691 path = NULL; 692 693 if (err != OK) { 694 jniThrowException( 695 env, 696 "java/io/IOException", 697 "Failed to instantiate extractor."); 698 return; 699 } 700} 701 702static void android_media_MediaExtractor_setDataSourceFd( 703 JNIEnv *env, jobject thiz, 704 jobject fileDescObj, jlong offset, jlong length) { 705 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 706 707 if (extractor == NULL) { 708 jniThrowException(env, "java/lang/IllegalStateException", NULL); 709 return; 710 } 711 712 if (fileDescObj == NULL) { 713 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 714 return; 715 } 716 717 int fd = jniGetFDFromFileDescriptor(env, fileDescObj); 718 719 status_t err = extractor->setDataSource(fd, offset, length); 720 721 if (err != OK) { 722 jniThrowException( 723 env, 724 "java/io/IOException", 725 "Failed to instantiate extractor."); 726 return; 727 } 728} 729 730static void android_media_MediaExtractor_setDataSourceCallback( 731 JNIEnv *env, jobject thiz, 732 jobject callbackObj) { 733 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 734 735 if (extractor == NULL) { 736 jniThrowException(env, "java/lang/IllegalStateException", NULL); 737 return; 738 } 739 740 if (callbackObj == NULL) { 741 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 742 return; 743 } 744 745 sp<JavaDataSourceBridge> bridge = new JavaDataSourceBridge(env, callbackObj); 746 status_t err = extractor->setDataSource(bridge); 747 748 if (err != OK) { 749 jniThrowException( 750 env, 751 "java/io/IOException", 752 "Failed to instantiate extractor."); 753 return; 754 } 755} 756 757static jlong android_media_MediaExtractor_getCachedDurationUs( 758 JNIEnv *env, jobject thiz) { 759 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 760 761 if (extractor == NULL) { 762 jniThrowException(env, "java/lang/IllegalStateException", NULL); 763 return -1ll; 764 } 765 766 int64_t cachedDurationUs; 767 bool eos; 768 if (!extractor->getCachedDuration(&cachedDurationUs, &eos)) { 769 return -1ll; 770 } 771 772 return cachedDurationUs; 773} 774 775static jboolean android_media_MediaExtractor_hasCacheReachedEOS( 776 JNIEnv *env, jobject thiz) { 777 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz); 778 779 if (extractor == NULL) { 780 jniThrowException(env, "java/lang/IllegalStateException", NULL); 781 return true; 782 } 783 784 int64_t cachedDurationUs; 785 bool eos; 786 if (!extractor->getCachedDuration(&cachedDurationUs, &eos)) { 787 return true; 788 } 789 790 return eos; 791} 792 793static void android_media_MediaExtractor_native_finalize( 794 JNIEnv *env, jobject thiz) { 795 android_media_MediaExtractor_release(env, thiz); 796} 797 798static JNINativeMethod gMethods[] = { 799 { "release", "()V", (void *)android_media_MediaExtractor_release }, 800 801 { "getTrackCount", "()I", (void *)android_media_MediaExtractor_getTrackCount }, 802 803 { "getFileFormatNative", "()Ljava/util/Map;", 804 (void *)android_media_MediaExtractor_getFileFormatNative }, 805 806 { "getTrackFormatNative", "(I)Ljava/util/Map;", 807 (void *)android_media_MediaExtractor_getTrackFormatNative }, 808 809 { "selectTrack", "(I)V", (void *)android_media_MediaExtractor_selectTrack }, 810 811 { "unselectTrack", "(I)V", 812 (void *)android_media_MediaExtractor_unselectTrack }, 813 814 { "seekTo", "(JI)V", (void *)android_media_MediaExtractor_seekTo }, 815 816 { "advance", "()Z", (void *)android_media_MediaExtractor_advance }, 817 818 { "readSampleData", "(Ljava/nio/ByteBuffer;I)I", 819 (void *)android_media_MediaExtractor_readSampleData }, 820 821 { "getSampleTrackIndex", "()I", 822 (void *)android_media_MediaExtractor_getSampleTrackIndex }, 823 824 { "getSampleTime", "()J", 825 (void *)android_media_MediaExtractor_getSampleTime }, 826 827 { "getSampleFlags", "()I", 828 (void *)android_media_MediaExtractor_getSampleFlags }, 829 830 { "getSampleCryptoInfo", "(Landroid/media/MediaCodec$CryptoInfo;)Z", 831 (void *)android_media_MediaExtractor_getSampleCryptoInfo }, 832 833 { "native_init", "()V", (void *)android_media_MediaExtractor_native_init }, 834 835 { "native_setup", "()V", 836 (void *)android_media_MediaExtractor_native_setup }, 837 838 { "native_finalize", "()V", 839 (void *)android_media_MediaExtractor_native_finalize }, 840 841 { "setDataSource", "(Ljava/lang/String;[Ljava/lang/String;" 842 "[Ljava/lang/String;)V", 843 (void *)android_media_MediaExtractor_setDataSource }, 844 845 { "setDataSource", "(Ljava/io/FileDescriptor;JJ)V", 846 (void *)android_media_MediaExtractor_setDataSourceFd }, 847 848 { "setDataSource", "(Landroid/media/DataSource;)V", 849 (void *)android_media_MediaExtractor_setDataSourceCallback }, 850 851 { "getCachedDuration", "()J", 852 (void *)android_media_MediaExtractor_getCachedDurationUs }, 853 854 { "hasCacheReachedEndOfStream", "()Z", 855 (void *)android_media_MediaExtractor_hasCacheReachedEOS }, 856}; 857 858int register_android_media_MediaExtractor(JNIEnv *env) { 859 return AndroidRuntime::registerNativeMethods(env, 860 "android/media/MediaExtractor", gMethods, NELEM(gMethods)); 861} 862