这一节我们将了解 ACodecBufferChannel 中的 buffer 传输机制
status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {std::shared_ptr<const std::vector<const BufferInfo>> array(std::atomic_load(&mInputBuffers));BufferInfoIterator it = findClientBuffer(array, buffer);if (it == array->end()) {return -ENOENT;}if (it->mClientBuffer != it->mCodecBuffer) {// Copy metadata from client to codec buffer.it->mCodecBuffer->meta()->clear();int64_t timeUs;CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs));it->mCodecBuffer->meta()->setInt64("timeUs", timeUs);int32_t eos;if (it->mClientBuffer->meta()->findInt32("eos", &eos)) {it->mCodecBuffer->meta()->setInt32("eos", eos);}int32_t csd;if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {it->mCodecBuffer->meta()->setInt32("csd", csd);}}ALOGV("queueInputBuffer #%d", it->mBufferId);sp<AMessage> msg = mInputBufferFilled->dup();msg->setObject("buffer", it->mCodecBuffer);msg->setInt32("buffer-id", it->mBufferId);msg->post();return OK;
}status_t ACodecBufferChannel::queueSecureInputBuffer(const sp<MediaCodecBuffer> &buffer, bool secure, const uint8_t *key,const uint8_t *iv, CryptoPlugin::Mode mode, CryptoPlugin::Pattern pattern,const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,AString *errorDetailMsg) {if (!hasCryptoOrDescrambler() || mDealer == nullptr) {return -ENOSYS;}std::shared_ptr<const std::vector<const BufferInfo>> array(std::atomic_load(&mInputBuffers));BufferInfoIterator it = findClientBuffer(array, buffer);if (it == array->end()) {return -ENOENT;}native_handle_t *secureHandle = NULL;if (secure) {sp<SecureBuffer> secureData =static_cast<SecureBuffer *>(it->mCodecBuffer.get());if (secureData->getDestinationType() != ICrypto::kDestinationTypeNativeHandle) {return BAD_VALUE;}secureHandle = static_cast<native_handle_t *>(secureData->getDestinationPointer());}ssize_t result = -1;ssize_t codecDataOffset = 0;if (numSubSamples == 1&& subSamples[0].mNumBytesOfClearData == 0&& subSamples[0].mNumBytesOfEncryptedData == 0) {// We don't need to go through crypto or descrambler if the input is empty.result = 0;} else if (mCrypto != NULL) {hardware::drm::V1_0::DestinationBuffer destination;if (secure) {destination.type = DrmBufferType::NATIVE_HANDLE;destination.secureMemory = hidl_handle(secureHandle);} else {destination.type = DrmBufferType::SHARED_MEMORY;IMemoryToSharedBuffer(mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory);}hardware::drm::V1_0::SharedBuffer source;IMemoryToSharedBuffer(it->mSharedEncryptedBuffer, mHeapSeqNum, &source);result = mCrypto->decrypt(key, iv, mode, pattern,source, it->mClientBuffer->offset(),subSamples, numSubSamples, destination, errorDetailMsg);if (result < 0) {return result;}if (destination.type == DrmBufferType::SHARED_MEMORY) {memcpy(it->mCodecBuffer->base(), mDecryptDestination->unsecurePointer(), result);}} else {// Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample// directly, the structure definitions should match as checked in DescramblerImpl.cpp.hidl_vec<SubSample> hidlSubSamples;hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);ssize_t offset;size_t size;it->mSharedEncryptedBuffer->getMemory(&offset, &size);hardware::cas::native::V1_0::SharedBuffer srcBuffer = {.heapBase = *mHidlMemory,.offset = (uint64_t) offset,.size = size};DestinationBuffer dstBuffer;if (secure) {dstBuffer.type = BufferType::NATIVE_HANDLE;dstBuffer.secureMemory = hidl_handle(secureHandle);} else {dstBuffer.type = BufferType::SHARED_MEMORY;dstBuffer.nonsecureMemory = srcBuffer;}Status status = Status::OK;hidl_string detailedError;ScramblingControl sctrl = ScramblingControl::UNSCRAMBLED;if (key != NULL) {sctrl = (ScramblingControl)key[0];// Adjust for the PES offsetcodecDataOffset = key[2] | (key[3] << 8);}auto returnVoid = mDescrambler->descramble(sctrl,hidlSubSamples,srcBuffer,0,dstBuffer,0,[&status, &result, &detailedError] (Status _status, uint32_t _bytesWritten,const hidl_string& _detailedError) {status = _status;result = (ssize_t)_bytesWritten;detailedError = _detailedError;});if (!returnVoid.isOk() || status != Status::OK || result < 0) {ALOGE("descramble failed, trans=%s, status=%d, result=%zd",returnVoid.description().c_str(), status, result);return UNKNOWN_ERROR;}if (result < codecDataOffset) {ALOGD("invalid codec data offset: %zd, result %zd", codecDataOffset, result);return BAD_VALUE;}ALOGV("descramble succeeded, %zd bytes", result);if (dstBuffer.type == BufferType::SHARED_MEMORY) {memcpy(it->mCodecBuffer->base(),(uint8_t*)it->mSharedEncryptedBuffer->unsecurePointer(),result);}}it->mCodecBuffer->setRange(codecDataOffset, result - codecDataOffset);// Copy metadata from client to codec buffer.it->mCodecBuffer->meta()->clear();int64_t timeUs;CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs));it->mCodecBuffer->meta()->setInt64("timeUs", timeUs);int32_t eos;if (it->mClientBuffer->meta()->findInt32("eos", &eos)) {it->mCodecBuffer->meta()->setInt32("eos", eos);}int32_t csd;if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {it->mCodecBuffer->meta()->setInt32("csd", csd);}ALOGV("queueSecureInputBuffer #%d", it->mBufferId);sp<AMessage> msg = mInputBufferFilled->dup();msg->setObject("buffer", it->mCodecBuffer);msg->setInt32("buffer-id", it->mBufferId);msg->post();return OK;
}