Loading media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp +117 −144 Original line number Diff line number Diff line Loading @@ -156,33 +156,7 @@ class Codec2AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase { // callback function to process onWorkDone received by Listener void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) { for (std::unique_ptr<C2Work>& work : workItems) { // handle configuration changes in work done if (!work->worklets.empty() && (work->worklets.front()->output.configUpdate.size() != 0)) { ALOGV("Config Update"); std::vector<std::unique_ptr<C2Param>> updates = std::move(work->worklets.front()->output.configUpdate); std::vector<C2Param*> configParam; std::vector<std::unique_ptr<C2SettingResult>> failures; for (size_t i = 0; i < updates.size(); ++i) { C2Param* param = updates[i].get(); if ((param->index() == C2StreamSampleRateInfo::output::PARAM_TYPE) || (param->index() == C2StreamChannelCountInfo::output::PARAM_TYPE)) { configParam.push_back(param); } } mComponent->config(configParam, C2_DONT_BLOCK, &failures); ASSERT_EQ(failures.size(), 0u); } mFramesReceived++; mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) != 0; auto frameIndexIt = std::find(mFlushedIndices.begin(), mFlushedIndices.end(), work->input.ordinal.frameIndex.peeku()); ALOGV("WorkDone: frameID received %d", (int)work->worklets.front()->output.ordinal.frameIndex.peeku()); if (!work->worklets.empty()) { // For decoder components current timestamp always exceeds // previous timestamp bool codecConfig = ((work->worklets.front()->output.flags & Loading @@ -202,17 +176,11 @@ class Codec2AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase { oBufferMetaData.push_back(meta); } } work->input.buffers.clear(); work->worklets.clear(); { typedef std::unique_lock<std::mutex> ULock; ULock l(mQueueLock); mWorkQueue.push_back(std::move(work)); if (!mFlushedIndices.empty()) { mFlushedIndices.erase(frameIndexIt); } mQueueCondition.notify_all(); bool mCsd = false; workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue, mEos, mCsd, mFramesReceived); (void)mCsd; } } } Loading Loading @@ -462,10 +430,13 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &comp } int size = (*Info)[frameID].bytesCount; char* data = (char*)malloc(size); ASSERT_NE(data, nullptr); eleStream.read(data, size); ASSERT_EQ(eleStream.gcount(), size); work->input.buffers.clear(); if (size) { std::shared_ptr<C2LinearBlock> block; ASSERT_EQ(C2_OK, linearPool->fetchLinearBlock( Loading @@ -485,11 +456,11 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &comp memcpy(view.base(), data, size); work->input.buffers.clear(); work->input.buffers.emplace_back(new LinearBuffer(block)); free(data); } work->worklets.clear(); work->worklets.emplace_back(new C2Worklet); free(data); std::list<std::unique_ptr<C2Work>> items; items.push_back(std::move(work)); Loading @@ -502,29 +473,6 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &comp } } void waitOnInputConsumption(std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, size_t bufferCount = MAX_INPUT_BUFFERS) { typedef std::unique_lock<std::mutex> ULock; uint32_t queueSize; uint32_t maxRetry = 0; { ULock l(queueLock); queueSize = workQueue.size(); } while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) { ULock l(queueLock); if (queueSize != workQueue.size()) { queueSize = workQueue.size(); maxRetry = 0; } else { queueCondition.wait_for(l, TIME_OUT); maxRetry++; } } } TEST_F(Codec2AudioDecHidlTest, validateCompName) { if (mDisableTest) return; ALOGV("Checks if the given component is a valid audio component"); Loading Loading @@ -718,7 +666,6 @@ TEST_F(Codec2AudioDecHidlTest, EOSTest) { ASSERT_EQ(mComponent->queue(&items), C2_OK); { typedef std::unique_lock<std::mutex> ULock; ULock l(mQueueLock); if (mWorkQueue.size() != MAX_INPUT_BUFFERS) { mQueueCondition.wait_for(l, TIME_OUT); Loading @@ -729,46 +676,6 @@ TEST_F(Codec2AudioDecHidlTest, EOSTest) { ASSERT_EQ(mComponent->stop(), C2_OK); } TEST_F(Codec2AudioDecHidlTest, EmptyBufferTest) { description("Tests empty input buffer"); if (mDisableTest) return; typedef std::unique_lock<std::mutex> ULock; ASSERT_EQ(mComponent->start(), C2_OK); std::unique_ptr<C2Work> work; // Prepare C2Work { ULock l(mQueueLock); if (!mWorkQueue.empty()) { work.swap(mWorkQueue.front()); mWorkQueue.pop_front(); } else { ASSERT_TRUE(false) << "mWorkQueue Empty at the start of test"; } } ASSERT_NE(work, nullptr); work->input.flags = (C2FrameData::flags_t)0; work->input.ordinal.timestamp = 0; work->input.ordinal.frameIndex = 0; work->input.buffers.clear(); work->worklets.clear(); work->worklets.emplace_back(new C2Worklet); std::list<std::unique_ptr<C2Work>> items; items.push_back(std::move(work)); ASSERT_EQ(mComponent->queue(&items), C2_OK); { typedef std::unique_lock<std::mutex> ULock; ULock l(mQueueLock); if (mWorkQueue.size() != MAX_INPUT_BUFFERS) { mQueueCondition.wait_for(l, TIME_OUT); } } ASSERT_EQ(mWorkQueue.size(), (size_t)MAX_INPUT_BUFFERS); ASSERT_EQ(mComponent->stop(), C2_OK); } TEST_F(Codec2AudioDecHidlTest, FlushTest) { description("Tests Flush calls"); if (mDisableTest) return; Loading Loading @@ -891,6 +798,72 @@ TEST_F(Codec2AudioDecHidlTest, FlushTest) { ASSERT_EQ(mComponent->stop(), C2_OK); } TEST_F(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) { description("Decode with multiple empty input frames"); if (mDisableTest) return; ASSERT_EQ(mComponent->start(), C2_OK); char mURL[512], info[512]; std::ifstream eleStream, eleInfo; strcpy(mURL, gEnv->getRes().c_str()); strcpy(info, gEnv->getRes().c_str()); GetURLForComponent(mCompName, mURL, info); eleInfo.open(info); ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found"; android::Vector<FrameInfo> Info; int bytesCount = 0; uint32_t frameId = 0; uint32_t flags = 0; uint32_t timestamp = 0; bool codecConfig = false; // This test introduces empty CSD after every 20th frame // and empty input frames at an interval of 5 frames. while (1) { if (!(frameId % 5)) { if (!(frameId % 20)) flags = 32; else flags = 0; bytesCount = 0; } else { if (!(eleInfo >> bytesCount)) break; eleInfo >> flags; eleInfo >> timestamp; codecConfig = flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0; } Info.push_back({bytesCount, flags, timestamp}); frameId++; } eleInfo.close(); ALOGV("mURL : %s", mURL); eleStream.open(mURL, std::ifstream::binary); ASSERT_EQ(eleStream.is_open(), true); ASSERT_NO_FATAL_FAILURE(decodeNFrames( mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices, mLinearPool, eleStream, &Info, 0, (int)Info.size())); // blocking call to ensures application to Wait till all the inputs are // consumed if (!mEos) { ALOGV("Waiting for input consumption"); ASSERT_NO_FATAL_FAILURE( waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue)); } eleStream.close(); if (mFramesReceived != Info.size()) { ALOGE("Input buffer count and Output buffer count mismatch"); ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived, Info.size()); ASSERT_TRUE(false); } ASSERT_EQ(mComponent->stop(), C2_OK); } } // anonymous namespace int main(int argc, char** argv) { Loading media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp +25 −102 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase { const StringToName kStringToName[] = { {"aac", aac}, {"flac", flac}, {"opus", opus}, {"amrnb", amrnb}, {"amrwb", amrwb}, }; Loading Loading @@ -135,45 +136,17 @@ class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase { // callback function to process onWorkDone received by Listener void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) { for (std::unique_ptr<C2Work>& work : workItems) { // handle configuration changes in work done if (!work->worklets.empty() && (work->worklets.front()->output.configUpdate.size() != 0)) { ALOGV("Config Update"); std::vector<std::unique_ptr<C2Param>> updates = std::move(work->worklets.front()->output.configUpdate); std::vector<C2Param*> configParam; std::vector<std::unique_ptr<C2SettingResult>> failures; for (size_t i = 0; i < updates.size(); ++i) { C2Param* param = updates[i].get(); if (param->index() == C2StreamCsdInfo::output::PARAM_TYPE) { mCsd = true; } } } mFramesReceived++; mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) != 0; auto frameIndexIt = std::find(mFlushedIndices.begin(), mFlushedIndices.end(), work->input.ordinal.frameIndex.peeku()); ALOGV("WorkDone: frameID received %d", (int)work->worklets.front()->output.ordinal.frameIndex.peeku()); work->input.buffers.clear(); work->worklets.clear(); { typedef std::unique_lock<std::mutex> ULock; ULock l(mQueueLock); mWorkQueue.push_back(std::move(work)); if (!mFlushedIndices.empty()) { mFlushedIndices.erase(frameIndexIt); } mQueueCondition.notify_all(); if (!work->worklets.empty()) { workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue, mEos, mCsd, mFramesReceived); } } } enum standardComp { aac, flac, opus, amrnb, amrwb, unknown_comp, Loading Loading @@ -275,6 +248,8 @@ void GetURLForComponent(Codec2AudioEncHidlTest::standardComp comp, char* mURL) { "bbb_raw_1ch_16khz_s16le.raw"}, {Codec2AudioEncHidlTest::standardComp::flac, "bbb_raw_2ch_48khz_s16le.raw"}, {Codec2AudioEncHidlTest::standardComp::opus, "bbb_raw_2ch_48khz_s16le.raw"}, }; for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) { Loading Loading @@ -334,6 +309,7 @@ void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &comp flushedIndices.emplace_back(frameID); } char* data = (char*)malloc(bytesCount); ASSERT_NE(data, nullptr); eleStream.read(data, bytesCount); ASSERT_EQ(eleStream.gcount(), bytesCount); std::shared_ptr<C2LinearBlock> block; Loading Loading @@ -372,29 +348,6 @@ void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &comp } } void waitOnInputConsumption(std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, size_t bufferCount = MAX_INPUT_BUFFERS) { typedef std::unique_lock<std::mutex> ULock; uint32_t queueSize; uint32_t maxRetry = 0; { ULock l(queueLock); queueSize = workQueue.size(); } while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) { ULock l(queueLock); if (queueSize != workQueue.size()) { queueSize = workQueue.size(); maxRetry = 0; } else { queueCondition.wait_for(l, TIME_OUT); maxRetry++; } } } TEST_F(Codec2AudioEncHidlTest, validateCompName) { if (mDisableTest) return; ALOGV("Checks if the given component is a valid audio component"); Loading Loading @@ -425,6 +378,11 @@ TEST_F(Codec2AudioEncHidlTest, EncodeTest) { nSampleRate = 48000; samplesPerFrame = 1152; break; case opus: nChannels = 2; nSampleRate = 48000; samplesPerFrame = 960; break; case amrnb: nChannels = 1; nSampleRate = 8000; Loading Loading @@ -458,7 +416,7 @@ TEST_F(Codec2AudioEncHidlTest, EncodeTest) { ALOGE("framesReceived : %d inputFrames : %u", mFramesReceived, numFrames); ASSERT_TRUE(false); } if ((mCompName == flac || mCompName == aac)) { if ((mCompName == flac || mCompName == opus || mCompName == aac)) { if (!mCsd) { ALOGE("CSD buffer missing"); ASSERT_TRUE(false); Loading Loading @@ -508,46 +466,6 @@ TEST_F(Codec2AudioEncHidlTest, EOSTest) { ASSERT_EQ(mComponent->stop(), C2_OK); } TEST_F(Codec2AudioEncHidlTest, EmptyBufferTest) { description("Tests empty input buffer"); if (mDisableTest) return; ASSERT_EQ(mComponent->start(), C2_OK); typedef std::unique_lock<std::mutex> ULock; std::unique_ptr<C2Work> work; { ULock l(mQueueLock); if (!mWorkQueue.empty()) { work.swap(mWorkQueue.front()); mWorkQueue.pop_front(); } else { ALOGE("mWorkQueue Empty is not expected at the start of the test"); ASSERT_TRUE(false); } } ASSERT_NE(work, nullptr); work->input.flags = (C2FrameData::flags_t)0; work->input.ordinal.timestamp = 0; work->input.ordinal.frameIndex = 0; work->input.buffers.clear(); work->worklets.clear(); work->worklets.emplace_back(new C2Worklet); std::list<std::unique_ptr<C2Work>> items; items.push_back(std::move(work)); ASSERT_EQ(mComponent->queue(&items), C2_OK); uint32_t queueSize; { ULock l(mQueueLock); queueSize = mWorkQueue.size(); if (queueSize < MAX_INPUT_BUFFERS) { mQueueCondition.wait_for(l, TIME_OUT); } } ASSERT_EQ(mWorkQueue.size(), (uint32_t)MAX_INPUT_BUFFERS); ASSERT_EQ(mComponent->stop(), C2_OK); } TEST_F(Codec2AudioEncHidlTest, FlushTest) { description("Test Request for flush"); if (mDisableTest) return; Loading @@ -574,6 +492,11 @@ TEST_F(Codec2AudioEncHidlTest, FlushTest) { nSampleRate = 48000; samplesPerFrame = 1152; break; case opus: nChannels = 2; nSampleRate = 48000; samplesPerFrame = 960; break; case amrnb: nChannels = 1; nSampleRate = 8000; Loading media/codec2/hidl/1.0/vts/audio/media_c2_audio_hidl_test_common.h +0 −3 Original line number Diff line number Diff line Loading @@ -17,8 +17,5 @@ #ifndef MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H #define MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H #define MAX_RETRY 20 #define TIME_OUT 200ms #define MAX_INPUT_BUFFERS 8 #endif // MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.cpp +101 −25 Original line number Diff line number Diff line Loading @@ -14,39 +14,115 @@ * limitations under the License. */ // #define LOG_NDEBUG 0 #define LOG_TAG "media_c2_hidl_test_common" #include <stdio.h> #include "media_c2_hidl_test_common.h" using ::android::hardware::media::c2::V1_0::FieldSupportedValues; void dumpFSV(const FieldSupportedValues& sv) { ALOGD("Dumping FSV data"); using namespace std; if (sv.type == FieldSupportedValues::Type::EMPTY) { ALOGD("FSV Value is Empty"); } if (sv.type == FieldSupportedValues::Type::RANGE) { ALOGD("Dumping FSV range"); cout << ".range(" << sv.range.min; if (sv.range.step != 0) { cout << ":" << sv.range.step; } if (sv.range.num != 1 || sv.range.denom != 1) { cout << ":" << sv.range.num << "/" << sv.range.denom; } cout << " " << sv.range.max << ")"; } if (sv.values.size()) { ALOGD("Dumping FSV value"); cout << (sv.type == FieldSupportedValues::Type::FLAGS ? ".flags(" : ".list("); const char* sep = ""; for (const auto& p : sv.values) { cout << sep << p; sep = ","; } cout << ")"; } cout << endl; // Test the codecs for NullBuffer, Empty Input Buffer with(out) flags set void testInputBuffer( const std::shared_ptr<android::Codec2Client::Component>& component, std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue, uint32_t flags, bool isNullBuffer) { std::unique_ptr<C2Work> work; { typedef std::unique_lock<std::mutex> ULock; ULock l(queueLock); if (!workQueue.empty()) { work.swap(workQueue.front()); workQueue.pop_front(); } else { ASSERT_TRUE(false) << "workQueue Empty at the start of test"; } } ASSERT_NE(work, nullptr); work->input.flags = (C2FrameData::flags_t)flags; work->input.ordinal.timestamp = 0; work->input.ordinal.frameIndex = 0; work->input.buffers.clear(); if (isNullBuffer) { work->input.buffers.emplace_back(nullptr); } work->worklets.clear(); work->worklets.emplace_back(new C2Worklet); std::list<std::unique_ptr<C2Work>> items; items.push_back(std::move(work)); ASSERT_EQ(component->queue(&items), C2_OK); } // Wait for all the inputs to be consumed by the plugin. void waitOnInputConsumption(std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, size_t bufferCount) { typedef std::unique_lock<std::mutex> ULock; uint32_t queueSize; uint32_t maxRetry = 0; { ULock l(queueLock); queueSize = workQueue.size(); } while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) { ULock l(queueLock); if (queueSize != workQueue.size()) { queueSize = workQueue.size(); maxRetry = 0; } else { queueCondition.wait_for(l, TIME_OUT); maxRetry++; } } } // process onWorkDone received by Listener void workDone( const std::shared_ptr<android::Codec2Client::Component>& component, std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices, std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd, uint32_t& framesReceived) { // handle configuration changes in work done if (work->worklets.front()->output.configUpdate.size() != 0) { ALOGV("Config Update"); std::vector<std::unique_ptr<C2Param>> updates = std::move(work->worklets.front()->output.configUpdate); std::vector<C2Param*> configParam; std::vector<std::unique_ptr<C2SettingResult>> failures; for (size_t i = 0; i < updates.size(); ++i) { C2Param* param = updates[i].get(); if (param->index() == C2StreamCsdInfo::output::PARAM_TYPE) { csd = true; } else if ((param->index() == C2StreamSampleRateInfo::output::PARAM_TYPE) || (param->index() == C2StreamChannelCountInfo::output::PARAM_TYPE) || (param->index() == C2VideoSizeStreamInfo::output::PARAM_TYPE)) { configParam.push_back(param); } } component->config(configParam, C2_DONT_BLOCK, &failures); ASSERT_EQ(failures.size(), 0u); } framesReceived++; eos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) != 0; auto frameIndexIt = std::find(flushedIndices.begin(), flushedIndices.end(), work->input.ordinal.frameIndex.peeku()); ALOGV("WorkDone: frameID received %d", (int)work->worklets.front()->output.ordinal.frameIndex.peeku()); work->input.buffers.clear(); work->worklets.clear(); { typedef std::unique_lock<std::mutex> ULock; ULock l(queueLock); workQueue.push_back(std::move(work)); if (!flushedIndices.empty()) { flushedIndices.erase(frameIndexIt); } queueCondition.notify_all(); } } No newline at end of file media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h +22 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <android/hardware/media/c2/1.0/types.h> #include <C2Component.h> #include <C2Config.h> #include <getopt.h> #include <hidl/HidlSupport.h> #include <media/stagefright/foundation/ALooper.h> Loading @@ -38,6 +39,10 @@ using ::android::hardware::hidl_string; #include <VtsHalHidlTargetTestEnvBase.h> #define MAX_RETRY 20 #define TIME_OUT 400ms #define MAX_INPUT_BUFFERS 8 /* * Handle Callback functions onWorkDone(), onTripped(), * onError(), onDeath(), onFramesRendered() Loading Loading @@ -176,5 +181,21 @@ class ComponentTestEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { /* * common functions declarations */ void dumpFSV(const FieldSupportedValues& sv); void testInputBuffer( const std::shared_ptr<android::Codec2Client::Component>& component, std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue, uint32_t flags, bool isNullBuffer); void waitOnInputConsumption(std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, size_t bufferCount = MAX_INPUT_BUFFERS); void workDone( const std::shared_ptr<android::Codec2Client::Component>& component, std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices, std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd, uint32_t& framesReceived); #endif // MEDIA_C2_HIDL_TEST_COMMON_H Loading
media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp +117 −144 Original line number Diff line number Diff line Loading @@ -156,33 +156,7 @@ class Codec2AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase { // callback function to process onWorkDone received by Listener void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) { for (std::unique_ptr<C2Work>& work : workItems) { // handle configuration changes in work done if (!work->worklets.empty() && (work->worklets.front()->output.configUpdate.size() != 0)) { ALOGV("Config Update"); std::vector<std::unique_ptr<C2Param>> updates = std::move(work->worklets.front()->output.configUpdate); std::vector<C2Param*> configParam; std::vector<std::unique_ptr<C2SettingResult>> failures; for (size_t i = 0; i < updates.size(); ++i) { C2Param* param = updates[i].get(); if ((param->index() == C2StreamSampleRateInfo::output::PARAM_TYPE) || (param->index() == C2StreamChannelCountInfo::output::PARAM_TYPE)) { configParam.push_back(param); } } mComponent->config(configParam, C2_DONT_BLOCK, &failures); ASSERT_EQ(failures.size(), 0u); } mFramesReceived++; mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) != 0; auto frameIndexIt = std::find(mFlushedIndices.begin(), mFlushedIndices.end(), work->input.ordinal.frameIndex.peeku()); ALOGV("WorkDone: frameID received %d", (int)work->worklets.front()->output.ordinal.frameIndex.peeku()); if (!work->worklets.empty()) { // For decoder components current timestamp always exceeds // previous timestamp bool codecConfig = ((work->worklets.front()->output.flags & Loading @@ -202,17 +176,11 @@ class Codec2AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase { oBufferMetaData.push_back(meta); } } work->input.buffers.clear(); work->worklets.clear(); { typedef std::unique_lock<std::mutex> ULock; ULock l(mQueueLock); mWorkQueue.push_back(std::move(work)); if (!mFlushedIndices.empty()) { mFlushedIndices.erase(frameIndexIt); } mQueueCondition.notify_all(); bool mCsd = false; workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue, mEos, mCsd, mFramesReceived); (void)mCsd; } } } Loading Loading @@ -462,10 +430,13 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &comp } int size = (*Info)[frameID].bytesCount; char* data = (char*)malloc(size); ASSERT_NE(data, nullptr); eleStream.read(data, size); ASSERT_EQ(eleStream.gcount(), size); work->input.buffers.clear(); if (size) { std::shared_ptr<C2LinearBlock> block; ASSERT_EQ(C2_OK, linearPool->fetchLinearBlock( Loading @@ -485,11 +456,11 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &comp memcpy(view.base(), data, size); work->input.buffers.clear(); work->input.buffers.emplace_back(new LinearBuffer(block)); free(data); } work->worklets.clear(); work->worklets.emplace_back(new C2Worklet); free(data); std::list<std::unique_ptr<C2Work>> items; items.push_back(std::move(work)); Loading @@ -502,29 +473,6 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &comp } } void waitOnInputConsumption(std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, size_t bufferCount = MAX_INPUT_BUFFERS) { typedef std::unique_lock<std::mutex> ULock; uint32_t queueSize; uint32_t maxRetry = 0; { ULock l(queueLock); queueSize = workQueue.size(); } while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) { ULock l(queueLock); if (queueSize != workQueue.size()) { queueSize = workQueue.size(); maxRetry = 0; } else { queueCondition.wait_for(l, TIME_OUT); maxRetry++; } } } TEST_F(Codec2AudioDecHidlTest, validateCompName) { if (mDisableTest) return; ALOGV("Checks if the given component is a valid audio component"); Loading Loading @@ -718,7 +666,6 @@ TEST_F(Codec2AudioDecHidlTest, EOSTest) { ASSERT_EQ(mComponent->queue(&items), C2_OK); { typedef std::unique_lock<std::mutex> ULock; ULock l(mQueueLock); if (mWorkQueue.size() != MAX_INPUT_BUFFERS) { mQueueCondition.wait_for(l, TIME_OUT); Loading @@ -729,46 +676,6 @@ TEST_F(Codec2AudioDecHidlTest, EOSTest) { ASSERT_EQ(mComponent->stop(), C2_OK); } TEST_F(Codec2AudioDecHidlTest, EmptyBufferTest) { description("Tests empty input buffer"); if (mDisableTest) return; typedef std::unique_lock<std::mutex> ULock; ASSERT_EQ(mComponent->start(), C2_OK); std::unique_ptr<C2Work> work; // Prepare C2Work { ULock l(mQueueLock); if (!mWorkQueue.empty()) { work.swap(mWorkQueue.front()); mWorkQueue.pop_front(); } else { ASSERT_TRUE(false) << "mWorkQueue Empty at the start of test"; } } ASSERT_NE(work, nullptr); work->input.flags = (C2FrameData::flags_t)0; work->input.ordinal.timestamp = 0; work->input.ordinal.frameIndex = 0; work->input.buffers.clear(); work->worklets.clear(); work->worklets.emplace_back(new C2Worklet); std::list<std::unique_ptr<C2Work>> items; items.push_back(std::move(work)); ASSERT_EQ(mComponent->queue(&items), C2_OK); { typedef std::unique_lock<std::mutex> ULock; ULock l(mQueueLock); if (mWorkQueue.size() != MAX_INPUT_BUFFERS) { mQueueCondition.wait_for(l, TIME_OUT); } } ASSERT_EQ(mWorkQueue.size(), (size_t)MAX_INPUT_BUFFERS); ASSERT_EQ(mComponent->stop(), C2_OK); } TEST_F(Codec2AudioDecHidlTest, FlushTest) { description("Tests Flush calls"); if (mDisableTest) return; Loading Loading @@ -891,6 +798,72 @@ TEST_F(Codec2AudioDecHidlTest, FlushTest) { ASSERT_EQ(mComponent->stop(), C2_OK); } TEST_F(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) { description("Decode with multiple empty input frames"); if (mDisableTest) return; ASSERT_EQ(mComponent->start(), C2_OK); char mURL[512], info[512]; std::ifstream eleStream, eleInfo; strcpy(mURL, gEnv->getRes().c_str()); strcpy(info, gEnv->getRes().c_str()); GetURLForComponent(mCompName, mURL, info); eleInfo.open(info); ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found"; android::Vector<FrameInfo> Info; int bytesCount = 0; uint32_t frameId = 0; uint32_t flags = 0; uint32_t timestamp = 0; bool codecConfig = false; // This test introduces empty CSD after every 20th frame // and empty input frames at an interval of 5 frames. while (1) { if (!(frameId % 5)) { if (!(frameId % 20)) flags = 32; else flags = 0; bytesCount = 0; } else { if (!(eleInfo >> bytesCount)) break; eleInfo >> flags; eleInfo >> timestamp; codecConfig = flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0; } Info.push_back({bytesCount, flags, timestamp}); frameId++; } eleInfo.close(); ALOGV("mURL : %s", mURL); eleStream.open(mURL, std::ifstream::binary); ASSERT_EQ(eleStream.is_open(), true); ASSERT_NO_FATAL_FAILURE(decodeNFrames( mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices, mLinearPool, eleStream, &Info, 0, (int)Info.size())); // blocking call to ensures application to Wait till all the inputs are // consumed if (!mEos) { ALOGV("Waiting for input consumption"); ASSERT_NO_FATAL_FAILURE( waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue)); } eleStream.close(); if (mFramesReceived != Info.size()) { ALOGE("Input buffer count and Output buffer count mismatch"); ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived, Info.size()); ASSERT_TRUE(false); } ASSERT_EQ(mComponent->stop(), C2_OK); } } // anonymous namespace int main(int argc, char** argv) { Loading
media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp +25 −102 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase { const StringToName kStringToName[] = { {"aac", aac}, {"flac", flac}, {"opus", opus}, {"amrnb", amrnb}, {"amrwb", amrwb}, }; Loading Loading @@ -135,45 +136,17 @@ class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase { // callback function to process onWorkDone received by Listener void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) { for (std::unique_ptr<C2Work>& work : workItems) { // handle configuration changes in work done if (!work->worklets.empty() && (work->worklets.front()->output.configUpdate.size() != 0)) { ALOGV("Config Update"); std::vector<std::unique_ptr<C2Param>> updates = std::move(work->worklets.front()->output.configUpdate); std::vector<C2Param*> configParam; std::vector<std::unique_ptr<C2SettingResult>> failures; for (size_t i = 0; i < updates.size(); ++i) { C2Param* param = updates[i].get(); if (param->index() == C2StreamCsdInfo::output::PARAM_TYPE) { mCsd = true; } } } mFramesReceived++; mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) != 0; auto frameIndexIt = std::find(mFlushedIndices.begin(), mFlushedIndices.end(), work->input.ordinal.frameIndex.peeku()); ALOGV("WorkDone: frameID received %d", (int)work->worklets.front()->output.ordinal.frameIndex.peeku()); work->input.buffers.clear(); work->worklets.clear(); { typedef std::unique_lock<std::mutex> ULock; ULock l(mQueueLock); mWorkQueue.push_back(std::move(work)); if (!mFlushedIndices.empty()) { mFlushedIndices.erase(frameIndexIt); } mQueueCondition.notify_all(); if (!work->worklets.empty()) { workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue, mEos, mCsd, mFramesReceived); } } } enum standardComp { aac, flac, opus, amrnb, amrwb, unknown_comp, Loading Loading @@ -275,6 +248,8 @@ void GetURLForComponent(Codec2AudioEncHidlTest::standardComp comp, char* mURL) { "bbb_raw_1ch_16khz_s16le.raw"}, {Codec2AudioEncHidlTest::standardComp::flac, "bbb_raw_2ch_48khz_s16le.raw"}, {Codec2AudioEncHidlTest::standardComp::opus, "bbb_raw_2ch_48khz_s16le.raw"}, }; for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) { Loading Loading @@ -334,6 +309,7 @@ void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &comp flushedIndices.emplace_back(frameID); } char* data = (char*)malloc(bytesCount); ASSERT_NE(data, nullptr); eleStream.read(data, bytesCount); ASSERT_EQ(eleStream.gcount(), bytesCount); std::shared_ptr<C2LinearBlock> block; Loading Loading @@ -372,29 +348,6 @@ void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &comp } } void waitOnInputConsumption(std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, size_t bufferCount = MAX_INPUT_BUFFERS) { typedef std::unique_lock<std::mutex> ULock; uint32_t queueSize; uint32_t maxRetry = 0; { ULock l(queueLock); queueSize = workQueue.size(); } while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) { ULock l(queueLock); if (queueSize != workQueue.size()) { queueSize = workQueue.size(); maxRetry = 0; } else { queueCondition.wait_for(l, TIME_OUT); maxRetry++; } } } TEST_F(Codec2AudioEncHidlTest, validateCompName) { if (mDisableTest) return; ALOGV("Checks if the given component is a valid audio component"); Loading Loading @@ -425,6 +378,11 @@ TEST_F(Codec2AudioEncHidlTest, EncodeTest) { nSampleRate = 48000; samplesPerFrame = 1152; break; case opus: nChannels = 2; nSampleRate = 48000; samplesPerFrame = 960; break; case amrnb: nChannels = 1; nSampleRate = 8000; Loading Loading @@ -458,7 +416,7 @@ TEST_F(Codec2AudioEncHidlTest, EncodeTest) { ALOGE("framesReceived : %d inputFrames : %u", mFramesReceived, numFrames); ASSERT_TRUE(false); } if ((mCompName == flac || mCompName == aac)) { if ((mCompName == flac || mCompName == opus || mCompName == aac)) { if (!mCsd) { ALOGE("CSD buffer missing"); ASSERT_TRUE(false); Loading Loading @@ -508,46 +466,6 @@ TEST_F(Codec2AudioEncHidlTest, EOSTest) { ASSERT_EQ(mComponent->stop(), C2_OK); } TEST_F(Codec2AudioEncHidlTest, EmptyBufferTest) { description("Tests empty input buffer"); if (mDisableTest) return; ASSERT_EQ(mComponent->start(), C2_OK); typedef std::unique_lock<std::mutex> ULock; std::unique_ptr<C2Work> work; { ULock l(mQueueLock); if (!mWorkQueue.empty()) { work.swap(mWorkQueue.front()); mWorkQueue.pop_front(); } else { ALOGE("mWorkQueue Empty is not expected at the start of the test"); ASSERT_TRUE(false); } } ASSERT_NE(work, nullptr); work->input.flags = (C2FrameData::flags_t)0; work->input.ordinal.timestamp = 0; work->input.ordinal.frameIndex = 0; work->input.buffers.clear(); work->worklets.clear(); work->worklets.emplace_back(new C2Worklet); std::list<std::unique_ptr<C2Work>> items; items.push_back(std::move(work)); ASSERT_EQ(mComponent->queue(&items), C2_OK); uint32_t queueSize; { ULock l(mQueueLock); queueSize = mWorkQueue.size(); if (queueSize < MAX_INPUT_BUFFERS) { mQueueCondition.wait_for(l, TIME_OUT); } } ASSERT_EQ(mWorkQueue.size(), (uint32_t)MAX_INPUT_BUFFERS); ASSERT_EQ(mComponent->stop(), C2_OK); } TEST_F(Codec2AudioEncHidlTest, FlushTest) { description("Test Request for flush"); if (mDisableTest) return; Loading @@ -574,6 +492,11 @@ TEST_F(Codec2AudioEncHidlTest, FlushTest) { nSampleRate = 48000; samplesPerFrame = 1152; break; case opus: nChannels = 2; nSampleRate = 48000; samplesPerFrame = 960; break; case amrnb: nChannels = 1; nSampleRate = 8000; Loading
media/codec2/hidl/1.0/vts/audio/media_c2_audio_hidl_test_common.h +0 −3 Original line number Diff line number Diff line Loading @@ -17,8 +17,5 @@ #ifndef MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H #define MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H #define MAX_RETRY 20 #define TIME_OUT 200ms #define MAX_INPUT_BUFFERS 8 #endif // MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.cpp +101 −25 Original line number Diff line number Diff line Loading @@ -14,39 +14,115 @@ * limitations under the License. */ // #define LOG_NDEBUG 0 #define LOG_TAG "media_c2_hidl_test_common" #include <stdio.h> #include "media_c2_hidl_test_common.h" using ::android::hardware::media::c2::V1_0::FieldSupportedValues; void dumpFSV(const FieldSupportedValues& sv) { ALOGD("Dumping FSV data"); using namespace std; if (sv.type == FieldSupportedValues::Type::EMPTY) { ALOGD("FSV Value is Empty"); } if (sv.type == FieldSupportedValues::Type::RANGE) { ALOGD("Dumping FSV range"); cout << ".range(" << sv.range.min; if (sv.range.step != 0) { cout << ":" << sv.range.step; } if (sv.range.num != 1 || sv.range.denom != 1) { cout << ":" << sv.range.num << "/" << sv.range.denom; } cout << " " << sv.range.max << ")"; } if (sv.values.size()) { ALOGD("Dumping FSV value"); cout << (sv.type == FieldSupportedValues::Type::FLAGS ? ".flags(" : ".list("); const char* sep = ""; for (const auto& p : sv.values) { cout << sep << p; sep = ","; } cout << ")"; } cout << endl; // Test the codecs for NullBuffer, Empty Input Buffer with(out) flags set void testInputBuffer( const std::shared_ptr<android::Codec2Client::Component>& component, std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue, uint32_t flags, bool isNullBuffer) { std::unique_ptr<C2Work> work; { typedef std::unique_lock<std::mutex> ULock; ULock l(queueLock); if (!workQueue.empty()) { work.swap(workQueue.front()); workQueue.pop_front(); } else { ASSERT_TRUE(false) << "workQueue Empty at the start of test"; } } ASSERT_NE(work, nullptr); work->input.flags = (C2FrameData::flags_t)flags; work->input.ordinal.timestamp = 0; work->input.ordinal.frameIndex = 0; work->input.buffers.clear(); if (isNullBuffer) { work->input.buffers.emplace_back(nullptr); } work->worklets.clear(); work->worklets.emplace_back(new C2Worklet); std::list<std::unique_ptr<C2Work>> items; items.push_back(std::move(work)); ASSERT_EQ(component->queue(&items), C2_OK); } // Wait for all the inputs to be consumed by the plugin. void waitOnInputConsumption(std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, size_t bufferCount) { typedef std::unique_lock<std::mutex> ULock; uint32_t queueSize; uint32_t maxRetry = 0; { ULock l(queueLock); queueSize = workQueue.size(); } while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) { ULock l(queueLock); if (queueSize != workQueue.size()) { queueSize = workQueue.size(); maxRetry = 0; } else { queueCondition.wait_for(l, TIME_OUT); maxRetry++; } } } // process onWorkDone received by Listener void workDone( const std::shared_ptr<android::Codec2Client::Component>& component, std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices, std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd, uint32_t& framesReceived) { // handle configuration changes in work done if (work->worklets.front()->output.configUpdate.size() != 0) { ALOGV("Config Update"); std::vector<std::unique_ptr<C2Param>> updates = std::move(work->worklets.front()->output.configUpdate); std::vector<C2Param*> configParam; std::vector<std::unique_ptr<C2SettingResult>> failures; for (size_t i = 0; i < updates.size(); ++i) { C2Param* param = updates[i].get(); if (param->index() == C2StreamCsdInfo::output::PARAM_TYPE) { csd = true; } else if ((param->index() == C2StreamSampleRateInfo::output::PARAM_TYPE) || (param->index() == C2StreamChannelCountInfo::output::PARAM_TYPE) || (param->index() == C2VideoSizeStreamInfo::output::PARAM_TYPE)) { configParam.push_back(param); } } component->config(configParam, C2_DONT_BLOCK, &failures); ASSERT_EQ(failures.size(), 0u); } framesReceived++; eos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) != 0; auto frameIndexIt = std::find(flushedIndices.begin(), flushedIndices.end(), work->input.ordinal.frameIndex.peeku()); ALOGV("WorkDone: frameID received %d", (int)work->worklets.front()->output.ordinal.frameIndex.peeku()); work->input.buffers.clear(); work->worklets.clear(); { typedef std::unique_lock<std::mutex> ULock; ULock l(queueLock); workQueue.push_back(std::move(work)); if (!flushedIndices.empty()) { flushedIndices.erase(frameIndexIt); } queueCondition.notify_all(); } } No newline at end of file
media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h +22 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <android/hardware/media/c2/1.0/types.h> #include <C2Component.h> #include <C2Config.h> #include <getopt.h> #include <hidl/HidlSupport.h> #include <media/stagefright/foundation/ALooper.h> Loading @@ -38,6 +39,10 @@ using ::android::hardware::hidl_string; #include <VtsHalHidlTargetTestEnvBase.h> #define MAX_RETRY 20 #define TIME_OUT 400ms #define MAX_INPUT_BUFFERS 8 /* * Handle Callback functions onWorkDone(), onTripped(), * onError(), onDeath(), onFramesRendered() Loading Loading @@ -176,5 +181,21 @@ class ComponentTestEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { /* * common functions declarations */ void dumpFSV(const FieldSupportedValues& sv); void testInputBuffer( const std::shared_ptr<android::Codec2Client::Component>& component, std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue, uint32_t flags, bool isNullBuffer); void waitOnInputConsumption(std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, size_t bufferCount = MAX_INPUT_BUFFERS); void workDone( const std::shared_ptr<android::Codec2Client::Component>& component, std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices, std::mutex& queueLock, std::condition_variable& queueCondition, std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd, uint32_t& framesReceived); #endif // MEDIA_C2_HIDL_TEST_COMMON_H