Skip to content

Commit

Permalink
Merge "CCodec: fix input surface throttling" into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Wonsik Kim authored and Gerrit Code Review committed May 25, 2024
2 parents 661b2bf + 1951d93 commit 577048b
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 16 deletions.
10 changes: 10 additions & 0 deletions media/aconfig/codec_fwk.aconfig
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ flag {
bug: "325520135"
}

flag {
name: "input_surface_throttle"
namespace: "codec_fwk"
description: "Bugfix flag for input surface throttle"
bug: "342269852"
metadata {
purpose: PURPOSE_BUGFIX
}
}

flag {
name: "large_audio_frame_finish"
namespace: "codec_fwk"
Expand Down
4 changes: 4 additions & 0 deletions media/codec2/sfplugin/C2AidlNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ void C2AidlNode::onInputBufferDone(c2_cntr64_t index) {
return mImpl->onInputBufferDone(index);
}

void C2AidlNode::onInputBufferEmptied() {
return mImpl->onInputBufferEmptied();
}

android_dataspace C2AidlNode::getDataspace() {
return mImpl->getDataspace();
}
Expand Down
8 changes: 7 additions & 1 deletion media/codec2/sfplugin/C2AidlNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,18 @@ class C2AidlNode : public ::aidl::android::media::BnAidlNode {
void setFrameSize(uint32_t width, uint32_t height);

/**
* Clean up work item reference.
* Notify that the input buffer reference is no longer needed by the component.
* Clean up if necessary.
*
* \param index input work index
*/
void onInputBufferDone(c2_cntr64_t index);

/**
* Notify input buffer is emptied.
*/
void onInputBufferEmptied();

/**
* Returns dataspace information from GraphicBufferSource.
*/
Expand Down
73 changes: 61 additions & 12 deletions media/codec2/sfplugin/C2NodeImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <C2Debug.h>
#include <C2PlatformSupport.h>

#include <android_media_codec.h>
#include <android/fdsan.h>
#include <media/stagefright/foundation/ColorUtils.h>
#include <ui/Fence.h>
Expand Down Expand Up @@ -373,7 +374,10 @@ status_t C2NodeImpl::submitBuffer(
}
work->worklets.clear();
work->worklets.emplace_back(new C2Worklet);
mBufferIdsInUse.lock()->emplace(work->input.ordinal.frameIndex.peeku(), buffer);
{
Mutexed<BuffersTracker>::Locked buffers(mBuffersTracker);
buffers->mIdsInUse.emplace(work->input.ordinal.frameIndex.peeku(), buffer);
}
mQueueThread->queue(comp, fenceFd, std::move(work), std::move(fd0), std::move(fd1));

return OK;
Expand Down Expand Up @@ -405,29 +409,74 @@ void C2NodeImpl::setFrameSize(uint32_t width, uint32_t height) {
}

void C2NodeImpl::onInputBufferDone(c2_cntr64_t index) {
if (mAidlHal) {
if (!mAidlBufferSource) {
ALOGD("Buffer source not set (index=%llu)", index.peekull());
if (android::media::codec::provider_->input_surface_throttle()) {
Mutexed<BuffersTracker>::Locked buffers(mBuffersTracker);
auto it = buffers->mIdsInUse.find(index.peeku());
if (it == buffers->mIdsInUse.end()) {
ALOGV("Untracked input index %llu (maybe already removed)", index.peekull());
return;
}
int32_t bufferId = it->second;
(void)buffers->mIdsInUse.erase(it);
buffers->mAvailableIds.push_back(bufferId);
} else {
if (!mBufferSource) {
ALOGD("Buffer source not set (index=%llu)", index.peekull());
if (!hasBufferSource()) {
return;
}
int32_t bufferId = 0;
{
Mutexed<BuffersTracker>::Locked buffers(mBuffersTracker);
auto it = buffers->mIdsInUse.find(index.peeku());
if (it == buffers->mIdsInUse.end()) {
ALOGV("Untracked input index %llu (maybe already removed)", index.peekull());
return;
}
bufferId = it->second;
(void)buffers->mIdsInUse.erase(it);
}
notifyInputBufferEmptied(bufferId);
}
}

void C2NodeImpl::onInputBufferEmptied() {
if (!android::media::codec::provider_->input_surface_throttle()) {
ALOGE("onInputBufferEmptied should not be called "
"when input_surface_throttle is false");
return;
}
if (!hasBufferSource()) {
return;
}
int32_t bufferId = 0;
{
decltype(mBufferIdsInUse)::Locked bufferIds(mBufferIdsInUse);
auto it = bufferIds->find(index.peeku());
if (it == bufferIds->end()) {
ALOGV("Untracked input index %llu (maybe already removed)", index.peekull());
Mutexed<BuffersTracker>::Locked buffers(mBuffersTracker);
if (buffers->mAvailableIds.empty()) {
ALOGV("The codec is ready to take more input buffers "
"but no input buffers are ready yet.");
return;
}
bufferId = it->second;
(void)bufferIds->erase(it);
bufferId = buffers->mAvailableIds.front();
buffers->mAvailableIds.pop_front();
}
notifyInputBufferEmptied(bufferId);
}

bool C2NodeImpl::hasBufferSource() {
if (mAidlHal) {
if (!mAidlBufferSource) {
ALOGD("Buffer source not set");
return false;
}
} else {
if (!mBufferSource) {
ALOGD("Buffer source not set");
return false;
}
}
return true;
}

void C2NodeImpl::notifyInputBufferEmptied(int32_t bufferId) {
if (mAidlHal) {
::ndk::ScopedFileDescriptor nullFence;
(void)mAidlBufferSource->onInputBufferEmptied(bufferId, nullFence);
Expand Down
22 changes: 20 additions & 2 deletions media/codec2/sfplugin/C2NodeImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,18 @@ struct C2NodeImpl {
void setFrameSize(uint32_t width, uint32_t height);

/**
* Clean up work item reference.
* Notify that the input buffer reference is no longer needed by the component.
* Clean up if necessary.
*
* \param index input work index
*/
void onInputBufferDone(c2_cntr64_t index);

/**
* Notify input buffer is emptied.
*/
void onInputBufferEmptied();

/**
* Returns dataspace information from GraphicBufferSource.
*/
Expand Down Expand Up @@ -118,12 +124,24 @@ struct C2NodeImpl {
c2_cntr64_t mPrevInputTimestamp; // input timestamp for previous frame
c2_cntr64_t mPrevCodecTimestamp; // adjusted (codec) timestamp for previous frame

Mutexed<std::map<uint64_t, uint32_t>> mBufferIdsInUse;
// Tracks the status of buffers
struct BuffersTracker {
BuffersTracker() = default;

// Keeps track of buffers that are used by the component. Maps timestamp -> ID
std::map<uint64_t, uint32_t> mIdsInUse;
// Keeps track of the buffer IDs that are available after being released from the component.
std::list<uint32_t> mAvailableIds;
};
Mutexed<BuffersTracker> mBuffersTracker;

class QueueThread;
sp<QueueThread> mQueueThread;

bool mAidlHal;

bool hasBufferSource();
void notifyInputBufferEmptied(int32_t bufferId);
};

} // namespace android
4 changes: 4 additions & 0 deletions media/codec2/sfplugin/C2OMXNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ void C2OMXNode::onInputBufferDone(c2_cntr64_t index) {
return mImpl->onInputBufferDone(index);
}

void C2OMXNode::onInputBufferEmptied() {
return mImpl->onInputBufferEmptied();
}

android_dataspace C2OMXNode::getDataspace() {
return mImpl->getDataspace();
}
Expand Down
8 changes: 7 additions & 1 deletion media/codec2/sfplugin/C2OMXNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,18 @@ struct C2OMXNode : public BnOMXNode {
void setFrameSize(uint32_t width, uint32_t height);

/**
* Clean up work item reference.
* Notify that the input buffer reference is no longer needed by the component.
* Clean up if necessary.
*
* \param index input work index
*/
void onInputBufferDone(c2_cntr64_t index);

/**
* Notify input buffer is emptied.
*/
void onInputBufferEmptied();

/**
* Returns dataspace information from GraphicBufferSource.
*/
Expand Down
8 changes: 8 additions & 0 deletions media/codec2/sfplugin/CCodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,10 @@ class HGraphicBufferSourceWrapper : public InputSurfaceWrapper {
mNode->onInputBufferDone(index);
}

void onInputBufferEmptied() override {
mNode->onInputBufferEmptied();
}

android_dataspace getDataspace() override {
return mNode->getDataspace();
}
Expand Down Expand Up @@ -663,6 +667,10 @@ class AGraphicBufferSourceWrapper : public InputSurfaceWrapper {
mNode->onInputBufferDone(index);
}

void onInputBufferEmptied() override {
mNode->onInputBufferEmptied();
}

android_dataspace getDataspace() override {
return mNode->getDataspace();
}
Expand Down
4 changes: 4 additions & 0 deletions media/codec2/sfplugin/CCodecBufferChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,10 @@ void CCodecBufferChannel::feedInputBufferIfAvailableInternal() {
return;
}
}
if (android::media::codec::provider_->input_surface_throttle()
&& mInputSurface != nullptr) {
mInputSurface->onInputBufferEmptied();
}
size_t numActiveSlots = 0;
while (!mPipelineWatcher.lock()->pipelineFull()) {
sp<MediaCodecBuffer> inBuffer;
Expand Down
7 changes: 7 additions & 0 deletions media/codec2/sfplugin/InputSurfaceWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,19 @@ class InputSurfaceWrapper {
}

/**
* Notify that the input buffer reference is no longer needed.
* Clean up C2Work related references if necessary. No-op by default.
*
* \param index index of input work.
*/
virtual void onInputBufferDone(c2_cntr64_t /* index */) {}

/**
* Signal one input buffer as emptied.
* No-op by default.
*/
virtual void onInputBufferEmptied() {}

/**
* Returns dataspace information from GraphicBufferSource.
*/
Expand Down

0 comments on commit 577048b

Please sign in to comment.