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
260c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <utils/Log.h>
270c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <utils/StrongPointer.h>
28050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen#include <media/hardware/CryptoAPI.h>
290c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/foundation/ABuffer.h>
300c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/foundation/AMessage.h>
310c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/MetaData.h>
320c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/NuMediaExtractor.h>
330c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/IMediaHTTPService.h>
340c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <android_runtime/AndroidRuntime.h>
350c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <android_util_Binder.h>
360c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
370c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <jni.h>
380c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
390c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenusing namespace android;
400c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
41e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenstatic media_status_t translate_error(status_t err) {
420c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (err == OK) {
43e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_OK;
440c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
450c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGE("sf error code: %d", err);
46e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_ERROR_UNKNOWN;
470c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
480c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
490c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenstruct AMediaExtractor {
500c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<NuMediaExtractor> mImpl;
51050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<ABuffer> mPsshBuf;
520c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
530c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen};
540c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
550c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenextern "C" {
560c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
573425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
580c3be875376adaee8d8e8dd917c64926e1513b29Marco NelissenAMediaExtractor* AMediaExtractor_new() {
590c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("ctor");
600c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    AMediaExtractor *mData = new AMediaExtractor();
610c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    mData->mImpl = new NuMediaExtractor();
620c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return mData;
630c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
640c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
653425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
66e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_delete(AMediaExtractor *mData) {
670c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("dtor");
680c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    delete mData;
69e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_OK;
700c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
710c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
723425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
73b187de1ada34a9023c05d020a4592686ba761278Glenn Kastenmedia_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor *mData, int fd, off64_t offset,
74b187de1ada34a9023c05d020a4592686ba761278Glenn Kasten        off64_t length) {
750c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
76e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return translate_error(mData->mImpl->setDataSource(fd, offset, length));
770c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
780c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
793425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
80e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) {
810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("setDataSource(%s)", location);
820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    // TODO: add header support
830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    JNIEnv *env = AndroidRuntime::getJNIEnv();
850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jobject service = NULL;
860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (env == NULL) {
870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        ALOGE("setDataSource(path) must be called from Java thread");
880c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        env->ExceptionClear();
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");
1500c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return mData->mImpl->advance();
1510c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1520c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1533425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
15479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissenmedia_status_t AMediaExtractor_seekTo(AMediaExtractor *ex, int64_t seekPosUs, SeekMode mode) {
15579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    android::MediaSource::ReadOptions::SeekMode sfmode;
15679e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    if (mode == AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC) {
15779e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC;
15879e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    } else if (mode == AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC) {
15979e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_CLOSEST_SYNC;
16079e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    } else {
16179e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_NEXT_SYNC;
16279e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    }
16379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen
16479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    return translate_error(ex->mImpl->seekTo(seekPosUs, sfmode));
16579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen}
16679e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen
16779e2b622702fb148ccff12d6f38643466555c4ebMarco NelissenEXPORT
168e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenssize_t AMediaExtractor_readSampleData(AMediaExtractor *mData, uint8_t *buffer, size_t capacity) {
1690c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    //ALOGV("readSampleData");
1700c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<ABuffer> tmp = new ABuffer(buffer, capacity);
1710c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->readSampleData(tmp) == OK) {
1720c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return tmp->size();
1730c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1740c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return -1;
1750c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1760c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1773425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
178e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenuint32_t AMediaExtractor_getSampleFlags(AMediaExtractor *mData) {
1790c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int sampleFlags = 0;
1800c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<MetaData> meta;
1810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    status_t err = mData->mImpl->getSampleMeta(&meta);
1820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (err != OK) {
1830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
1840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int32_t val;
1860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) {
187e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_SYNC;
1880c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    uint32_t type;
1910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    const void *data;
1920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t size;
1930c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) {
194e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_ENCRYPTED;
1950c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return sampleFlags;
1970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1980c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1993425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
2000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_getSampleTrackIndex(AMediaExtractor *mData) {
2010c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t idx;
2020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->getSampleTrackIndex(&idx) != OK) {
2030c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
2040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return idx;
2060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2070c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2083425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
209eb4860c305def68c5965474bb43c67c2c9d49bbbMarco Nelissenint64_t AMediaExtractor_getSampleTime(AMediaExtractor *mData) {
2100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int64_t time;
2110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->getSampleTime(&time) != OK) {
2120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
2130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return time;
2150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2160c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2173425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
218050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenPsshInfo* AMediaExtractor_getPsshInfo(AMediaExtractor *ex) {
219050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
220050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (ex->mPsshBuf != NULL) {
221050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return (PsshInfo*) ex->mPsshBuf->data();
222050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
223050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
224050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<AMessage> format;
225050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mImpl->getFileFormat(&format);
226050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<ABuffer> buffer;
227050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if(!format->findBuffer("pssh", &buffer)) {
228050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
229050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
230050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
231050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // the format of the buffer is 1 or more of:
232050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //    {
233050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        16 byte uuid
234050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        4 byte data length N
235050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        N bytes of data
236050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //    }
237050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
238050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // Determine the number of entries in the source data.
239050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // Since we got the data from stagefright, we trust it is valid and properly formatted.
240050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const uint8_t* data = buffer->data();
241050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t len = buffer->size();
242050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t numentries = 0;
243050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    while (len > 0) {
244050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        numentries++;
245050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
246050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // skip uuid
247050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += 16;
248050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= 16;
249050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
250050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // get data length
251050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t datalen = *((uint32_t*)data);
252050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += 4;
253050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= 4;
254050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
255050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // skip the data
256050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += datalen;
257050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= datalen;
258050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
259050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
26058344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // there are <numentries> in the source buffer, we need
26158344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // (source buffer size) - (sizeof(uint32_t) * numentries) + sizeof(size_t)
26258344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    //  + ((sizeof(void*) + sizeof(size_t)) * numentries) bytes for the PsshInfo structure
26358344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // Or in other words, the data lengths in the source structure are replaced by size_t
26458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // (which may be the same size or larger, for 64 bit), and in addition there is an
26558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // extra pointer for each entry, and an extra size_t for the entire PsshInfo.
26658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    size_t newsize = buffer->size() - (sizeof(uint32_t) * numentries) + sizeof(size_t)
26758344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen            + ((sizeof(void*) + sizeof(size_t)) * numentries);
268050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mPsshBuf = new ABuffer(newsize);
269050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mPsshBuf->setRange(0, newsize);
270050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
271050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // copy data
272050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const uint8_t* src = buffer->data();
273050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    uint8_t* dst = ex->mPsshBuf->data();
27458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    uint8_t* dstdata = dst + sizeof(size_t) + numentries * sizeof(PsshEntry);
27558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    *((size_t*)dst) = numentries;
27658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    dst += sizeof(size_t);
277050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    for (size_t i = 0; i < numentries; i++) {
278050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // copy uuid
279050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dst, src, 16);
280050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        src += 16;
281050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dst += 16;
282050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
283050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // get/copy data length
284050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t datalen = *((uint32_t*)src);
28558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        *((size_t*)dst) = datalen;
28658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        src += sizeof(uint32_t);
28758344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        dst += sizeof(size_t);
288050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
289050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // the next entry in the destination is a pointer to the actual data, which we store
290050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // after the array of PsshEntry
29158344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        *((void**)dst) = dstdata;
29258344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        dst += sizeof(void*);
293050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
294050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // copy the actual data
295050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dstdata, src, datalen);
296050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dstdata += datalen;
297050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        src += datalen;
298050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
299050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
300050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return (PsshInfo*) ex->mPsshBuf->data();
301050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
302050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
3033425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
304050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenAMediaCodecCryptoInfo *AMediaExtractor_getSampleCryptoInfo(AMediaExtractor *ex) {
305050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<MetaData> meta;
306050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if(ex->mImpl->getSampleMeta(&meta) != 0) {
307050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
308050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
309050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
310050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    uint32_t type;
311050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *crypteddata;
312050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t cryptedsize;
313050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
314050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
315050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
316050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t numSubSamples = cryptedsize / sizeof(size_t);
317050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
318050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *cleardata;
319050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t clearsize;
320050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
321050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (clearsize != cryptedsize) {
322050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // The two must be of the same length.
323050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
324050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
325050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
326050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
327050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *key;
328050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t keysize;
329050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyCryptoIV, &type, &key, &keysize)) {
330050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (keysize != 16) {
331050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // IVs must be 16 bytes in length.
332050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
333050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
334050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
335050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
336050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *iv;
337050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t ivsize;
338050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
339050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (ivsize != 16) {
340050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // IVs must be 16 bytes in length.
341050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
342050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
343050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
344050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
345050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    int32_t mode;
346050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!meta->findInt32(kKeyCryptoMode, &mode)) {
347050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        mode = CryptoPlugin::kMode_AES_CTR;
348050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
349050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
350050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return AMediaCodecCryptoInfo_new(
351050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            numSubSamples,
352050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (uint8_t*) key,
353050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (uint8_t*) iv,
35479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen            (cryptoinfo_mode_t) mode,
355050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (size_t*) cleardata,
356050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (size_t*) crypteddata);
357050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
358050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
3590c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
3600c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} // extern "C"
3610c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
362