Merge "cameraserver: Remove framework only keys before sending capture requests to hal." into sc-qpr1-dev
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 342d771..57cdcd0 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -287,6 +287,7 @@
     mOutputDelayRingBufferWritePos = 0;
     mOutputDelayRingBufferReadPos = 0;
     mOutputDelayRingBufferFilled = 0;
+    mOutputDelayRingBuffer.reset();
     mBuffersInfo.clear();
 
     status_t status = UNKNOWN_ERROR;
@@ -308,10 +309,7 @@
         aacDecoder_Close(mAACDecoder);
         mAACDecoder = nullptr;
     }
-    if (mOutputDelayRingBuffer) {
-        delete[] mOutputDelayRingBuffer;
-        mOutputDelayRingBuffer = nullptr;
-    }
+    mOutputDelayRingBuffer.reset();
 }
 
 status_t C2SoftAacDec::initDecoder() {
@@ -327,7 +325,7 @@
 
     mOutputDelayCompensated = 0;
     mOutputDelayRingBufferSize = 2048 * MAX_CHANNEL_COUNT * kNumDelayBlocksMax;
-    mOutputDelayRingBuffer = new short[mOutputDelayRingBufferSize];
+    mOutputDelayRingBuffer.reset(new short[mOutputDelayRingBufferSize]);
     mOutputDelayRingBufferWritePos = 0;
     mOutputDelayRingBufferReadPos = 0;
     mOutputDelayRingBufferFilled = 0;
diff --git a/media/codec2/components/aac/C2SoftAacDec.h b/media/codec2/components/aac/C2SoftAacDec.h
index 986187c..a03fc70 100644
--- a/media/codec2/components/aac/C2SoftAacDec.h
+++ b/media/codec2/components/aac/C2SoftAacDec.h
@@ -93,7 +93,7 @@
     bool mEndOfOutput;
     int32_t mOutputDelayCompensated;
     int32_t mOutputDelayRingBufferSize;
-    short *mOutputDelayRingBuffer;
+    std::unique_ptr<short[]> mOutputDelayRingBuffer;
     int32_t mOutputDelayRingBufferWritePos;
     int32_t mOutputDelayRingBufferReadPos;
     int32_t mOutputDelayRingBufferFilled;
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index 74b099c..9e3a823 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -100,8 +100,10 @@
         ASSERT_NE(mLinearPool, nullptr);
 
         std::vector<std::unique_ptr<C2Param>> queried;
-        mComponent->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE}, C2_DONT_BLOCK, &queried);
-        ASSERT_GT(queried.size(), 0);
+        c2_status_t c2err = mComponent->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
+                                              C2_DONT_BLOCK, &queried);
+        ASSERT_EQ(c2err, C2_OK) << "Query media type failed";
+        ASSERT_EQ(queried.size(), 1) << "Size of the vector returned is invalid";
 
         mMime = ((C2PortMediaTypeSetting::input*)queried[0].get())->m.value;
 
@@ -277,24 +279,20 @@
     };
     std::vector<std::unique_ptr<C2Param>> inParams;
     c2_status_t status = component->query({}, indices, C2_DONT_BLOCK, &inParams);
-    if (status != C2_OK && inParams.size() == 0) {
-        ALOGE("Query media type failed => %d", status);
-        ASSERT_TRUE(false);
-    } else {
-        size_t offset = sizeof(C2Param);
-        for (size_t i = 0; i < inParams.size(); ++i) {
-            C2Param* param = inParams[i].get();
-            bitStreamInfo[i] = *(int32_t*)((uint8_t*)param + offset);
-        }
-        if (mime.find("3gpp") != std::string::npos) {
-            ASSERT_EQ(bitStreamInfo[0], 8000);
-            ASSERT_EQ(bitStreamInfo[1], 1);
-        } else if (mime.find("amr-wb") != std::string::npos) {
-            ASSERT_EQ(bitStreamInfo[0], 16000);
-            ASSERT_EQ(bitStreamInfo[1], 1);
-        } else if (mime.find("gsm") != std::string::npos) {
-            ASSERT_EQ(bitStreamInfo[0], 8000);
-        }
+    ASSERT_EQ(status, C2_OK) << "Query sample rate and channel count info failed";
+    ASSERT_EQ(inParams.size(), indices.size()) << "Size of the vector returned is invalid";
+
+    bitStreamInfo[0] = C2StreamSampleRateInfo::output::From(inParams[0].get())->value;
+    bitStreamInfo[1] = C2StreamChannelCountInfo::output::From(inParams[1].get())->value;
+    if (mime.find("3gpp") != std::string::npos) {
+        ASSERT_EQ(bitStreamInfo[0], 8000);
+        ASSERT_EQ(bitStreamInfo[1], 1);
+    } else if (mime.find("amr-wb") != std::string::npos) {
+        ASSERT_EQ(bitStreamInfo[0], 16000);
+        ASSERT_EQ(bitStreamInfo[1], 1);
+    } else if (mime.find("gsm") != std::string::npos) {
+        ASSERT_EQ(bitStreamInfo[0], 8000);
+        ASSERT_EQ(bitStreamInfo[1], 1);
     }
 }
 
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
index d77b943..bd7ec0d 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
@@ -73,26 +73,22 @@
         ASSERT_NE(mLinearPool, nullptr);
 
         std::vector<std::unique_ptr<C2Param>> queried;
-        mComponent->query({}, {C2PortMediaTypeSetting::output::PARAM_TYPE}, C2_DONT_BLOCK,
-                          &queried);
-        ASSERT_GT(queried.size(), 0);
+        c2_status_t c2err = mComponent->query({}, {C2PortMediaTypeSetting::output::PARAM_TYPE},
+                                              C2_DONT_BLOCK, &queried);
+        ASSERT_EQ(c2err, C2_OK) << "Query media type failed";
+        ASSERT_EQ(queried.size(), 1) << "Size of the vector returned is invalid";
 
         mMime = ((C2PortMediaTypeSetting::output*)queried[0].get())->m.value;
         mEos = false;
         mCsd = false;
         mFramesReceived = 0;
+        mEncoderFrameSize = 0;
         mWorkResult = C2_OK;
         mOutputSize = 0u;
-        getInputMaxBufSize();
-
-        c2_status_t status = getChannelCount(&mNumChannels);
-        ASSERT_EQ(status, C2_OK) << "Unable to get supported channel count";
-
-        status = getSampleRate(&mSampleRate);
-        ASSERT_EQ(status, C2_OK) << "Unable to get supported sample rate";
-
-        status = getSamplesPerFrame(mNumChannels, &mSamplesPerFrame);
-        ASSERT_EQ(status, C2_OK) << "Unable to get supported number of samples per frame";
+        ASSERT_NO_FATAL_FAILURE(getInputMaxBufSize());
+        ASSERT_NO_FATAL_FAILURE(getChannelCount(&mNumChannels));
+        ASSERT_NO_FATAL_FAILURE(getSampleRate(&mSampleRate));
+        ASSERT_NO_FATAL_FAILURE(getSamplesPerFrame(mNumChannels, &mSamplesPerFrame));
 
         getFile(mNumChannels, mSampleRate);
     }
@@ -108,9 +104,9 @@
     // Get the test parameters from GetParam call.
     virtual void getParams() {}
 
-    c2_status_t getChannelCount(int32_t* nChannels);
-    c2_status_t getSampleRate(int32_t* nSampleRate);
-    c2_status_t getSamplesPerFrame(int32_t nChannels, int32_t* samplesPerFrame);
+    void getChannelCount(int32_t* nChannels);
+    void getSampleRate(int32_t* nSampleRate);
+    void getSamplesPerFrame(int32_t nChannels, int32_t* samplesPerFrame);
 
     void getFile(int32_t channelCount, int32_t sampleRate);
 
@@ -146,6 +142,7 @@
     uint32_t mFramesReceived;
     int32_t mInputMaxBufSize;
     uint64_t mOutputSize;
+    uint32_t mEncoderFrameSize;
     std::list<uint64_t> mFlushedIndices;
 
     C2BlockPool::local_id_t mBlockPoolId;
@@ -173,21 +170,13 @@
 
     // In encoder components, fetch the size of input buffer allocated
     void getInputMaxBufSize() {
-        int32_t bitStreamInfo[1] = {0};
         std::vector<std::unique_ptr<C2Param>> inParams;
         c2_status_t status = mComponent->query({}, {C2StreamMaxBufferSizeInfo::input::PARAM_TYPE},
                                                C2_DONT_BLOCK, &inParams);
-        if (status != C2_OK && inParams.size() == 0) {
-            ALOGE("Query MaxBufferSizeInfo failed => %d", status);
-            ASSERT_TRUE(false);
-        } else {
-            size_t offset = sizeof(C2Param);
-            for (size_t i = 0; i < inParams.size(); ++i) {
-                C2Param* param = inParams[i].get();
-                bitStreamInfo[i] = *(int32_t*)((uint8_t*)param + offset);
-            }
-        }
-        mInputMaxBufSize = bitStreamInfo[0];
+        ASSERT_EQ(status, C2_OK) << "Query max buffer size info failed";
+        ASSERT_EQ(inParams.size(), 1) << "Size of the vector returned is invalid";
+
+        mInputMaxBufSize = C2StreamMaxBufferSizeInfo::input::From(inParams[0].get())->value;
     }
 };
 
@@ -243,17 +232,15 @@
     return false;
 }
 
-c2_status_t Codec2AudioEncHidlTestBase::getChannelCount(int32_t* nChannels) {
+void Codec2AudioEncHidlTestBase::getChannelCount(int32_t* nChannels) {
     std::unique_ptr<C2StreamChannelCountInfo::input> channelCount =
             std::make_unique<C2StreamChannelCountInfo::input>();
     std::vector<C2FieldSupportedValuesQuery> validValueInfos = {
             C2FieldSupportedValuesQuery::Current(
                     C2ParamField(channelCount.get(), &C2StreamChannelCountInfo::value))};
     c2_status_t c2err = mComponent->querySupportedValues(validValueInfos, C2_DONT_BLOCK);
-    if (c2err != C2_OK || validValueInfos.size() != 1u) {
-        ALOGE("querySupportedValues_vb failed for channelCount");
-        return c2err;
-    }
+    ASSERT_EQ(c2err, C2_OK) << "Query channel count info failed";
+    ASSERT_EQ(validValueInfos.size(), 1) << "Size of the vector returned is invalid";
 
     // setting default value of channelCount
     *nChannels = 1;
@@ -280,37 +267,45 @@
             break;
         }
         default:
+            ASSERT_TRUE(false) << "Unsupported type: " << c2FSV.type;
             break;
     }
-    return C2_OK;
+    return;
 }
-c2_status_t Codec2AudioEncHidlTestBase::getSampleRate(int32_t* nSampleRate) {
+void Codec2AudioEncHidlTestBase::getSampleRate(int32_t* nSampleRate) {
     // Use the default sample rate for mComponents
     std::vector<std::unique_ptr<C2Param>> queried;
     c2_status_t c2err = mComponent->query({}, {C2StreamSampleRateInfo::input::PARAM_TYPE},
                                           C2_DONT_BLOCK, &queried);
-    if (c2err != C2_OK || queried.size() == 0) return c2err;
+    ASSERT_EQ(c2err, C2_OK) << "Query sample rate info failed";
+    ASSERT_EQ(queried.size(), 1) << "Size of the vector returned is invalid";
 
-    size_t offset = sizeof(C2Param);
-    C2Param* param = queried[0].get();
-    *nSampleRate = *(int32_t*)((uint8_t*)param + offset);
-
-    return C2_OK;
+    *nSampleRate = C2StreamSampleRateInfo::input::From(queried[0].get())->value;
+    return;
 }
 
-c2_status_t Codec2AudioEncHidlTestBase::getSamplesPerFrame(int32_t nChannels,
-                                                           int32_t* samplesPerFrame) {
+void Codec2AudioEncHidlTestBase::getSamplesPerFrame(int32_t nChannels, int32_t* samplesPerFrame) {
     std::vector<std::unique_ptr<C2Param>> queried;
-    c2_status_t c2err = mComponent->query({}, {C2StreamMaxBufferSizeInfo::input::PARAM_TYPE},
+    c2_status_t c2err = mComponent->query({}, {C2StreamAudioFrameSizeInfo::input::PARAM_TYPE},
                                           C2_DONT_BLOCK, &queried);
-    if (c2err != C2_OK || queried.size() == 0) return c2err;
 
-    size_t offset = sizeof(C2Param);
-    C2Param* param = queried[0].get();
-    uint32_t maxInputSize = *(uint32_t*)((uint8_t*)param + offset);
+    if (c2err == C2_OK && queried.size() == 1) {
+        mEncoderFrameSize = C2StreamAudioFrameSizeInfo::input::From(queried[0].get())->value;
+        if (mEncoderFrameSize) {
+            *samplesPerFrame = mEncoderFrameSize;
+            return;
+        }
+    }
+
+    c2err = mComponent->query({}, {C2StreamMaxBufferSizeInfo::input::PARAM_TYPE}, C2_DONT_BLOCK,
+                              &queried);
+    ASSERT_EQ(c2err, C2_OK) << "Query max buffer size info failed";
+    ASSERT_EQ(queried.size(), 1) << "Size of the vector returned is invalid";
+
+    uint32_t maxInputSize = C2StreamMaxBufferSizeInfo::input::From(queried[0].get())->value;
     *samplesPerFrame = std::min((maxInputSize / (nChannels * 2)), kMaxSamplesPerFrame);
 
-    return C2_OK;
+    return;
 }
 
 // LookUpTable of clips and metadata for component testing
@@ -440,10 +435,13 @@
     ALOGV("EncodeTest");
     if (mDisableTest) GTEST_SKIP() << "Test is disabled";
     bool signalEOS = std::get<2>(GetParam());
-    // Ratio w.r.t to mInputMaxBufSize
-    int32_t inputMaxBufRatio = std::get<3>(GetParam());
-    mSamplesPerFrame = ((mInputMaxBufSize / inputMaxBufRatio) / (mNumChannels * 2));
-
+    // Set samples per frame based on inputMaxBufRatio if component does not
+    // advertise supported frame size
+    if (!mEncoderFrameSize) {
+        // Ratio w.r.t to mInputMaxBufSize
+        int32_t inputMaxBufRatio = std::get<3>(GetParam());
+        mSamplesPerFrame = ((mInputMaxBufSize / inputMaxBufRatio) / (mNumChannels * 2));
+    }
     ALOGV("signalEOS %d mInputMaxBufSize %d mSamplesPerFrame %d", signalEOS, mInputMaxBufSize,
           mSamplesPerFrame);
 
@@ -603,12 +601,11 @@
         std::vector<std::unique_ptr<C2Param>> inParams;
         c2_status_t c2_status = mComponent->query({}, {C2StreamChannelCountInfo::input::PARAM_TYPE},
                                                   C2_DONT_BLOCK, &inParams);
-        ASSERT_TRUE(!c2_status && inParams.size())
-                << "Query configured channelCount failed => %d" << c2_status;
+        ASSERT_EQ(c2_status, C2_OK) << "Query channel count info failed";
+        ASSERT_EQ(inParams.size(), 1) << "Size of the vector returned is invalid";
 
-        size_t offset = sizeof(C2Param);
-        C2Param* param = inParams[0].get();
-        int32_t channelCount = *(int32_t*)((uint8_t*)param + offset);
+        int32_t channelCount = C2StreamChannelCountInfo::input::From(inParams[0].get())->value;
+
         if (channelCount != nChannels) {
             std::cout << "[   WARN   ] Test Skipped for ChannelCount " << nChannels << "\n";
             continue;
@@ -692,13 +689,11 @@
         std::vector<std::unique_ptr<C2Param>> inParams;
         c2_status_t c2_status = mComponent->query({}, {C2StreamSampleRateInfo::input::PARAM_TYPE},
                                                   C2_DONT_BLOCK, &inParams);
+        ASSERT_EQ(c2_status, C2_OK) << "Query sample rate info failed";
+        ASSERT_EQ(inParams.size(), 1) << "Size of the vector returned is invalid";
 
-        ASSERT_TRUE(!c2_status && inParams.size())
-                << "Query configured SampleRate failed => %d" << c2_status;
-        size_t offset = sizeof(C2Param);
-        C2Param* param = inParams[0].get();
-        int32_t configuredSampleRate = *(int32_t*)((uint8_t*)param + offset);
-
+        int32_t configuredSampleRate =
+                C2StreamSampleRateInfo::input::From(inParams[0].get())->value;
         if (configuredSampleRate != nSampleRate) {
             std::cout << "[   WARN   ] Test Skipped for SampleRate " << nSampleRate << "\n";
             continue;
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 95a4674..67873fa 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -123,8 +123,10 @@
         ASSERT_NE(mLinearPool, nullptr);
 
         std::vector<std::unique_ptr<C2Param>> queried;
-        mComponent->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE}, C2_DONT_BLOCK, &queried);
-        ASSERT_GT(queried.size(), 0);
+        c2_status_t c2err = mComponent->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
+                                              C2_DONT_BLOCK, &queried);
+        ASSERT_EQ(c2err, C2_OK) << "Query media type failed";
+        ASSERT_EQ(queried.size(), 1) << "Size of the vector returned is invalid";
 
         mMime = ((C2PortMediaTypeSetting::input*)queried[0].get())->m.value;
         mEos = false;
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index a6507e7..366025f 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -74,9 +74,10 @@
         ASSERT_NE(mGraphicPool, nullptr);
 
         std::vector<std::unique_ptr<C2Param>> queried;
-        mComponent->query({}, {C2PortMediaTypeSetting::output::PARAM_TYPE}, C2_DONT_BLOCK,
-                          &queried);
-        ASSERT_GT(queried.size(), 0);
+        c2_status_t c2err = mComponent->query({}, {C2PortMediaTypeSetting::output::PARAM_TYPE},
+                                              C2_DONT_BLOCK, &queried);
+        ASSERT_EQ(c2err, C2_OK) << "Query media type failed";
+        ASSERT_EQ(queried.size(), 1) << "Size of the vector returned is invalid";
 
         mMime = ((C2PortMediaTypeSetting::output*)queried[0].get())->m.value;
         std::cout << "mime : " << mMime << "\n";
@@ -531,9 +532,17 @@
                   << " resetting num BFrames to 0\n";
         mConfigBPictures = false;
     } else {
-        size_t offset = sizeof(C2Param);
-        C2Param* param = inParams[0].get();
-        int32_t numBFrames = *(int32_t*)((uint8_t*)param + offset);
+        int32_t numBFrames = 0;
+        C2StreamGopTuning::output* gop = C2StreamGopTuning::output::From(inParams[0].get());
+        if (gop && gop->flexCount() >= 1) {
+            for (size_t i = 0; i < gop->flexCount(); ++i) {
+                const C2GopLayerStruct& layer = gop->m.values[i];
+                if (layer.type_ == C2Config::picture_type_t(P_FRAME | B_FRAME)) {
+                    numBFrames = layer.count;
+                    break;
+                }
+            }
+        }
 
         if (!numBFrames) {
             std::cout << "[   WARN   ] Bframe not supported for " << mComponentName
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index 29cc564..333a2ca 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -96,7 +96,10 @@
         if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
             int32_t stride = img->mPlane[0].mRowInc;
             mFormatWithImageData->setInt32(KEY_STRIDE, stride);
-            ALOGD("[%s] updating stride = %d", mName, stride);
+            mFormatWithImageData->setInt32(KEY_WIDTH, img->mWidth);
+            mFormatWithImageData->setInt32(KEY_HEIGHT, img->mHeight);
+            ALOGD("[%s] updating stride = %d, width: %d, height: %d",
+                  mName, stride, img->mWidth, img->mHeight);
             if (img->mNumPlanes > 1 && stride > 0) {
                 int64_t offsetDelta =
                     (int64_t)img->mPlane[1].mOffset - (int64_t)img->mPlane[0].mOffset;
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 62c8fcd..4070478 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -248,10 +248,7 @@
 
         // align width and height to support subsampling cleanly
         uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
-
-        int32_t fmtHeight = mHeight;
-        format->findInt32(KEY_HEIGHT, &fmtHeight);
-        uint32_t vStride = align(fmtHeight, 2);
+        uint32_t vStride = align(view.crop().height, 2);
 
         bool tryWrapping = !copy;
 
diff --git a/media/codec2/vndk/C2PlatformStorePluginLoader.cpp b/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
index bee028a..2a888a8 100644
--- a/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
+++ b/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
@@ -59,13 +59,14 @@
 
 c2_status_t C2PlatformStorePluginLoader::createBlockPool(
         ::C2Allocator::id_t allocatorId, ::C2BlockPool::local_id_t blockPoolId,
-        std::shared_ptr<C2BlockPool>* pool) {
+        std::shared_ptr<C2BlockPool>* pool,
+        std::function<void(C2BlockPool *)> deleter) {
     if (mCreateBlockPool == nullptr) {
         ALOGD("Handle or CreateBlockPool symbol is null");
         return C2_NOT_FOUND;
     }
 
-    std::shared_ptr<::C2BlockPool> ptr(mCreateBlockPool(allocatorId, blockPoolId));
+    std::shared_ptr<::C2BlockPool> ptr(mCreateBlockPool(allocatorId, blockPoolId), deleter);
     if (ptr) {
         *pool = ptr;
         return C2_OK;
@@ -75,14 +76,16 @@
 }
 
 c2_status_t C2PlatformStorePluginLoader::createAllocator(
-        ::C2Allocator::id_t allocatorId, std::shared_ptr<C2Allocator>* const allocator) {
+        ::C2Allocator::id_t allocatorId,
+        std::shared_ptr<C2Allocator>* const allocator,
+        std::function<void(C2Allocator *)> deleter) {
     if (mCreateAllocator == nullptr) {
         ALOGD("Handle or CreateAllocator symbol is null");
         return C2_NOT_FOUND;
     }
 
     c2_status_t res = C2_CORRUPTED;
-    allocator->reset(mCreateAllocator(allocatorId, &res));
+    allocator->reset(mCreateAllocator(allocatorId, &res), deleter);
     if (res != C2_OK) {
         ALOGD("Failed to CreateAllocator by id: %u, res: %d", allocatorId, res);
         allocator->reset();
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index c07c09e..1660c38 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -443,6 +443,7 @@
 public:
     _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {}
 
+private:
     c2_status_t _createBlockPool(
             C2PlatformAllocatorStore::id_t allocatorId,
             std::vector<std::shared_ptr<const C2Component>> components,
@@ -456,14 +457,19 @@
         if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
             allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
         }
+        auto deleter = [this, poolId](C2BlockPool *pool) {
+            std::unique_lock lock(mMutex);
+            mBlockPools.erase(poolId);
+            mComponents.erase(poolId);
+            delete pool;
+        };
         switch(allocatorId) {
             case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
                 res = allocatorStore->fetchAllocator(
                         C2PlatformAllocatorStore::ION, &allocator);
                 if (res == C2_OK) {
-                    std::shared_ptr<C2BlockPool> ptr =
-                            std::make_shared<C2PooledBlockPool>(
-                                    allocator, poolId);
+                    std::shared_ptr<C2BlockPool> ptr(
+                            new C2PooledBlockPool(allocator, poolId), deleter);
                     *pool = ptr;
                     mBlockPools[poolId] = ptr;
                     mComponents[poolId].insert(
@@ -475,9 +481,8 @@
                 res = allocatorStore->fetchAllocator(
                         C2PlatformAllocatorStore::BLOB, &allocator);
                 if (res == C2_OK) {
-                    std::shared_ptr<C2BlockPool> ptr =
-                            std::make_shared<C2PooledBlockPool>(
-                                    allocator, poolId);
+                    std::shared_ptr<C2BlockPool> ptr(
+                            new C2PooledBlockPool(allocator, poolId), deleter);
                     *pool = ptr;
                     mBlockPools[poolId] = ptr;
                     mComponents[poolId].insert(
@@ -490,8 +495,8 @@
                 res = allocatorStore->fetchAllocator(
                         C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
                 if (res == C2_OK) {
-                    std::shared_ptr<C2BlockPool> ptr =
-                        std::make_shared<C2PooledBlockPool>(allocator, poolId);
+                    std::shared_ptr<C2BlockPool> ptr(
+                        new C2PooledBlockPool(allocator, poolId), deleter);
                     *pool = ptr;
                     mBlockPools[poolId] = ptr;
                     mComponents[poolId].insert(
@@ -503,9 +508,8 @@
                 res = allocatorStore->fetchAllocator(
                         C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
                 if (res == C2_OK) {
-                    std::shared_ptr<C2BlockPool> ptr =
-                            std::make_shared<C2BufferQueueBlockPool>(
-                                    allocator, poolId);
+                    std::shared_ptr<C2BlockPool> ptr(
+                            new C2BufferQueueBlockPool(allocator, poolId), deleter);
                     *pool = ptr;
                     mBlockPools[poolId] = ptr;
                     mComponents[poolId].insert(
@@ -517,7 +521,7 @@
                 // Try to create block pool from platform store plugins.
                 std::shared_ptr<C2BlockPool> ptr;
                 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
-                        allocatorId, poolId, &ptr);
+                        allocatorId, poolId, &ptr, deleter);
                 if (res == C2_OK) {
                     *pool = ptr;
                     mBlockPools[poolId] = ptr;
@@ -530,17 +534,20 @@
         return res;
     }
 
+public:
     c2_status_t createBlockPool(
             C2PlatformAllocatorStore::id_t allocatorId,
             std::vector<std::shared_ptr<const C2Component>> components,
             std::shared_ptr<C2BlockPool> *pool) {
+        std::unique_lock lock(mMutex);
         return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
     }
 
-    bool getBlockPool(
+    c2_status_t getBlockPool(
             C2BlockPool::local_id_t blockPoolId,
             std::shared_ptr<const C2Component> component,
             std::shared_ptr<C2BlockPool> *pool) {
+        std::unique_lock lock(mMutex);
         // TODO: use one iterator for multiple blockpool type scalability.
         std::shared_ptr<C2BlockPool> ptr;
         auto it = mBlockPools.find(blockPoolId);
@@ -558,14 +565,22 @@
                         });
                 if (found != mComponents[blockPoolId].end()) {
                     *pool = ptr;
-                    return true;
+                    return C2_OK;
                 }
             }
         }
-        return false;
+        // TODO: remove this. this is temporary
+        if (blockPoolId == C2BlockPool::PLATFORM_START) {
+            return _createBlockPool(
+                    C2PlatformAllocatorStore::BUFFERQUEUE, {component}, blockPoolId, pool);
+        }
+        return C2_NOT_FOUND;
     }
 
 private:
+    // Deleter needs to hold this mutex, and there is a small chance that deleter
+    // is invoked while the mutex is held.
+    std::recursive_mutex mMutex;
     C2BlockPool::local_id_t mBlockPoolSeqId;
 
     std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
@@ -574,7 +589,6 @@
 
 static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
     std::make_unique<_C2BlockPoolCache>();
-static std::mutex sBlockPoolCacheMutex;
 
 } // anynymous namespace
 
@@ -582,15 +596,12 @@
         C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
         std::shared_ptr<C2BlockPool> *pool) {
     pool->reset();
-    std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
     std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
     std::shared_ptr<C2Allocator> allocator;
     c2_status_t res = C2_NOT_FOUND;
 
     if (id >= C2BlockPool::PLATFORM_START) {
-        if (sBlockPoolCache->getBlockPool(id, component, pool)) {
-            return C2_OK;
-        }
+        return sBlockPoolCache->getBlockPool(id, component, pool);
     }
 
     switch (id) {
@@ -606,11 +617,6 @@
             *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
         }
         break;
-    // TODO: remove this. this is temporary
-    case C2BlockPool::PLATFORM_START:
-        res = sBlockPoolCache->_createBlockPool(
-                C2PlatformAllocatorStore::BUFFERQUEUE, {component}, id, pool);
-        break;
     default:
         break;
     }
@@ -623,7 +629,6 @@
         std::shared_ptr<C2BlockPool> *pool) {
     pool->reset();
 
-    std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
     return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
 }
 
@@ -633,7 +638,6 @@
         std::shared_ptr<C2BlockPool> *pool) {
     pool->reset();
 
-    std::lock_guard<std::mutex> lock(sBlockPoolCacheMutex);
     return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
 }
 
diff --git a/media/codec2/vndk/include/C2PlatformStorePluginLoader.h b/media/codec2/vndk/include/C2PlatformStorePluginLoader.h
index 4c10643..73d1b5e 100644
--- a/media/codec2/vndk/include/C2PlatformStorePluginLoader.h
+++ b/media/codec2/vndk/include/C2PlatformStorePluginLoader.h
@@ -61,9 +61,11 @@
      * \retval C2_NOT_FOUND the extension symbol was not found.
      * \retval C2_BAD_INDEX the input allocatorId is not defined in platform store extension.
      */
-    c2_status_t createBlockPool(::C2Allocator::id_t allocatorId,
-                                ::C2BlockPool::local_id_t blockPoolId,
-                                std::shared_ptr<C2BlockPool>* pool);
+    c2_status_t createBlockPool(
+            ::C2Allocator::id_t allocatorId,
+            ::C2BlockPool::local_id_t blockPoolId,
+            std::shared_ptr<C2BlockPool>* pool,
+            std::function<void(C2BlockPool *)> deleter = std::default_delete<C2BlockPool>());
 
     /**
      * Creates allocator from platform store extension.
@@ -81,8 +83,10 @@
      * \retval C2_BAD_INDEX the input allocatorId is not defined in platform store extension.
      * \retval C2_NO_MEMORY not enough memory to create the allocator
      */
-    c2_status_t createAllocator(::C2Allocator::id_t allocatorId,
-                                std::shared_ptr<C2Allocator>* const allocator);
+    c2_status_t createAllocator(
+            ::C2Allocator::id_t allocatorId,
+            std::shared_ptr<C2Allocator>* const allocator,
+            std::function<void(C2Allocator *)> deleter = std::default_delete<C2Allocator>());
 
 private:
     explicit C2PlatformStorePluginLoader(const char *libPath);
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index efd4070..b513e45 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -883,9 +883,18 @@
     }
 
     int32_t width, height, stride;
-    CHECK(outputFormat->findInt32("width", &width));
-    CHECK(outputFormat->findInt32("height", &height));
-    CHECK(outputFormat->findInt32("stride", &stride));
+    if (outputFormat->findInt32("width", &width) == false) {
+        ALOGE("MediaImageDecoder::onOutputReceived:width is missing in outputFormat");
+        return ERROR_MALFORMED;
+    }
+    if (outputFormat->findInt32("height", &height) == false) {
+        ALOGE("MediaImageDecoder::onOutputReceived:height is missing in outputFormat");
+        return ERROR_MALFORMED;
+    }
+    if (outputFormat->findInt32("stride", &stride) == false) {
+        ALOGE("MediaImageDecoder::onOutputReceived:stride is missing in outputFormat");
+        return ERROR_MALFORMED;
+    }
 
     if (mFrame == NULL) {
         sp<IMemory> frameMem = allocVideoFrame(