Merge "stagefright: fix block model operations for OMX codecs" into rvc-dev am: 3e8d51cb46
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/11732367
Change-Id: I1d3279bd7382b36ba8e9bdaead5824945de4e41b
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index fa13f32..88b15ae 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -22,11 +22,14 @@
#include <C2Buffer.h>
+#include <Codec2BufferUtils.h>
+
#include <android/hardware/cas/native/1.0/IDescrambler.h>
#include <android/hardware/drm/1.0/types.h>
#include <binder/MemoryDealer.h>
#include <hidlmemory/FrameworkUtils.h>
#include <media/openmax/OMX_Core.h>
+#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaCodec.h>
@@ -91,15 +94,27 @@
}
status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
- if (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;
}
+ 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);
@@ -267,16 +282,30 @@
}
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<ABuffer> 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 890a939..fac6350 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -285,6 +285,7 @@
"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 7f5e762..983fa56 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2496,6 +2496,18 @@
}
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 @@
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 @@
sp<hardware::HidlMemory> 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<MemoryDealer> sDealer = new MemoryDealer(
kInitialDealerCapacity, "CSD(1MB)");
@@ -3598,6 +3618,9 @@
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 @@
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<WrapperObject<std::shared_ptr<C2Buffer>>> obj{
+ new WrapperObject<std::shared_ptr<C2Buffer>>{
+ 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 @@
return err;
}
+status_t MediaCodec::handleLeftover(size_t index) {
+ if (mLeftover.empty()) {
+ return OK;
+ }
+ sp<AMessage> msg = mLeftover.front();
+ mLeftover.pop_front();
+ msg->setSize("index", index);
+ return onQueueInputBuffer(msg);
+}
+
//static
size_t MediaCodec::CreateFramesRenderedMessage(
const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 7f308c0..02ab4c0 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -515,6 +515,9 @@
class ReleaseSurface;
std::unique_ptr<ReleaseSurface> mReleaseSurface;
+ std::list<sp<AMessage>> mLeftover;
+ status_t handleLeftover(size_t index);
+
sp<BatteryChecker> mBatteryChecker;
void statsBufferSent(int64_t presentationUs);