2 * Copyright 2012, The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "MediaExtractor-JNI"
19 #include <utils/Log.h>
21 #include "android_media_MediaDataSource.h"
22 #include "android_media_MediaExtractor.h"
23 #include "android_media_MediaMetricsJNI.h"
24 #include "android_media_Utils.h"
25 #include "android_os_HwRemoteBinder.h"
26 #include "android_runtime/AndroidRuntime.h"
27 #include "android_runtime/Log.h"
28 #include "android_util_Binder.h"
32 #include <android/hardware/cas/1.0/BpHwCas.h>
33 #include <android/hardware/cas/1.0/BnHwCas.h>
34 #include <hidl/HybridInterface.h>
35 #include <media/IMediaHTTPService.h>
36 #include <media/hardware/CryptoAPI.h>
37 #include <media/stagefright/foundation/ABuffer.h>
38 #include <media/stagefright/foundation/ADebug.h>
39 #include <media/stagefright/foundation/AMessage.h>
40 #include <media/stagefright/DataSource.h>
41 #include <media/stagefright/MediaErrors.h>
42 #include <media/stagefright/MetaData.h>
43 #include <media/stagefright/NuMediaExtractor.h>
44 #include <nativehelper/ScopedLocalRef.h>
48 using namespace hardware::cas::V1_0;
53 jmethodID cryptoInfoSetID;
56 static fields_t gFields;
58 JMediaExtractor::JMediaExtractor(JNIEnv *env, jobject thiz)
61 jclass clazz = env->GetObjectClass(thiz);
64 mClass = (jclass)env->NewGlobalRef(clazz);
65 mObject = env->NewWeakGlobalRef(thiz);
67 mImpl = new NuMediaExtractor;
70 JMediaExtractor::~JMediaExtractor() {
71 JNIEnv *env = AndroidRuntime::getJNIEnv();
73 env->DeleteWeakGlobalRef(mObject);
75 env->DeleteGlobalRef(mClass);
79 status_t JMediaExtractor::setDataSource(
80 const sp<IMediaHTTPService> &httpService,
82 const KeyedVector<String8, String8> *headers) {
83 return mImpl->setDataSource(httpService, path, headers);
86 status_t JMediaExtractor::setDataSource(int fd, off64_t offset, off64_t size) {
87 return mImpl->setDataSource(fd, offset, size);
90 status_t JMediaExtractor::setDataSource(const sp<DataSource> &datasource) {
91 return mImpl->setDataSource(datasource);
94 status_t JMediaExtractor::setMediaCas(JNIEnv *env, jobject casBinderObj) {
95 if (casBinderObj == NULL) {
99 sp<hardware::IBinder> hwBinder =
100 JHwRemoteBinder::GetNativeContext(env, casBinderObj)->getBinder();
101 if (hwBinder == NULL) {
105 sp<ICas> cas = hardware::fromBinder<ICas, BpHwCas, BnHwCas>(hwBinder);
111 if (!createHalToken(cas, &halToken)) {
115 return mImpl->setMediaCas(halToken);
118 size_t JMediaExtractor::countTracks() const {
119 return mImpl->countTracks();
122 status_t JMediaExtractor::getTrackFormat(size_t index, jobject *format) const {
125 if ((err = mImpl->getTrackFormat(index, &msg)) != OK) {
129 JNIEnv *env = AndroidRuntime::getJNIEnv();
131 return ConvertMessageToMap(env, msg, format);
134 status_t JMediaExtractor::getFileFormat(jobject *format) const {
137 if ((err = mImpl->getFileFormat(&msg)) != OK) {
141 JNIEnv *env = AndroidRuntime::getJNIEnv();
143 return ConvertMessageToMap(env, msg, format);
146 status_t JMediaExtractor::selectTrack(size_t index) {
147 return mImpl->selectTrack(index);
150 status_t JMediaExtractor::unselectTrack(size_t index) {
151 return mImpl->unselectTrack(index);
154 status_t JMediaExtractor::seekTo(
155 int64_t timeUs, MediaSource::ReadOptions::SeekMode mode) {
156 return mImpl->seekTo(timeUs, mode);
159 status_t JMediaExtractor::advance() {
160 return mImpl->advance();
163 status_t JMediaExtractor::readSampleData(
164 jobject byteBuf, size_t offset, size_t *sampleSize) {
165 JNIEnv *env = AndroidRuntime::getJNIEnv();
167 void *dst = env->GetDirectBufferAddress(byteBuf);
170 jbyteArray byteArray = NULL;
172 ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer"));
173 CHECK(byteBufClass.get() != NULL);
177 env->GetMethodID(byteBufClass.get(), "array", "()[B");
178 CHECK(arrayID != NULL);
181 (jbyteArray)env->CallObjectMethod(byteBuf, arrayID);
183 if (byteArray == NULL) {
184 return INVALID_OPERATION;
188 dst = env->GetByteArrayElements(byteArray, &isCopy);
190 dstSize = (size_t) env->GetArrayLength(byteArray);
192 dstSize = (size_t) env->GetDirectBufferCapacity(byteBuf);
195 if (dstSize < offset) {
196 if (byteArray != NULL) {
197 env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0);
203 sp<ABuffer> buffer = new ABuffer((char *)dst + offset, dstSize - offset);
205 status_t err = mImpl->readSampleData(buffer);
207 if (byteArray != NULL) {
208 env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0);
215 *sampleSize = buffer->size();
217 jmethodID positionID = env->GetMethodID(
218 byteBufClass.get(), "position", "(I)Ljava/nio/Buffer;");
220 CHECK(positionID != NULL);
222 jmethodID limitID = env->GetMethodID(
223 byteBufClass.get(), "limit", "(I)Ljava/nio/Buffer;");
225 CHECK(limitID != NULL);
227 jobject me = env->CallObjectMethod(
228 byteBuf, limitID, offset + *sampleSize);
229 env->DeleteLocalRef(me);
230 me = env->CallObjectMethod(
231 byteBuf, positionID, offset);
232 env->DeleteLocalRef(me);
238 status_t JMediaExtractor::getSampleTrackIndex(size_t *trackIndex) {
239 return mImpl->getSampleTrackIndex(trackIndex);
242 status_t JMediaExtractor::getSampleTime(int64_t *sampleTimeUs) {
243 return mImpl->getSampleTime(sampleTimeUs);
246 status_t JMediaExtractor::getSampleFlags(uint32_t *sampleFlags) {
250 status_t err = mImpl->getSampleMeta(&meta);
257 if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) {
258 (*sampleFlags) |= NuMediaExtractor::SAMPLE_FLAG_SYNC;
264 if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) {
265 (*sampleFlags) |= NuMediaExtractor::SAMPLE_FLAG_ENCRYPTED;
271 status_t JMediaExtractor::getMetrics(Parcel *reply) const {
273 status_t status = mImpl->getMetrics(reply);
278 status_t JMediaExtractor::getSampleMeta(sp<MetaData> *sampleMeta) {
279 return mImpl->getSampleMeta(sampleMeta);
282 bool JMediaExtractor::getCachedDuration(int64_t *durationUs, bool *eos) const {
283 return mImpl->getCachedDuration(durationUs, eos);
286 } // namespace android
288 ////////////////////////////////////////////////////////////////////////////////
290 using namespace android;
292 static sp<JMediaExtractor> setMediaExtractor(
293 JNIEnv *env, jobject thiz, const sp<JMediaExtractor> &extractor) {
294 sp<JMediaExtractor> old =
295 (JMediaExtractor *)env->GetLongField(thiz, gFields.context);
297 if (extractor != NULL) {
298 extractor->incStrong(thiz);
301 old->decStrong(thiz);
303 env->SetLongField(thiz, gFields.context, (jlong)extractor.get());
308 static sp<JMediaExtractor> getMediaExtractor(JNIEnv *env, jobject thiz) {
309 return (JMediaExtractor *)env->GetLongField(thiz, gFields.context);
312 static void android_media_MediaExtractor_release(JNIEnv *env, jobject thiz) {
313 setMediaExtractor(env, thiz, NULL);
316 static jint android_media_MediaExtractor_getTrackCount(
317 JNIEnv *env, jobject thiz) {
318 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
320 if (extractor == NULL) {
321 jniThrowException(env, "java/lang/IllegalStateException", NULL);
325 return (jint) extractor->countTracks();
328 static jobject android_media_MediaExtractor_getTrackFormatNative(
329 JNIEnv *env, jobject thiz, jint index) {
330 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
332 if (extractor == NULL) {
333 jniThrowException(env, "java/lang/IllegalStateException", NULL);
338 status_t err = extractor->getTrackFormat(index, &format);
341 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
348 static jobject android_media_MediaExtractor_getFileFormatNative(
349 JNIEnv *env, jobject thiz) {
350 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
352 if (extractor == NULL) {
353 jniThrowException(env, "java/lang/IllegalStateException", NULL);
358 status_t err = extractor->getFileFormat(&format);
361 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
368 static void android_media_MediaExtractor_selectTrack(
369 JNIEnv *env, jobject thiz, jint index) {
370 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
372 if (extractor == NULL) {
373 jniThrowException(env, "java/lang/IllegalStateException", NULL);
377 status_t err = extractor->selectTrack(index);
380 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
385 static void android_media_MediaExtractor_unselectTrack(
386 JNIEnv *env, jobject thiz, jint index) {
387 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
389 if (extractor == NULL) {
390 jniThrowException(env, "java/lang/IllegalStateException", NULL);
394 status_t err = extractor->unselectTrack(index);
397 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
402 static void android_media_MediaExtractor_seekTo(
403 JNIEnv *env, jobject thiz, jlong timeUs, jint mode) {
404 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
406 if (extractor == NULL) {
407 jniThrowException(env, "java/lang/IllegalStateException", NULL);
411 if (mode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC
412 || mode >= MediaSource::ReadOptions::SEEK_CLOSEST) {
413 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
417 extractor->seekTo(timeUs, (MediaSource::ReadOptions::SeekMode)mode);
420 static jboolean android_media_MediaExtractor_advance(
421 JNIEnv *env, jobject thiz) {
422 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
424 if (extractor == NULL) {
425 jniThrowException(env, "java/lang/IllegalStateException", NULL);
429 status_t err = extractor->advance();
431 if (err == ERROR_END_OF_STREAM) {
433 } else if (err != OK) {
434 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
441 static jint android_media_MediaExtractor_readSampleData(
442 JNIEnv *env, jobject thiz, jobject byteBuf, jint offset) {
443 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
445 if (extractor == NULL) {
446 jniThrowException(env, "java/lang/IllegalStateException", NULL);
451 status_t err = extractor->readSampleData(byteBuf, offset, &sampleSize);
453 if (err == ERROR_END_OF_STREAM) {
455 } else if (err != OK) {
456 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
460 return (jint) sampleSize;
463 static jint android_media_MediaExtractor_getSampleTrackIndex(
464 JNIEnv *env, jobject thiz) {
465 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
467 if (extractor == NULL) {
468 jniThrowException(env, "java/lang/IllegalStateException", NULL);
473 status_t err = extractor->getSampleTrackIndex(&trackIndex);
475 if (err == ERROR_END_OF_STREAM) {
477 } else if (err != OK) {
478 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
482 return (jint) trackIndex;
485 static jlong android_media_MediaExtractor_getSampleTime(
486 JNIEnv *env, jobject thiz) {
487 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
489 if (extractor == NULL) {
490 jniThrowException(env, "java/lang/IllegalStateException", NULL);
494 int64_t sampleTimeUs;
495 status_t err = extractor->getSampleTime(&sampleTimeUs);
497 if (err == ERROR_END_OF_STREAM) {
499 } else if (err != OK) {
500 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
504 return (jlong) sampleTimeUs;
507 static jint android_media_MediaExtractor_getSampleFlags(
508 JNIEnv *env, jobject thiz) {
509 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
511 if (extractor == NULL) {
512 jniThrowException(env, "java/lang/IllegalStateException", NULL);
516 uint32_t sampleFlags;
517 status_t err = extractor->getSampleFlags(&sampleFlags);
519 if (err == ERROR_END_OF_STREAM) {
521 } else if (err != OK) {
522 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
526 return (jint) sampleFlags;
529 static jboolean android_media_MediaExtractor_getSampleCryptoInfo(
530 JNIEnv *env, jobject thiz, jobject cryptoInfoObj) {
531 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
533 if (extractor == NULL) {
534 jniThrowException(env, "java/lang/IllegalStateException", NULL);
539 status_t err = extractor->getSampleMeta(&meta);
548 if (!meta->findData(kKeyEncryptedSizes, &type, &data, &size)) {
552 size_t numSubSamples = size / sizeof(int32_t);
554 if (numSubSamples == 0) {
558 jintArray numBytesOfEncryptedDataObj = env->NewIntArray(numSubSamples);
560 jint *dst = env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
561 for (size_t i = 0; i < numSubSamples; ++i) {
562 dst[i] = ((const int32_t *)data)[i];
564 env->ReleaseIntArrayElements(numBytesOfEncryptedDataObj, dst, 0);
567 size_t encSize = size;
568 jintArray numBytesOfPlainDataObj = NULL;
569 if (meta->findData(kKeyPlainSizes, &type, &data, &size)) {
570 if (size != encSize) {
571 // The two must be of the same length.
575 numBytesOfPlainDataObj = env->NewIntArray(numSubSamples);
577 jint *dst = env->GetIntArrayElements(numBytesOfPlainDataObj, &isCopy);
578 for (size_t i = 0; i < numSubSamples; ++i) {
579 dst[i] = ((const int32_t *)data)[i];
581 env->ReleaseIntArrayElements(numBytesOfPlainDataObj, dst, 0);
585 jbyteArray keyObj = NULL;
586 if (meta->findData(kKeyCryptoKey, &type, &data, &size)) {
588 // Keys must be 16 bytes in length.
592 keyObj = env->NewByteArray(size);
594 jbyte *dst = env->GetByteArrayElements(keyObj, &isCopy);
595 memcpy(dst, data, size);
596 env->ReleaseByteArrayElements(keyObj, dst, 0);
600 jbyteArray ivObj = NULL;
601 if (meta->findData(kKeyCryptoIV, &type, &data, &size)) {
603 // IVs must be 16 bytes in length.
607 ivObj = env->NewByteArray(size);
609 jbyte *dst = env->GetByteArrayElements(ivObj, &isCopy);
610 memcpy(dst, data, size);
611 env->ReleaseByteArrayElements(ivObj, dst, 0);
616 if (!meta->findInt32(kKeyCryptoMode, &mode)) {
617 mode = CryptoPlugin::kMode_AES_CTR;
622 gFields.cryptoInfoSetID,
624 numBytesOfPlainDataObj,
625 numBytesOfEncryptedDataObj,
633 static void android_media_MediaExtractor_native_init(JNIEnv *env) {
634 jclass clazz = env->FindClass("android/media/MediaExtractor");
635 CHECK(clazz != NULL);
637 gFields.context = env->GetFieldID(clazz, "mNativeContext", "J");
638 CHECK(gFields.context != NULL);
640 clazz = env->FindClass("android/media/MediaCodec$CryptoInfo");
641 CHECK(clazz != NULL);
643 gFields.cryptoInfoSetID =
644 env->GetMethodID(clazz, "set", "(I[I[I[B[BI)V");
647 static void android_media_MediaExtractor_native_setup(
648 JNIEnv *env, jobject thiz) {
649 sp<JMediaExtractor> extractor = new JMediaExtractor(env, thiz);
650 setMediaExtractor(env,thiz, extractor);
653 static void android_media_MediaExtractor_setDataSource(
654 JNIEnv *env, jobject thiz,
655 jobject httpServiceBinderObj,
657 jobjectArray keysArray,
658 jobjectArray valuesArray) {
659 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
661 if (extractor == NULL) {
662 jniThrowException(env, "java/lang/IllegalStateException", NULL);
666 if (pathObj == NULL) {
667 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
671 KeyedVector<String8, String8> headers;
672 if (!ConvertKeyValueArraysToKeyedVector(
673 env, keysArray, valuesArray, &headers)) {
677 const char *path = env->GetStringUTFChars(pathObj, NULL);
683 sp<IMediaHTTPService> httpService;
684 if (httpServiceBinderObj != NULL) {
685 sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj);
686 httpService = interface_cast<IMediaHTTPService>(binder);
689 status_t err = extractor->setDataSource(httpService, path, &headers);
691 env->ReleaseStringUTFChars(pathObj, path);
697 "java/io/IOException",
698 "Failed to instantiate extractor.");
703 static void android_media_MediaExtractor_setDataSourceFd(
704 JNIEnv *env, jobject thiz,
705 jobject fileDescObj, jlong offset, jlong length) {
706 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
708 if (extractor == NULL) {
709 jniThrowException(env, "java/lang/IllegalStateException", NULL);
713 if (fileDescObj == NULL) {
714 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
718 int fd = jniGetFDFromFileDescriptor(env, fileDescObj);
720 status_t err = extractor->setDataSource(fd, offset, length);
725 "java/io/IOException",
726 "Failed to instantiate extractor.");
731 static void android_media_MediaExtractor_setDataSourceCallback(
732 JNIEnv *env, jobject thiz,
733 jobject callbackObj) {
734 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
736 if (extractor == NULL) {
737 jniThrowException(env, "java/lang/IllegalStateException", NULL);
741 if (callbackObj == NULL) {
742 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
746 sp<DataSource> bridge =
747 DataSource::CreateFromIDataSource(new JMediaDataSource(env, callbackObj));
748 status_t err = extractor->setDataSource(bridge);
751 // Clear bridge so that JMediaDataSource::close() is called _before_
752 // we throw the IOException.
753 // Otherwise close() gets called when we go out of scope, it calls
754 // Java with a pending exception and crashes the process.
758 "java/io/IOException",
759 "Failed to instantiate extractor.");
764 static void android_media_MediaExtractor_setMediaCas(
765 JNIEnv *env, jobject thiz, jobject casBinderObj) {
766 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
768 if (extractor == NULL) {
769 jniThrowException(env, "java/lang/IllegalStateException", NULL);
773 status_t err = extractor->setMediaCas(env, casBinderObj);
779 "java/lang/IllegalArgumentException",
780 "Failed to set MediaCas on extractor.");
784 static jlong android_media_MediaExtractor_getCachedDurationUs(
785 JNIEnv *env, jobject thiz) {
786 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
788 if (extractor == NULL) {
789 jniThrowException(env, "java/lang/IllegalStateException", NULL);
793 int64_t cachedDurationUs;
795 if (!extractor->getCachedDuration(&cachedDurationUs, &eos)) {
799 return (jlong) cachedDurationUs;
802 static jboolean android_media_MediaExtractor_hasCacheReachedEOS(
803 JNIEnv *env, jobject thiz) {
804 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
806 if (extractor == NULL) {
807 jniThrowException(env, "java/lang/IllegalStateException", NULL);
811 int64_t cachedDurationUs;
813 if (!extractor->getCachedDuration(&cachedDurationUs, &eos)) {
817 return eos ? JNI_TRUE : JNI_FALSE;
820 static void android_media_MediaExtractor_native_finalize(
821 JNIEnv *env, jobject thiz) {
822 android_media_MediaExtractor_release(env, thiz);
826 android_media_MediaExtractor_native_getMetrics(JNIEnv * env, jobject thiz)
828 ALOGV("android_media_MediaExtractor_native_getMetrics");
830 sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
831 if (extractor == NULL ) {
832 jniThrowException(env, "java/lang/IllegalStateException", NULL);
836 // get what we have for the metrics from the codec
838 status_t err = extractor->getMetrics(&reply);
840 ALOGE("getMetrics failed");
841 return (jobject) NULL;
844 // build and return the Bundle
845 MediaAnalyticsItem *item = new MediaAnalyticsItem;
846 item->readFromParcel(reply);
847 jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL);
857 static const JNINativeMethod gMethods[] = {
858 { "release", "()V", (void *)android_media_MediaExtractor_release },
860 { "getTrackCount", "()I", (void *)android_media_MediaExtractor_getTrackCount },
862 { "getFileFormatNative", "()Ljava/util/Map;",
863 (void *)android_media_MediaExtractor_getFileFormatNative },
865 { "getTrackFormatNative", "(I)Ljava/util/Map;",
866 (void *)android_media_MediaExtractor_getTrackFormatNative },
868 { "selectTrack", "(I)V", (void *)android_media_MediaExtractor_selectTrack },
870 { "unselectTrack", "(I)V",
871 (void *)android_media_MediaExtractor_unselectTrack },
873 { "seekTo", "(JI)V", (void *)android_media_MediaExtractor_seekTo },
875 { "advance", "()Z", (void *)android_media_MediaExtractor_advance },
877 { "readSampleData", "(Ljava/nio/ByteBuffer;I)I",
878 (void *)android_media_MediaExtractor_readSampleData },
880 { "getSampleTrackIndex", "()I",
881 (void *)android_media_MediaExtractor_getSampleTrackIndex },
883 { "getSampleTime", "()J",
884 (void *)android_media_MediaExtractor_getSampleTime },
886 { "getSampleFlags", "()I",
887 (void *)android_media_MediaExtractor_getSampleFlags },
889 { "getSampleCryptoInfo", "(Landroid/media/MediaCodec$CryptoInfo;)Z",
890 (void *)android_media_MediaExtractor_getSampleCryptoInfo },
892 { "native_init", "()V", (void *)android_media_MediaExtractor_native_init },
894 { "native_setup", "()V",
895 (void *)android_media_MediaExtractor_native_setup },
897 { "native_finalize", "()V",
898 (void *)android_media_MediaExtractor_native_finalize },
900 { "nativeSetDataSource",
901 "(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
902 "[Ljava/lang/String;)V",
903 (void *)android_media_MediaExtractor_setDataSource },
905 { "setDataSource", "(Ljava/io/FileDescriptor;JJ)V",
906 (void *)android_media_MediaExtractor_setDataSourceFd },
908 { "setDataSource", "(Landroid/media/MediaDataSource;)V",
909 (void *)android_media_MediaExtractor_setDataSourceCallback },
911 { "nativeSetMediaCas", "(Landroid/os/IHwBinder;)V",
912 (void *)android_media_MediaExtractor_setMediaCas },
914 { "getCachedDuration", "()J",
915 (void *)android_media_MediaExtractor_getCachedDurationUs },
917 { "hasCacheReachedEndOfStream", "()Z",
918 (void *)android_media_MediaExtractor_hasCacheReachedEOS },
920 {"native_getMetrics", "()Landroid/os/PersistableBundle;",
921 (void *)android_media_MediaExtractor_native_getMetrics},
924 int register_android_media_MediaExtractor(JNIEnv *env) {
925 return AndroidRuntime::registerNativeMethods(env,
926 "android/media/MediaExtractor", gMethods, NELEM(gMethods));