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
73e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor *mData, int fd, off64_t offset, off64_t length) {
740c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
75e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return translate_error(mData->mImpl->setDataSource(fd, offset, length));
760c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
770c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
783425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
79e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) {
800c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("setDataSource(%s)", location);
810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    // TODO: add header support
820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    JNIEnv *env = AndroidRuntime::getJNIEnv();
840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jobject service = NULL;
850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (env == NULL) {
860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        ALOGE("setDataSource(path) must be called from Java thread");
870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        env->ExceptionClear();
88e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_UNSUPPORTED;
890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jclass mediahttpclass = env->FindClass("android/media/MediaHTTPService");
920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mediahttpclass == NULL) {
930c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        ALOGE("can't find MediaHttpService");
940c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        env->ExceptionClear();
95e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_UNSUPPORTED;
960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
980c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jmethodID mediaHttpCreateMethod = env->GetStaticMethodID(mediahttpclass,
990c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            "createHttpServiceBinderIfNecessary", "(Ljava/lang/String;)Landroid/os/IBinder;");
1000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mediaHttpCreateMethod == NULL) {
1010c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        ALOGE("can't find method");
1020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        env->ExceptionClear();
103e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_UNSUPPORTED;
1040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jstring jloc = env->NewStringUTF(location);
1070c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1080c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    service = env->CallStaticObjectMethod(mediahttpclass, mediaHttpCreateMethod, jloc);
1090c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    env->DeleteLocalRef(jloc);
1100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<IMediaHTTPService> httpService;
1120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (service != NULL) {
1130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        sp<IBinder> binder = ibinderForJavaObject(env, service);
1140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        httpService = interface_cast<IMediaHTTPService>(binder);
1150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1160c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
117e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    status_t err = mData->mImpl->setDataSource(httpService, location, NULL);
1180c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    env->ExceptionClear();
119e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return translate_error(err);
1200c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1210c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1223425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
123e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissensize_t AMediaExtractor_getTrackCount(AMediaExtractor *mData) {
1240c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return mData->mImpl->countTracks();
1250c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1260c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1273425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1280c3be875376adaee8d8e8dd917c64926e1513b29Marco NelissenAMediaFormat* AMediaExtractor_getTrackFormat(AMediaExtractor *mData, size_t idx) {
1290c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<AMessage> format;
1300c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    mData->mImpl->getTrackFormat(idx, &format);
1310c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return AMediaFormat_fromMsg(&format);
1320c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1330c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1343425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
135e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_selectTrack(AMediaExtractor *mData, size_t idx) {
13698f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn    ALOGV("selectTrack(%zu)", idx);
1370c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return translate_error(mData->mImpl->selectTrack(idx));
1380c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1390c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1403425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
141e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_unselectTrack(AMediaExtractor *mData, size_t idx) {
14298f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn    ALOGV("unselectTrack(%zu)", idx);
1430c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return translate_error(mData->mImpl->unselectTrack(idx));
1440c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1450c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1463425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1470c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenbool AMediaExtractor_advance(AMediaExtractor *mData) {
1480c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    //ALOGV("advance");
1490c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return mData->mImpl->advance();
1500c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1510c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1523425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
15379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissenmedia_status_t AMediaExtractor_seekTo(AMediaExtractor *ex, int64_t seekPosUs, SeekMode mode) {
15479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    android::MediaSource::ReadOptions::SeekMode sfmode;
15579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    if (mode == AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC) {
15679e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC;
15779e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    } else if (mode == AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC) {
15879e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_CLOSEST_SYNC;
15979e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    } else {
16079e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_NEXT_SYNC;
16179e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    }
16279e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen
16379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    return translate_error(ex->mImpl->seekTo(seekPosUs, sfmode));
16479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen}
16579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen
16679e2b622702fb148ccff12d6f38643466555c4ebMarco NelissenEXPORT
167e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenssize_t AMediaExtractor_readSampleData(AMediaExtractor *mData, uint8_t *buffer, size_t capacity) {
1680c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    //ALOGV("readSampleData");
1690c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<ABuffer> tmp = new ABuffer(buffer, capacity);
1700c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->readSampleData(tmp) == OK) {
1710c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return tmp->size();
1720c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1730c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return -1;
1740c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1750c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1763425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
177e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenuint32_t AMediaExtractor_getSampleFlags(AMediaExtractor *mData) {
1780c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int sampleFlags = 0;
1790c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<MetaData> meta;
1800c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    status_t err = mData->mImpl->getSampleMeta(&meta);
1810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (err != OK) {
1820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
1830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int32_t val;
1850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) {
186e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_SYNC;
1870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1880c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    uint32_t type;
1900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    const void *data;
1910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t size;
1920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) {
193e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_ENCRYPTED;
1940c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1950c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return sampleFlags;
1960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1983425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1990c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_getSampleTrackIndex(AMediaExtractor *mData) {
2000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t idx;
2010c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->getSampleTrackIndex(&idx) != OK) {
2020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
2030c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return idx;
2050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2073425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
208eb4860c305def68c5965474bb43c67c2c9d49bbbMarco Nelissenint64_t AMediaExtractor_getSampleTime(AMediaExtractor *mData) {
2090c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int64_t time;
2100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->getSampleTime(&time) != OK) {
2110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
2120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return time;
2140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2163425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
217050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenPsshInfo* AMediaExtractor_getPsshInfo(AMediaExtractor *ex) {
218050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
219050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (ex->mPsshBuf != NULL) {
220050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return (PsshInfo*) ex->mPsshBuf->data();
221050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
222050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
223050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<AMessage> format;
224050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mImpl->getFileFormat(&format);
225050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<ABuffer> buffer;
226050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if(!format->findBuffer("pssh", &buffer)) {
227050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
228050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
229050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
230050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // the format of the buffer is 1 or more of:
231050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //    {
232050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        16 byte uuid
233050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        4 byte data length N
234050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        N bytes of data
235050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //    }
236050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
237050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // Determine the number of entries in the source data.
238050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // Since we got the data from stagefright, we trust it is valid and properly formatted.
239050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const uint8_t* data = buffer->data();
240050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t len = buffer->size();
241050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t numentries = 0;
242050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    while (len > 0) {
243050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        numentries++;
244050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
245050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // skip uuid
246050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += 16;
247050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= 16;
248050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
249050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // get data length
250050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t datalen = *((uint32_t*)data);
251050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += 4;
252050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= 4;
253050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
254050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // skip the data
255050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += datalen;
256050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= datalen;
257050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
258050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
25958344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // there are <numentries> in the source buffer, we need
26058344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // (source buffer size) - (sizeof(uint32_t) * numentries) + sizeof(size_t)
26158344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    //  + ((sizeof(void*) + sizeof(size_t)) * numentries) bytes for the PsshInfo structure
26258344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // Or in other words, the data lengths in the source structure are replaced by size_t
26358344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // (which may be the same size or larger, for 64 bit), and in addition there is an
26458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // extra pointer for each entry, and an extra size_t for the entire PsshInfo.
26558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    size_t newsize = buffer->size() - (sizeof(uint32_t) * numentries) + sizeof(size_t)
26658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen            + ((sizeof(void*) + sizeof(size_t)) * numentries);
267050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mPsshBuf = new ABuffer(newsize);
268050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mPsshBuf->setRange(0, newsize);
269050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
270050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // copy data
271050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const uint8_t* src = buffer->data();
272050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    uint8_t* dst = ex->mPsshBuf->data();
27358344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    uint8_t* dstdata = dst + sizeof(size_t) + numentries * sizeof(PsshEntry);
27458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    *((size_t*)dst) = numentries;
27558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    dst += sizeof(size_t);
276050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    for (size_t i = 0; i < numentries; i++) {
277050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // copy uuid
278050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dst, src, 16);
279050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        src += 16;
280050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dst += 16;
281050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
282050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // get/copy data length
283050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t datalen = *((uint32_t*)src);
28458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        *((size_t*)dst) = datalen;
28558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        src += sizeof(uint32_t);
28658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        dst += sizeof(size_t);
287050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
288050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // the next entry in the destination is a pointer to the actual data, which we store
289050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // after the array of PsshEntry
29058344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        *((void**)dst) = dstdata;
29158344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        dst += sizeof(void*);
292050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
293050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // copy the actual data
294050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dstdata, src, datalen);
295050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dstdata += datalen;
296050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        src += datalen;
297050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
298050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
299050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return (PsshInfo*) ex->mPsshBuf->data();
300050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
301050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
3023425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
303050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenAMediaCodecCryptoInfo *AMediaExtractor_getSampleCryptoInfo(AMediaExtractor *ex) {
304050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<MetaData> meta;
305050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if(ex->mImpl->getSampleMeta(&meta) != 0) {
306050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
307050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
308050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
309050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    uint32_t type;
310050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *crypteddata;
311050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t cryptedsize;
312050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
313050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
314050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
315050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t numSubSamples = cryptedsize / sizeof(size_t);
316050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
317050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *cleardata;
318050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t clearsize;
319050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
320050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (clearsize != cryptedsize) {
321050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // The two must be of the same length.
322050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
323050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
324050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
325050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
326050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *key;
327050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t keysize;
328050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyCryptoIV, &type, &key, &keysize)) {
329050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (keysize != 16) {
330050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // IVs must be 16 bytes in length.
331050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
332050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
333050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
334050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
335050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *iv;
336050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t ivsize;
337050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
338050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (ivsize != 16) {
339050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // IVs must be 16 bytes in length.
340050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
341050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
342050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
343050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
344050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    int32_t mode;
345050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!meta->findInt32(kKeyCryptoMode, &mode)) {
346050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        mode = CryptoPlugin::kMode_AES_CTR;
347050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
348050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
349050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return AMediaCodecCryptoInfo_new(
350050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            numSubSamples,
351050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (uint8_t*) key,
352050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (uint8_t*) iv,
35379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen            (cryptoinfo_mode_t) mode,
354050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (size_t*) cleardata,
355050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (size_t*) crypteddata);
356050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
357050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
3580c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
3590c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} // extern "C"
3600c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
361