RESTRICT AUTOMERGE CCodec: don't queue EOS work without allocating pipeline capacity
Bug: 122375559
Test: atest CtsMediaTestCases:MediaSyncTest#testPlayAudio
Change-Id: I096bd723bb607fc46d9289d4887f63492f666e37
diff --git a/media/sfplugin/CCodecBufferChannel.cpp b/media/sfplugin/CCodecBufferChannel.cpp
index 1e4874f..2cdea6e 100644
--- a/media/sfplugin/CCodecBufferChannel.cpp
+++ b/media/sfplugin/CCodecBufferChannel.cpp
@@ -1494,7 +1494,8 @@
mFirstValidFrameIndex(0u),
mMetaMode(MODE_NONE),
mAvailablePipelineCapacity(),
- mInputMetEos(false) {
+ mInputMetEos(false),
+ mPendingEosTimestamp(INT64_MIN) {
Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
buffers->reset(new DummyInputBuffers(""));
}
@@ -1579,23 +1580,13 @@
std::list<std::unique_ptr<C2Work>> items;
items.push_back(std::move(work));
c2_status_t err = mComponent->queue(&items);
-
- if (err == C2_OK && eos && buffer->size() > 0u) {
- mCCodecCallback->onWorkQueued(false);
- work.reset(new C2Work);
- work->input.ordinal.timestamp = timeUs;
- work->input.ordinal.frameIndex = mFrameIndex++;
- // WORKAROUND: keep client timestamp in customOrdinal
- work->input.ordinal.customOrdinal = timeUs;
- work->input.buffers.clear();
- work->input.flags = C2FrameData::FLAG_END_OF_STREAM;
-
- items.clear();
- items.push_back(std::move(work));
- err = mComponent->queue(&items);
- }
if (err == C2_OK) {
- mCCodecCallback->onWorkQueued(eos);
+ if (eos && buffer->size() > 0u) {
+ mCCodecCallback->onWorkQueued(false);
+ mPendingEosTimestamp = timeUs;
+ } else {
+ mCCodecCallback->onWorkQueued(eos);
+ }
Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
bool released = (*buffers)->releaseBuffer(buffer, nullptr, true);
@@ -1728,8 +1719,30 @@
}
void CCodecBufferChannel::feedInputBufferIfAvailableInternal() {
- while (!mInputMetEos &&
+ while ((!mInputMetEos || mPendingEosTimestamp != INT64_MIN) &&
mAvailablePipelineCapacity.allocate("feedInputBufferIfAvailable")) {
+ int64_t pendingEosTimestamp = mPendingEosTimestamp.exchange(INT64_MIN);
+ if (pendingEosTimestamp != INT64_MIN) {
+ mAvailablePipelineCapacity.freeInputSlots(1, "feedInputBufferIfAvailable: queue eos");
+
+ std::unique_ptr<C2Work> work(new C2Work);
+ work->input.ordinal.timestamp = pendingEosTimestamp;
+ work->input.ordinal.frameIndex = mFrameIndex++;
+ // WORKAROUND: keep client timestamp in customOrdinal
+ work->input.ordinal.customOrdinal = pendingEosTimestamp;
+ work->input.buffers.clear();
+ work->input.flags = C2FrameData::FLAG_END_OF_STREAM;
+
+ std::list<std::unique_ptr<C2Work>> items;
+ items.push_back(std::move(work));
+ if (mComponent->queue(&items) == C2_OK) {
+ mCCodecCallback->onWorkQueued(true);
+ } else {
+ ALOGD("[%s] failed to queue EOS to the component", mName);
+ mCCodecCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
+ }
+ continue;
+ }
sp<MediaCodecBuffer> inBuffer;
size_t index;
{
@@ -2220,6 +2233,7 @@
}
mInputMetEos = false;
+ mPendingEosTimestamp = INT64_MIN;
mSync.start();
return OK;
}
diff --git a/media/sfplugin/CCodecBufferChannel.h b/media/sfplugin/CCodecBufferChannel.h
index 8631235..86739ab 100644
--- a/media/sfplugin/CCodecBufferChannel.h
+++ b/media/sfplugin/CCodecBufferChannel.h
@@ -351,6 +351,7 @@
PipelineCapacity mAvailablePipelineCapacity;
std::atomic_bool mInputMetEos;
+ std::atomic_int64_t mPendingEosTimestamp;
inline bool hasCryptoOrDescrambler() {
return mCrypto != NULL || mDescrambler != NULL;