android_media_MediaExtractor.cpp revision 88572f7a3e9d7ef85c26865a0150f3c2041561c2
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
2888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
2988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
3088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
3188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/DataSource.h>
3288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaErrors.h>
3388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/NuMediaExtractor.h>
3488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android {
3688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
3888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
3988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
4088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
4288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
4488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaExtractor::JMediaExtractor(JNIEnv *env, jobject thiz)
4688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
4788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      mObject(NULL) {
4888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
4988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
5088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
5288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
5388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mImpl = new NuMediaExtractor;
5588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
5688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaExtractor::~JMediaExtractor() {
5888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
5988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
6188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
6288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
6388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
6488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
6588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::setDataSource(const char *path) {
6788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->setDataSource(path);
6888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
6988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubersize_t JMediaExtractor::countTracks() const {
7188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->countTracks();
7288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
7388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::getTrackFormat(size_t index, jobject *format) const {
7588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
7688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
7788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if ((err = mImpl->getTrackFormat(index, &msg)) != OK) {
7888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
7988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
8088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
8288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
8488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
8588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::selectTrack(size_t index) {
8788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->selectTrack(index);
8888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
8988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::seekTo(int64_t timeUs) {
9188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->seekTo(timeUs);
9288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
9388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::advance() {
9588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->advance();
9688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
9788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::readSampleData(
9988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject byteBuf, size_t offset, size_t *sampleSize) {
10088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    void *dst = env->GetDirectBufferAddress(byteBuf);
10388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (dst == NULL) {
10588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        // XXX if dst is NULL also fall back to "array()"
10688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return INVALID_OPERATION;
10788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
10888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jlong dstSize = env->GetDirectBufferCapacity(byteBuf);
11088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (dstSize < offset) {
11288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -ERANGE;
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<ABuffer> buffer = new ABuffer((char *)dst + offset, dstSize - offset);
11688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = mImpl->readSampleData(buffer);
11888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
12088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
12188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
12288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *sampleSize = buffer->size();
12488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
12688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
12788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::getSampleTrackIndex(size_t *trackIndex) {
12988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->getSampleTrackIndex(trackIndex);
13088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
13188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaExtractor::getSampleTime(int64_t *sampleTimeUs) {
13388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mImpl->getSampleTime(sampleTimeUs);
13488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
13588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
13788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
13988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
14188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaExtractor> setMediaExtractor(
14388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaExtractor> &extractor) {
14488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> old =
14588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (JMediaExtractor *)env->GetIntField(thiz, gFields.context);
14688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor != NULL) {
14888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        extractor->incStrong(thiz);
14988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
15088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
15188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
15288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
15388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->SetIntField(thiz, gFields.context, (int)extractor.get());
15488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
15688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
15788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaExtractor> getMediaExtractor(JNIEnv *env, jobject thiz) {
15988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return (JMediaExtractor *)env->GetIntField(thiz, gFields.context);
16088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
16188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_release(JNIEnv *env, jobject thiz) {
16388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaExtractor(env, thiz, NULL);
16488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
16588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaExtractor_countTracks(
16788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
16888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
16988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
17188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
17288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
17388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
17488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return extractor->countTracks();
17688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
17788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject android_media_MediaExtractor_getTrackFormat(
17988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jint index) {
18088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
18188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
18388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
18488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
18588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
18888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->getTrackFormat(index, &format);
18988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
19188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
19288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
19388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
19488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return format;
19688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
19788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_selectTrack(
19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jint index) {
20088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
20188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
20388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
20488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
20588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
20688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->selectTrack(index);
20888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
21088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
21188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
21288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
21388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
21488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_seekTo(
21688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jlong timeUs) {
21788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
21888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
22088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
22188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
22288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
22388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->seekTo(timeUs);
22588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
22788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
22888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
22988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
23088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
23188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jboolean android_media_MediaExtractor_advance(
23388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
23488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
23588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
23788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
23888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
23988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
24088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->advance();
24288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
24488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
24588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
24788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
24888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
24988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return true;
25188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
25288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaExtractor_readSampleData(
25488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject byteBuf, jint offset) {
25588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
25688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
25988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
26088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
26188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t sampleSize;
26388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->readSampleData(byteBuf, offset, &sampleSize);
26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
26888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
26988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
27088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
27188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return sampleSize;
27388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
27488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaExtractor_getSampleTrackIndex(
27688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
27788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
27888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
28088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
28188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
28388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t trackIndex;
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->getSampleTrackIndex(&trackIndex);
28688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
29388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return trackIndex;
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jlong android_media_MediaExtractor_getSampleTime(
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
29988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
30088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (extractor == NULL) {
30288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
30388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1ll;
30488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
30588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t sampleTimeUs;
30788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->getSampleTime(&sampleTimeUs);
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == ERROR_END_OF_STREAM) {
31088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1ll;
31188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (err != OK) {
31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
31388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return false;
31488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
31588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return sampleTimeUs;
31788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
31888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_native_init(JNIEnv *env) {
32088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("android/media/MediaExtractor");
32188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
32288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    gFields.context = env->GetFieldID(clazz, "mNativeContext", "I");
32488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DataSource::RegisterDefaultSniffers();
32788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
32888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_native_setup(
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jstring path) {
33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaExtractor> extractor = new JMediaExtractor(env, thiz);
33288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (path == NULL) {
33488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
33788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    const char *tmp = env->GetStringUTFChars(path, NULL);
33988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (tmp == NULL) {
34188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
34288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
34388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = extractor->setDataSource(tmp);
34588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->ReleaseStringUTFChars(path, tmp);
34788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    tmp = NULL;
34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
35088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(
35188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env,
35288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "java/io/IOException",
35388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "Failed to instantiate extractor.");
35488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
35588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
35688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaExtractor(env,thiz, extractor);
35888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
35988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaExtractor_native_finalize(
36188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaExtractor_release(env, thiz);
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
36488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic JNINativeMethod gMethods[] = {
36688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "release", "()V", (void *)android_media_MediaExtractor_release },
36788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "countTracks", "()I", (void *)android_media_MediaExtractor_countTracks },
36988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getTrackFormat", "(I)Ljava/util/Map;",
37188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (void *)android_media_MediaExtractor_getTrackFormat },
37288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "selectTrack", "(I)V", (void *)android_media_MediaExtractor_selectTrack },
37488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "seekTo", "(J)V", (void *)android_media_MediaExtractor_seekTo },
37688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "advance", "()Z", (void *)android_media_MediaExtractor_advance },
37888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "readSampleData", "(Ljava/nio/ByteBuffer;I)I",
38088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (void *)android_media_MediaExtractor_readSampleData },
38188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getSampleTrackIndex", "()I",
38388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (void *)android_media_MediaExtractor_getSampleTrackIndex },
38488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getSampleTime", "()J",
38688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        (void *)android_media_MediaExtractor_getSampleTime },
38788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaExtractor_native_init },
38988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_setup", "(Ljava/lang/String;)V",
39188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaExtractor_native_setup },
39288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
39488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaExtractor_native_finalize },
39588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
39688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaExtractor(JNIEnv *env) {
39888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
39988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaExtractor", gMethods, NELEM(gMethods));
40088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
401