From 936a89c0178961a0257f6587dee4c263b05404c6 Mon Sep 17 00:00:00 2001 From: Wonsik Kim Date: Fri, 8 May 2020 16:07:50 -0700 Subject: [PATCH] CCodec: revise resource releases Bug: 155673235 Bug: 155820476 Bug: 155821127 Test: atest CtsMediaTestCases:MediaCodecCapabilitiesTest Test: atest CtsMediaTestCases:android.media.cts.EncoderTest Test: atest GtsYouTubeTestCases:DecodePerformanceTest Test: atest CtsMediaTestCases -- --module-arg CtsMediaTestCases:size:small Change-Id: Ib63c2ad59991c6814e68f222373caec5f638231f --- media/codec2/sfplugin/CCodec.cpp | 14 ++-- media/codec2/sfplugin/CCodecBufferChannel.cpp | 69 ++++++++++++++----- media/codec2/sfplugin/CCodecBufferChannel.h | 10 +++ media/codec2/sfplugin/CCodecBuffers.h | 2 +- media/libstagefright/MediaCodec.cpp | 1 + 5 files changed, 74 insertions(+), 22 deletions(-) diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp index 1e4560cb1b..a3fff35876 100644 --- a/media/codec2/sfplugin/CCodec.cpp +++ b/media/codec2/sfplugin/CCodec.cpp @@ -1379,7 +1379,7 @@ void CCodec::initiateStop() { state->set(STOPPING); } - mChannel->stop(); + mChannel->reset(); (new AMessage(kWhatStop, this))->post(); } @@ -1406,9 +1406,6 @@ void CCodec::stop() { // TODO: convert err into status_t mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL); } - // Assure buffers are not owned when stop() was called without flush(). - std::list> flushedWork; - mChannel->flush(flushedWork); { Mutexed>::Locked configLocked(mConfig); @@ -1468,7 +1465,7 @@ void CCodec::initiateRelease(bool sendCallback /* = true */) { } } - mChannel->stop(); + mChannel->reset(); // thiz holds strong ref to this while the thread is running. sp thiz(this); std::thread([thiz, sendCallback] { thiz->release(sendCallback); }).detach(); @@ -1495,6 +1492,7 @@ void CCodec::release(bool sendCallback) { state->set(RELEASED); state->comp.reset(); } + (new AMessage(kWhatRelease, this))->post(); if (sendCallback) { mCallback->onReleaseCompleted(); } @@ -1759,6 +1757,12 @@ void CCodec::onMessageReceived(const sp &msg) { flush(); break; } + case kWhatRelease: { + mChannel->release(); + mClient.reset(); + mClientListener.reset(); + break; + } case kWhatCreateInputSurface: { // Surface operations may be briefly blocking. setDeadline(now, 1500ms, "createInputSurface"); diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp index 553c013661..7d80ef3e8c 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.cpp +++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp @@ -713,7 +713,7 @@ void CCodecBufferChannel::feedInputBufferIfAvailableInternal() { return; } else { Mutexed::Locked output(mOutput); - if (output->buffers->numClientBuffers() >= output->numSlots) { + if (!output->buffers || output->buffers->numClientBuffers() >= output->numSlots) { return; } } @@ -1401,6 +1401,30 @@ void CCodecBufferChannel::stop() { } } +void CCodecBufferChannel::reset() { + stop(); + { + Mutexed::Locked input(mInput); + input->buffers.reset(new DummyInputBuffers("")); + } + { + Mutexed::Locked output(mOutput); + output->buffers.reset(); + } +} + +void CCodecBufferChannel::release() { + mComponent.reset(); + mInputAllocator.reset(); + mOutputSurface.lock()->surface.clear(); + { + Mutexed::Locked blockPools{mBlockPools}; + blockPools->inputPool.reset(); + blockPools->outputPoolIntf.reset(); + } +} + + void CCodecBufferChannel::flush(const std::list> &flushedWork) { ALOGV("[%s] flush", mName); { @@ -1431,7 +1455,9 @@ void CCodecBufferChannel::flush(const std::list> &flushe } { Mutexed::Locked output(mOutput); - output->buffers->flush(flushedWork); + if (output->buffers) { + output->buffers->flush(flushedWork); + } } mReorderStash.lock()->flush(); mPipelineWatcher.lock()->flush(); @@ -1469,20 +1495,25 @@ bool CCodecBufferChannel::handleWork( std::unique_ptr work, const sp &outputFormat, const C2StreamInitDataInfo::output *initData) { - if (outputFormat != nullptr) { + { Mutexed::Locked output(mOutput); - ALOGD("[%s] onWorkDone: output format changed to %s", - mName, outputFormat->debugString().c_str()); - output->buffers->setFormat(outputFormat); - - AString mediaType; - if (outputFormat->findString(KEY_MIME, &mediaType) - && mediaType == MIMETYPE_AUDIO_RAW) { - int32_t channelCount; - int32_t sampleRate; - if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount) - && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) { - output->buffers->updateSkipCutBuffer(sampleRate, channelCount); + if (!output->buffers) { + return false; + } + if (outputFormat != nullptr) { + ALOGD("[%s] onWorkDone: output format changed to %s", + mName, outputFormat->debugString().c_str()); + output->buffers->setFormat(outputFormat); + + AString mediaType; + if (outputFormat->findString(KEY_MIME, &mediaType) + && mediaType == MIMETYPE_AUDIO_RAW) { + int32_t channelCount; + int32_t sampleRate; + if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount) + && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) { + output->buffers->updateSkipCutBuffer(sampleRate, channelCount); + } } } } @@ -1606,6 +1637,9 @@ bool CCodecBufferChannel::handleWork( size_t numInputSlots = mInput.lock()->numSlots; { Mutexed::Locked output(mOutput); + if (!output->buffers) { + return false; + } output->outputDelay = outputDelay.value; numOutputSlots = outputDelay.value + kSmoothnessFactor; if (output->numSlots < numOutputSlots) { @@ -1695,7 +1729,7 @@ bool CCodecBufferChannel::handleWork( if (initData != nullptr) { Mutexed::Locked output(mOutput); - if (output->buffers->registerCsd(initData, &index, &outBuffer) == OK) { + if (output->buffers && output->buffers->registerCsd(initData, &index, &outBuffer) == OK) { outBuffer->meta()->setInt64("timeUs", timestamp.peek()); outBuffer->meta()->setInt32("flags", MediaCodec::BUFFER_FLAG_CODECCONFIG); ALOGV("[%s] onWorkDone: csd index = %zu [%p]", mName, index, outBuffer.get()); @@ -1758,6 +1792,9 @@ void CCodecBufferChannel::sendOutputBuffers() { } Mutexed::Locked output(mOutput); + if (!output->buffers) { + return; + } status_t err = output->buffers->registerBuffer(entry.buffer, &index, &outBuffer); if (err != OK) { bool outputBuffersChanged = false; diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h index 0263211006..f6e702407b 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.h +++ b/media/codec2/sfplugin/CCodecBufferChannel.h @@ -138,6 +138,16 @@ public: */ void stop(); + /** + * Stop queueing buffers to the component and release all buffers. + */ + void reset(); + + /** + * Release all resources. + */ + void release(); + void flush(const std::list> &flushedWork); /** diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h index 6244acdfc0..eec79f17f1 100644 --- a/media/codec2/sfplugin/CCodecBuffers.h +++ b/media/codec2/sfplugin/CCodecBuffers.h @@ -416,7 +416,7 @@ public: size_t *index, sp *buffer, std::function &)> match = - [](const sp &) { return true; }); + [](const sp &buffer) { return (buffer != nullptr); }); /** * Return the buffer from the client, and get the C2Buffer object back from diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 11f2f383cd..e748b01445 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -2641,6 +2641,7 @@ void MediaCodec::onMessageReceived(const sp &msg) { } mResourceManagerProxy->removeClient(); + mReleaseSurface.reset(); if (mReplyID != nullptr) { (new AMessage)->postReply(mReplyID);