10c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen/*
20c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * Copyright (C) 2014 The Android Open Source Project
30c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen *
40c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * Licensed under the Apache License, Version 2.0 (the "License");
50c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * you may not use this file except in compliance with the License.
60c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * You may obtain a copy of the License at
70c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen *
80c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen *      http://www.apache.org/licenses/LICENSE-2.0
90c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen *
100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * Unless required by applicable law or agreed to in writing, software
110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * distributed under the License is distributed on an "AS IS" BASIS,
120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * See the License for the specific language governing permissions and
140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen * limitations under the License.
150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen */
160c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
17c7a11b2208aa8f1e6a39eb70a136fbc0dafd3260Marco Nelissen//#define LOG_NDEBUG 0
180c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#define LOG_TAG "NdkMediaExtractor"
190c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
200c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
21050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen#include "NdkMediaError.h"
220c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include "NdkMediaExtractor.h"
230c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include "NdkMediaFormatPriv.h"
240c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
250c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
26214c833fcde68833691cc54d2a4cd995d7eb0e16Aurimas Liutikas#include <inttypes.h>
270c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <utils/Log.h>
280c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <utils/StrongPointer.h>
29050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen#include <media/hardware/CryptoAPI.h>
300c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/foundation/ABuffer.h>
310c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/foundation/AMessage.h>
320c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/MetaData.h>
330c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/NuMediaExtractor.h>
340c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/IMediaHTTPService.h>
350c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <android_runtime/AndroidRuntime.h>
360c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <android_util_Binder.h>
370c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
380c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <jni.h>
390c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
400c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenusing namespace android;
410c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
42e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenstatic media_status_t translate_error(status_t err) {
430c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (err == OK) {
44e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_OK;
450c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
460c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGE("sf error code: %d", err);
47e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_ERROR_UNKNOWN;
480c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
490c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
500c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenstruct AMediaExtractor {
510c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<NuMediaExtractor> mImpl;
52050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<ABuffer> mPsshBuf;
530c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
540c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen};
550c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
560c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenextern "C" {
570c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
583425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
590c3be875376adaee8d8e8dd917c64926e1513b29Marco NelissenAMediaExtractor* AMediaExtractor_new() {
600c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("ctor");
610c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    AMediaExtractor *mData = new AMediaExtractor();
620c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    mData->mImpl = new NuMediaExtractor();
630c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return mData;
640c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
650c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
663425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
67e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_delete(AMediaExtractor *mData) {
680c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("dtor");
690c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    delete mData;
70e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_OK;
710c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
720c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
733425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
74b187de1ada34a9023c05d020a4592686ba761278Glenn Kastenmedia_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor *mData, int fd, off64_t offset,
75b187de1ada34a9023c05d020a4592686ba761278Glenn Kasten        off64_t length) {
76214c833fcde68833691cc54d2a4cd995d7eb0e16Aurimas Liutikas    ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
77e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return translate_error(mData->mImpl->setDataSource(fd, offset, length));
780c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
790c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
803425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
81e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) {
820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("setDataSource(%s)", location);
830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    // TODO: add header support
840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    JNIEnv *env = AndroidRuntime::getJNIEnv();
860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jobject service = NULL;
870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (env == NULL) {
880c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        ALOGE("setDataSource(path) must be called from Java thread");
89e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_UNSUPPORTED;
900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jclass mediahttpclass = env->FindClass("android/media/MediaHTTPService");
930c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mediahttpclass == NULL) {
940c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        ALOGE("can't find MediaHttpService");
950c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        env->ExceptionClear();
96e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_UNSUPPORTED;
970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
980c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
990c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jmethodID mediaHttpCreateMethod = env->GetStaticMethodID(mediahttpclass,
1000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            "createHttpServiceBinderIfNecessary", "(Ljava/lang/String;)Landroid/os/IBinder;");
1010c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mediaHttpCreateMethod == NULL) {
1020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        ALOGE("can't find method");
1030c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        env->ExceptionClear();
104e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_UNSUPPORTED;
1050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1070c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jstring jloc = env->NewStringUTF(location);
1080c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1090c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    service = env->CallStaticObjectMethod(mediahttpclass, mediaHttpCreateMethod, jloc);
1100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    env->DeleteLocalRef(jloc);
1110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<IMediaHTTPService> httpService;
1130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (service != NULL) {
1140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        sp<IBinder> binder = ibinderForJavaObject(env, service);
1150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        httpService = interface_cast<IMediaHTTPService>(binder);
1160c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1170c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
118e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    status_t err = mData->mImpl->setDataSource(httpService, location, NULL);
1190c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    env->ExceptionClear();
120e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return translate_error(err);
1210c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1220c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1233425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
124e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissensize_t AMediaExtractor_getTrackCount(AMediaExtractor *mData) {
1250c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return mData->mImpl->countTracks();
1260c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1270c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1283425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1290c3be875376adaee8d8e8dd917c64926e1513b29Marco NelissenAMediaFormat* AMediaExtractor_getTrackFormat(AMediaExtractor *mData, size_t idx) {
1300c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<AMessage> format;
1310c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    mData->mImpl->getTrackFormat(idx, &format);
1320c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return AMediaFormat_fromMsg(&format);
1330c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1340c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1353425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
136e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_selectTrack(AMediaExtractor *mData, size_t idx) {
13798f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn    ALOGV("selectTrack(%zu)", idx);
1380c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return translate_error(mData->mImpl->selectTrack(idx));
1390c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1400c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1413425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
142e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_unselectTrack(AMediaExtractor *mData, size_t idx) {
14398f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn    ALOGV("unselectTrack(%zu)", idx);
1440c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return translate_error(mData->mImpl->unselectTrack(idx));
1450c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1460c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1473425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1480c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenbool AMediaExtractor_advance(AMediaExtractor *mData) {
1490c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    //ALOGV("advance");
15070452261b0ed8e47676641ee5cc546dc5f8333baRobert Shih    status_t err = mData->mImpl->advance();
15170452261b0ed8e47676641ee5cc546dc5f8333baRobert Shih    if (err == ERROR_END_OF_STREAM) {
15270452261b0ed8e47676641ee5cc546dc5f8333baRobert Shih        return false;
15370452261b0ed8e47676641ee5cc546dc5f8333baRobert Shih    } else if (err != OK) {
15470452261b0ed8e47676641ee5cc546dc5f8333baRobert Shih        ALOGE("sf error code: %d", err);
15570452261b0ed8e47676641ee5cc546dc5f8333baRobert Shih        return false;
15670452261b0ed8e47676641ee5cc546dc5f8333baRobert Shih    }
15770452261b0ed8e47676641ee5cc546dc5f8333baRobert Shih    return true;
1580c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1590c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1603425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
16179e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissenmedia_status_t AMediaExtractor_seekTo(AMediaExtractor *ex, int64_t seekPosUs, SeekMode mode) {
16279e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    android::MediaSource::ReadOptions::SeekMode sfmode;
16379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    if (mode == AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC) {
16479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC;
16579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    } else if (mode == AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC) {
16679e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_CLOSEST_SYNC;
16779e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    } else {
16879e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_NEXT_SYNC;
16979e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    }
17079e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen
17179e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    return translate_error(ex->mImpl->seekTo(seekPosUs, sfmode));
17279e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen}
17379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen
17479e2b622702fb148ccff12d6f38643466555c4ebMarco NelissenEXPORT
175e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenssize_t AMediaExtractor_readSampleData(AMediaExtractor *mData, uint8_t *buffer, size_t capacity) {
1760c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    //ALOGV("readSampleData");
1770c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<ABuffer> tmp = new ABuffer(buffer, capacity);
1780c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->readSampleData(tmp) == OK) {
1790c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return tmp->size();
1800c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return -1;
1820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1843425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
185e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenuint32_t AMediaExtractor_getSampleFlags(AMediaExtractor *mData) {
1860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int sampleFlags = 0;
1870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<MetaData> meta;
1880c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    status_t err = mData->mImpl->getSampleMeta(&meta);
1890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (err != OK) {
1900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
1910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int32_t val;
1930c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) {
194e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_SYNC;
1950c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    uint32_t type;
1980c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    const void *data;
1990c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t size;
2000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) {
201e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_ENCRYPTED;
2020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2030c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return sampleFlags;
2040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2063425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
2070c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_getSampleTrackIndex(AMediaExtractor *mData) {
2080c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t idx;
2090c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->getSampleTrackIndex(&idx) != OK) {
2100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
2110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return idx;
2130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2153425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
216eb4860c305def68c5965474bb43c67c2c9d49bbbMarco Nelissenint64_t AMediaExtractor_getSampleTime(AMediaExtractor *mData) {
2170c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int64_t time;
2180c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->getSampleTime(&time) != OK) {
2190c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
2200c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2210c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return time;
2220c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2230c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2243425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
225050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenPsshInfo* AMediaExtractor_getPsshInfo(AMediaExtractor *ex) {
226050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
227050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (ex->mPsshBuf != NULL) {
228050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return (PsshInfo*) ex->mPsshBuf->data();
229050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
230050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
231050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<AMessage> format;
232050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mImpl->getFileFormat(&format);
233050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<ABuffer> buffer;
234050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if(!format->findBuffer("pssh", &buffer)) {
235050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
236050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
237050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
238050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // the format of the buffer is 1 or more of:
239050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //    {
240050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        16 byte uuid
241050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        4 byte data length N
242050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        N bytes of data
243050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //    }
244050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
245050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // Determine the number of entries in the source data.
246050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // Since we got the data from stagefright, we trust it is valid and properly formatted.
247050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const uint8_t* data = buffer->data();
248050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t len = buffer->size();
249050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t numentries = 0;
250050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    while (len > 0) {
251050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        numentries++;
252050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
253346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        if (len < 16) {
254346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            ALOGE("invalid PSSH data");
255346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            return NULL;
256346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        }
257050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // skip uuid
258050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += 16;
259050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= 16;
260050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
261050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // get data length
262346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        if (len < 4) {
263346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            ALOGE("invalid PSSH data");
264346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            return NULL;
265346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        }
266050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t datalen = *((uint32_t*)data);
267050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += 4;
268050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= 4;
269050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
270346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        if (len < datalen) {
271346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            ALOGE("invalid PSSH data");
272346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            return NULL;
273346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        }
274050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // skip the data
275050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += datalen;
276050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= datalen;
277050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
278050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
27958344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // there are <numentries> in the source buffer, we need
28058344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // (source buffer size) - (sizeof(uint32_t) * numentries) + sizeof(size_t)
28158344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    //  + ((sizeof(void*) + sizeof(size_t)) * numentries) bytes for the PsshInfo structure
28258344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // Or in other words, the data lengths in the source structure are replaced by size_t
28358344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // (which may be the same size or larger, for 64 bit), and in addition there is an
28458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // extra pointer for each entry, and an extra size_t for the entire PsshInfo.
28558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    size_t newsize = buffer->size() - (sizeof(uint32_t) * numentries) + sizeof(size_t)
28658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen            + ((sizeof(void*) + sizeof(size_t)) * numentries);
287346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen    if (newsize <= buffer->size()) {
288346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        ALOGE("invalid PSSH data");
289346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        return NULL;
290346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen    }
291050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mPsshBuf = new ABuffer(newsize);
292050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mPsshBuf->setRange(0, newsize);
293050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
294050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // copy data
295050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const uint8_t* src = buffer->data();
296050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    uint8_t* dst = ex->mPsshBuf->data();
29758344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    uint8_t* dstdata = dst + sizeof(size_t) + numentries * sizeof(PsshEntry);
29858344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    *((size_t*)dst) = numentries;
29958344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    dst += sizeof(size_t);
300050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    for (size_t i = 0; i < numentries; i++) {
301050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // copy uuid
302050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dst, src, 16);
303050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        src += 16;
304050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dst += 16;
305050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
306050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // get/copy data length
307050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t datalen = *((uint32_t*)src);
30858344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        *((size_t*)dst) = datalen;
30958344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        src += sizeof(uint32_t);
31058344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        dst += sizeof(size_t);
311050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
312050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // the next entry in the destination is a pointer to the actual data, which we store
313050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // after the array of PsshEntry
31458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        *((void**)dst) = dstdata;
31558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        dst += sizeof(void*);
316050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
317050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // copy the actual data
318050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dstdata, src, datalen);
319050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dstdata += datalen;
320050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        src += datalen;
321050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
322050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
323050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return (PsshInfo*) ex->mPsshBuf->data();
324050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
325050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
3263425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
327050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenAMediaCodecCryptoInfo *AMediaExtractor_getSampleCryptoInfo(AMediaExtractor *ex) {
328050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<MetaData> meta;
329050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if(ex->mImpl->getSampleMeta(&meta) != 0) {
330050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
331050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
332050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
333050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    uint32_t type;
334050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *crypteddata;
335050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t cryptedsize;
336050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
337050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
338050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
339050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t numSubSamples = cryptedsize / sizeof(size_t);
340050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
341050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *cleardata;
342050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t clearsize;
343050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
344050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (clearsize != cryptedsize) {
345050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // The two must be of the same length.
346050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
347050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
348050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
349050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
350050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *key;
351050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t keysize;
352b2fb3c9787e4cc372e87b71eb55bfe008b2693ccEdwin Wong    if (meta->findData(kKeyCryptoKey, &type, &key, &keysize)) {
353050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (keysize != 16) {
354b2fb3c9787e4cc372e87b71eb55bfe008b2693ccEdwin Wong            // Keys must be 16 bytes in length.
355050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
356050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
357050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
358050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
359050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *iv;
360050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t ivsize;
361050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
362050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (ivsize != 16) {
363050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // IVs must be 16 bytes in length.
364050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
365050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
366050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
367050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
368050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    int32_t mode;
369050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!meta->findInt32(kKeyCryptoMode, &mode)) {
370050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        mode = CryptoPlugin::kMode_AES_CTR;
371050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
372050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
373050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return AMediaCodecCryptoInfo_new(
374050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            numSubSamples,
375050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (uint8_t*) key,
376050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (uint8_t*) iv,
37779e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen            (cryptoinfo_mode_t) mode,
378050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (size_t*) cleardata,
379050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (size_t*) crypteddata);
380050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
381050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
3820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
3830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} // extern "C"
3840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
385