188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber/*
288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Copyright 2012, The Android Open Source Project
388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *
488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * you may not use this file except in compliance with the License.
688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * You may obtain a copy of the License at
788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *
888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *
1088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Unless required by applicable law or agreed to in writing, software
1188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * See the License for the specific language governing permissions and
1488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * limitations under the License.
1588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber */
1688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber//#define LOG_NDEBUG 0
1888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#define LOG_TAG "MediaExtractor-JNI"
1988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <utils/Log.h>
2088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_media_MediaExtractor.h"
2288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_media_Utils.h"
2488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_runtime/AndroidRuntime.h"
2588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "jni.h"
2688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "JNIHelp.h"
2788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28ab57d03bdb3010d4957fb88c8acb30575ca02ec9Andreas Huber#include <media/hardware/CryptoAPI.h>
2988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
3088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
3188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
3288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/DataSource.h>
3388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaErrors.h>
3491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber#include <media/stagefright/MetaData.h>
3588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/NuMediaExtractor.h>
3688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android {
3888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
4088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
4191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
4291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jmethodID cryptoInfoSetID;
4388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
4488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
4688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
47c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissenclass JavaDataSourceBridge : public DataSource {
48c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    jmethodID mReadMethod;
49c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    jmethodID mGetSizeMethod;
50c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    jmethodID mCloseMethod;
51c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    jobject   mDataSource;
52c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen public:
53c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    JavaDataSourceBridge(JNIEnv *env, jobject source) {
54c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        mDataSource = env->NewGlobalRef(source);
55c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
56c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        jclass datasourceclass = env->GetObjectClass(mDataSource);
57c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        CHECK(datasourceclass != NULL);
58c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
59c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        mReadMethod = env->GetMethodID(datasourceclass, "readAt", "(J[BI)I");
60c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        CHECK(mReadMethod != NULL);
61c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
62c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        mGetSizeMethod = env->GetMethodID(datasourceclass, "getSize", "()J");
63c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        CHECK(mGetSizeMethod != NULL);
64c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
65c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        mCloseMethod = env->GetMethodID(datasourceclass, "close", "()V");
66c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        CHECK(mCloseMethod != NULL);
67c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    }
68c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
69c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    ~JavaDataSourceBridge() {
70c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        JNIEnv *env = AndroidRuntime::getJNIEnv();
71c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        env->CallVoidMethod(mDataSource, mCloseMethod);
72c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        env->DeleteGlobalRef(mDataSource);
73c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    }
74c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
75c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    virtual status_t initCheck() const {
76c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        return OK;
77c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    }
78c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
79c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    virtual ssize_t readAt(off64_t offset, void* buffer, size_t size) {
80c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        JNIEnv *env = AndroidRuntime::getJNIEnv();
81c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
82c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        // XXX could optimize this by reusing the same array
83c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        jbyteArray byteArrayObj = env->NewByteArray(size);
84c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        env->DeleteLocalRef(env->GetObjectClass(mDataSource));
85c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        env->DeleteLocalRef(env->GetObjectClass(byteArrayObj));
86c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, size);
87c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        env->GetByteArrayRegion(byteArrayObj, 0, size, (jbyte*) buffer);
88c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        env->DeleteLocalRef(byteArrayObj);
89c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        if (env->ExceptionCheck()) {
90c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen            ALOGW("Exception occurred while reading %d at %lld", size, offset);
91c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen            LOGW_EX(env);
92c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen            env->ExceptionClear();
93c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen            return -1;
94c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        }
95c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        return numread;
96c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    }
97c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
98c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    virtual status_t getSize(off64_t *size) {
99c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        JNIEnv *env = AndroidRuntime::getJNIEnv();
100c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
101c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        CHECK(size != NULL);
102c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
103c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        int64_t len = env->CallLongMethod(mDataSource, mGetSizeMethod);
104c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        if (len < 0) {
105c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen            *size = ERROR_UNSUPPORTED;
106c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        } else {
107c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen            *size = len;
108c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        }
109c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        return OK;
110c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    }
111c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen};
112c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaExtractor::JMediaExtractor(JNIEnv *env, jobject thiz)
11688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
11788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      mObject(NULL) {
11888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
11988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
12088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
12288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
12388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mImpl = new NuMediaExtractor;
12588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
12688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaExtractor::~JMediaExtractor() {
12888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
12988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
13188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
13288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
13388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
13488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
13588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberstatus_t JMediaExtractor::setDataSource(
13707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        const char *path, const KeyedVector<String8, String8> *headers) {
13807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    return mImpl->setDataSource(path, headers);
13907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber}
14007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
14107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberstatus_t JMediaExtractor::setDataSource(int fd, off64_t offset, off64_t size) {
14207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    return mImpl->setDataSource(fd, offset, size);
14388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
14488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
145c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissenstatus_t JMediaExtractor::setDataSource(const sp<DataSource> &datasource) {
146c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    return mImpl->setDataSource(datasource);
147c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen}
148c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
14988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubersize_t JMediaExtractor::countTracks() const {
15088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->countTracks();
15188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
15288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::getTrackFormat(size_t index, jobject *format) const {
15488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
15588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
15688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if ((err = mImpl->getTrackFormat(index, &msg)) != OK) {
15788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
15888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
15988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
16188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
16388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
16488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::selectTrack(size_t index) {
16688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->selectTrack(index);
16788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
16888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
169f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huberstatus_t JMediaExtractor::unselectTrack(size_t index) {
170f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    return mImpl->unselectTrack(index);
171f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber}
172f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
173f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huberstatus_t JMediaExtractor::seekTo(
174f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode) {
175f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    return mImpl->seekTo(timeUs, mode);
17688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
17788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::advance() {
17988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->advance();
18088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
18188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::readSampleData(
18388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject byteBuf, size_t offset, size_t *sampleSize) {
18488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
18588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    void *dst = env->GetDirectBufferAddress(byteBuf);
18788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
188c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber    jlong dstSize;
189c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber    jbyteArray byteArray = NULL;
190c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
19188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (dst == NULL) {
192c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        jclass byteBufClass = env->FindClass("java/nio/ByteBuffer");
193c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        CHECK(byteBufClass != NULL);
194c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
195c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        jmethodID arrayID =
196c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber            env->GetMethodID(byteBufClass, "array", "()[B");
197c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        CHECK(arrayID != NULL);
198c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
199c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        byteArray =
200c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber            (jbyteArray)env->CallObjectMethod(byteBuf, arrayID);
201c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
202c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        if (byteArray == NULL) {
203c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber            return INVALID_OPERATION;
204c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        }
20588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
206c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        jboolean isCopy;
207c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        dst = env->GetByteArrayElements(byteArray, &isCopy);
208c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
209c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        dstSize = env->GetArrayLength(byteArray);
210c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber    } else {
211c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        dstSize = env->GetDirectBufferCapacity(byteBuf);
212c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber    }
21388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (dstSize < offset) {
215c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        if (byteArray != NULL) {
216c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber            env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0);
217c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        }
218c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
21988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -ERANGE;
22088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
22188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<ABuffer> buffer = new ABuffer((char *)dst + offset, dstSize - offset);
22388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = mImpl->readSampleData(buffer);
22588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
226c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber    if (byteArray != NULL) {
227c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0);
228c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber    }
229c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
23088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
23188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
23288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
23388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *sampleSize = buffer->size();
23588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
23788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
23888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::getSampleTrackIndex(size_t *trackIndex) {
24088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->getSampleTrackIndex(trackIndex);
24188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
24288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::getSampleTime(int64_t *sampleTimeUs) {
24488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->getSampleTime(sampleTimeUs);
24588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2479b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huberstatus_t JMediaExtractor::getSampleFlags(uint32_t *sampleFlags) {
24891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    *sampleFlags = 0;
24991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
25091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    sp<MetaData> meta;
25191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    status_t err = mImpl->getSampleMeta(&meta);
25291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
25391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (err != OK) {
25491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        return err;
25591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
25691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
25791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    int32_t val;
25891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) {
25991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (*sampleFlags) |= NuMediaExtractor::SAMPLE_FLAG_SYNC;
26091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
26191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
26291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    uint32_t type;
26391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    const void *data;
26491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    size_t size;
26591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) {
26691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (*sampleFlags) |= NuMediaExtractor::SAMPLE_FLAG_ENCRYPTED;
26791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
26891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
26991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    return OK;
27091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber}
27191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
27291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huberstatus_t JMediaExtractor::getSampleMeta(sp<MetaData> *sampleMeta) {
27391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    return mImpl->getSampleMeta(sampleMeta);
2749b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber}
2759b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
27674a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huberbool JMediaExtractor::getCachedDuration(int64_t *durationUs, bool *eos) const {
27774a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    return mImpl->getCachedDuration(durationUs, eos);
27874a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber}
27974a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
28088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
28188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
28388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaExtractor> setMediaExtractor(
28788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaExtractor> &extractor) {
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> old =
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (JMediaExtractor *)env->GetIntField(thiz, gFields.context);
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor != NULL) {
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        extractor->incStrong(thiz);
29388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
29488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->SetIntField(thiz, gFields.context, (int)extractor.get());
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
30088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
30188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaExtractor> getMediaExtractor(JNIEnv *env, jobject thiz) {
30388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return (JMediaExtractor *)env->GetIntField(thiz, gFields.context);
30488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
30588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_release(JNIEnv *env, jobject thiz) {
30788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaExtractor(env, thiz, NULL);
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
30988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberstatic jint android_media_MediaExtractor_getTrackCount(
31188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
31388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
31588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
31607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        return -1;
31788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
31888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return extractor->countTracks();
32088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
32188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberstatic jobject android_media_MediaExtractor_getTrackFormatNative(
32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jint index) {
32488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
32788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
32888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
32988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
33288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->getTrackFormat(index, &format);
33388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
33788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
33888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return format;
34088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
34188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_selectTrack(
34388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jint index) {
34488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
34588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
34788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
35088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->selectTrack(index);
35288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
35488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
35588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
35688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
35788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
35888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
359f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huberstatic void android_media_MediaExtractor_unselectTrack(
360f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        JNIEnv *env, jobject thiz, jint index) {
361f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
362f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
363f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    if (extractor == NULL) {
364f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
365f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        return;
366f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    }
367f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
368f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    status_t err = extractor->unselectTrack(index);
369f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
370f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    if (err != OK) {
371f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
372f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        return;
373f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    }
374f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber}
375f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
37688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_seekTo(
377f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        JNIEnv *env, jobject thiz, jlong timeUs, jint mode) {
37888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
37988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
38188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
38288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
38388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
38488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
385f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    if (mode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC
386f86374adec8bd77af7b012f788ea59575296facbAndreas Huber            || mode >= MediaSource::ReadOptions::SEEK_CLOSEST) {
387f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
388f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        return;
389f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    }
390f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
391f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    extractor->seekTo(timeUs, (MediaSource::ReadOptions::SeekMode)mode);
39288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
39388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jboolean android_media_MediaExtractor_advance(
39588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
39688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
39788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
39988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
40088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
40188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
40288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->advance();
40488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
40688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
40788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
40888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
40988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
41088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
41188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return true;
41388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
41488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaExtractor_readSampleData(
41688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject byteBuf, jint offset) {
41788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
41888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
42088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
42188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
42288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
42388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t sampleSize;
42588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->readSampleData(byteBuf, offset, &sampleSize);
42688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
42888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
42988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
43088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
43188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
43288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
43388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return sampleSize;
43588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
43688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaExtractor_getSampleTrackIndex(
43888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
43988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
44088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
44288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
44388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
44488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
44588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t trackIndex;
44788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->getSampleTrackIndex(&trackIndex);
44888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
45088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
45188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
45288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
45388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
45488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
45588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return trackIndex;
45788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
45888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jlong android_media_MediaExtractor_getSampleTime(
46088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
46188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
46288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
46488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
46588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1ll;
46688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
46788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t sampleTimeUs;
46988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->getSampleTime(&sampleTimeUs);
47088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
47188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
47288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1ll;
47388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
47488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
47588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
47688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
47788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
47888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return sampleTimeUs;
47988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
48088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4819b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huberstatic jint android_media_MediaExtractor_getSampleFlags(
4829b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber        JNIEnv *env, jobject thiz) {
4839b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
4849b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
4859b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    if (extractor == NULL) {
4869b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
4879b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber        return -1ll;
4889b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    }
4899b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
4909b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    uint32_t sampleFlags;
4919b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    status_t err = extractor->getSampleFlags(&sampleFlags);
4929b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
4939b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    if (err == ERROR_END_OF_STREAM) {
4949b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber        return -1ll;
4959b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    } else if (err != OK) {
4969b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
4979b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber        return false;
4989b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    }
4999b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
5009b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    return sampleFlags;
5019b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber}
5029b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
50391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huberstatic jboolean android_media_MediaExtractor_getSampleCryptoInfo(
50491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        JNIEnv *env, jobject thiz, jobject cryptoInfoObj) {
50591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
50691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
50791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (extractor == NULL) {
50891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
50991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        return -1ll;
51091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
51191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
51291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    sp<MetaData> meta;
51391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    status_t err = extractor->getSampleMeta(&meta);
51491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
51591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (err != OK) {
51691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        return false;
51791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
51891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
51991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    uint32_t type;
52091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    const void *data;
52191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    size_t size;
52291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (!meta->findData(kKeyEncryptedSizes, &type, &data, &size)) {
52391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        return false;
52491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
52591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
52691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    size_t numSubSamples = size / sizeof(size_t);
52791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
52891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (numSubSamples == 0) {
52991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        return false;
53091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
53191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
53291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfEncryptedDataObj = env->NewIntArray(numSubSamples);
53391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jboolean isCopy;
53491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint *dst = env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
53591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    for (size_t i = 0; i < numSubSamples; ++i) {
53691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        dst[i] = ((const size_t *)data)[i];
53791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
53891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    env->ReleaseIntArrayElements(numBytesOfEncryptedDataObj, dst, 0);
53991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    dst = NULL;
54091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
54191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    size_t encSize = size;
54291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfPlainDataObj = NULL;
543ab57d03bdb3010d4957fb88c8acb30575ca02ec9Andreas Huber    if (meta->findData(kKeyPlainSizes, &type, &data, &size)) {
54491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        if (size != encSize) {
54591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            // The two must be of the same length.
54691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            return false;
54791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        }
54891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
54991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        numBytesOfPlainDataObj = env->NewIntArray(numSubSamples);
55091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jboolean isCopy;
55191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jint *dst = env->GetIntArrayElements(numBytesOfPlainDataObj, &isCopy);
55291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        for (size_t i = 0; i < numSubSamples; ++i) {
55391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            dst[i] = ((const size_t *)data)[i];
55491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        }
55591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->ReleaseIntArrayElements(numBytesOfPlainDataObj, dst, 0);
55691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        dst = NULL;
55791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
55891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
55991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray keyObj = NULL;
56091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (meta->findData(kKeyCryptoKey, &type, &data, &size)) {
56191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        if (size != 16) {
56291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            // Keys must be 16 bytes in length.
56391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            return false;
56491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        }
56591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
56691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        keyObj = env->NewByteArray(size);
56791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jboolean isCopy;
56891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jbyte *dst = env->GetByteArrayElements(keyObj, &isCopy);
56991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        memcpy(dst, data, size);
57091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->ReleaseByteArrayElements(keyObj, dst, 0);
57191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        dst = NULL;
57291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
57391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
57491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray ivObj = NULL;
57591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (meta->findData(kKeyCryptoIV, &type, &data, &size)) {
57691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        if (size != 16) {
57791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            // IVs must be 16 bytes in length.
57891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            return false;
57991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        }
58091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
58191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        ivObj = env->NewByteArray(size);
58291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jboolean isCopy;
58391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jbyte *dst = env->GetByteArrayElements(ivObj, &isCopy);
58491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        memcpy(dst, data, size);
58591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->ReleaseByteArrayElements(ivObj, dst, 0);
58691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        dst = NULL;
58791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
58891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
58991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    int32_t mode;
59091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (!meta->findInt32(kKeyCryptoMode, &mode)) {
591ab57d03bdb3010d4957fb88c8acb30575ca02ec9Andreas Huber        mode = CryptoPlugin::kMode_AES_CTR;
59291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
59391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
59491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    env->CallVoidMethod(
59591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            cryptoInfoObj,
59691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            gFields.cryptoInfoSetID,
59791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            numSubSamples,
59891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            numBytesOfPlainDataObj,
59991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            numBytesOfEncryptedDataObj,
60091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            keyObj,
60191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            ivObj,
60291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            mode);
60391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
60491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    return true;
60591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber}
60691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
60788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_native_init(JNIEnv *env) {
60888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("android/media/MediaExtractor");
60988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
61088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
61188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    gFields.context = env->GetFieldID(clazz, "mNativeContext", "I");
61288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
61388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
61491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    clazz = env->FindClass("android/media/MediaCodec$CryptoInfo");
61591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(clazz != NULL);
61691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
61791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoSetID =
61891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetMethodID(clazz, "set", "(I[I[I[B[BI)V");
61991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
62088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DataSource::RegisterDefaultSniffers();
62188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
62288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
62388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_native_setup(
62407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        JNIEnv *env, jobject thiz) {
62588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = new JMediaExtractor(env, thiz);
62607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    setMediaExtractor(env,thiz, extractor);
62707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber}
62888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
62907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberstatic void android_media_MediaExtractor_setDataSource(
63007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        JNIEnv *env, jobject thiz,
63107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        jstring pathObj, jobjectArray keysArray, jobjectArray valuesArray) {
63207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
63307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
63407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    if (extractor == NULL) {
63507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
63607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        return;
63707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    }
63807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
63907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    if (pathObj == NULL) {
64088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
64188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
64288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
64388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
64407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    KeyedVector<String8, String8> headers;
64507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    if (!ConvertKeyValueArraysToKeyedVector(
64607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                env, keysArray, valuesArray, &headers)) {
64707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        return;
64807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    }
64988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
65007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    const char *path = env->GetStringUTFChars(pathObj, NULL);
65107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
65207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    if (path == NULL) {
65388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
65488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
65588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
65607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    status_t err = extractor->setDataSource(path, &headers);
65788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
65807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    env->ReleaseStringUTFChars(pathObj, path);
65907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    path = NULL;
66088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
66188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
66288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(
66388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env,
66488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "java/io/IOException",
66588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "Failed to instantiate extractor.");
66688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
66788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
66807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber}
66988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
67007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberstatic void android_media_MediaExtractor_setDataSourceFd(
67107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        JNIEnv *env, jobject thiz,
67207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        jobject fileDescObj, jlong offset, jlong length) {
67307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
67407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
67507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    if (extractor == NULL) {
67607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
67707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        return;
67807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    }
67907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
68007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    if (fileDescObj == NULL) {
68107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
68207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        return;
68307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    }
68407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
68507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    int fd = jniGetFDFromFileDescriptor(env, fileDescObj);
68607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
68707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    status_t err = extractor->setDataSource(fd, offset, length);
68807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
68907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    if (err != OK) {
69007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        jniThrowException(
69107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                env,
69207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                "java/io/IOException",
69307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                "Failed to instantiate extractor.");
69407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        return;
69507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    }
69688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
69788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
698c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissenstatic void android_media_MediaExtractor_setDataSourceCallback(
699c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        JNIEnv *env, jobject thiz,
700c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        jobject callbackObj) {
701c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
702c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
703c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    if (extractor == NULL) {
704c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        jniThrowException(env, "java/lang/IllegalStateException", NULL);
705c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        return;
706c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    }
707c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
708c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    if (callbackObj == NULL) {
709c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
710c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        return;
711c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    }
712c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
713c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    sp<JavaDataSourceBridge> bridge = new JavaDataSourceBridge(env, callbackObj);
714c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    status_t err = extractor->setDataSource(bridge);
715c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
716c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    if (err != OK) {
717c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        jniThrowException(
718c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen                env,
719c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen                "java/io/IOException",
720c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen                "Failed to instantiate extractor.");
721c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        return;
722c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    }
723c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen}
724c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
72574a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huberstatic jlong android_media_MediaExtractor_getCachedDurationUs(
72674a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        JNIEnv *env, jobject thiz) {
72774a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
72874a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
72974a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    if (extractor == NULL) {
73074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
73174a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        return -1ll;
73274a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    }
73374a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
73474a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    int64_t cachedDurationUs;
73574a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    bool eos;
73674a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    if (!extractor->getCachedDuration(&cachedDurationUs, &eos)) {
73774a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        return -1ll;
73874a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    }
73974a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
74074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    return cachedDurationUs;
74174a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber}
74274a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
74374a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huberstatic jboolean android_media_MediaExtractor_hasCacheReachedEOS(
74474a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        JNIEnv *env, jobject thiz) {
74574a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
74674a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
74774a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    if (extractor == NULL) {
74874a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
74974a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        return true;
75074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    }
75174a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
75274a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    int64_t cachedDurationUs;
75374a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    bool eos;
75474a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    if (!extractor->getCachedDuration(&cachedDurationUs, &eos)) {
75574a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        return true;
75674a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    }
75774a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
75874a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    return eos;
75974a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber}
76074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
76188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_native_finalize(
76288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
76388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaExtractor_release(env, thiz);
76488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
76588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
76688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic JNINativeMethod gMethods[] = {
76788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "release", "()V", (void *)android_media_MediaExtractor_release },
76888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
76960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    { "getTrackCount", "()I", (void *)android_media_MediaExtractor_getTrackCount },
77088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    { "getTrackFormatNative", "(I)Ljava/util/Map;",
77260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        (void *)android_media_MediaExtractor_getTrackFormatNative },
77388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "selectTrack", "(I)V", (void *)android_media_MediaExtractor_selectTrack },
77588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
776f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    { "unselectTrack", "(I)V",
777f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        (void *)android_media_MediaExtractor_unselectTrack },
778f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
779f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    { "seekTo", "(JI)V", (void *)android_media_MediaExtractor_seekTo },
78088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "advance", "()Z", (void *)android_media_MediaExtractor_advance },
78288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "readSampleData", "(Ljava/nio/ByteBuffer;I)I",
78488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (void *)android_media_MediaExtractor_readSampleData },
78588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getSampleTrackIndex", "()I",
78788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (void *)android_media_MediaExtractor_getSampleTrackIndex },
78888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getSampleTime", "()J",
79088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (void *)android_media_MediaExtractor_getSampleTime },
79188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7929b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    { "getSampleFlags", "()I",
7939b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber        (void *)android_media_MediaExtractor_getSampleFlags },
7949b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
79591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    { "getSampleCryptoInfo", "(Landroid/media/MediaCodec$CryptoInfo;)Z",
79691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (void *)android_media_MediaExtractor_getSampleCryptoInfo },
79791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
79888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaExtractor_native_init },
79988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    { "native_setup", "()V",
80188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaExtractor_native_setup },
80288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
80488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaExtractor_native_finalize },
80507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
80607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    { "setDataSource", "(Ljava/lang/String;[Ljava/lang/String;"
80707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                       "[Ljava/lang/String;)V",
80807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      (void *)android_media_MediaExtractor_setDataSource },
80907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
81007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    { "setDataSource", "(Ljava/io/FileDescriptor;JJ)V",
81107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      (void *)android_media_MediaExtractor_setDataSourceFd },
81274a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
813c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    { "setDataSource", "(Landroid/media/DataSource;)V",
814c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen      (void *)android_media_MediaExtractor_setDataSourceCallback },
815c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
81674a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    { "getCachedDuration", "()J",
81774a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber      (void *)android_media_MediaExtractor_getCachedDurationUs },
81874a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
81974a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    { "hasCacheReachedEndOfStream", "()Z",
82074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber      (void *)android_media_MediaExtractor_hasCacheReachedEOS },
82188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
82288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
82388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaExtractor(JNIEnv *env) {
82488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
82588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaExtractor", gMethods, NELEM(gMethods));
82688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
827