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");
890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        env->ExceptionClear();
90e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_UNSUPPORTED;
910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
930c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jclass mediahttpclass = env->FindClass("android/media/MediaHTTPService");
940c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mediahttpclass == NULL) {
950c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        ALOGE("can't find MediaHttpService");
960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        env->ExceptionClear();
97e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_UNSUPPORTED;
980c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
990c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jmethodID mediaHttpCreateMethod = env->GetStaticMethodID(mediahttpclass,
1010c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            "createHttpServiceBinderIfNecessary", "(Ljava/lang/String;)Landroid/os/IBinder;");
1020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mediaHttpCreateMethod == NULL) {
1030c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        ALOGE("can't find method");
1040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        env->ExceptionClear();
105e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_UNSUPPORTED;
1060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1070c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1080c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    jstring jloc = env->NewStringUTF(location);
1090c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    service = env->CallStaticObjectMethod(mediahttpclass, mediaHttpCreateMethod, jloc);
1110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    env->DeleteLocalRef(jloc);
1120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<IMediaHTTPService> httpService;
1140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (service != NULL) {
1150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        sp<IBinder> binder = ibinderForJavaObject(env, service);
1160c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        httpService = interface_cast<IMediaHTTPService>(binder);
1170c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1180c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
119e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    status_t err = mData->mImpl->setDataSource(httpService, location, NULL);
1200c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    env->ExceptionClear();
121e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return translate_error(err);
1220c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1230c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1243425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
125e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissensize_t AMediaExtractor_getTrackCount(AMediaExtractor *mData) {
1260c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return mData->mImpl->countTracks();
1270c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1280c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1293425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1300c3be875376adaee8d8e8dd917c64926e1513b29Marco NelissenAMediaFormat* AMediaExtractor_getTrackFormat(AMediaExtractor *mData, size_t idx) {
1310c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<AMessage> format;
1320c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    mData->mImpl->getTrackFormat(idx, &format);
1330c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return AMediaFormat_fromMsg(&format);
1340c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1350c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1363425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
137e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_selectTrack(AMediaExtractor *mData, size_t idx) {
13898f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn    ALOGV("selectTrack(%zu)", idx);
1390c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return translate_error(mData->mImpl->selectTrack(idx));
1400c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1410c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1423425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
143e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaExtractor_unselectTrack(AMediaExtractor *mData, size_t idx) {
14498f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn    ALOGV("unselectTrack(%zu)", idx);
1450c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return translate_error(mData->mImpl->unselectTrack(idx));
1460c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1470c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1483425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1490c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenbool AMediaExtractor_advance(AMediaExtractor *mData) {
1500c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    //ALOGV("advance");
1510c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return mData->mImpl->advance();
1520c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1530c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1543425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
15579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissenmedia_status_t AMediaExtractor_seekTo(AMediaExtractor *ex, int64_t seekPosUs, SeekMode mode) {
15679e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    android::MediaSource::ReadOptions::SeekMode sfmode;
15779e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    if (mode == AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC) {
15879e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC;
15979e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    } else if (mode == AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC) {
16079e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_CLOSEST_SYNC;
16179e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    } else {
16279e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        sfmode = android::MediaSource::ReadOptions::SEEK_NEXT_SYNC;
16379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    }
16479e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen
16579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    return translate_error(ex->mImpl->seekTo(seekPosUs, sfmode));
16679e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen}
16779e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen
16879e2b622702fb148ccff12d6f38643466555c4ebMarco NelissenEXPORT
169e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenssize_t AMediaExtractor_readSampleData(AMediaExtractor *mData, uint8_t *buffer, size_t capacity) {
1700c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    //ALOGV("readSampleData");
1710c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<ABuffer> tmp = new ABuffer(buffer, capacity);
1720c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->readSampleData(tmp) == OK) {
1730c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return tmp->size();
1740c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1750c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return -1;
1760c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1770c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1783425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
179e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenuint32_t AMediaExtractor_getSampleFlags(AMediaExtractor *mData) {
1800c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int sampleFlags = 0;
1810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<MetaData> meta;
1820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    status_t err = mData->mImpl->getSampleMeta(&meta);
1830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (err != OK) {
1840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
1850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int32_t val;
1870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) {
188e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_SYNC;
1890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    uint32_t type;
1920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    const void *data;
1930c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t size;
1940c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) {
195e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        sampleFlags |= AMEDIAEXTRACTOR_SAMPLE_FLAG_ENCRYPTED;
1960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return sampleFlags;
1980c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1990c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2003425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
2010c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_getSampleTrackIndex(AMediaExtractor *mData) {
2020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t idx;
2030c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->getSampleTrackIndex(&idx) != OK) {
2040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
2050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return idx;
2070c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2080c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2093425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
210eb4860c305def68c5965474bb43c67c2c9d49bbbMarco Nelissenint64_t AMediaExtractor_getSampleTime(AMediaExtractor *mData) {
2110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int64_t time;
2120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->getSampleTime(&time) != OK) {
2130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
2140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return time;
2160c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2170c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2183425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
219050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenPsshInfo* AMediaExtractor_getPsshInfo(AMediaExtractor *ex) {
220050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
221050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (ex->mPsshBuf != NULL) {
222050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return (PsshInfo*) ex->mPsshBuf->data();
223050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
224050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
225050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<AMessage> format;
226050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mImpl->getFileFormat(&format);
227050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<ABuffer> buffer;
228050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if(!format->findBuffer("pssh", &buffer)) {
229050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
230050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
231050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
232050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // the format of the buffer is 1 or more of:
233050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //    {
234050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        16 byte uuid
235050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        4 byte data length N
236050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        N bytes of data
237050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //    }
238050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
239050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // Determine the number of entries in the source data.
240050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // Since we got the data from stagefright, we trust it is valid and properly formatted.
241050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const uint8_t* data = buffer->data();
242050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t len = buffer->size();
243050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t numentries = 0;
244050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    while (len > 0) {
245050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        numentries++;
246050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
247346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        if (len < 16) {
248346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            ALOGE("invalid PSSH data");
249346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            return NULL;
250346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        }
251050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // skip uuid
252050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += 16;
253050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= 16;
254050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
255050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // get data length
256346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        if (len < 4) {
257346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            ALOGE("invalid PSSH data");
258346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            return NULL;
259346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        }
260050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t datalen = *((uint32_t*)data);
261050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += 4;
262050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= 4;
263050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
264346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        if (len < datalen) {
265346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            ALOGE("invalid PSSH data");
266346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen            return NULL;
267346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        }
268050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // skip the data
269050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += datalen;
270050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= datalen;
271050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
272050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
27358344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // there are <numentries> in the source buffer, we need
27458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // (source buffer size) - (sizeof(uint32_t) * numentries) + sizeof(size_t)
27558344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    //  + ((sizeof(void*) + sizeof(size_t)) * numentries) bytes for the PsshInfo structure
27658344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // Or in other words, the data lengths in the source structure are replaced by size_t
27758344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // (which may be the same size or larger, for 64 bit), and in addition there is an
27858344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    // extra pointer for each entry, and an extra size_t for the entire PsshInfo.
27958344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    size_t newsize = buffer->size() - (sizeof(uint32_t) * numentries) + sizeof(size_t)
28058344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen            + ((sizeof(void*) + sizeof(size_t)) * numentries);
281346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen    if (newsize <= buffer->size()) {
282346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        ALOGE("invalid PSSH data");
283346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen        return NULL;
284346bb516cc55944fbdf683a928b7e99fac2f7eb6Marco Nelissen    }
285050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mPsshBuf = new ABuffer(newsize);
286050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mPsshBuf->setRange(0, newsize);
287050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
288050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // copy data
289050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const uint8_t* src = buffer->data();
290050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    uint8_t* dst = ex->mPsshBuf->data();
29158344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    uint8_t* dstdata = dst + sizeof(size_t) + numentries * sizeof(PsshEntry);
29258344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    *((size_t*)dst) = numentries;
29358344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen    dst += sizeof(size_t);
294050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    for (size_t i = 0; i < numentries; i++) {
295050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // copy uuid
296050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dst, src, 16);
297050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        src += 16;
298050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dst += 16;
299050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
300050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // get/copy data length
301050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t datalen = *((uint32_t*)src);
30258344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        *((size_t*)dst) = datalen;
30358344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        src += sizeof(uint32_t);
30458344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        dst += sizeof(size_t);
305050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
306050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // the next entry in the destination is a pointer to the actual data, which we store
307050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // after the array of PsshEntry
30858344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        *((void**)dst) = dstdata;
30958344bc9165a9465a63acc874f3e71251a0d7f50Marco Nelissen        dst += sizeof(void*);
310050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
311050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // copy the actual data
312050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dstdata, src, datalen);
313050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dstdata += datalen;
314050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        src += datalen;
315050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
316050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
317050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return (PsshInfo*) ex->mPsshBuf->data();
318050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
319050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
3203425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
321050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenAMediaCodecCryptoInfo *AMediaExtractor_getSampleCryptoInfo(AMediaExtractor *ex) {
322050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<MetaData> meta;
323050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if(ex->mImpl->getSampleMeta(&meta) != 0) {
324050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
325050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
326050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
327050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    uint32_t type;
328050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *crypteddata;
329050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t cryptedsize;
330050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
331050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
332050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
333050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t numSubSamples = cryptedsize / sizeof(size_t);
334050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
335050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *cleardata;
336050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t clearsize;
337050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
338050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (clearsize != cryptedsize) {
339050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // The two must be of the same length.
340050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
341050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
342050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
343050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
344050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *key;
345050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t keysize;
346050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyCryptoIV, &type, &key, &keysize)) {
347050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (keysize != 16) {
348050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // IVs must be 16 bytes in length.
349050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
350050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
351050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
352050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
353050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *iv;
354050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t ivsize;
355050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
356050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (ivsize != 16) {
357050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // IVs must be 16 bytes in length.
358050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
359050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
360050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
361050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
362050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    int32_t mode;
363050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!meta->findInt32(kKeyCryptoMode, &mode)) {
364050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        mode = CryptoPlugin::kMode_AES_CTR;
365050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
366050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
367050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return AMediaCodecCryptoInfo_new(
368050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            numSubSamples,
369050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (uint8_t*) key,
370050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (uint8_t*) iv,
37179e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen            (cryptoinfo_mode_t) mode,
372050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (size_t*) cleardata,
373050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (size_t*) crypteddata);
374050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
375050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
3760c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
3770c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} // extern "C"
3780c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
379