@@ -44,6 +44,72 @@ struct fields_t {
4444
4545static fields_t gFields ;
4646
47+ class 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+
47113// //////////////////////////////////////////////////////////////////////////////
48114
49115JMediaExtractor::JMediaExtractor (JNIEnv *env, jobject thiz)
@@ -76,6 +142,10 @@ status_t JMediaExtractor::setDataSource(int fd, off64_t offset, off64_t size) {
76142 return mImpl ->setDataSource (fd, offset, size);
77143}
78144
145+ status_t JMediaExtractor::setDataSource (const sp<DataSource> &datasource) {
146+ return mImpl ->setDataSource (datasource);
147+ }
148+
79149size_t JMediaExtractor::countTracks () const {
80150 return mImpl ->countTracks ();
81151}
@@ -625,6 +695,33 @@ static void android_media_MediaExtractor_setDataSourceFd(
625695 }
626696}
627697
698+ static void android_media_MediaExtractor_setDataSourceCallback (
699+ JNIEnv *env, jobject thiz,
700+ jobject callbackObj) {
701+ sp<JMediaExtractor> extractor = getMediaExtractor (env, thiz);
702+
703+ if (extractor == NULL ) {
704+ jniThrowException (env, " java/lang/IllegalStateException" , NULL );
705+ return ;
706+ }
707+
708+ if (callbackObj == NULL ) {
709+ jniThrowException (env, " java/lang/IllegalArgumentException" , NULL );
710+ return ;
711+ }
712+
713+ sp<JavaDataSourceBridge> bridge = new JavaDataSourceBridge (env, callbackObj);
714+ status_t err = extractor->setDataSource (bridge);
715+
716+ if (err != OK) {
717+ jniThrowException (
718+ env,
719+ " java/io/IOException" ,
720+ " Failed to instantiate extractor." );
721+ return ;
722+ }
723+ }
724+
628725static jlong android_media_MediaExtractor_getCachedDurationUs (
629726 JNIEnv *env, jobject thiz) {
630727 sp<JMediaExtractor> extractor = getMediaExtractor (env, thiz);
@@ -713,6 +810,9 @@ static JNINativeMethod gMethods[] = {
713810 { " setDataSource" , " (Ljava/io/FileDescriptor;JJ)V" ,
714811 (void *)android_media_MediaExtractor_setDataSourceFd },
715812
813+ { " setDataSource" , " (Landroid/media/DataSource;)V" ,
814+ (void *)android_media_MediaExtractor_setDataSourceCallback },
815+
716816 { " getCachedDuration" , " ()J" ,
717817 (void *)android_media_MediaExtractor_getCachedDurationUs },
718818
0 commit comments