ACodecBufferChannel.cpp revision 4c161506a542671f96177b16830f9b362f7a6c61
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 287dff26e5f53b248fd8cc6605850240c7e7c5438dcWonsik Kimvoid 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