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"
2587eac99a21772ae56018cb81db6966557b459554Ruben Brunk#include "android_runtime/Log.h"
2688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "jni.h"
2788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "JNIHelp.h"
284eaa2938084353a54dc259466172909329a048ccChris Watkins#include "android_media_MediaDataSource.h"
2988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber#include <media/IMediaHTTPService.h>
31ab57d03bdb3010d4957fb88c8acb30575ca02ec9Andreas Huber#include <media/hardware/CryptoAPI.h>
3288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
3388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
3488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
3588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/DataSource.h>
3688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaErrors.h>
3791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber#include <media/stagefright/MetaData.h>
3888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/NuMediaExtractor.h>
3988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
407be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar#include <nativehelper/ScopedLocalRef.h>
417be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar
42d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber#include "android_util_Binder.h"
43d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber
4488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android {
4588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
4788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
4891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
4991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jmethodID cryptoInfoSetID;
5088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
5188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
5388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaExtractor::JMediaExtractor(JNIEnv *env, jobject thiz)
5588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
5688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      mObject(NULL) {
5788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
5888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
5988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
6188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
6288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mImpl = new NuMediaExtractor;
6488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
6588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaExtractor::~JMediaExtractor() {
6788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
6888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
7088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
7188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
7288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
7388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
7488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberstatus_t JMediaExtractor::setDataSource(
76d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber        const sp<IMediaHTTPService> &httpService,
77d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber        const char *path,
78d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber        const KeyedVector<String8, String8> *headers) {
79d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber    return mImpl->setDataSource(httpService, path, headers);
8007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber}
8107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
8207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberstatus_t JMediaExtractor::setDataSource(int fd, off64_t offset, off64_t size) {
8307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    return mImpl->setDataSource(fd, offset, size);
8488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
8588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
86c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissenstatus_t JMediaExtractor::setDataSource(const sp<DataSource> &datasource) {
87c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    return mImpl->setDataSource(datasource);
88c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen}
89c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
9088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubersize_t JMediaExtractor::countTracks() const {
9188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->countTracks();
9288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
9388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::getTrackFormat(size_t index, jobject *format) const {
9588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
9688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
9788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if ((err = mImpl->getTrackFormat(index, &msg)) != OK) {
9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
9988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
10088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
10488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
10588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
106e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissenstatus_t JMediaExtractor::getFileFormat(jobject *format) const {
107e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    sp<AMessage> msg;
108e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    status_t err;
109e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    if ((err = mImpl->getFileFormat(&msg)) != OK) {
110e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen        return err;
111e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    }
112e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen
113e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    JNIEnv *env = AndroidRuntime::getJNIEnv();
114e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen
115e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    return ConvertMessageToMap(env, msg, format);
116e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen}
117e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen
11888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::selectTrack(size_t index) {
11988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->selectTrack(index);
12088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
12188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
122f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huberstatus_t JMediaExtractor::unselectTrack(size_t index) {
123f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    return mImpl->unselectTrack(index);
124f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber}
125f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
126f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huberstatus_t JMediaExtractor::seekTo(
127f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode) {
128f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    return mImpl->seekTo(timeUs, mode);
12988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
13088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::advance() {
13288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->advance();
13388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
13488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::readSampleData(
13688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject byteBuf, size_t offset, size_t *sampleSize) {
13788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
13888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    void *dst = env->GetDirectBufferAddress(byteBuf);
14088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
141075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    size_t dstSize;
142c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber    jbyteArray byteArray = NULL;
143c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
1447be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer"));
1457be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    CHECK(byteBufClass.get() != NULL);
146c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
1477be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    if (dst == NULL) {
148c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        jmethodID arrayID =
1497be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar            env->GetMethodID(byteBufClass.get(), "array", "()[B");
150c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        CHECK(arrayID != NULL);
151c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
152c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        byteArray =
153c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber            (jbyteArray)env->CallObjectMethod(byteBuf, arrayID);
154c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
155c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        if (byteArray == NULL) {
156c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber            return INVALID_OPERATION;
157c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        }
15888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
159c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        jboolean isCopy;
160c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        dst = env->GetByteArrayElements(byteArray, &isCopy);
161c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
162075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        dstSize = (size_t) env->GetArrayLength(byteArray);
163c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber    } else {
164075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        dstSize = (size_t) env->GetDirectBufferCapacity(byteBuf);
165c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber    }
16688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (dstSize < offset) {
168c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        if (byteArray != NULL) {
169c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber            env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0);
170c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        }
171c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
17288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -ERANGE;
17388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
17488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<ABuffer> buffer = new ABuffer((char *)dst + offset, dstSize - offset);
17688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = mImpl->readSampleData(buffer);
17888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
179c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber    if (byteArray != NULL) {
180c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber        env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0);
181c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber    }
182c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber
18388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
18488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
18588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *sampleSize = buffer->size();
18888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1897be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    jmethodID positionID = env->GetMethodID(
1907be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar            byteBufClass.get(), "position", "(I)Ljava/nio/Buffer;");
1917be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar
1927be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    CHECK(positionID != NULL);
1937be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar
1947be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    jmethodID limitID = env->GetMethodID(
1957be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar            byteBufClass.get(), "limit", "(I)Ljava/nio/Buffer;");
1967be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar
1977be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    CHECK(limitID != NULL);
1987be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar
1997be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    jobject me = env->CallObjectMethod(
2007be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar            byteBuf, limitID, offset + *sampleSize);
2017be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    env->DeleteLocalRef(me);
2027be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    me = env->CallObjectMethod(
2037be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar            byteBuf, positionID, offset);
2047be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    env->DeleteLocalRef(me);
2057be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    me = NULL;
2067be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar
20788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
20888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
20988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::getSampleTrackIndex(size_t *trackIndex) {
21188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->getSampleTrackIndex(trackIndex);
21288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
21388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::getSampleTime(int64_t *sampleTimeUs) {
21588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->getSampleTime(sampleTimeUs);
21688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
21788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2189b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huberstatus_t JMediaExtractor::getSampleFlags(uint32_t *sampleFlags) {
21991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    *sampleFlags = 0;
22091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
22191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    sp<MetaData> meta;
22291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    status_t err = mImpl->getSampleMeta(&meta);
22391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
22491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (err != OK) {
22591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        return err;
22691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
22791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
22891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    int32_t val;
22991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) {
23091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (*sampleFlags) |= NuMediaExtractor::SAMPLE_FLAG_SYNC;
23191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
23291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
23391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    uint32_t type;
23491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    const void *data;
23591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    size_t size;
23691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) {
23791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (*sampleFlags) |= NuMediaExtractor::SAMPLE_FLAG_ENCRYPTED;
23891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
23991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
24091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    return OK;
24191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber}
24291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
24391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huberstatus_t JMediaExtractor::getSampleMeta(sp<MetaData> *sampleMeta) {
24491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    return mImpl->getSampleMeta(sampleMeta);
2459b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber}
2469b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
24774a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huberbool JMediaExtractor::getCachedDuration(int64_t *durationUs, bool *eos) const {
24874a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    return mImpl->getCachedDuration(durationUs, eos);
24974a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber}
25074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
25188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
25288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
25488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
25688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaExtractor> setMediaExtractor(
25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaExtractor> &extractor) {
25988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> old =
260075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        (JMediaExtractor *)env->GetLongField(thiz, gFields.context);
26188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor != NULL) {
26388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        extractor->incStrong(thiz);
26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
268075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, gFields.context, (jlong)extractor.get());
26988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
27188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
27288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaExtractor> getMediaExtractor(JNIEnv *env, jobject thiz) {
274075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (JMediaExtractor *)env->GetLongField(thiz, gFields.context);
27588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
27688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_release(JNIEnv *env, jobject thiz) {
27888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaExtractor(env, thiz, NULL);
27988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
28088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberstatic jint android_media_MediaExtractor_getTrackCount(
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
28388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
28488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
28688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
28707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        return -1;
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
290075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (jint) extractor->countTracks();
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberstatic jobject android_media_MediaExtractor_getTrackFormatNative(
29488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jint index) {
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
29988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
30088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
30188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
30388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->getTrackFormat(index, &format);
30488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
30688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
30788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
30988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return format;
31188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
313e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissenstatic jobject android_media_MediaExtractor_getFileFormatNative(
314e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen        JNIEnv *env, jobject thiz) {
315e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
316e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen
317e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    if (extractor == NULL) {
318e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen        jniThrowException(env, "java/lang/IllegalStateException", NULL);
319e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen        return NULL;
320e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    }
321e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen
322e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    jobject format;
323e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    status_t err = extractor->getFileFormat(&format);
324e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen
325e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    if (err != OK) {
326e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
327e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen        return NULL;
328e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    }
329e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen
330e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    return format;
331e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen}
332e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen
33388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_selectTrack(
33488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jint index) {
33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
33888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
33988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
34088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
34188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->selectTrack(index);
34388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
34588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
34688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
34788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
350f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huberstatic void android_media_MediaExtractor_unselectTrack(
351f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        JNIEnv *env, jobject thiz, jint index) {
352f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
353f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
354f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    if (extractor == NULL) {
355f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
356f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        return;
357f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    }
358f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
359f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    status_t err = extractor->unselectTrack(index);
360f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
361f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    if (err != OK) {
362f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
363f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        return;
364f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    }
365f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber}
366f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
36788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_seekTo(
368f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        JNIEnv *env, jobject thiz, jlong timeUs, jint mode) {
36988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
37088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
37288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
37388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
37488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
37588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
376f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    if (mode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC
377f86374adec8bd77af7b012f788ea59575296facbAndreas Huber            || mode >= MediaSource::ReadOptions::SEEK_CLOSEST) {
378f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
379f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        return;
380f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    }
381f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
382f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    extractor->seekTo(timeUs, (MediaSource::ReadOptions::SeekMode)mode);
38388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
38488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jboolean android_media_MediaExtractor_advance(
38688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
38788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
38888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
39088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
391075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return JNI_FALSE;
39288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
39388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->advance();
39588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
397075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return JNI_FALSE;
39888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
39988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
400075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return JNI_FALSE;
40188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
40288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
403075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return JNI_TRUE;
40488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
40588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaExtractor_readSampleData(
40788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject byteBuf, jint offset) {
40888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
40988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
41188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
41288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
41388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
41488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t sampleSize;
41688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->readSampleData(byteBuf, offset, &sampleSize);
41788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
41988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
42088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
42188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
422075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return -1;
42388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
42488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
425075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (jint) sampleSize;
42688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
42788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaExtractor_getSampleTrackIndex(
42988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
43088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
43188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
43388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
43488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
43588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
43688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t trackIndex;
43888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->getSampleTrackIndex(&trackIndex);
43988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
44188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
44288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
44388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
444075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return -1;
44588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
44688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
447075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (jint) trackIndex;
44888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
44988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jlong android_media_MediaExtractor_getSampleTime(
45188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
45288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
45388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
45588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
45688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1ll;
45788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
45888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t sampleTimeUs;
46088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->getSampleTime(&sampleTimeUs);
46188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
46388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1ll;
46488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
46588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
466075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return -1ll;
46788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
46888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
469075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (jlong) sampleTimeUs;
47088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
47188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4729b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huberstatic jint android_media_MediaExtractor_getSampleFlags(
4739b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber        JNIEnv *env, jobject thiz) {
4749b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
4759b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
4769b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    if (extractor == NULL) {
4779b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
478075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return -1;
4799b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    }
4809b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
4819b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    uint32_t sampleFlags;
4829b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    status_t err = extractor->getSampleFlags(&sampleFlags);
4839b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
4849b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    if (err == ERROR_END_OF_STREAM) {
485075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return -1;
4869b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    } else if (err != OK) {
4879b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
488075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return -1;
4899b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    }
4909b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
491075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (jint) sampleFlags;
4929b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber}
4939b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
49491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huberstatic jboolean android_media_MediaExtractor_getSampleCryptoInfo(
49591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        JNIEnv *env, jobject thiz, jobject cryptoInfoObj) {
49691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
49791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
49891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (extractor == NULL) {
49991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
500075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return JNI_FALSE;
50191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
50291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
50391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    sp<MetaData> meta;
50491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    status_t err = extractor->getSampleMeta(&meta);
50591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
50691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (err != OK) {
507075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return JNI_FALSE;
50891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
50991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
51091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    uint32_t type;
51191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    const void *data;
51291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    size_t size;
51391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (!meta->findData(kKeyEncryptedSizes, &type, &data, &size)) {
514075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return JNI_FALSE;
51591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
51691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
517e92416dfeb115939231819c5edb593b8bb81cc6dAshok Bhat    size_t numSubSamples = size / sizeof(int32_t);
51891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
51991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (numSubSamples == 0) {
520075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return JNI_FALSE;
52191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
52291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
52391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfEncryptedDataObj = env->NewIntArray(numSubSamples);
52491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jboolean isCopy;
52591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint *dst = env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
52691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    for (size_t i = 0; i < numSubSamples; ++i) {
527e92416dfeb115939231819c5edb593b8bb81cc6dAshok Bhat        dst[i] = ((const int32_t *)data)[i];
52891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
52991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    env->ReleaseIntArrayElements(numBytesOfEncryptedDataObj, dst, 0);
53091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    dst = NULL;
53191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
53291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    size_t encSize = size;
53391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfPlainDataObj = NULL;
534ab57d03bdb3010d4957fb88c8acb30575ca02ec9Andreas Huber    if (meta->findData(kKeyPlainSizes, &type, &data, &size)) {
53591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        if (size != encSize) {
53691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            // The two must be of the same length.
537075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat            return JNI_FALSE;
53891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        }
53991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
54091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        numBytesOfPlainDataObj = env->NewIntArray(numSubSamples);
54191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jboolean isCopy;
54291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jint *dst = env->GetIntArrayElements(numBytesOfPlainDataObj, &isCopy);
54391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        for (size_t i = 0; i < numSubSamples; ++i) {
544e92416dfeb115939231819c5edb593b8bb81cc6dAshok Bhat            dst[i] = ((const int32_t *)data)[i];
54591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        }
54691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->ReleaseIntArrayElements(numBytesOfPlainDataObj, dst, 0);
54791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        dst = NULL;
54891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
54991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
55091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray keyObj = NULL;
55191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (meta->findData(kKeyCryptoKey, &type, &data, &size)) {
55291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        if (size != 16) {
55391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            // Keys must be 16 bytes in length.
554075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat            return JNI_FALSE;
55591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        }
55691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
55791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        keyObj = env->NewByteArray(size);
55891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jboolean isCopy;
55991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jbyte *dst = env->GetByteArrayElements(keyObj, &isCopy);
56091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        memcpy(dst, data, size);
56191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->ReleaseByteArrayElements(keyObj, dst, 0);
56291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        dst = NULL;
56391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
56491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
56591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray ivObj = NULL;
56691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (meta->findData(kKeyCryptoIV, &type, &data, &size)) {
56791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        if (size != 16) {
56891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            // IVs must be 16 bytes in length.
569075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat            return JNI_FALSE;
57091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        }
57191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
57291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        ivObj = env->NewByteArray(size);
57391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jboolean isCopy;
57491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jbyte *dst = env->GetByteArrayElements(ivObj, &isCopy);
57591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        memcpy(dst, data, size);
57691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->ReleaseByteArrayElements(ivObj, dst, 0);
57791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        dst = NULL;
57891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
57991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
58091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    int32_t mode;
58191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    if (!meta->findInt32(kKeyCryptoMode, &mode)) {
582ab57d03bdb3010d4957fb88c8acb30575ca02ec9Andreas Huber        mode = CryptoPlugin::kMode_AES_CTR;
58391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    }
58491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
58591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    env->CallVoidMethod(
58691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            cryptoInfoObj,
58791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            gFields.cryptoInfoSetID,
588136c08a7d3678e9fcf22667e75b0904a94add6bbAshok Bhat            (jint)numSubSamples,
58991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            numBytesOfPlainDataObj,
59091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            numBytesOfEncryptedDataObj,
59191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            keyObj,
59291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            ivObj,
59391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber            mode);
59491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
595075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return JNI_TRUE;
59691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber}
59791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
59888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_native_init(JNIEnv *env) {
59988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("android/media/MediaExtractor");
60088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
60188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
602075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    gFields.context = env->GetFieldID(clazz, "mNativeContext", "J");
60388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
60488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
60591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    clazz = env->FindClass("android/media/MediaCodec$CryptoInfo");
60691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(clazz != NULL);
60791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
60891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoSetID =
60991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetMethodID(clazz, "set", "(I[I[I[B[BI)V");
61091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
61188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DataSource::RegisterDefaultSniffers();
61288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
61388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
61488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_native_setup(
61507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        JNIEnv *env, jobject thiz) {
61688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = new JMediaExtractor(env, thiz);
61707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    setMediaExtractor(env,thiz, extractor);
61807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber}
61988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
62007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberstatic void android_media_MediaExtractor_setDataSource(
62107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        JNIEnv *env, jobject thiz,
622d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber        jobject httpServiceBinderObj,
623d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber        jstring pathObj,
624d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber        jobjectArray keysArray,
625d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber        jobjectArray valuesArray) {
62607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
62707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
62807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    if (extractor == NULL) {
62907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
63007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        return;
63107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    }
63207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
63307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    if (pathObj == NULL) {
63488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
63588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
63688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
63788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
63807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    KeyedVector<String8, String8> headers;
63907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    if (!ConvertKeyValueArraysToKeyedVector(
64007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                env, keysArray, valuesArray, &headers)) {
64107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        return;
64207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    }
64388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
64407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    const char *path = env->GetStringUTFChars(pathObj, NULL);
64507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
64607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    if (path == NULL) {
64788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
64888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
64988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
650d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber    sp<IMediaHTTPService> httpService;
651d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber    if (httpServiceBinderObj != NULL) {
652d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber        sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj);
653d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber        httpService = interface_cast<IMediaHTTPService>(binder);
654d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber    }
655d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber
656d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber    status_t err = extractor->setDataSource(httpService, 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
7134eaa2938084353a54dc259466172909329a048ccChris Watkins    sp<DataSource> bridge =
7144eaa2938084353a54dc259466172909329a048ccChris Watkins        DataSource::CreateFromIDataSource(new JMediaDataSource(env, callbackObj));
715c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    status_t err = extractor->setDataSource(bridge);
716c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
717c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    if (err != OK) {
718bc10185fa1669a151568feb72277785d323fc344Chong Zhang        // Clear bridge so that JMediaDataSource::close() is called _before_
719bc10185fa1669a151568feb72277785d323fc344Chong Zhang        // we throw the IOException.
720bc10185fa1669a151568feb72277785d323fc344Chong Zhang        // Otherwise close() gets called when we go out of scope, it calls
721bc10185fa1669a151568feb72277785d323fc344Chong Zhang        // Java with a pending exception and crashes the process.
722bc10185fa1669a151568feb72277785d323fc344Chong Zhang        bridge.clear();
723c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        jniThrowException(
724c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen                env,
725c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen                "java/io/IOException",
726c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen                "Failed to instantiate extractor.");
727c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen        return;
728c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen    }
729c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen}
730c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
73174a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huberstatic jlong android_media_MediaExtractor_getCachedDurationUs(
73274a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        JNIEnv *env, jobject thiz) {
73374a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
73474a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
73574a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    if (extractor == NULL) {
73674a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
73774a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        return -1ll;
73874a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    }
73974a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
74074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    int64_t cachedDurationUs;
74174a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    bool eos;
74274a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    if (!extractor->getCachedDuration(&cachedDurationUs, &eos)) {
74374a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        return -1ll;
74474a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    }
74574a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
746075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (jlong) cachedDurationUs;
74774a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber}
74874a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
74974a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huberstatic jboolean android_media_MediaExtractor_hasCacheReachedEOS(
75074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        JNIEnv *env, jobject thiz) {
75174a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
75274a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
75374a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    if (extractor == NULL) {
75474a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
755075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return JNI_TRUE;
75674a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    }
75774a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
75874a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    int64_t cachedDurationUs;
75974a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    bool eos;
76074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    if (!extractor->getCachedDuration(&cachedDurationUs, &eos)) {
761075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return JNI_TRUE;
76274a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    }
76374a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
764075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return eos ? JNI_TRUE : JNI_FALSE;
76574a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber}
76674a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
76788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_native_finalize(
76888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
76988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaExtractor_release(env, thiz);
77088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
77188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77276f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = {
77388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "release", "()V", (void *)android_media_MediaExtractor_release },
77488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    { "getTrackCount", "()I", (void *)android_media_MediaExtractor_getTrackCount },
77688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
777e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    { "getFileFormatNative", "()Ljava/util/Map;",
778e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen        (void *)android_media_MediaExtractor_getFileFormatNative },
779e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen
78060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    { "getTrackFormatNative", "(I)Ljava/util/Map;",
78160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        (void *)android_media_MediaExtractor_getTrackFormatNative },
78288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "selectTrack", "(I)V", (void *)android_media_MediaExtractor_selectTrack },
78488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
785f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    { "unselectTrack", "(I)V",
786f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber        (void *)android_media_MediaExtractor_unselectTrack },
787f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber
788f2855b3df5994e165b29025c4c49d8e7d634c034Andreas Huber    { "seekTo", "(JI)V", (void *)android_media_MediaExtractor_seekTo },
78988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "advance", "()Z", (void *)android_media_MediaExtractor_advance },
79188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "readSampleData", "(Ljava/nio/ByteBuffer;I)I",
79388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (void *)android_media_MediaExtractor_readSampleData },
79488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getSampleTrackIndex", "()I",
79688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (void *)android_media_MediaExtractor_getSampleTrackIndex },
79788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getSampleTime", "()J",
79988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (void *)android_media_MediaExtractor_getSampleTime },
80088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8019b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber    { "getSampleFlags", "()I",
8029b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber        (void *)android_media_MediaExtractor_getSampleFlags },
8039b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber
80491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    { "getSampleCryptoInfo", "(Landroid/media/MediaCodec$CryptoInfo;)Z",
80591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (void *)android_media_MediaExtractor_getSampleCryptoInfo },
80691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
80788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaExtractor_native_init },
80888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    { "native_setup", "()V",
81088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaExtractor_native_setup },
81188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
81288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
81388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaExtractor_native_finalize },
81407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
815d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber    { "nativeSetDataSource",
816d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber        "(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
817d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber        "[Ljava/lang/String;)V",
81807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      (void *)android_media_MediaExtractor_setDataSource },
81907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
82007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    { "setDataSource", "(Ljava/io/FileDescriptor;JJ)V",
82107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      (void *)android_media_MediaExtractor_setDataSourceFd },
82274a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
8234eaa2938084353a54dc259466172909329a048ccChris Watkins    { "setDataSource", "(Landroid/media/MediaDataSource;)V",
824c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen      (void *)android_media_MediaExtractor_setDataSourceCallback },
825c209a06cfdcf633f12a299245312e3ac32bff27cMarco Nelissen
82674a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    { "getCachedDuration", "()J",
82774a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber      (void *)android_media_MediaExtractor_getCachedDurationUs },
82874a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber
82974a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber    { "hasCacheReachedEndOfStream", "()Z",
83074a78b0f6e8c07cfc7da8f043987f6de0648bc05Andreas Huber      (void *)android_media_MediaExtractor_hasCacheReachedEOS },
83188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
83288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
83388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaExtractor(JNIEnv *env) {
83488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
83588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaExtractor", gMethods, NELEM(gMethods));
83688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
837