diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp index fa13f3291baec120d8c1501d6b4d0d645f3fba42..88b15aeb0819c28f419564d2ed2458d2b61e0e0f 100644 --- a/media/libstagefright/ACodecBufferChannel.cpp +++ b/media/libstagefright/ACodecBufferChannel.cpp @@ -22,11 +22,14 @@ #include +#include + #include #include #include #include #include +#include #include #include #include @@ -91,15 +94,27 @@ ACodecBufferChannel::ACodecBufferChannel( } status_t ACodecBufferChannel::queueInputBuffer(const sp &buffer) { - if (mDealer != nullptr) { - return -ENOSYS; - } std::shared_ptr> 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 msg = mInputBufferFilled->dup(); msg->setObject("buffer", it->mCodecBuffer); @@ -267,16 +282,30 @@ status_t ACodecBufferChannel::attachBuffer( } C2ConstLinearBlock block{c2Buffer->data().linearBlocks().front()}; C2ReadView view{block.map().get()}; - if (view.capacity() > buffer->capacity()) { - return -ENOSYS; - } - memcpy(buffer->base(), view.data(), view.capacity()); - buffer->setRange(0, view.capacity()); + size_t copyLength = std::min(size_t(view.capacity()), buffer->capacity()); + ALOGV_IF(view.capacity() > buffer->capacity(), + "view.capacity() = %zu, buffer->capacity() = %zu", + view.capacity(), buffer->capacity()); + memcpy(buffer->base(), view.data(), copyLength); + buffer->setRange(0, copyLength); break; } case C2BufferData::GRAPHIC: { - // TODO - return -ENOSYS; + sp imageData; + if (!buffer->format()->findBuffer("image-data", &imageData)) { + return -ENOSYS; + } + if (c2Buffer->data().graphicBlocks().size() != 1u) { + return -ENOSYS; + } + C2ConstGraphicBlock block{c2Buffer->data().graphicBlocks().front()}; + const C2GraphicView view{block.map().get()}; + status_t err = ImageCopy( + buffer->base(), (const MediaImage2 *)(imageData->base()), view); + if (err != OK) { + return err; + } + break; } case C2BufferData::LINEAR_CHUNKS: [[fallthrough]]; case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]]; diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp index 890a939a664065283adc3db3c3ac03a851a224f0..fac63500ed3de844b0e622ab0d40382de0c73ccc 100644 --- a/media/libstagefright/Android.bp +++ b/media/libstagefright/Android.bp @@ -285,6 +285,7 @@ cc_library { "libutils", "libmedia_helper", "libsfplugin_ccodec", + "libsfplugin_ccodec_utils", "libstagefright_codecbase", "libstagefright_foundation", "libstagefright_omx_utils", diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 7f5e762ea3fd913f1864aab7843707e6d51b7a71..983fa56d66b1ba306ce3179553918021db1f1aaf 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -2496,6 +2496,18 @@ void MediaCodec::onMessageReceived(const sp &msg) { } break; } + if (!mLeftover.empty()) { + ssize_t index = dequeuePortBuffer(kPortIndexInput); + CHECK_GE(index, 0); + + status_t err = handleLeftover(index); + if (err != OK) { + setStickyError(err); + postActivityNotificationIfPossible(); + cancelPendingDequeueOperations(); + } + break; + } if (mFlags & kFlagIsAsync) { if (!mHaveInputSurface) { @@ -3185,7 +3197,15 @@ void MediaCodec::onMessageReceived(const sp &msg) { break; } - status_t err = onQueueInputBuffer(msg); + status_t err = UNKNOWN_ERROR; + if (!mLeftover.empty()) { + mLeftover.push_back(msg); + size_t index; + msg->findSize("index", &index); + err = handleLeftover(index); + } else { + err = onQueueInputBuffer(msg); + } PostReplyWithError(replyID, err); break; @@ -3472,8 +3492,8 @@ status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) { sp memory; size_t offset = 0; - if ((mFlags & kFlagUseBlockModel) && mOwnerName.startsWith("codec2::")) { - if (mCrypto) { + if (mFlags & kFlagUseBlockModel) { + if (hasCryptoOrDescrambler()) { constexpr size_t kInitialDealerCapacity = 1048576; // 1MB thread_local sp sDealer = new MemoryDealer( kInitialDealerCapacity, "CSD(1MB)"); @@ -3598,6 +3618,9 @@ void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) { CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); Mutex::Autolock al(mBufferLock); + if (portIndex == kPortIndexInput) { + mLeftover.clear(); + } for (size_t i = 0; i < mPortBuffers[portIndex].size(); ++i) { BufferInfo *info = &mPortBuffers[portIndex][i]; @@ -3728,7 +3751,26 @@ status_t MediaCodec::onQueueInputBuffer(const sp &msg) { err = mBufferChannel->attachEncryptedBuffer( memory, (mFlags & kFlagIsSecure), key, iv, mode, pattern, offset, subSamples, numSubSamples, buffer); + } else { + err = UNKNOWN_ERROR; + } + + if (err == OK && !buffer->asC2Buffer() + && c2Buffer && c2Buffer->data().type() == C2BufferData::LINEAR) { + C2ConstLinearBlock block{c2Buffer->data().linearBlocks().front()}; + if (block.size() > buffer->size()) { + C2ConstLinearBlock leftover = block.subBlock( + block.offset() + buffer->size(), block.size() - buffer->size()); + sp>> obj{ + new WrapperObject>{ + C2Buffer::CreateLinearBuffer(leftover)}}; + msg->setObject("c2buffer", obj); + mLeftover.push_front(msg); + // Not sending EOS if we have leftovers + flags &= ~BUFFER_FLAG_EOS; + } } + offset = buffer->offset(); size = buffer->size(); if (err != OK) { @@ -3793,6 +3835,16 @@ status_t MediaCodec::onQueueInputBuffer(const sp &msg) { return err; } +status_t MediaCodec::handleLeftover(size_t index) { + if (mLeftover.empty()) { + return OK; + } + sp msg = mLeftover.front(); + mLeftover.pop_front(); + msg->setSize("index", index); + return onQueueInputBuffer(msg); +} + //static size_t MediaCodec::CreateFramesRenderedMessage( const std::list &done, sp &msg) { diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h index 7f308c0c7c1a7ca4a276ca85a5ab347be1b7ade8..02ab4c05f266cdf24b266638bc125c51df77f998 100644 --- a/media/libstagefright/include/media/stagefright/MediaCodec.h +++ b/media/libstagefright/include/media/stagefright/MediaCodec.h @@ -515,6 +515,9 @@ private: class ReleaseSurface; std::unique_ptr mReleaseSurface; + std::list> mLeftover; + status_t handleLeftover(size_t index); + sp mBatteryChecker; void statsBufferSent(int64_t presentationUs);