NdkMediaExtractor.cpp revision 3425fd5a55dd31e261d2f2a9590c762d6d0a6b79
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
170c3be875376adaee8d8e8dd917c64926e1513b29Marco 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
410c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenstatic int translate_error(status_t err) {
420c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (err == OK) {
430c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return OK;
440c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
450c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGE("sf error code: %d", err);
46050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return AMEDIAERROR_GENERIC;
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
660c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_delete(AMediaExtractor *mData) {
670c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("dtor");
680c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    delete mData;
690c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return OK;
700c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
710c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
723425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
730c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_setDataSourceFd(AMediaExtractor *mData, int fd, off64_t offset, off64_t length) {
740c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
750c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    mData->mImpl->setDataSource(fd, offset, length);
760c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return 0;
770c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
780c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
793425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
800c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint 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();
89050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return AMEDIAERROR_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();
96050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return AMEDIAERROR_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();
104050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return AMEDIAERROR_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
1180c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    mData->mImpl->setDataSource(httpService, location, NULL);
1190c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    env->ExceptionClear();
120050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return OK;
1210c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1220c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1233425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1240c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint 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
1360c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_selectTrack(AMediaExtractor *mData, size_t idx) {
1370c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("selectTrack(%z)", idx);
1380c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return translate_error(mData->mImpl->selectTrack(idx));
1390c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1400c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1413425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1420c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_unselectTrack(AMediaExtractor *mData, size_t idx) {
1430c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("unselectTrack(%z)", 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
1540c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_readSampleData(AMediaExtractor *mData, uint8_t *buffer, size_t capacity) {
1550c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    //ALOGV("readSampleData");
1560c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<ABuffer> tmp = new ABuffer(buffer, capacity);
1570c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->readSampleData(tmp) == OK) {
1580c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return tmp->size();
1590c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1600c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return -1;
1610c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1620c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1633425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1640c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_getSampleFlags(AMediaExtractor *mData) {
1650c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int sampleFlags = 0;
1660c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<MetaData> meta;
1670c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    status_t err = mData->mImpl->getSampleMeta(&meta);
1680c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (err != OK) {
1690c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
1700c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1710c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int32_t val;
1720c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (meta->findInt32(kKeyIsSyncFrame, &val) && val != 0) {
1730c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        sampleFlags |= NuMediaExtractor::SAMPLE_FLAG_SYNC;
1740c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1750c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1760c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    uint32_t type;
1770c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    const void *data;
1780c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t size;
1790c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (meta->findData(kKeyEncryptedSizes, &type, &data, &size)) {
1800c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        sampleFlags |= NuMediaExtractor::SAMPLE_FLAG_ENCRYPTED;
1810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return sampleFlags;
1830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1853425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint AMediaExtractor_getSampleTrackIndex(AMediaExtractor *mData) {
1870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t idx;
1880c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->getSampleTrackIndex(&idx) != OK) {
1890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
1900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return idx;
1920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1930c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1943425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
1950c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenint64_t AMediaExtractor_getSampletime(AMediaExtractor *mData) {
1960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int64_t time;
1970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mImpl->getSampleTime(&time) != OK) {
1980c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return -1;
1990c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return time;
2010c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2033425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
204050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenPsshInfo* AMediaExtractor_getPsshInfo(AMediaExtractor *ex) {
205050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
206050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (ex->mPsshBuf != NULL) {
207050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return (PsshInfo*) ex->mPsshBuf->data();
208050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
209050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
210050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<AMessage> format;
211050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mImpl->getFileFormat(&format);
212050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<ABuffer> buffer;
213050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if(!format->findBuffer("pssh", &buffer)) {
214050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
215050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
216050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
217050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // the format of the buffer is 1 or more of:
218050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //    {
219050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        16 byte uuid
220050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        4 byte data length N
221050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //        N bytes of data
222050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    //    }
223050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
224050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // Determine the number of entries in the source data.
225050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // Since we got the data from stagefright, we trust it is valid and properly formatted.
226050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const uint8_t* data = buffer->data();
227050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t len = buffer->size();
228050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t numentries = 0;
229050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    while (len > 0) {
230050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        numentries++;
231050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
232050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // skip uuid
233050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += 16;
234050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= 16;
235050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
236050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // get data length
237050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t datalen = *((uint32_t*)data);
238050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += 4;
239050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= 4;
240050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
241050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // skip the data
242050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        data += datalen;
243050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        len -= datalen;
244050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
245050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
246050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // there are <numentries> in the buffer, we need
247050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // (source buffer size) + 4 + (4 * numentries) bytes for the PsshInfo structure
248050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t newsize = buffer->size() + 4 + (4 * numentries);
249050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mPsshBuf = new ABuffer(newsize);
250050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ex->mPsshBuf->setRange(0, newsize);
251050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
252050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // copy data
253050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const uint8_t* src = buffer->data();
254050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    uint8_t* dst = ex->mPsshBuf->data();
255050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    uint8_t* dstdata = dst + 4 + numentries * sizeof(PsshEntry);
256050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    *((uint32_t*)dst) = numentries;
257050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    dst += 4;
258050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    for (size_t i = 0; i < numentries; i++) {
259050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // copy uuid
260050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dst, src, 16);
261050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        src += 16;
262050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dst += 16;
263050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
264050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // get/copy data length
265050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t datalen = *((uint32_t*)src);
266050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dst, src, 4);
267050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        src += 4;
268050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dst += 4;
269050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
270050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // the next entry in the destination is a pointer to the actual data, which we store
271050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // after the array of PsshEntry
272050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dst, &dstdata, sizeof(dstdata));
273050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dst += 4;
274050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
275050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        // copy the actual data
276050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        memcpy(dstdata, src, datalen);
277050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        dstdata += datalen;
278050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        src += datalen;
279050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
280050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
281050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return (PsshInfo*) ex->mPsshBuf->data();
282050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
283050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
2843425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
285050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenAMediaCodecCryptoInfo *AMediaExtractor_getSampleCryptoInfo(AMediaExtractor *ex) {
286050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    sp<MetaData> meta;
287050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if(ex->mImpl->getSampleMeta(&meta) != 0) {
288050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
289050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
290050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
291050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    uint32_t type;
292050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *crypteddata;
293050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t cryptedsize;
294050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
295050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
296050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
297050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t numSubSamples = cryptedsize / sizeof(size_t);
298050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
299050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *cleardata;
300050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t clearsize;
301050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
302050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (clearsize != cryptedsize) {
303050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // The two must be of the same length.
304050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
305050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
306050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
307050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
308050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *key;
309050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t keysize;
310050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyCryptoIV, &type, &key, &keysize)) {
311050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (keysize != 16) {
312050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // IVs must be 16 bytes in length.
313050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
314050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
315050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
316050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
317050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    const void *iv;
318050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t ivsize;
319050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
320050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        if (ivsize != 16) {
321050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            // IVs must be 16 bytes in length.
322050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            return NULL;
323050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        }
324050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
325050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
326050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    int32_t mode;
327050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!meta->findInt32(kKeyCryptoMode, &mode)) {
328050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        mode = CryptoPlugin::kMode_AES_CTR;
329050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
330050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
331050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return AMediaCodecCryptoInfo_new(
332050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            numSubSamples,
333050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (uint8_t*) key,
334050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (uint8_t*) iv,
335050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            mode,
336050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (size_t*) cleardata,
337050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (size_t*) crypteddata);
338050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
339050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
3400c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
3410c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} // extern "C"
3420c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
343