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
1798f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn#include <inttypes.h>
1898f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn
19c7a11b2208aa8f1e6a39eb70a136fbc0dafd3260Marco Nelissen//#define LOG_NDEBUG 0
200c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#define LOG_TAG "NdkMediaCodec"
210c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
220c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include "NdkMediaCodec.h"
23050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen#include "NdkMediaError.h"
24050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen#include "NdkMediaCryptoPriv.h"
250c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include "NdkMediaFormatPriv.h"
260c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
270c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <utils/Log.h>
280c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <utils/StrongPointer.h>
290c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <gui/Surface.h>
300c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
310c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/foundation/ALooper.h>
320c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/foundation/AMessage.h>
330c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/foundation/ABuffer.h>
340c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
350c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/MediaCodec.h>
360c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen#include <media/stagefright/MediaErrors.h>
370c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
380c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenusing namespace android;
390c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
400c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
41e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenstatic media_status_t translate_error(status_t err) {
420c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (err == OK) {
43e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_OK;
440c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    } else if (err == -EAGAIN) {
45e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return (media_status_t) AMEDIACODEC_INFO_TRY_AGAIN_LATER;
460c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
470c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGE("sf error code: %d", err);
48e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_ERROR_UNKNOWN;
490c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
500c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
51cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissenenum {
52cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    kWhatActivityNotify,
53cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    kWhatRequestActivityNotifications,
54cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    kWhatStopActivityNotifications,
55cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen};
56cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
570c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
580c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenclass CodecHandler: public AHandler {
59cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissenprivate:
60cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    AMediaCodec* mCodec;
610c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenpublic:
62cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    CodecHandler(AMediaCodec *codec);
630c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    virtual void onMessageReceived(const sp<AMessage> &msg);
640c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen};
650c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
66e22a64b6887240fc9910d6fc8afb0e6f81507047Marco Nelissentypedef void (*OnCodecEvent)(AMediaCodec *codec, void *userdata);
67e22a64b6887240fc9910d6fc8afb0e6f81507047Marco Nelissen
68cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissenstruct AMediaCodec {
69cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    sp<android::MediaCodec> mCodec;
70cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    sp<ALooper> mLooper;
71cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    sp<CodecHandler> mHandler;
72cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    sp<AMessage> mActivityNotification;
73cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    int32_t mGeneration;
74cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    bool mRequestedActivityNotification;
75cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    OnCodecEvent mCallback;
76cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    void *mCallbackUserData;
77cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen};
780c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
79cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco NelissenCodecHandler::CodecHandler(AMediaCodec *codec) {
80cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    mCodec = codec;
810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenvoid CodecHandler::onMessageReceived(const sp<AMessage> &msg) {
84cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
85cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    switch (msg->what()) {
86cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen        case kWhatRequestActivityNotifications:
87cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen        {
88cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            if (mCodec->mRequestedActivityNotification) {
89cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen                break;
90cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            }
91cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
92cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            mCodec->mCodec->requestActivityNotification(mCodec->mActivityNotification);
93cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            mCodec->mRequestedActivityNotification = true;
94cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            break;
95cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen        }
96cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
97cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen        case kWhatActivityNotify:
98cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen        {
99cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            {
100cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen                int32_t generation;
101cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen                msg->findInt32("generation", &generation);
102cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
103cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen                if (generation != mCodec->mGeneration) {
104cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen                    // stale
105cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen                    break;
106cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen                }
107cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
108cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen                mCodec->mRequestedActivityNotification = false;
109cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            }
110cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
111cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            if (mCodec->mCallback) {
112cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen                mCodec->mCallback(mCodec, mCodec->mCallbackUserData);
113cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            }
114cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            break;
115cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen        }
116cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
117cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen        case kWhatStopActivityNotifications:
118cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen        {
119cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            uint32_t replyID;
120cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            msg->senderAwaitsResponse(&replyID);
121cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
122cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            mCodec->mGeneration++;
123cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            mCodec->mRequestedActivityNotification = false;
124cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
125cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            sp<AMessage> response = new AMessage;
126cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            response->postReply(replyID);
127cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            break;
128cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen        }
129cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
130cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen        default:
131cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            ALOGE("shouldn't be here");
132cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen            break;
133cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    }
134cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
1350c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1360c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
137cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
138cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissenstatic void requestActivityNotification(AMediaCodec *codec) {
139cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    (new AMessage(kWhatRequestActivityNotifications, codec->mHandler->id()))->post();
140cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen}
1410c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1420c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenextern "C" {
1430c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1440c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenstatic AMediaCodec * createAMediaCodec(const char *name, bool name_is_type, bool encoder) {
1450c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    AMediaCodec *mData = new AMediaCodec();
1460c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    mData->mLooper = new ALooper;
1470c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    mData->mLooper->setName("NDK MediaCodec_looper");
1480c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    status_t ret = mData->mLooper->start(
1490c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            false,      // runOnCallingThread
1500c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            true,       // canCallJava XXX
1510c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            PRIORITY_FOREGROUND);
1520c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (name_is_type) {
1530c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        mData->mCodec = android::MediaCodec::CreateByType(mData->mLooper, name, encoder);
1540c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    } else {
1550c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        mData->mCodec = android::MediaCodec::CreateByComponentName(mData->mLooper, name);
1560c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
157cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    mData->mHandler = new CodecHandler(mData);
1580c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    mData->mLooper->registerHandler(mData->mHandler);
159cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    mData->mGeneration = 1;
160cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    mData->mRequestedActivityNotification = false;
161cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    mData->mCallback = NULL;
162cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
1630c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return mData;
1640c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1650c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1663425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
16786aa02ce274826dc80ffa00766b16172c47503fdMarco NelissenAMediaCodec* AMediaCodec_createCodecByName(const char *name) {
1680c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return createAMediaCodec(name, false, false);
1690c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1700c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1713425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
17286aa02ce274826dc80ffa00766b16172c47503fdMarco NelissenAMediaCodec* AMediaCodec_createDecoderByType(const char *mime_type) {
1730c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return createAMediaCodec(mime_type, true, false);
1740c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1750c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1763425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
17786aa02ce274826dc80ffa00766b16172c47503fdMarco NelissenAMediaCodec* AMediaCodec_createEncoderByType(const char *name) {
17886aa02ce274826dc80ffa00766b16172c47503fdMarco Nelissen    return createAMediaCodec(name, true, true);
1790c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1800c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1813425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
182e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodec_delete(AMediaCodec *mData) {
1830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mCodec != NULL) {
1840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        mData->mCodec->release();
1850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        mData->mCodec.clear();
1860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1880c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mLooper != NULL) {
1890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        mData->mLooper->unregisterHandler(mData->mHandler->id());
1900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        mData->mLooper->stop();
1910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        mData->mLooper.clear();
1920c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
1930c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    delete mData;
194e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_OK;
1950c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
1960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
1973425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
198e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodec_configure(
199050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        AMediaCodec *mData,
200050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        const AMediaFormat* format,
201050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        ANativeWindow* window,
202050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        AMediaCrypto *crypto,
203050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t flags) {
2040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<AMessage> nativeFormat;
2050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    AMediaFormat_getFormat(format, &nativeFormat);
2060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGV("configure with format: %s", nativeFormat->debugString(0).c_str());
2070c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<Surface> surface = NULL;
2080c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (window != NULL) {
2090c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        surface = (Surface*) window;
2100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2110c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
212050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return translate_error(mData->mCodec->configure(nativeFormat, surface,
213050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            crypto ? crypto->mCrypto : NULL, flags));
2140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2163425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
217e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodec_start(AMediaCodec *mData) {
218cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    status_t ret =  mData->mCodec->start();
219cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    if (ret != OK) {
220cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen        return translate_error(ret);
221cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    }
222cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler->id());
223cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    mData->mActivityNotification->setInt32("generation", mData->mGeneration);
224cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    requestActivityNotification(mData);
225e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_OK;
2260c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2270c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2283425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
229e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodec_stop(AMediaCodec *mData) {
230e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    media_status_t ret = translate_error(mData->mCodec->stop());
231cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
232cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler->id());
233cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    sp<AMessage> response;
234cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    msg->postAndAwaitResponse(&response);
235cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    mData->mActivityNotification.clear();
236cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
237cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    return ret;
2380c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2390c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2403425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
241e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodec_flush(AMediaCodec *mData) {
2420c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return translate_error(mData->mCodec->flush());
2430c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2440c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2453425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
2460c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec *mData, int64_t timeoutUs) {
2470c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t idx;
2480c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    status_t ret = mData->mCodec->dequeueInputBuffer(&idx, timeoutUs);
249cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    requestActivityNotification(mData);
2500c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (ret == OK) {
2510c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return idx;
2520c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2530c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return translate_error(ret);
2540c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2550c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2563425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
2570c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenuint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
2580c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    android::Vector<android::sp<android::ABuffer> > abufs;
2590c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mCodec->getInputBuffers(&abufs) == 0) {
2600c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        size_t n = abufs.size();
2610c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        if (idx >= n) {
26298f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn            ALOGE("buffer index %zu out of range", idx);
2630c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            return NULL;
2640c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        }
2650c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        if (out_size != NULL) {
2660c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            *out_size = abufs[idx]->capacity();
2670c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        }
2680c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return abufs[idx]->data();
2690c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2700c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGE("couldn't get input buffers");
2710c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return NULL;
2720c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2730c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2743425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
2750c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenuint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
2760c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    android::Vector<android::sp<android::ABuffer> > abufs;
2770c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (mData->mCodec->getOutputBuffers(&abufs) == 0) {
2780c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        size_t n = abufs.size();
2790c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        if (idx >= n) {
28098f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn            ALOGE("buffer index %zu out of range", idx);
2810c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            return NULL;
2820c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        }
2830c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        if (out_size != NULL) {
2840c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            *out_size = abufs[idx]->capacity();
2850c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        }
2860c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return abufs[idx]->data();
2870c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
2880c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    ALOGE("couldn't get output buffers");
2890c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return NULL;
2900c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
2910c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2923425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
293e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodec_queueInputBuffer(AMediaCodec *mData,
2940c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags) {
2950c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
2960c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    AString errorMsg;
2970c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    status_t ret = mData->mCodec->queueInputBuffer(idx, offset, size, time, flags, &errorMsg);
2980c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return translate_error(ret);
2990c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
3000c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
3013425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
3020c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissenssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec *mData,
3030c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        AMediaCodecBufferInfo *info, int64_t timeoutUs) {
3040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t idx;
3050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t offset;
3060c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    size_t size;
3070c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    uint32_t flags;
3080c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    int64_t presentationTimeUs;
3090c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    status_t ret = mData->mCodec->dequeueOutputBuffer(&idx, &offset, &size, &presentationTimeUs,
3100c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            &flags, timeoutUs);
311cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    requestActivityNotification(mData);
3120c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    switch (ret) {
3130c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        case OK:
3140c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            info->offset = offset;
3150c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            info->size = size;
3160c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            info->flags = flags;
3170c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            info->presentationTimeUs = presentationTimeUs;
3180c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            return idx;
3190c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        case -EAGAIN:
3200c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            return AMEDIACODEC_INFO_TRY_AGAIN_LATER;
3210c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        case android::INFO_FORMAT_CHANGED:
3220c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            return AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED;
3230c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        case INFO_OUTPUT_BUFFERS_CHANGED:
3240c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            return AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED;
3250c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        default:
3260c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen            break;
3270c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
3280c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return translate_error(ret);
3290c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
3300c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
3313425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
3320c3be875376adaee8d8e8dd917c64926e1513b29Marco NelissenAMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec *mData) {
3330c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    sp<AMessage> format;
3340c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    mData->mCodec->getOutputFormat(&format);
3350c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    return AMediaFormat_fromMsg(&format);
3360c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
3370c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
3383425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
339e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, bool render) {
3400c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    if (render) {
3410c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx));
3420c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    } else {
3430c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen        return translate_error(mData->mCodec->releaseOutputBuffer(idx));
3440c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen    }
3450c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen}
3460c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
3473425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
34879e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissenmedia_status_t AMediaCodec_releaseOutputBufferAtTime(
34979e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        AMediaCodec *mData, size_t idx, int64_t timestampNs) {
35098f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn    ALOGV("render @ %" PRId64, timestampNs);
35179e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen    return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx, timestampNs));
35279e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen}
35379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen
354e22a64b6887240fc9910d6fc8afb0e6f81507047Marco Nelissen//EXPORT
355e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback, void *userdata) {
356cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    mData->mCallback = callback;
357cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen    mData->mCallbackUserData = userdata;
358e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_OK;
359cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen}
360cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
361050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissentypedef struct AMediaCodecCryptoInfo {
362050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        int numsubsamples;
363050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint8_t key[16];
364050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint8_t iv[16];
36579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        cryptoinfo_mode_t mode;
366050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        size_t *clearbytes;
367050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        size_t *encryptedbytes;
368050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen} AMediaCodecCryptoInfo;
369050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
3703425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
371e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodec_queueSecureInputBuffer(
372050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        AMediaCodec* codec,
373050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        size_t idx,
374050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        off_t offset,
375050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        AMediaCodecCryptoInfo* crypto,
376050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint64_t time,
377050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint32_t flags) {
378050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
379050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[crypto->numsubsamples];
380050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    for (int i = 0; i < crypto->numsubsamples; i++) {
381050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        subSamples[i].mNumBytesOfClearData = crypto->clearbytes[i];
382050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        subSamples[i].mNumBytesOfEncryptedData = crypto->encryptedbytes[i];
383050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
384050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
385050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    AString errormsg;
386050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    status_t err  = codec->mCodec->queueSecureInputBuffer(idx,
387050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            offset,
388050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            subSamples,
389050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            crypto->numsubsamples,
390050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            crypto->key,
391050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            crypto->iv,
392050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            (CryptoPlugin::Mode) crypto->mode,
393050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            time,
394050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            flags,
395050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen            &errormsg);
396050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (err != 0) {
397050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        ALOGE("queSecureInputBuffer: %s", errormsg.c_str());
398050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
399829e097f832b4c4c41733f9b77121888204d993eMarco Nelissen    delete [] subSamples;
400050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return translate_error(err);
401050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
402050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
403050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
404050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
4053425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
406050eb3280d7305b84f723d515be2dc9606dc39d1Marco NelissenAMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new(
407050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        int numsubsamples,
408050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint8_t key[16],
409050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        uint8_t iv[16],
41079e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        cryptoinfo_mode_t mode,
411050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        size_t *clearbytes,
412050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        size_t *encryptedbytes) {
413050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
414050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // size needed to store all the crypto data
415050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    size_t cryptosize = sizeof(AMediaCodecCryptoInfo) + sizeof(size_t) * numsubsamples * 2;
416050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    AMediaCodecCryptoInfo *ret = (AMediaCodecCryptoInfo*) malloc(cryptosize);
417050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!ret) {
41898f28cde0d5d682956b5e6b119823e7e8d40415bMark Salyzyn        ALOGE("couldn't allocate %zu bytes", cryptosize);
419050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen        return NULL;
420050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
421050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ret->numsubsamples = numsubsamples;
422050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    memcpy(ret->key, key, 16);
423050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    memcpy(ret->iv, iv, 16);
424050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    ret->mode = mode;
425050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
426050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    // clearbytes and encryptedbytes point at the actual data, which follows
427829e097f832b4c4c41733f9b77121888204d993eMarco Nelissen    ret->clearbytes = (size_t*) (ret + 1); // point immediately after the struct
428829e097f832b4c4c41733f9b77121888204d993eMarco Nelissen    ret->encryptedbytes = ret->clearbytes + numsubsamples; // point after the clear sizes
429050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
430829e097f832b4c4c41733f9b77121888204d993eMarco Nelissen    memcpy(ret->clearbytes, clearbytes, numsubsamples * sizeof(size_t));
431829e097f832b4c4c41733f9b77121888204d993eMarco Nelissen    memcpy(ret->encryptedbytes, encryptedbytes, numsubsamples * sizeof(size_t));
432050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
433050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return ret;
434050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
435050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
436050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
4373425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
438e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo* info) {
439050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    free(info);
440e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_OK;
441050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
442050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
4433425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
444050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissensize_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo* ci) {
445050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return ci->numsubsamples;
446050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
447050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
4483425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
449e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
450e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    if (!ci) {
451e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_INVALID_OBJECT;
452e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    }
453e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    if (!dst) {
454e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_INVALID_PARAMETER;
455050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
456050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    memcpy(dst, ci->key, 16);
457e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_OK;
458050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
459050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
4603425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
461e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
462e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    if (!ci) {
463e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_INVALID_OBJECT;
464e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    }
465e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    if (!dst) {
466e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_INVALID_PARAMETER;
467050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
468050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    memcpy(dst, ci->iv, 16);
469e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_OK;
470050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
471050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
4723425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
47379e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissencryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo* ci) {
474050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    if (!ci) {
47579e2b622702fb148ccff12d6f38643466555c4ebMarco Nelissen        return (cryptoinfo_mode_t) AMEDIA_ERROR_INVALID_OBJECT;
476050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
477050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    return ci->mode;
478050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
479050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
4803425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
481e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
482e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    if (!ci) {
483e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_INVALID_OBJECT;
484e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    }
485e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    if (!dst) {
486e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_INVALID_PARAMETER;
487050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
488050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    memcpy(dst, ci->clearbytes, sizeof(size_t) * ci->numsubsamples);
489e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_OK;
490050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
491050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen
4923425fd5a55dd31e261d2f2a9590c762d6d0a6b79Marco NelissenEXPORT
493e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissenmedia_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
494e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    if (!ci) {
495e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_INVALID_OBJECT;
496e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    }
497e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    if (!dst) {
498e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen        return AMEDIA_ERROR_INVALID_PARAMETER;
499050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    }
500050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen    memcpy(dst, ci->encryptedbytes, sizeof(size_t) * ci->numsubsamples);
501e419d7cd5c62b4b5866a45d59c5770bb470193c1Marco Nelissen    return AMEDIA_OK;
502050eb3280d7305b84f723d515be2dc9606dc39d1Marco Nelissen}
503cdb42cdc5ccb785edabe1ee6407134fbae5662a9Marco Nelissen
5040c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen} // extern "C"
5050c3be875376adaee8d8e8dd917c64926e1513b29Marco Nelissen
506