Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b75a9c8 authored by Andreas Huber's avatar Andreas Huber
Browse files

New API to support submitting encrypted buffers to the decoder.

Change-Id: I69dd60e43078c4211c6123cf6e0ce90e676bf873
related-to-bug: 6275919
parent 3f502bfc
Loading
Loading
Loading
Loading
+21 −8
Original line number Original line Diff line number Diff line
@@ -296,15 +296,28 @@ static int decode(
                    if (sampleFlags & NuMediaExtractor::SAMPLE_FLAG_ENCRYPTED) {
                    if (sampleFlags & NuMediaExtractor::SAMPLE_FLAG_ENCRYPTED) {
                        CHECK(decryptInputBuffers);
                        CHECK(decryptInputBuffers);


                        bufferFlags |= MediaCodec::BUFFER_FLAG_ENCRYPTED;
                        CryptoPlugin::SubSample ss;
                    }
                        ss.mNumBytesOfClearData = 0;
                        ss.mNumBytesOfEncryptedData = buffer->size();


                        err = state->mCodec->queueSecureInputBuffer(
                                index,
                                0 /* offset */,
                                &ss,
                                1 /* numSubSamples */,
                                NULL /* key */,
                                NULL /* iv */,
                                CryptoPlugin::kMode_AES_WV,
                                timeUs,
                                bufferFlags);
                    } else {
                        err = state->mCodec->queueInputBuffer(
                        err = state->mCodec->queueInputBuffer(
                                index,
                                index,
                                0 /* offset */,
                                0 /* offset */,
                                buffer->size(),
                                buffer->size(),
                                timeUs,
                                timeUs,
                                bufferFlags);
                                bufferFlags);
                    }


                    CHECK_EQ(err, (status_t)OK);
                    CHECK_EQ(err, (status_t)OK);


+12 −1
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#define MEDIA_CODEC_H_
#define MEDIA_CODEC_H_


#include <gui/ISurfaceTexture.h>
#include <gui/ISurfaceTexture.h>
#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/foundation/AHandler.h>
#include <utils/Vector.h>
#include <utils/Vector.h>


@@ -40,7 +41,6 @@ struct MediaCodec : public AHandler {
        BUFFER_FLAG_SYNCFRAME   = 1,
        BUFFER_FLAG_SYNCFRAME   = 1,
        BUFFER_FLAG_CODECCONFIG = 2,
        BUFFER_FLAG_CODECCONFIG = 2,
        BUFFER_FLAG_EOS         = 4,
        BUFFER_FLAG_EOS         = 4,
        BUFFER_FLAG_ENCRYPTED   = 8,
    };
    };


    static sp<MediaCodec> CreateByType(
    static sp<MediaCodec> CreateByType(
@@ -74,6 +74,17 @@ struct MediaCodec : public AHandler {
            int64_t presentationTimeUs,
            int64_t presentationTimeUs,
            uint32_t flags);
            uint32_t flags);


    status_t queueSecureInputBuffer(
            size_t index,
            size_t offset,
            const CryptoPlugin::SubSample *subSamples,
            size_t numSubSamples,
            const uint8_t key[16],
            const uint8_t iv[16],
            CryptoPlugin::Mode mode,
            int64_t presentationTimeUs,
            uint32_t flags);

    status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs = 0ll);
    status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs = 0ll);


    status_t dequeueOutputBuffer(
    status_t dequeueOutputBuffer(
+11 −0
Original line number Original line Diff line number Diff line
@@ -97,6 +97,17 @@ struct BpCrypto : public BpInterface<ICrypto> {
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeInt32(secure);
        data.writeInt32(secure);
        data.writeInt32(mode);
        data.writeInt32(mode);

        static const uint8_t kDummy[16] = { 0 };

        if (key == NULL) {
            key = kDummy;
        }

        if (iv == NULL) {
            iv = kDummy;
        }

        data.write(key, 16);
        data.write(key, 16);
        data.write(iv, 16);
        data.write(iv, 16);


+69 −20
Original line number Original line Diff line number Diff line
@@ -191,6 +191,31 @@ status_t MediaCodec::queueInputBuffer(
    return PostAndAwaitResponse(msg, &response);
    return PostAndAwaitResponse(msg, &response);
}
}


status_t MediaCodec::queueSecureInputBuffer(
        size_t index,
        size_t offset,
        const CryptoPlugin::SubSample *subSamples,
        size_t numSubSamples,
        const uint8_t key[16],
        const uint8_t iv[16],
        CryptoPlugin::Mode mode,
        int64_t presentationTimeUs,
        uint32_t flags) {
    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
    msg->setSize("index", index);
    msg->setSize("offset", offset);
    msg->setPointer("subSamples", (void *)subSamples);
    msg->setSize("numSubSamples", numSubSamples);
    msg->setPointer("key", (void *)key);
    msg->setPointer("iv", (void *)iv);
    msg->setInt32("mode", mode);
    msg->setInt64("timeUs", presentationTimeUs);
    msg->setInt32("flags", flags);

    sp<AMessage> response;
    return PostAndAwaitResponse(msg, &response);
}

status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
    sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id());
    sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id());
    msg->setInt64("timeoutUs", timeoutUs);
    msg->setInt64("timeoutUs", timeoutUs);
@@ -1149,10 +1174,51 @@ status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
    uint32_t flags;
    uint32_t flags;
    CHECK(msg->findSize("index", &index));
    CHECK(msg->findSize("index", &index));
    CHECK(msg->findSize("offset", &offset));
    CHECK(msg->findSize("offset", &offset));
    CHECK(msg->findSize("size", &size));
    CHECK(msg->findInt64("timeUs", &timeUs));
    CHECK(msg->findInt64("timeUs", &timeUs));
    CHECK(msg->findInt32("flags", (int32_t *)&flags));
    CHECK(msg->findInt32("flags", (int32_t *)&flags));


    const CryptoPlugin::SubSample *subSamples;
    size_t numSubSamples;
    const uint8_t *key;
    const uint8_t *iv;
    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;

    // We allow the simpler queueInputBuffer API to be used even in
    // secure mode, by fabricating a single unencrypted subSample.
    CryptoPlugin::SubSample ss;

    if (msg->findSize("size", &size)) {
        if (mCrypto != NULL) {
            ss.mNumBytesOfClearData = size;
            ss.mNumBytesOfEncryptedData = 0;

            subSamples = &ss;
            numSubSamples = 1;
            key = NULL;
            iv = NULL;
        }
    } else {
        if (mCrypto == NULL) {
            return -EINVAL;
        }

        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
        CHECK(msg->findSize("numSubSamples", &numSubSamples));
        CHECK(msg->findPointer("key", (void **)&key));
        CHECK(msg->findPointer("iv", (void **)&iv));

        int32_t tmp;
        CHECK(msg->findInt32("mode", &tmp));

        mode = (CryptoPlugin::Mode)tmp;

        size = 0;
        for (size_t i = 0; i < numSubSamples; ++i) {
            size += subSamples[i].mNumBytesOfClearData;
            size += subSamples[i].mNumBytesOfEncryptedData;
        }
    }

    if (index >= mPortBuffers[kPortIndexInput].size()) {
    if (index >= mPortBuffers[kPortIndexInput].size()) {
        return -ERANGE;
        return -ERANGE;
    }
    }
@@ -1187,29 +1253,14 @@ status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
            return -ERANGE;
            return -ERANGE;
        }
        }


        uint8_t key[16];
        uint8_t iv[16];

        CryptoPlugin::Mode mode;
        CryptoPlugin::SubSample ss;
        if (flags & BUFFER_FLAG_ENCRYPTED) {
            mode = CryptoPlugin::kMode_AES_WV;
            ss.mNumBytesOfClearData = 0;
            ss.mNumBytesOfEncryptedData = size;
        } else {
            mode = CryptoPlugin::kMode_Unencrypted;
            ss.mNumBytesOfClearData = size;
            ss.mNumBytesOfEncryptedData = 0;
        }

        status_t err = mCrypto->decrypt(
        status_t err = mCrypto->decrypt(
                (mFlags & kFlagIsSecure) != 0,
                (mFlags & kFlagIsSecure) != 0,
                key,
                key,
                iv,
                iv,
                mode,
                mode,
                info->mEncryptedData->base() + offset,
                info->mEncryptedData->base() + offset,
                &ss,
                subSamples,
                1 /* numSubSamples */,
                numSubSamples,
                info->mData->base());
                info->mData->base());


        if (err != OK) {
        if (err != OK) {
@@ -1217,8 +1268,6 @@ status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
        }
        }


        info->mData->setRange(0, size);
        info->mData->setRange(0, size);
    } else if (flags & BUFFER_FLAG_ENCRYPTED) {
        return -EINVAL;
    }
    }


    reply->setBuffer("buffer", info->mData);
    reply->setBuffer("buffer", info->mData);