1dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim/*
2dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim * Copyright 2016, The Android Open Source Project
3dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim *
4dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim * Licensed under the Apache License, Version 2.0 (the "License");
5dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim * you may not use this file except in compliance with the License.
6dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim * You may obtain a copy of the License at
7dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim *
8dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim *     http://www.apache.org/licenses/LICENSE-2.0
9dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim *
10dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim * Unless required by applicable law or agreed to in writing, software
11dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim * distributed under the License is distributed on an "AS IS" BASIS,
12dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim * See the License for the specific language governing permissions and
14dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim * limitations under the License.
15dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim */
16dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
17dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim//#define LOG_NDEBUG 0
18dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#define LOG_TAG "ACodecBufferChannel"
19dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include <utils/Log.h>
20dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
21dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include <numeric>
22dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
233b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang#include <android/media/IDescrambler.h>
24dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include <binder/MemoryDealer.h>
25dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include <media/openmax/OMX_Core.h>
26dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include <media/stagefright/foundation/AMessage.h>
27dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include <media/stagefright/foundation/AUtils.h>
28dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include <media/stagefright/MediaCodec.h>
29dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include <media/MediaCodecBuffer.h>
30dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include <system/window.h>
31dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
32dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include "include/ACodecBufferChannel.h"
33dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include "include/SecureBuffer.h"
34dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim#include "include/SharedMemoryBuffer.h"
35dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
36dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimnamespace android {
373b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangusing binder::Status;
383b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangusing MediaDescrambler::DescrambleInfo;
39dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimusing BufferInfo = ACodecBufferChannel::BufferInfo;
40dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimusing BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
41dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
42d07c92742fc5801cab8e99801f591365986acbe9Chong ZhangACodecBufferChannel::~ACodecBufferChannel() {
436dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang    if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
446dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang        mCrypto->unsetHeap(mHeapSeqNum);
45d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang    }
46d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang}
47d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang
48dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimstatic BufferInfoIterator findClientBuffer(
49dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        const std::shared_ptr<const std::vector<const BufferInfo>> &array,
50dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        const sp<MediaCodecBuffer> &buffer) {
51dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    return std::find_if(
52dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            array->begin(), array->end(),
53dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            [buffer](const BufferInfo &info) { return info.mClientBuffer == buffer; });
54dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
55dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
56dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimstatic BufferInfoIterator findBufferId(
57dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        const std::shared_ptr<const std::vector<const BufferInfo>> &array,
58dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        IOMX::buffer_id bufferId) {
59dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    return std::find_if(
60dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            array->begin(), array->end(),
61dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            [bufferId](const BufferInfo &info) { return bufferId == info.mBufferId; });
62dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
63dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
64dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik KimACodecBufferChannel::BufferInfo::BufferInfo(
65dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        const sp<MediaCodecBuffer> &buffer,
66dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        IOMX::buffer_id bufferId,
67dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        const sp<IMemory> &sharedEncryptedBuffer)
68dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    : mClientBuffer(
69dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim          (sharedEncryptedBuffer == nullptr)
70dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim          ? buffer
71dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim          : new SharedMemoryBuffer(buffer->format(), sharedEncryptedBuffer)),
72dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim      mCodecBuffer(buffer),
73dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim      mBufferId(bufferId),
74dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim      mSharedEncryptedBuffer(sharedEncryptedBuffer) {
75dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
76dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
77dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik KimACodecBufferChannel::ACodecBufferChannel(
78dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained)
79dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    : mInputBufferFilled(inputBufferFilled),
806dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang      mOutputBufferDrained(outputBufferDrained),
816dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang      mHeapSeqNum(-1) {
82dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
83dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
84dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimstatus_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
853c2c5556f44765abe7e3dc25584a2ccb316a9b14Wonsik Kim    if (mDealer != nullptr) {
863c2c5556f44765abe7e3dc25584a2ccb316a9b14Wonsik Kim        return -ENOSYS;
873c2c5556f44765abe7e3dc25584a2ccb316a9b14Wonsik Kim    }
88dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::shared_ptr<const std::vector<const BufferInfo>> array(
89dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::atomic_load(&mInputBuffers));
90dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    BufferInfoIterator it = findClientBuffer(array, buffer);
91dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (it == array->end()) {
92dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        return -ENOENT;
93dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
94dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    ALOGV("queueInputBuffer #%d", it->mBufferId);
95dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    sp<AMessage> msg = mInputBufferFilled->dup();
96dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->setObject("buffer", it->mCodecBuffer);
97dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->setInt32("buffer-id", it->mBufferId);
98dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->post();
99dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    return OK;
100dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
101dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
102dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimstatus_t ACodecBufferChannel::queueSecureInputBuffer(
103a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        const sp<MediaCodecBuffer> &buffer, bool secure, const uint8_t *key,
104a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        const uint8_t *iv, CryptoPlugin::Mode mode, CryptoPlugin::Pattern pattern,
105a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
106dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        AString *errorDetailMsg) {
1073c2c5556f44765abe7e3dc25584a2ccb316a9b14Wonsik Kim    if (!hasCryptoOrDescrambler() || mDealer == nullptr) {
108dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        return -ENOSYS;
109dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
110dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::shared_ptr<const std::vector<const BufferInfo>> array(
111dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::atomic_load(&mInputBuffers));
112dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    BufferInfoIterator it = findClientBuffer(array, buffer);
113dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (it == array->end()) {
114dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        return -ENOENT;
115dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
116dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
117a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker    ICrypto::DestinationBuffer destination;
118dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (secure) {
119a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        sp<SecureBuffer> secureData =
120a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker                static_cast<SecureBuffer *>(it->mCodecBuffer.get());
121a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        destination.mType = secureData->getDestinationType();
122a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        if (destination.mType != ICrypto::kDestinationTypeNativeHandle) {
123a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker            return BAD_VALUE;
124a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        }
125a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        destination.mHandle =
126a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker                static_cast<native_handle_t *>(secureData->getDestinationPointer());
127dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    } else {
128a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        destination.mType = ICrypto::kDestinationTypeSharedMemory;
129a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        destination.mSharedMemory = mDecryptDestination;
130dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
1313b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang
1326dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang    ICrypto::SourceBuffer source;
1336dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang    source.mSharedMemory = it->mSharedEncryptedBuffer;
1346dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang    source.mHeapSeqNum = mHeapSeqNum;
1356dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang
1363b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang    ssize_t result = -1;
1373b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang    if (mCrypto != NULL) {
1383b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        result = mCrypto->decrypt(key, iv, mode, pattern,
1396dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang                source, it->mClientBuffer->offset(),
1406dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang                subSamples, numSubSamples, destination, errorDetailMsg);
1413b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang    } else {
1423b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        DescrambleInfo descrambleInfo;
1433b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        descrambleInfo.dstType = destination.mType ==
1443b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang                ICrypto::kDestinationTypeSharedMemory ?
1453b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang                DescrambleInfo::kDestinationTypeVmPointer :
1463b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang                DescrambleInfo::kDestinationTypeNativeHandle;
1473b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        descrambleInfo.scramblingControl = key != NULL ?
1483b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang                (DescramblerPlugin::ScramblingControl)key[0] :
1493b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang                DescramblerPlugin::kScrambling_Unscrambled;
1503b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        descrambleInfo.numSubSamples = numSubSamples;
1513b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        descrambleInfo.subSamples = (DescramblerPlugin::SubSample *)subSamples;
1523b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        descrambleInfo.srcMem = it->mSharedEncryptedBuffer;
1533b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        descrambleInfo.srcOffset = 0;
1543b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        descrambleInfo.dstPtr = NULL;
1553b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        descrambleInfo.dstOffset = 0;
1563b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang
1573b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        int32_t descrambleResult = -1;
1583b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        Status status = mDescrambler->descramble(descrambleInfo, &descrambleResult);
1593b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang
1603b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        if (status.isOk()) {
1613b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang            result = descrambleResult;
1623b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        }
1633b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang
1643b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        if (result < 0) {
1653b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang            ALOGE("descramble failed, exceptionCode=%d, err=%d, result=%zd",
1663b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang                    status.exceptionCode(), status.transactionError(), result);
1673b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        } else {
1683b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang            ALOGV("descramble succeeded, result=%zd", result);
1693b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        }
1703b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang
1713b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        if (result > 0 && destination.mType == ICrypto::kDestinationTypeSharedMemory) {
1723b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang            memcpy(destination.mSharedMemory->pointer(),
1733b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang                    (uint8_t*)it->mSharedEncryptedBuffer->pointer(), result);
1743b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        }
1753b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang    }
176dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
177dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (result < 0) {
178dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        return result;
179dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
180dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
181a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker    if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
182a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        memcpy(it->mCodecBuffer->base(), destination.mSharedMemory->pointer(), result);
183a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker    }
184a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker
185dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    it->mCodecBuffer->setRange(0, result);
186dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
187dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    // Copy metadata from client to codec buffer.
188dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    it->mCodecBuffer->meta()->clear();
189dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    int64_t timeUs;
190dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs));
191dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    it->mCodecBuffer->meta()->setInt64("timeUs", timeUs);
192dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    int32_t eos;
193dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (it->mClientBuffer->meta()->findInt32("eos", &eos)) {
194dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        it->mCodecBuffer->meta()->setInt32("eos", eos);
195dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
196dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    int32_t csd;
197dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
198dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        it->mCodecBuffer->meta()->setInt32("csd", csd);
199dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
200dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
201dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    ALOGV("queueSecureInputBuffer #%d", it->mBufferId);
202dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    sp<AMessage> msg = mInputBufferFilled->dup();
203dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->setObject("buffer", it->mCodecBuffer);
204dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->setInt32("buffer-id", it->mBufferId);
205dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->post();
206dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    return OK;
207dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
208dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
209dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimstatus_t ACodecBufferChannel::renderOutputBuffer(
210dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) {
211dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::shared_ptr<const std::vector<const BufferInfo>> array(
212dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::atomic_load(&mOutputBuffers));
213dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    BufferInfoIterator it = findClientBuffer(array, buffer);
214dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (it == array->end()) {
215dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        return -ENOENT;
216dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
217dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
218dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    ALOGV("renderOutputBuffer #%d", it->mBufferId);
219dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    sp<AMessage> msg = mOutputBufferDrained->dup();
220dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->setObject("buffer", buffer);
221dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->setInt32("buffer-id", it->mBufferId);
222dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->setInt32("render", true);
223dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->setInt64("timestampNs", timestampNs);
224dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->post();
225dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    return OK;
226dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
227dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
228dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimstatus_t ACodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
229dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::shared_ptr<const std::vector<const BufferInfo>> array(
230dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::atomic_load(&mInputBuffers));
231dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    bool input = true;
232dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    BufferInfoIterator it = findClientBuffer(array, buffer);
233dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (it == array->end()) {
234dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        array = std::atomic_load(&mOutputBuffers);
235dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        input = false;
236dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        it = findClientBuffer(array, buffer);
237dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        if (it == array->end()) {
238dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            return -ENOENT;
239dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        }
240dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
241dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    ALOGV("discardBuffer #%d", it->mBufferId);
242dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    sp<AMessage> msg = input ? mInputBufferFilled->dup() : mOutputBufferDrained->dup();
243dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->setObject("buffer", it->mCodecBuffer);
244dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->setInt32("buffer-id", it->mBufferId);
245dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->setInt32("discarded", true);
246dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    msg->post();
247dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    return OK;
248dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
249dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
250dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimvoid ACodecBufferChannel::getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
251dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::shared_ptr<const std::vector<const BufferInfo>> inputBuffers(
252dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::atomic_load(&mInputBuffers));
253dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    array->clear();
254dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    for (const BufferInfo &elem : *inputBuffers) {
255dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        array->push_back(elem.mClientBuffer);
256dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
257dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
258dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
259dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimvoid ACodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
260dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::shared_ptr<const std::vector<const BufferInfo>> outputBuffers(
261dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::atomic_load(&mOutputBuffers));
262dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    array->clear();
263dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    for (const BufferInfo &elem : *outputBuffers) {
264dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        array->push_back(elem.mClientBuffer);
265dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
266dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
267dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
268d07c92742fc5801cab8e99801f591365986acbe9Chong Zhangsp<MemoryDealer> ACodecBufferChannel::makeMemoryDealer(size_t heapSize) {
269d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang    sp<MemoryDealer> dealer;
2706dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang    if (mDealer != nullptr && mCrypto != nullptr && mHeapSeqNum >= 0) {
2716dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang        mCrypto->unsetHeap(mHeapSeqNum);
272d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang    }
273d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang    dealer = new MemoryDealer(heapSize, "ACodecBufferChannel");
274d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang    if (mCrypto != nullptr) {
2756dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang        int32_t seqNum = mCrypto->setHeap(dealer->getMemoryHeap());
2766dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang        if (seqNum >= 0) {
2776dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang            mHeapSeqNum = seqNum;
2786dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang            ALOGD("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
2796dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang        } else {
2806dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang            mHeapSeqNum = -1;
2816dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang            ALOGD("setHeap failed, setting mHeapSeqNum=-1");
2826dcab2bafd847be84c2c2230bbd04af9c45c491eChong Zhang        }
283d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang    }
284d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang    return dealer;
285d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang}
286d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang
2874a9ab2a382558941ea7fe92324a3d97848686ca8Dongwon Kangvoid ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
2883b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang    if (hasCryptoOrDescrambler()) {
289dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        size_t totalSize = std::accumulate(
290dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim                array.begin(), array.end(), 0u,
291dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim                [alignment = MemoryDealer::getAllocationAlignment()]
292dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim                (size_t sum, const BufferAndId& elem) {
293dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim                    return sum + align(elem.mBuffer->capacity(), alignment);
294dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim                });
295a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker        size_t maxSize = std::accumulate(
296a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker                array.begin(), array.end(), 0u,
297a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker                [alignment = MemoryDealer::getAllocationAlignment()]
298a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker                (size_t max, const BufferAndId& elem) {
299a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker                    return std::max(max, align(elem.mBuffer->capacity(), alignment));
300a53d6553fce1818bdf87833f93633c93ad1b5915Jeff Tinker                });
301d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang        size_t destinationBufferSize = maxSize;
302d07c92742fc5801cab8e99801f591365986acbe9Chong Zhang        size_t heapSize = totalSize + destinationBufferSize;
3034c161506a542671f96177b16830f9b362f7a6c61Jeff Tinker        if (heapSize > 0) {
3044c161506a542671f96177b16830f9b362f7a6c61Jeff Tinker            mDealer = makeMemoryDealer(heapSize);
3054c161506a542671f96177b16830f9b362f7a6c61Jeff Tinker            mDecryptDestination = mDealer->allocate(destinationBufferSize);
3064c161506a542671f96177b16830f9b362f7a6c61Jeff Tinker        }
307dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
308dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::vector<const BufferInfo> inputBuffers;
309dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    for (const BufferAndId &elem : array) {
310dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        sp<IMemory> sharedEncryptedBuffer;
3113b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang        if (hasCryptoOrDescrambler()) {
312dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            sharedEncryptedBuffer = mDealer->allocate(elem.mBuffer->capacity());
313dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        }
314dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        inputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, sharedEncryptedBuffer);
315dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
316dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::atomic_store(
317dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            &mInputBuffers,
318dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::make_shared<const std::vector<const BufferInfo>>(inputBuffers));
319dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
320dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
321dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimvoid ACodecBufferChannel::setOutputBufferArray(const std::vector<BufferAndId> &array) {
322dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::vector<const BufferInfo> outputBuffers;
323dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    for (const BufferAndId &elem : array) {
324dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        outputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, nullptr);
325dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
326dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::atomic_store(
327dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            &mOutputBuffers,
328dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::make_shared<const std::vector<const BufferInfo>>(outputBuffers));
329dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
330dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
331dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimvoid ACodecBufferChannel::fillThisBuffer(IOMX::buffer_id bufferId) {
332dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    ALOGV("fillThisBuffer #%d", bufferId);
333dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::shared_ptr<const std::vector<const BufferInfo>> array(
334dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::atomic_load(&mInputBuffers));
335dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    BufferInfoIterator it = findBufferId(array, bufferId);
336dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
337dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (it == array->end()) {
338dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        ALOGE("fillThisBuffer: unrecognized buffer #%d", bufferId);
339dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        return;
340dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
341dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (it->mClientBuffer != it->mCodecBuffer) {
342dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        it->mClientBuffer->setFormat(it->mCodecBuffer->format());
343dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
344dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
345dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    mCallback->onInputBufferAvailable(
346dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::distance(array->begin(), it),
347dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            it->mClientBuffer);
348dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
349dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
350dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimvoid ACodecBufferChannel::drainThisBuffer(
351dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        IOMX::buffer_id bufferId,
352dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        OMX_U32 omxFlags) {
353dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    ALOGV("drainThisBuffer #%d", bufferId);
354dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    std::shared_ptr<const std::vector<const BufferInfo>> array(
355dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::atomic_load(&mOutputBuffers));
356dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    BufferInfoIterator it = findBufferId(array, bufferId);
357dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
358dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (it == array->end()) {
359dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        ALOGE("drainThisBuffer: unrecognized buffer #%d", bufferId);
360dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        return;
361dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
362dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (it->mClientBuffer != it->mCodecBuffer) {
363dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        it->mClientBuffer->setFormat(it->mCodecBuffer->format());
364dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
365dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
366dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    uint32_t flags = 0;
367dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
368dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        flags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
369dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
370dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
371dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
372dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
373dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    if (omxFlags & OMX_BUFFERFLAG_EOS) {
374dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim        flags |= MediaCodec::BUFFER_FLAG_EOS;
375dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    }
376dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    it->mClientBuffer->meta()->setInt32("flags", flags);
377dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
378dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim    mCallback->onOutputBufferAvailable(
379dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            std::distance(array->begin(), it),
380dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim            it->mClientBuffer);
381dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}
382dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim
383dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kim}  // namespace android
384