Loading media/codec2/sfplugin/CCodecBufferChannel.cpp +256 −0 Original line number Diff line number Diff line Loading @@ -483,6 +483,130 @@ int32_t CCodecBufferChannel::getHeapSeqNum(const sp<HidlMemory> &memory) { return heapSeqNum; } typedef WrapperObject<std::vector<AccessUnitInfo>> BufferInfosWrapper; typedef WrapperObject<std::vector<std::unique_ptr<CodecCryptoInfo>>> CryptoInfosWrapper; status_t CCodecBufferChannel::attachEncryptedBuffers( const sp<hardware::HidlMemory> &memory, size_t offset, const sp<MediaCodecBuffer> &buffer, bool secure, AString* errorDetailMsg) { static const C2MemoryUsage kDefaultReadWriteUsage{ C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}; if (!hasCryptoOrDescrambler()) { ALOGE("attachEncryptedBuffers requires Crypto/descrambler object"); return -ENOSYS; } size_t size = 0; CHECK(buffer->meta()->findSize("ssize", &size)); if (size == 0) { buffer->setRange(0, 0); return OK; } sp<RefBase> obj; CHECK(buffer->meta()->findObject("cryptoInfos", &obj)); sp<CryptoInfosWrapper> cryptoInfos{(CryptoInfosWrapper *)obj.get()}; CHECK(buffer->meta()->findObject("accessUnitInfo", &obj)); sp<BufferInfosWrapper> bufferInfos{(BufferInfosWrapper *)obj.get()}; if (secure || (mCrypto == nullptr)) { if (cryptoInfos->value.size() != 1) { ALOGE("Cannot decrypt multiple access units"); return -ENOSYS; } // we are dealing with just one cryptoInfo or descrambler. std::unique_ptr<CodecCryptoInfo> info = std::move(cryptoInfos->value[0]); if (info == nullptr) { ALOGE("Cannot decrypt, CryptoInfos are null."); return -ENOSYS; } return attachEncryptedBuffer( memory, secure, info->mKey, info->mIv, info->mMode, info->mPattern, offset, info->mSubSamples, info->mNumSubSamples, buffer, errorDetailMsg); } std::shared_ptr<C2BlockPool> pool = mBlockPools.lock()->inputPool; std::shared_ptr<C2LinearBlock> block; c2_status_t err = pool->fetchLinearBlock( size, kDefaultReadWriteUsage, &block); if (err != C2_OK) { ALOGI("[%s] attachEncryptedBuffers: fetchLinearBlock failed: size = %zu (%s) err = %d", mName, size, secure ? "secure" : "non-secure", err); return NO_MEMORY; } ensureDecryptDestination(size); C2WriteView wView = block->map().get(); if (wView.error() != C2_OK) { ALOGI("[%s] attachEncryptedBuffers: block map error: %d (non-secure)", mName, wView.error()); return UNKNOWN_ERROR; } ssize_t result = -1; ssize_t codecDataOffset = 0; size_t inBufferOffset = 0; size_t outBufferSize = 0; uint32_t cryptoInfoIdx = 0; int32_t heapSeqNum = getHeapSeqNum(memory); hardware::drm::V1_0::SharedBuffer src{(uint32_t)heapSeqNum, offset, size}; hardware::drm::V1_0::DestinationBuffer dst; dst.type = DrmBufferType::SHARED_MEMORY; IMemoryToSharedBuffer( mDecryptDestination, mHeapSeqNum, &dst.nonsecureMemory); for (int i = 0; i < bufferInfos->value.size(); i++) { if (bufferInfos->value[i].mSize > 0) { std::unique_ptr<CodecCryptoInfo> info = std::move(cryptoInfos->value[cryptoInfoIdx++]); result = mCrypto->decrypt( (uint8_t*)info->mKey, (uint8_t*)info->mIv, info->mMode, info->mPattern, src, inBufferOffset, info->mSubSamples, info->mNumSubSamples, dst, errorDetailMsg); inBufferOffset += bufferInfos->value[i].mSize; if (result < 0) { ALOGI("[%s] attachEncryptedBuffers: decrypt failed: result = %zd", mName, result); return result; } if (wView.error() == C2_OK) { if (wView.size() < result) { ALOGI("[%s] attachEncryptedBuffers: block size too small:" "size=%u result=%zd (non-secure)", mName, wView.size(), result); return UNKNOWN_ERROR; } memcpy(wView.data(), mDecryptDestination->unsecurePointer(), result); bufferInfos->value[i].mSize = result; wView.setOffset(wView.offset() + result); } outBufferSize += result; } } if (wView.error() == C2_OK) { wView.setOffset(0); } std::shared_ptr<C2Buffer> c2Buffer{C2Buffer::CreateLinearBuffer( block->share(codecDataOffset, outBufferSize - codecDataOffset, C2Fence{}))}; if (!buffer->copy(c2Buffer)) { ALOGI("[%s] attachEncryptedBuffers: buffer copy failed", mName); return -ENOSYS; } return OK; } status_t CCodecBufferChannel::attachEncryptedBuffer( const sp<hardware::HidlMemory> &memory, bool secure, Loading Loading @@ -777,6 +901,138 @@ status_t CCodecBufferChannel::queueSecureInputBuffer( return queueInputBufferInternal(buffer, block, bufferSize); } status_t CCodecBufferChannel::queueSecureInputBuffers( const sp<MediaCodecBuffer> &buffer, bool secure, AString *errorDetailMsg) { QueueGuard guard(mSync); if (!guard.isRunning()) { ALOGD("[%s] No more buffers should be queued at current state.", mName); return -ENOSYS; } if (!hasCryptoOrDescrambler()) { ALOGE("queueSecureInputBuffers requires a Crypto/descrambler Object"); return -ENOSYS; } sp<RefBase> obj; CHECK(buffer->meta()->findObject("cryptoInfos", &obj)); sp<CryptoInfosWrapper> cryptoInfos{(CryptoInfosWrapper *)obj.get()}; CHECK(buffer->meta()->findObject("accessUnitInfo", &obj)); sp<BufferInfosWrapper> bufferInfos{(BufferInfosWrapper *)obj.get()}; if (secure || mCrypto == nullptr) { if (cryptoInfos->value.size() != 1) { ALOGE("Cannot decrypt multiple access units on native handles"); return -ENOSYS; } std::unique_ptr<CodecCryptoInfo> info = std::move(cryptoInfos->value[0]); if (info == nullptr) { ALOGE("Cannot decrypt, CryptoInfos are null"); return -ENOSYS; } return queueSecureInputBuffer( buffer, secure, info->mKey, info->mIv, info->mMode, info->mPattern, info->mSubSamples, info->mNumSubSamples, errorDetailMsg); } sp<EncryptedLinearBlockBuffer> encryptedBuffer((EncryptedLinearBlockBuffer *)buffer.get()); std::shared_ptr<C2LinearBlock> block; size_t allocSize = buffer->size(); size_t bufferSize = 0; c2_status_t blockRes = C2_OK; bool copied = false; ScopedTrace trace(ATRACE_TAG, android::base::StringPrintf( "CCodecBufferChannel::decrypt(%s)", mName).c_str()); if (mSendEncryptedInfoBuffer) { static const C2MemoryUsage kDefaultReadWriteUsage{ C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}; constexpr int kAllocGranule0 = 1024 * 64; constexpr int kAllocGranule1 = 1024 * 1024; std::shared_ptr<C2BlockPool> pool = mBlockPools.lock()->inputPool; // round up encrypted sizes to limit fragmentation and encourage buffer reuse if (allocSize <= kAllocGranule1) { bufferSize = align(allocSize, kAllocGranule0); } else { bufferSize = align(allocSize, kAllocGranule1); } blockRes = pool->fetchLinearBlock( bufferSize, kDefaultReadWriteUsage, &block); if (blockRes == C2_OK) { C2WriteView view = block->map().get(); if (view.error() == C2_OK && view.size() == bufferSize) { copied = true; // TODO: only copy clear sections memcpy(view.data(), buffer->data(), allocSize); } } } if (!copied) { block.reset(); } // size of cryptoInfo and accessUnitInfo should be the same? ssize_t result = -1; ssize_t codecDataOffset = 0; size_t inBufferOffset = 0; size_t outBufferSize = 0; uint32_t cryptoInfoIdx = 0; { // scoped this block to enable destruction of mappedBlock std::unique_ptr<EncryptedLinearBlockBuffer::MappedBlock> mappedBlock = nullptr; hardware::drm::V1_0::DestinationBuffer destination; destination.type = DrmBufferType::SHARED_MEMORY; IMemoryToSharedBuffer( mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory); encryptedBuffer->getMappedBlock(&mappedBlock); hardware::drm::V1_0::SharedBuffer source; encryptedBuffer->fillSourceBuffer(&source); for (int i = 0 ; i < bufferInfos->value.size(); i++) { if (bufferInfos->value[i].mSize > 0) { std::unique_ptr<CodecCryptoInfo> info = std::move(cryptoInfos->value[cryptoInfoIdx++]); if (info->mNumSubSamples == 1 && info->mSubSamples[0].mNumBytesOfClearData == 0 && info->mSubSamples[0].mNumBytesOfEncryptedData == 0) { // no data so we only populate the bufferInfo result = 0; } else { result = mCrypto->decrypt( (uint8_t*)info->mKey, (uint8_t*)info->mIv, info->mMode, info->mPattern, source, inBufferOffset, info->mSubSamples, info->mNumSubSamples, destination, errorDetailMsg); inBufferOffset += bufferInfos->value[i].mSize; if (result < 0) { ALOGI("[%s] decrypt failed: result=%zd", mName, result); return result; } if (destination.type == DrmBufferType::SHARED_MEMORY && mappedBlock) { mappedBlock->copyDecryptedContent(mDecryptDestination, result); } bufferInfos->value[i].mSize = result; outBufferSize += result; } } } buffer->setRange(codecDataOffset, outBufferSize - codecDataOffset); } return queueInputBufferInternal(buffer, block, bufferSize); } void CCodecBufferChannel::feedInputBufferIfAvailable() { QueueGuard guard(mSync); if (!guard.isRunning()) { Loading media/codec2/sfplugin/CCodecBufferChannel.h +10 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,10 @@ public: const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, AString *errorDetailMsg) override; status_t queueSecureInputBuffers( const sp<MediaCodecBuffer> &buffer, bool secure, AString *errorDetailMsg) override; status_t attachBuffer( const std::shared_ptr<C2Buffer> &c2Buffer, const sp<MediaCodecBuffer> &buffer) override; Loading @@ -88,6 +92,12 @@ public: size_t numSubSamples, const sp<MediaCodecBuffer> &buffer, AString* errorDetailMsg) override; status_t attachEncryptedBuffers( const sp<hardware::HidlMemory> &memory, size_t offset, const sp<MediaCodecBuffer> &buffer, bool secure, AString* errorDetailMsg) override; status_t renderOutputBuffer( const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override; void pollForRenderedBuffers() override; Loading media/codec2/sfplugin/Codec2Buffer.cpp +31 −0 Original line number Diff line number Diff line Loading @@ -1036,6 +1036,37 @@ native_handle_t *EncryptedLinearBlockBuffer::handle() const { return const_cast<native_handle_t *>(mBlock->handle()); } void EncryptedLinearBlockBuffer::getMappedBlock( std::unique_ptr<MappedBlock> * const mappedBlock) const { if (mappedBlock) { mappedBlock->reset(new EncryptedLinearBlockBuffer::MappedBlock(mBlock)); } return; } EncryptedLinearBlockBuffer::MappedBlock::MappedBlock( const std::shared_ptr<C2LinearBlock> &block) : mView(block->map().get()) { } bool EncryptedLinearBlockBuffer::MappedBlock::copyDecryptedContent( const sp<IMemory> &decrypted, size_t length) { if (mView.error() != C2_OK) { return false; } if (mView.size() < length) { ALOGE("View size(%d) less than decrypted length(%zu)", mView.size(), length); return false; } memcpy(mView.data(), decrypted->unsecurePointer(), length); mView.setOffset(mView.offset() + length); return true; } EncryptedLinearBlockBuffer::MappedBlock::~MappedBlock() { mView.setOffset(0); } using ::aidl::android::hardware::graphics::common::Cta861_3; using ::aidl::android::hardware::graphics::common::Smpte2086; Loading media/codec2/sfplugin/Codec2Buffer.h +11 −0 Original line number Diff line number Diff line Loading @@ -384,6 +384,17 @@ public: */ native_handle_t *handle() const; class MappedBlock { public: explicit MappedBlock(const std::shared_ptr<C2LinearBlock> &block); virtual ~MappedBlock(); bool copyDecryptedContent(const sp<IMemory> &decrypted, size_t length); private: C2WriteView mView; }; void getMappedBlock(std::unique_ptr<MappedBlock> * const mappedBlock) const; private: std::shared_ptr<C2LinearBlock> mBlock; Loading media/libstagefright/CryptoAsync.cpp +49 −15 Original line number Diff line number Diff line Loading @@ -30,6 +30,36 @@ namespace android { CryptoAsync::CryptoAsyncInfo::CryptoAsyncInfo(const std::unique_ptr<CodecCryptoInfo> &info) { if (info == nullptr) { return; } size_t key_len = (info->mKey != nullptr)? 16 : 0; size_t iv_len = (info->mIv != nullptr)? 16 : 0; mNumSubSamples = info->mNumSubSamples; mMode = info->mMode; mPattern = info->mPattern; if (key_len > 0) { mKeyBuffer = ABuffer::CreateAsCopy((void*)info->mKey, key_len); mKey = (uint8_t*)(mKeyBuffer.get() != nullptr ? mKeyBuffer.get()->data() : nullptr); } if (iv_len > 0) { mIvBuffer = ABuffer::CreateAsCopy((void*)info->mIv, iv_len); mIv = (uint8_t*)(mIvBuffer.get() != nullptr ? mIvBuffer.get()->data() : nullptr); } mSubSamplesBuffer = new ABuffer(sizeof(CryptoPlugin::SubSample) * mNumSubSamples); if (mSubSamplesBuffer.get()) { CryptoPlugin::SubSample * samples = (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data()); for (int s = 0 ; s < mNumSubSamples ; s++) { samples[s].mNumBytesOfClearData = info->mSubSamples[s].mNumBytesOfClearData; samples[s].mNumBytesOfEncryptedData = info->mSubSamples[s].mNumBytesOfEncryptedData; } mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data(); } } CryptoAsync::~CryptoAsync() { } Loading Loading @@ -79,23 +109,27 @@ status_t CryptoAsync::decryptAndQueue(sp<AMessage> & msg) { sp<ABuffer> keyBuffer; sp<ABuffer> ivBuffer; sp<ABuffer> subSamplesBuffer; AString errorDetailMsg; msg->findObject("buffer", &obj); msg->findInt32("secure", &secure); sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); if (buffer->meta()->findObject("cryptoInfos", &obj)) { err = channel->queueSecureInputBuffers(buffer, secure, &errorDetailMsg); } else { msg->findInt32("encryptBlocks", (int32_t*)&pattern.mEncryptBlocks); msg->findInt32("skipBlocks", (int32_t*)&pattern.mSkipBlocks); msg->findBuffer("key", &keyBuffer); msg->findBuffer("iv", &ivBuffer); msg->findBuffer("subSamples", &subSamplesBuffer); msg->findInt32("secure", &secure); msg->findSize("numSubSamples", &numSubSamples); msg->findObject("buffer", &obj); msg->findInt32("mode", (int32_t*)&mode); AString errorDetailMsg; const uint8_t * key = keyBuffer.get() != nullptr ? keyBuffer.get()->data() : nullptr; const uint8_t * iv = ivBuffer.get() != nullptr ? ivBuffer.get()->data() : nullptr; const CryptoPlugin::SubSample * subSamples = (CryptoPlugin::SubSample *)(subSamplesBuffer.get()->data()); sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); err = channel->queueSecureInputBuffer(buffer, secure, key, iv, mode, pattern, subSamples, numSubSamples, &errorDetailMsg); } if (err != OK) { std::list<sp<AMessage>> errorList; msg->removeEntryByName("buffer"); Loading Loading
media/codec2/sfplugin/CCodecBufferChannel.cpp +256 −0 Original line number Diff line number Diff line Loading @@ -483,6 +483,130 @@ int32_t CCodecBufferChannel::getHeapSeqNum(const sp<HidlMemory> &memory) { return heapSeqNum; } typedef WrapperObject<std::vector<AccessUnitInfo>> BufferInfosWrapper; typedef WrapperObject<std::vector<std::unique_ptr<CodecCryptoInfo>>> CryptoInfosWrapper; status_t CCodecBufferChannel::attachEncryptedBuffers( const sp<hardware::HidlMemory> &memory, size_t offset, const sp<MediaCodecBuffer> &buffer, bool secure, AString* errorDetailMsg) { static const C2MemoryUsage kDefaultReadWriteUsage{ C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}; if (!hasCryptoOrDescrambler()) { ALOGE("attachEncryptedBuffers requires Crypto/descrambler object"); return -ENOSYS; } size_t size = 0; CHECK(buffer->meta()->findSize("ssize", &size)); if (size == 0) { buffer->setRange(0, 0); return OK; } sp<RefBase> obj; CHECK(buffer->meta()->findObject("cryptoInfos", &obj)); sp<CryptoInfosWrapper> cryptoInfos{(CryptoInfosWrapper *)obj.get()}; CHECK(buffer->meta()->findObject("accessUnitInfo", &obj)); sp<BufferInfosWrapper> bufferInfos{(BufferInfosWrapper *)obj.get()}; if (secure || (mCrypto == nullptr)) { if (cryptoInfos->value.size() != 1) { ALOGE("Cannot decrypt multiple access units"); return -ENOSYS; } // we are dealing with just one cryptoInfo or descrambler. std::unique_ptr<CodecCryptoInfo> info = std::move(cryptoInfos->value[0]); if (info == nullptr) { ALOGE("Cannot decrypt, CryptoInfos are null."); return -ENOSYS; } return attachEncryptedBuffer( memory, secure, info->mKey, info->mIv, info->mMode, info->mPattern, offset, info->mSubSamples, info->mNumSubSamples, buffer, errorDetailMsg); } std::shared_ptr<C2BlockPool> pool = mBlockPools.lock()->inputPool; std::shared_ptr<C2LinearBlock> block; c2_status_t err = pool->fetchLinearBlock( size, kDefaultReadWriteUsage, &block); if (err != C2_OK) { ALOGI("[%s] attachEncryptedBuffers: fetchLinearBlock failed: size = %zu (%s) err = %d", mName, size, secure ? "secure" : "non-secure", err); return NO_MEMORY; } ensureDecryptDestination(size); C2WriteView wView = block->map().get(); if (wView.error() != C2_OK) { ALOGI("[%s] attachEncryptedBuffers: block map error: %d (non-secure)", mName, wView.error()); return UNKNOWN_ERROR; } ssize_t result = -1; ssize_t codecDataOffset = 0; size_t inBufferOffset = 0; size_t outBufferSize = 0; uint32_t cryptoInfoIdx = 0; int32_t heapSeqNum = getHeapSeqNum(memory); hardware::drm::V1_0::SharedBuffer src{(uint32_t)heapSeqNum, offset, size}; hardware::drm::V1_0::DestinationBuffer dst; dst.type = DrmBufferType::SHARED_MEMORY; IMemoryToSharedBuffer( mDecryptDestination, mHeapSeqNum, &dst.nonsecureMemory); for (int i = 0; i < bufferInfos->value.size(); i++) { if (bufferInfos->value[i].mSize > 0) { std::unique_ptr<CodecCryptoInfo> info = std::move(cryptoInfos->value[cryptoInfoIdx++]); result = mCrypto->decrypt( (uint8_t*)info->mKey, (uint8_t*)info->mIv, info->mMode, info->mPattern, src, inBufferOffset, info->mSubSamples, info->mNumSubSamples, dst, errorDetailMsg); inBufferOffset += bufferInfos->value[i].mSize; if (result < 0) { ALOGI("[%s] attachEncryptedBuffers: decrypt failed: result = %zd", mName, result); return result; } if (wView.error() == C2_OK) { if (wView.size() < result) { ALOGI("[%s] attachEncryptedBuffers: block size too small:" "size=%u result=%zd (non-secure)", mName, wView.size(), result); return UNKNOWN_ERROR; } memcpy(wView.data(), mDecryptDestination->unsecurePointer(), result); bufferInfos->value[i].mSize = result; wView.setOffset(wView.offset() + result); } outBufferSize += result; } } if (wView.error() == C2_OK) { wView.setOffset(0); } std::shared_ptr<C2Buffer> c2Buffer{C2Buffer::CreateLinearBuffer( block->share(codecDataOffset, outBufferSize - codecDataOffset, C2Fence{}))}; if (!buffer->copy(c2Buffer)) { ALOGI("[%s] attachEncryptedBuffers: buffer copy failed", mName); return -ENOSYS; } return OK; } status_t CCodecBufferChannel::attachEncryptedBuffer( const sp<hardware::HidlMemory> &memory, bool secure, Loading Loading @@ -777,6 +901,138 @@ status_t CCodecBufferChannel::queueSecureInputBuffer( return queueInputBufferInternal(buffer, block, bufferSize); } status_t CCodecBufferChannel::queueSecureInputBuffers( const sp<MediaCodecBuffer> &buffer, bool secure, AString *errorDetailMsg) { QueueGuard guard(mSync); if (!guard.isRunning()) { ALOGD("[%s] No more buffers should be queued at current state.", mName); return -ENOSYS; } if (!hasCryptoOrDescrambler()) { ALOGE("queueSecureInputBuffers requires a Crypto/descrambler Object"); return -ENOSYS; } sp<RefBase> obj; CHECK(buffer->meta()->findObject("cryptoInfos", &obj)); sp<CryptoInfosWrapper> cryptoInfos{(CryptoInfosWrapper *)obj.get()}; CHECK(buffer->meta()->findObject("accessUnitInfo", &obj)); sp<BufferInfosWrapper> bufferInfos{(BufferInfosWrapper *)obj.get()}; if (secure || mCrypto == nullptr) { if (cryptoInfos->value.size() != 1) { ALOGE("Cannot decrypt multiple access units on native handles"); return -ENOSYS; } std::unique_ptr<CodecCryptoInfo> info = std::move(cryptoInfos->value[0]); if (info == nullptr) { ALOGE("Cannot decrypt, CryptoInfos are null"); return -ENOSYS; } return queueSecureInputBuffer( buffer, secure, info->mKey, info->mIv, info->mMode, info->mPattern, info->mSubSamples, info->mNumSubSamples, errorDetailMsg); } sp<EncryptedLinearBlockBuffer> encryptedBuffer((EncryptedLinearBlockBuffer *)buffer.get()); std::shared_ptr<C2LinearBlock> block; size_t allocSize = buffer->size(); size_t bufferSize = 0; c2_status_t blockRes = C2_OK; bool copied = false; ScopedTrace trace(ATRACE_TAG, android::base::StringPrintf( "CCodecBufferChannel::decrypt(%s)", mName).c_str()); if (mSendEncryptedInfoBuffer) { static const C2MemoryUsage kDefaultReadWriteUsage{ C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}; constexpr int kAllocGranule0 = 1024 * 64; constexpr int kAllocGranule1 = 1024 * 1024; std::shared_ptr<C2BlockPool> pool = mBlockPools.lock()->inputPool; // round up encrypted sizes to limit fragmentation and encourage buffer reuse if (allocSize <= kAllocGranule1) { bufferSize = align(allocSize, kAllocGranule0); } else { bufferSize = align(allocSize, kAllocGranule1); } blockRes = pool->fetchLinearBlock( bufferSize, kDefaultReadWriteUsage, &block); if (blockRes == C2_OK) { C2WriteView view = block->map().get(); if (view.error() == C2_OK && view.size() == bufferSize) { copied = true; // TODO: only copy clear sections memcpy(view.data(), buffer->data(), allocSize); } } } if (!copied) { block.reset(); } // size of cryptoInfo and accessUnitInfo should be the same? ssize_t result = -1; ssize_t codecDataOffset = 0; size_t inBufferOffset = 0; size_t outBufferSize = 0; uint32_t cryptoInfoIdx = 0; { // scoped this block to enable destruction of mappedBlock std::unique_ptr<EncryptedLinearBlockBuffer::MappedBlock> mappedBlock = nullptr; hardware::drm::V1_0::DestinationBuffer destination; destination.type = DrmBufferType::SHARED_MEMORY; IMemoryToSharedBuffer( mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory); encryptedBuffer->getMappedBlock(&mappedBlock); hardware::drm::V1_0::SharedBuffer source; encryptedBuffer->fillSourceBuffer(&source); for (int i = 0 ; i < bufferInfos->value.size(); i++) { if (bufferInfos->value[i].mSize > 0) { std::unique_ptr<CodecCryptoInfo> info = std::move(cryptoInfos->value[cryptoInfoIdx++]); if (info->mNumSubSamples == 1 && info->mSubSamples[0].mNumBytesOfClearData == 0 && info->mSubSamples[0].mNumBytesOfEncryptedData == 0) { // no data so we only populate the bufferInfo result = 0; } else { result = mCrypto->decrypt( (uint8_t*)info->mKey, (uint8_t*)info->mIv, info->mMode, info->mPattern, source, inBufferOffset, info->mSubSamples, info->mNumSubSamples, destination, errorDetailMsg); inBufferOffset += bufferInfos->value[i].mSize; if (result < 0) { ALOGI("[%s] decrypt failed: result=%zd", mName, result); return result; } if (destination.type == DrmBufferType::SHARED_MEMORY && mappedBlock) { mappedBlock->copyDecryptedContent(mDecryptDestination, result); } bufferInfos->value[i].mSize = result; outBufferSize += result; } } } buffer->setRange(codecDataOffset, outBufferSize - codecDataOffset); } return queueInputBufferInternal(buffer, block, bufferSize); } void CCodecBufferChannel::feedInputBufferIfAvailable() { QueueGuard guard(mSync); if (!guard.isRunning()) { Loading
media/codec2/sfplugin/CCodecBufferChannel.h +10 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,10 @@ public: const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, AString *errorDetailMsg) override; status_t queueSecureInputBuffers( const sp<MediaCodecBuffer> &buffer, bool secure, AString *errorDetailMsg) override; status_t attachBuffer( const std::shared_ptr<C2Buffer> &c2Buffer, const sp<MediaCodecBuffer> &buffer) override; Loading @@ -88,6 +92,12 @@ public: size_t numSubSamples, const sp<MediaCodecBuffer> &buffer, AString* errorDetailMsg) override; status_t attachEncryptedBuffers( const sp<hardware::HidlMemory> &memory, size_t offset, const sp<MediaCodecBuffer> &buffer, bool secure, AString* errorDetailMsg) override; status_t renderOutputBuffer( const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override; void pollForRenderedBuffers() override; Loading
media/codec2/sfplugin/Codec2Buffer.cpp +31 −0 Original line number Diff line number Diff line Loading @@ -1036,6 +1036,37 @@ native_handle_t *EncryptedLinearBlockBuffer::handle() const { return const_cast<native_handle_t *>(mBlock->handle()); } void EncryptedLinearBlockBuffer::getMappedBlock( std::unique_ptr<MappedBlock> * const mappedBlock) const { if (mappedBlock) { mappedBlock->reset(new EncryptedLinearBlockBuffer::MappedBlock(mBlock)); } return; } EncryptedLinearBlockBuffer::MappedBlock::MappedBlock( const std::shared_ptr<C2LinearBlock> &block) : mView(block->map().get()) { } bool EncryptedLinearBlockBuffer::MappedBlock::copyDecryptedContent( const sp<IMemory> &decrypted, size_t length) { if (mView.error() != C2_OK) { return false; } if (mView.size() < length) { ALOGE("View size(%d) less than decrypted length(%zu)", mView.size(), length); return false; } memcpy(mView.data(), decrypted->unsecurePointer(), length); mView.setOffset(mView.offset() + length); return true; } EncryptedLinearBlockBuffer::MappedBlock::~MappedBlock() { mView.setOffset(0); } using ::aidl::android::hardware::graphics::common::Cta861_3; using ::aidl::android::hardware::graphics::common::Smpte2086; Loading
media/codec2/sfplugin/Codec2Buffer.h +11 −0 Original line number Diff line number Diff line Loading @@ -384,6 +384,17 @@ public: */ native_handle_t *handle() const; class MappedBlock { public: explicit MappedBlock(const std::shared_ptr<C2LinearBlock> &block); virtual ~MappedBlock(); bool copyDecryptedContent(const sp<IMemory> &decrypted, size_t length); private: C2WriteView mView; }; void getMappedBlock(std::unique_ptr<MappedBlock> * const mappedBlock) const; private: std::shared_ptr<C2LinearBlock> mBlock; Loading
media/libstagefright/CryptoAsync.cpp +49 −15 Original line number Diff line number Diff line Loading @@ -30,6 +30,36 @@ namespace android { CryptoAsync::CryptoAsyncInfo::CryptoAsyncInfo(const std::unique_ptr<CodecCryptoInfo> &info) { if (info == nullptr) { return; } size_t key_len = (info->mKey != nullptr)? 16 : 0; size_t iv_len = (info->mIv != nullptr)? 16 : 0; mNumSubSamples = info->mNumSubSamples; mMode = info->mMode; mPattern = info->mPattern; if (key_len > 0) { mKeyBuffer = ABuffer::CreateAsCopy((void*)info->mKey, key_len); mKey = (uint8_t*)(mKeyBuffer.get() != nullptr ? mKeyBuffer.get()->data() : nullptr); } if (iv_len > 0) { mIvBuffer = ABuffer::CreateAsCopy((void*)info->mIv, iv_len); mIv = (uint8_t*)(mIvBuffer.get() != nullptr ? mIvBuffer.get()->data() : nullptr); } mSubSamplesBuffer = new ABuffer(sizeof(CryptoPlugin::SubSample) * mNumSubSamples); if (mSubSamplesBuffer.get()) { CryptoPlugin::SubSample * samples = (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data()); for (int s = 0 ; s < mNumSubSamples ; s++) { samples[s].mNumBytesOfClearData = info->mSubSamples[s].mNumBytesOfClearData; samples[s].mNumBytesOfEncryptedData = info->mSubSamples[s].mNumBytesOfEncryptedData; } mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data(); } } CryptoAsync::~CryptoAsync() { } Loading Loading @@ -79,23 +109,27 @@ status_t CryptoAsync::decryptAndQueue(sp<AMessage> & msg) { sp<ABuffer> keyBuffer; sp<ABuffer> ivBuffer; sp<ABuffer> subSamplesBuffer; AString errorDetailMsg; msg->findObject("buffer", &obj); msg->findInt32("secure", &secure); sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); if (buffer->meta()->findObject("cryptoInfos", &obj)) { err = channel->queueSecureInputBuffers(buffer, secure, &errorDetailMsg); } else { msg->findInt32("encryptBlocks", (int32_t*)&pattern.mEncryptBlocks); msg->findInt32("skipBlocks", (int32_t*)&pattern.mSkipBlocks); msg->findBuffer("key", &keyBuffer); msg->findBuffer("iv", &ivBuffer); msg->findBuffer("subSamples", &subSamplesBuffer); msg->findInt32("secure", &secure); msg->findSize("numSubSamples", &numSubSamples); msg->findObject("buffer", &obj); msg->findInt32("mode", (int32_t*)&mode); AString errorDetailMsg; const uint8_t * key = keyBuffer.get() != nullptr ? keyBuffer.get()->data() : nullptr; const uint8_t * iv = ivBuffer.get() != nullptr ? ivBuffer.get()->data() : nullptr; const CryptoPlugin::SubSample * subSamples = (CryptoPlugin::SubSample *)(subSamplesBuffer.get()->data()); sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); err = channel->queueSecureInputBuffer(buffer, secure, key, iv, mode, pattern, subSamples, numSubSamples, &errorDetailMsg); } if (err != OK) { std::list<sp<AMessage>> errorList; msg->removeEntryByName("buffer"); Loading