Android 13 - Media框架(22)- ACodecBufferChannel

这一节我们将了解 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 offset
            codecDataOffset = 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;
}

你可能感兴趣的:(Android,Media,android,C++,Framework,Media,多媒体)