Merge "Control audio HAL services in start/stop" into rvc-dev
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index 8b7f57d..f87f830 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -139,8 +139,13 @@
std::vector<uint8_t> sessionId = session->sessionId();
Status status = setSecurityLevel(sessionId, securityLevel);
+ if (status == Status::OK) {
+ mOpenSessionOkCount++;
+ } else {
+ mSessionLibrary->destroySession(session);
+ sessionId.clear();
+ }
_hidl_cb(status, toHidlVec(sessionId));
- mOpenSessionOkCount++;
return Void();
}
@@ -151,12 +156,12 @@
sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
if (session.get()) {
+ mSessionLibrary->destroySession(session);
if (session->getMockError() != Status_V1_2::OK) {
sendSessionLostState(sessionId);
return Status::ERROR_DRM_INVALID_STATE;
}
mCloseSessionOkCount++;
- mSessionLibrary->destroySession(session);
return Status::OK;
}
mCloseSessionNotOpenedCount++;
@@ -387,6 +392,7 @@
if (isOfflineLicense) {
if (isRelease) {
mFileHandle.DeleteLicense(keySetId);
+ mSessionLibrary->destroySession(session);
} else {
if (!makeKeySetId(&keySetId)) {
_hidl_cb(Status::ERROR_DRM_UNKNOWN, hidl_vec<uint8_t>());
diff --git a/media/codec2/hidl/1.0/vts/OWNERS b/media/codec2/hidl/1.0/vts/OWNERS
index 6733e0c..dbe89cf 100644
--- a/media/codec2/hidl/1.0/vts/OWNERS
+++ b/media/codec2/hidl/1.0/vts/OWNERS
@@ -5,5 +5,4 @@
wonsik@google.com
# VTS team
-yim@google.com
-zhuoyao@google.com
+dshi@google.com
diff --git a/media/codec2/hidl/1.0/vts/functional/Android.bp b/media/codec2/hidl/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..5f0ba7d
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/Android.bp
@@ -0,0 +1,101 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+filegroup {
+ name: "media_c2_v1_audio_decode_res",
+ path: "res",
+ srcs: [
+ "res/bbb_aac_stereo_128kbps_48000hz.aac",
+ "res/bbb_aac_stereo_128kbps_48000hz.info",
+ "res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info",
+ "res/bbb_amrwb_1ch_14kbps_16000hz.amrwb",
+ "res/bbb_amrwb_1ch_14kbps_16000hz.info",
+ "res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info",
+ "res/bbb_flac_stereo_680kbps_48000hz.flac",
+ "res/bbb_flac_stereo_680kbps_48000hz.info",
+ "res/bbb_g711alaw_1ch_8khz.info",
+ "res/bbb_g711alaw_1ch_8khz.raw",
+ "res/bbb_g711mulaw_1ch_8khz.info",
+ "res/bbb_g711mulaw_1ch_8khz.raw",
+ "res/bbb_gsm_1ch_8khz_13kbps.info",
+ "res/bbb_gsm_1ch_8khz_13kbps.raw",
+ "res/bbb_mp3_stereo_192kbps_48000hz.info",
+ "res/bbb_mp3_stereo_192kbps_48000hz.mp3",
+ "res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info",
+ "res/bbb_opus_stereo_128kbps_48000hz.info",
+ "res/bbb_opus_stereo_128kbps_48000hz.opus",
+ "res/bbb_raw_1ch_8khz_s32le.info",
+ "res/bbb_raw_1ch_8khz_s32le.raw",
+ "res/bbb_vorbis_stereo_128kbps_48000hz.info",
+ "res/bbb_vorbis_stereo_128kbps_48000hz.vorbis",
+ "res/sine_amrnb_1ch_12kbps_8000hz.amrnb",
+ "res/sine_amrnb_1ch_12kbps_8000hz.info",
+ "res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info",
+ ],
+}
+
+filegroup {
+ name: "media_c2_v1_audio_encode_res",
+ path: "res",
+ srcs: [
+ "res/bbb_raw_2ch_48khz_s16le.raw",
+ "res/bbb_raw_1ch_8khz_s16le.raw",
+ "res/bbb_raw_1ch_16khz_s16le.raw",
+ ],
+}
+
+filegroup {
+ name: "media_c2_v1_video_decode_res",
+ path: "res",
+ srcs: [
+ "res/bbb_avc_176x144_300kbps_60fps.h264",
+ "res/bbb_avc_640x360_768kbps_30fps.h264",
+ "res/bbb_avc_176x144_300kbps_60fps.info",
+ "res/bbb_avc_640x360_768kbps_30fps.info",
+ "res/bbb_hevc_176x144_176kbps_60fps.hevc",
+ "res/bbb_hevc_640x360_1600kbps_30fps.hevc",
+ "res/bbb_hevc_176x144_176kbps_60fps.info",
+ "res/bbb_hevc_640x360_1600kbps_30fps.info",
+ "res/bbb_mpeg2_176x144_105kbps_25fps.m2v",
+ "res/bbb_mpeg2_352x288_1mbps_60fps.m2v",
+ "res/bbb_mpeg2_176x144_105kbps_25fps.info",
+ "res/bbb_mpeg2_352x288_1mbps_60fps.info",
+ "res/bbb_h263_352x288_300kbps_12fps.h263",
+ "res/bbb_h263_352x288_300kbps_12fps.info",
+ "res/bbb_mpeg4_352x288_512kbps_30fps.m4v",
+ "res/bbb_mpeg4_352x288_512kbps_30fps.info",
+ "res/bbb_vp8_176x144_240kbps_60fps.vp8",
+ "res/bbb_vp8_640x360_2mbps_30fps.vp8",
+ "res/bbb_vp8_176x144_240kbps_60fps.info",
+ "res/bbb_vp8_640x360_2mbps_30fps.info",
+ "res/bbb_vp9_176x144_285kbps_60fps.vp9",
+ "res/bbb_vp9_640x360_1600kbps_30fps.vp9",
+ "res/bbb_vp9_176x144_285kbps_60fps.info",
+ "res/bbb_vp9_640x360_1600kbps_30fps.info",
+ "res/bbb_av1_640_360.av1",
+ "res/bbb_av1_176_144.av1",
+ "res/bbb_av1_640_360.info",
+ "res/bbb_av1_176_144.info",
+ ],
+}
+
+filegroup {
+ name: "media_c2_v1_video_encode_res",
+ path: "res",
+ srcs: [
+ "res/bbb_352x288_420p_30fps_32frames.yuv",
+ ],
+}
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/Android.bp b/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
index 65f0d09..014cbe9 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/Android.bp
@@ -16,18 +16,22 @@
cc_test {
name: "VtsHalMediaC2V1_0TargetAudioDecTest",
+ stem: "vts_media_c2_v1_0_audio_dec_test",
defaults: ["VtsHalMediaC2V1_0Defaults"],
srcs: [
"VtsHalMediaC2V1_0TargetAudioDecTest.cpp",
- //"media_audio_hidl_test_common.cpp"
],
+ data: [":media_c2_v1_audio_decode_res"],
+ test_config: "VtsHalMediaC2V1_0TargetAudioDecTest.xml",
}
cc_test {
name: "VtsHalMediaC2V1_0TargetAudioEncTest",
+ stem: "vts_media_c2_v1_0_audio_enc_test",
defaults: ["VtsHalMediaC2V1_0Defaults"],
srcs: [
"VtsHalMediaC2V1_0TargetAudioEncTest.cpp",
- //"media_audio_hidl_test_common.cpp"
],
+ data: [":media_c2_v1_audio_encode_res"],
+ test_config: "VtsHalMediaC2V1_0TargetAudioEncTest.xml",
}
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 20f4665..264abba 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
@@ -19,21 +19,20 @@
#include <android-base/logging.h>
#include <gtest/gtest.h>
-#include <algorithm>
+#include <hidl/GtestPrinter.h>
#include <stdio.h>
+#include <algorithm>
#include <fstream>
-#include <codec2/hidl/client.h>
#include <C2AllocatorIon.h>
-#include <C2Config.h>
-#include <C2Debug.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <codec2/hidl/client.h>
using android::C2AllocatorIon;
-#include <VtsHalHidlTargetTestBase.h>
-#include "media_c2_audio_hidl_test_common.h"
#include "media_c2_hidl_test_common.h"
struct FrameInfo {
@@ -42,57 +41,44 @@
int64_t timestamp;
};
-class LinearBuffer : public C2Buffer {
- public:
- explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
- : C2Buffer(
- {block->share(block->offset(), block->size(), ::C2Fence())}) {}
-};
+static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
+ kDecodeTestParameters;
-static ComponentTestEnvironment* gEnv = nullptr;
+// Resource directory
+static std::string sResourceDir = "";
+
+class LinearBuffer : public C2Buffer {
+ public:
+ explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
+ : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
+};
namespace {
-class Codec2AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
-
- public:
- ::std::string getTestCaseInfo() const override {
- return ::std::string() +
- "Component: " + gEnv->getComponent().c_str() + " | " +
- "Instance: " + gEnv->getInstance().c_str() + " | " +
- "Res: " + gEnv->getRes().c_str();
- }
-
+class Codec2AudioDecHidlTestBase : public ::testing::Test {
+ public:
// google.codec2 Audio test setup
virtual void SetUp() override {
- Super::SetUp();
+ getParams();
mDisableTest = false;
ALOGV("Codec2AudioDecHidlTest SetUp");
mClient = android::Codec2Client::CreateFromService(
- gEnv->getInstance().c_str(),
- !bool(android::Codec2Client::CreateFromService("default", true)));
+ mInstanceName.c_str(),
+ !bool(android::Codec2Client::CreateFromService("default", true)));
ASSERT_NE(mClient, nullptr);
- mListener.reset(new CodecListener(
- [this](std::list<std::unique_ptr<C2Work>>& workItems) {
- handleWorkDone(workItems);
- }));
+ mListener.reset(new CodecListener([this](std::list<std::unique_ptr<C2Work>>& workItems) {
+ handleWorkDone(workItems);
+ }));
ASSERT_NE(mListener, nullptr);
for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
mWorkQueue.emplace_back(new C2Work);
}
- mClient->createComponent(gEnv->getComponent().c_str(), mListener,
- &mComponent);
+ mClient->createComponent(mComponentName, mListener, &mComponent);
ASSERT_NE(mComponent, nullptr);
- std::shared_ptr<C2AllocatorStore> store =
- android::GetCodec2PlatformAllocatorStore();
- CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR,
- &mLinearAllocator),
- C2_OK);
- mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator,
- mBlockPoolId++);
+ std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+ CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator), C2_OK);
+ mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
ASSERT_NE(mLinearPool, nullptr);
mCompName = unknown_comp;
@@ -101,27 +87,17 @@
standardComp CompName;
};
const StringToName kStringToName[] = {
- {"xaac", xaac},
- {"mp3", mp3},
- {"amrnb", amrnb},
- {"amrwb", amrwb},
- {"aac", aac},
- {"vorbis", vorbis},
- {"opus", opus},
- {"pcm", pcm},
- {"g711.alaw", g711alaw},
- {"g711.mlaw", g711mlaw},
- {"gsm", gsm},
- {"raw", raw},
- {"flac", flac},
+ {"xaac", xaac}, {"mp3", mp3}, {"amrnb", amrnb},
+ {"amrwb", amrwb}, {"aac", aac}, {"vorbis", vorbis},
+ {"opus", opus}, {"pcm", pcm}, {"g711.alaw", g711alaw},
+ {"g711.mlaw", g711mlaw}, {"gsm", gsm}, {"raw", raw},
+ {"flac", flac},
};
- const size_t kNumStringToName =
- sizeof(kStringToName) / sizeof(kStringToName[0]);
+ const size_t kNumStringToName = sizeof(kStringToName) / sizeof(kStringToName[0]);
// Find the component type
- std::string comp = std::string(gEnv->getComponent());
for (size_t i = 0; i < kNumStringToName; ++i) {
- if (strcasestr(comp.c_str(), kStringToName[i].Name)) {
+ if (strcasestr(mComponentName.c_str(), kStringToName[i].Name)) {
mCompName = kStringToName[i].CompName;
break;
}
@@ -140,9 +116,11 @@
mComponent->release();
mComponent = nullptr;
}
- Super::TearDown();
}
+ // Get the test parameters from GetParam call.
+ virtual void getParams() {}
+
struct outputMetaData {
uint64_t timestampUs;
uint32_t rangeLength;
@@ -155,25 +133,27 @@
// previous timestamp
bool codecConfig = ((work->worklets.front()->output.flags &
C2FrameData::FLAG_CODEC_CONFIG) != 0);
- if (!codecConfig &&
- !work->worklets.front()->output.buffers.empty()) {
+ if (!codecConfig && !work->worklets.front()->output.buffers.empty()) {
EXPECT_GE(work->worklets.front()->output.ordinal.timestamp.peeku(),
- mTimestampUs);
- mTimestampUs =
- work->worklets.front()->output.ordinal.timestamp.peeku();
- uint32_t rangeLength =
- work->worklets.front()->output.buffers[0]->data()
- .linearBlocks().front().map().get().capacity();
- //List of timestamp values and output size to calculate timestamp
+ mTimestampUs);
+ mTimestampUs = work->worklets.front()->output.ordinal.timestamp.peeku();
+ uint32_t rangeLength = work->worklets.front()
+ ->output.buffers[0]
+ ->data()
+ .linearBlocks()
+ .front()
+ .map()
+ .get()
+ .capacity();
+ // List of timestamp values and output size to calculate timestamp
if (mTimestampDevTest) {
outputMetaData meta = {mTimestampUs, rangeLength};
oBufferMetaData.push_back(meta);
}
}
bool mCsd = false;
- workDone(mComponent, work, mFlushedIndices, mQueueLock,
- mQueueCondition, mWorkQueue, mEos, mCsd,
- mFramesReceived);
+ workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue,
+ mEos, mCsd, mFramesReceived);
(void)mCsd;
}
}
@@ -196,6 +176,8 @@
unknown_comp,
};
+ std::string mInstanceName;
+ std::string mComponentName;
bool mEos;
bool mDisableTest;
bool mTimestampDevTest;
@@ -218,15 +200,23 @@
std::shared_ptr<android::Codec2Client::Listener> mListener;
std::shared_ptr<android::Codec2Client::Component> mComponent;
- protected:
+ protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
};
-void validateComponent(
- const std::shared_ptr<android::Codec2Client::Component>& component,
- Codec2AudioDecHidlTest::standardComp compName, bool& disableTest) {
+class Codec2AudioDecHidlTest
+ : public Codec2AudioDecHidlTestBase,
+ public ::testing::WithParamInterface<std::tuple<std::string, std::string>> {
+ void getParams() {
+ mInstanceName = std::get<0>(GetParam());
+ mComponentName = std::get<1>(GetParam());
+ }
+};
+
+void validateComponent(const std::shared_ptr<android::Codec2Client::Component>& component,
+ Codec2AudioDecHidlTest::standardComp compName, bool& disableTest) {
// Validate its a C2 Component
if (component->getName().find("c2") == std::string::npos) {
ALOGE("Not a c2 component");
@@ -241,14 +231,12 @@
return;
}
std::vector<std::unique_ptr<C2Param>> queried;
- c2_status_t c2err =
- component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
- C2_DONT_BLOCK, &queried);
+ c2_status_t c2err = component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
+ C2_DONT_BLOCK, &queried);
if (c2err != C2_OK && queried.size() == 0) {
ALOGE("Query media type failed => %d", c2err);
} else {
- std::string inputDomain =
- ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
+ std::string inputDomain = ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
if (inputDomain.find("audio/") == std::string::npos) {
ALOGE("Expected Audio Component");
disableTest = true;
@@ -266,16 +254,14 @@
}
// Set Default config param.
-bool setupConfigParam(
- const std::shared_ptr<android::Codec2Client::Component>& component,
- int32_t* bitStreamInfo) {
+bool setupConfigParam(const std::shared_ptr<android::Codec2Client::Component>& component,
+ int32_t* bitStreamInfo) {
std::vector<std::unique_ptr<C2SettingResult>> failures;
C2StreamSampleRateInfo::output sampleRateInfo(0u, bitStreamInfo[0]);
C2StreamChannelCountInfo::output channelCountInfo(0u, bitStreamInfo[1]);
std::vector<C2Param*> configParam{&sampleRateInfo, &channelCountInfo};
- c2_status_t status =
- component->config(configParam, C2_DONT_BLOCK, &failures);
+ c2_status_t status = component->config(configParam, C2_DONT_BLOCK, &failures);
if (status == C2_OK && failures.size() == 0u) return true;
return false;
}
@@ -283,17 +269,15 @@
// In decoder components, often the input parameters get updated upon
// parsing the header of elementary stream. Client needs to collect this
// information and reconfigure
-void getInputChannelInfo(
- const std::shared_ptr<android::Codec2Client::Component>& component,
- Codec2AudioDecHidlTest::standardComp compName, int32_t* bitStreamInfo) {
+void getInputChannelInfo(const std::shared_ptr<android::Codec2Client::Component>& component,
+ Codec2AudioDecHidlTest::standardComp compName, int32_t* bitStreamInfo) {
// query nSampleRate and nChannels
std::initializer_list<C2Param::Index> indices{
- C2StreamSampleRateInfo::output::PARAM_TYPE,
- C2StreamChannelCountInfo::output::PARAM_TYPE,
+ C2StreamSampleRateInfo::output::PARAM_TYPE,
+ C2StreamChannelCountInfo::output::PARAM_TYPE,
};
std::vector<std::unique_ptr<C2Param>> inParams;
- c2_status_t status =
- component->query({}, indices, C2_DONT_BLOCK, &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);
@@ -328,8 +312,8 @@
#define STREAM_COUNT 2
// LookUpTable of clips and metadata for component testing
-void GetURLForComponent(Codec2AudioDecHidlTest::standardComp comp, char* mURL,
- char* info, size_t streamIndex = 0) {
+void GetURLForComponent(Codec2AudioDecHidlTest::standardComp comp, char* mURL, char* info,
+ size_t streamIndex = 0) {
struct CompToURL {
Codec2AudioDecHidlTest::standardComp comp;
const char mURL[STREAM_COUNT][512];
@@ -338,52 +322,47 @@
ASSERT_TRUE(streamIndex < STREAM_COUNT);
static const CompToURL kCompToURL[] = {
- {Codec2AudioDecHidlTest::standardComp::xaac,
- {"bbb_aac_stereo_128kbps_48000hz.aac",
- "bbb_aac_stereo_128kbps_48000hz.aac"},
- {"bbb_aac_stereo_128kbps_48000hz.info",
- "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
- {Codec2AudioDecHidlTest::standardComp::mp3,
- {"bbb_mp3_stereo_192kbps_48000hz.mp3",
- "bbb_mp3_stereo_192kbps_48000hz.mp3"},
- {"bbb_mp3_stereo_192kbps_48000hz.info",
- "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"}},
- {Codec2AudioDecHidlTest::standardComp::aac,
- {"bbb_aac_stereo_128kbps_48000hz.aac",
- "bbb_aac_stereo_128kbps_48000hz.aac"},
- {"bbb_aac_stereo_128kbps_48000hz.info",
- "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
- {Codec2AudioDecHidlTest::standardComp::amrnb,
- {"sine_amrnb_1ch_12kbps_8000hz.amrnb",
- "sine_amrnb_1ch_12kbps_8000hz.amrnb"},
- {"sine_amrnb_1ch_12kbps_8000hz.info",
- "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"}},
- {Codec2AudioDecHidlTest::standardComp::amrwb,
- {"bbb_amrwb_1ch_14kbps_16000hz.amrwb",
- "bbb_amrwb_1ch_14kbps_16000hz.amrwb"},
- {"bbb_amrwb_1ch_14kbps_16000hz.info",
- "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"}},
- {Codec2AudioDecHidlTest::standardComp::vorbis,
- {"bbb_vorbis_stereo_128kbps_48000hz.vorbis", ""},
- {"bbb_vorbis_stereo_128kbps_48000hz.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::opus,
- {"bbb_opus_stereo_128kbps_48000hz.opus", ""},
- {"bbb_opus_stereo_128kbps_48000hz.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::g711alaw,
- {"bbb_g711alaw_1ch_8khz.raw", ""},
- {"bbb_g711alaw_1ch_8khz.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::g711mlaw,
- {"bbb_g711mulaw_1ch_8khz.raw", ""},
- {"bbb_g711mulaw_1ch_8khz.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::gsm,
- {"bbb_gsm_1ch_8khz_13kbps.raw", ""},
- {"bbb_gsm_1ch_8khz_13kbps.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::raw,
- {"bbb_raw_1ch_8khz_s32le.raw", ""},
- {"bbb_raw_1ch_8khz_s32le.info", ""}},
- {Codec2AudioDecHidlTest::standardComp::flac,
- {"bbb_flac_stereo_680kbps_48000hz.flac", ""},
- {"bbb_flac_stereo_680kbps_48000hz.info", ""}},
+ {Codec2AudioDecHidlTest::standardComp::xaac,
+ {"bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.aac"},
+ {"bbb_aac_stereo_128kbps_48000hz.info",
+ "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
+ {Codec2AudioDecHidlTest::standardComp::mp3,
+ {"bbb_mp3_stereo_192kbps_48000hz.mp3", "bbb_mp3_stereo_192kbps_48000hz.mp3"},
+ {"bbb_mp3_stereo_192kbps_48000hz.info",
+ "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"}},
+ {Codec2AudioDecHidlTest::standardComp::aac,
+ {"bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.aac"},
+ {"bbb_aac_stereo_128kbps_48000hz.info",
+ "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
+ {Codec2AudioDecHidlTest::standardComp::amrnb,
+ {"sine_amrnb_1ch_12kbps_8000hz.amrnb", "sine_amrnb_1ch_12kbps_8000hz.amrnb"},
+ {"sine_amrnb_1ch_12kbps_8000hz.info",
+ "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"}},
+ {Codec2AudioDecHidlTest::standardComp::amrwb,
+ {"bbb_amrwb_1ch_14kbps_16000hz.amrwb", "bbb_amrwb_1ch_14kbps_16000hz.amrwb"},
+ {"bbb_amrwb_1ch_14kbps_16000hz.info",
+ "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"}},
+ {Codec2AudioDecHidlTest::standardComp::vorbis,
+ {"bbb_vorbis_stereo_128kbps_48000hz.vorbis", ""},
+ {"bbb_vorbis_stereo_128kbps_48000hz.info", ""}},
+ {Codec2AudioDecHidlTest::standardComp::opus,
+ {"bbb_opus_stereo_128kbps_48000hz.opus", ""},
+ {"bbb_opus_stereo_128kbps_48000hz.info", ""}},
+ {Codec2AudioDecHidlTest::standardComp::g711alaw,
+ {"bbb_g711alaw_1ch_8khz.raw", ""},
+ {"bbb_g711alaw_1ch_8khz.info", ""}},
+ {Codec2AudioDecHidlTest::standardComp::g711mlaw,
+ {"bbb_g711mulaw_1ch_8khz.raw", ""},
+ {"bbb_g711mulaw_1ch_8khz.info", ""}},
+ {Codec2AudioDecHidlTest::standardComp::gsm,
+ {"bbb_gsm_1ch_8khz_13kbps.raw", ""},
+ {"bbb_gsm_1ch_8khz_13kbps.info", ""}},
+ {Codec2AudioDecHidlTest::standardComp::raw,
+ {"bbb_raw_1ch_8khz_s32le.raw", ""},
+ {"bbb_raw_1ch_8khz_s32le.info", ""}},
+ {Codec2AudioDecHidlTest::standardComp::flac,
+ {"bbb_flac_stereo_680kbps_48000hz.flac", ""},
+ {"bbb_flac_stereo_680kbps_48000hz.info", ""}},
};
for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
@@ -396,13 +375,11 @@
}
void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
- std::mutex &queueLock, std::condition_variable& queueCondition,
+ std::mutex& queueLock, std::condition_variable& queueCondition,
std::list<std::unique_ptr<C2Work>>& workQueue,
- std::list<uint64_t>& flushedIndices,
- std::shared_ptr<C2BlockPool>& linearPool,
- std::ifstream& eleStream,
- android::Vector<FrameInfo>* Info,
- int offset, int range, bool signalEOS = true) {
+ std::list<uint64_t>& flushedIndices, std::shared_ptr<C2BlockPool>& linearPool,
+ std::ifstream& eleStream, android::Vector<FrameInfo>* Info, int offset,
+ int range, bool signalEOS = true) {
typedef std::unique_lock<std::mutex> ULock;
int frameID = offset;
int maxRetry = 0;
@@ -426,8 +403,7 @@
}
int64_t timestamp = (*Info)[frameID].timestamp;
if ((*Info)[frameID].flags) flags = 1u << ((*Info)[frameID].flags - 1);
- if (signalEOS && ((frameID == (int)Info->size() - 1) ||
- (frameID == (offset + range - 1))))
+ if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
flags |= C2FrameData::FLAG_END_OF_STREAM;
work->input.flags = (C2FrameData::flags_t)flags;
@@ -448,9 +424,8 @@
if (size) {
std::shared_ptr<C2LinearBlock> block;
ASSERT_EQ(C2_OK,
- linearPool->fetchLinearBlock(
- size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
- &block));
+ linearPool->fetchLinearBlock(
+ size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
ASSERT_TRUE(block);
// Write View
@@ -482,45 +457,49 @@
}
}
-TEST_F(Codec2AudioDecHidlTest, validateCompName) {
- if (mDisableTest) return;
+TEST_P(Codec2AudioDecHidlTest, validateCompName) {
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
ALOGV("Checks if the given component is a valid audio component");
validateComponent(mComponent, mCompName, mDisableTest);
ASSERT_EQ(mDisableTest, false);
}
-TEST_F(Codec2AudioDecHidlTest, configComp) {
+TEST_P(Codec2AudioDecHidlTest, configComp) {
description("Tests component specific configuration");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
ASSERT_EQ(mComponent->start(), C2_OK);
int32_t bitStreamInfo[2] = {0};
- ASSERT_NO_FATAL_FAILURE(
- getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
setupConfigParam(mComponent, bitStreamInfo);
ASSERT_EQ(mComponent->stop(), C2_OK);
}
class Codec2AudioDecDecodeTest
- : public Codec2AudioDecHidlTest,
- public ::testing::WithParamInterface<std::pair<int32_t, bool>> {
+ : public Codec2AudioDecHidlTestBase,
+ public ::testing::WithParamInterface<
+ std::tuple<std::string, std::string, std::string, std::string>> {
+ void getParams() {
+ mInstanceName = std::get<0>(GetParam());
+ mComponentName = std::get<1>(GetParam());
+ }
};
TEST_P(Codec2AudioDecDecodeTest, DecodeTest) {
description("Decodes input file");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
- uint32_t streamIndex = GetParam().first;
- bool signalEOS = GetParam().second;
+ uint32_t streamIndex = std::stoi(std::get<2>(GetParam()));
+ ;
+ bool signalEOS = !std::get<3>(GetParam()).compare("true");
mTimestampDevTest = true;
char mURL[512], info[512];
std::ifstream eleStream, eleInfo;
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(mCompName, mURL, info, streamIndex);
- if (!strcmp(mURL, gEnv->getRes().c_str())) {
- ALOGV("EMPTY INPUT gEnv->getRes().c_str() %s mURL %s ",
- gEnv->getRes().c_str(), mURL);
+ if (!strcmp(mURL, sResourceDir.c_str())) {
+ ALOGV("EMPTY INPUT sResourceDir.c_str() %s mURL %s ", sResourceDir.c_str(), mURL);
return;
}
@@ -534,10 +513,8 @@
if (!(eleInfo >> bytesCount)) break;
eleInfo >> flags;
eleInfo >> timestamp;
- bool codecConfig =
- ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0;
- if (mTimestampDevTest && !codecConfig)
- mTimestampUslist.push_back(timestamp);
+ bool codecConfig = ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0;
+ if (mTimestampDevTest && !codecConfig) mTimestampUslist.push_back(timestamp);
Info.push_back({bytesCount, flags, timestamp});
}
eleInfo.close();
@@ -549,8 +526,7 @@
bitStreamInfo[0] = 8000;
bitStreamInfo[1] = 1;
} else {
- ASSERT_NO_FATAL_FAILURE(
- getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
}
if (!setupConfigParam(mComponent, bitStreamInfo)) {
std::cout << "[ WARN ] Test Skipped \n";
@@ -560,29 +536,25 @@
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(), signalEOS));
+ ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+ (int)Info.size(), signalEOS));
// If EOS is not sent, sending empty input with EOS flag
size_t infoSize = Info.size();
if (!signalEOS) {
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
- ASSERT_NO_FATAL_FAILURE(
- testInputBuffer(mComponent, mQueueLock, mWorkQueue,
- C2FrameData::FLAG_END_OF_STREAM, false));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
+ ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
+ C2FrameData::FLAG_END_OF_STREAM, false));
infoSize += 1;
}
// blocking call to ensures application to Wait till all the inputs are
// consumed
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
eleStream.close();
if (mFramesReceived != infoSize) {
ALOGE("Input buffer count and Output buffer count mismatch");
- ALOGE("framesReceived : %d inputFrames : %zu", mFramesReceived,
- infoSize);
+ ALOGE("framesReceived : %d inputFrames : %zu", mFramesReceived, infoSize);
ASSERT_TRUE(false);
}
ASSERT_EQ(mEos, true);
@@ -590,8 +562,7 @@
uint64_t expTs;
uint32_t samplesReceived = 0;
// Update SampleRate and ChannelCount
- ASSERT_NO_FATAL_FAILURE(
- getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
int nSampleRate = bitStreamInfo[0];
int nChannels = bitStreamInfo[1];
std::list<uint64_t>::iterator itIn = mTimestampUslist.begin();
@@ -614,23 +585,17 @@
}
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-// DecodeTest with StreamIndex and EOS / No EOS
-INSTANTIATE_TEST_CASE_P(StreamIndexAndEOS, Codec2AudioDecDecodeTest,
- ::testing::Values(std::make_pair(0, false),
- std::make_pair(0, true),
- std::make_pair(1, false),
- std::make_pair(1, true)));
// thumbnail test
-TEST_F(Codec2AudioDecHidlTest, ThumbnailTest) {
+TEST_P(Codec2AudioDecHidlTest, ThumbnailTest) {
description("Test Request for thumbnail");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
char mURL[512], info[512];
std::ifstream eleStream, eleInfo;
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(mCompName, mURL, info);
eleInfo.open(info);
@@ -651,8 +616,7 @@
bitStreamInfo[0] = 8000;
bitStreamInfo[1] = 1;
} else {
- ASSERT_NO_FATAL_FAILURE(
- getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
}
if (!setupConfigParam(mComponent, bitStreamInfo)) {
std::cout << "[ WARN ] Test Skipped \n";
@@ -672,20 +636,19 @@
} while (!(flags & SYNC_FRAME));
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, i + 1));
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+ ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+ i + 1));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
eleStream.close();
EXPECT_GE(mFramesReceived, 1U);
ASSERT_EQ(mEos, true);
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2AudioDecHidlTest, EOSTest) {
+TEST_P(Codec2AudioDecHidlTest, EOSTest) {
description("Test empty input buffer with EOS flag");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
typedef std::unique_lock<std::mutex> ULock;
ASSERT_EQ(mComponent->start(), C2_OK);
std::unique_ptr<C2Work> work;
@@ -723,15 +686,15 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2AudioDecHidlTest, FlushTest) {
+TEST_P(Codec2AudioDecHidlTest, FlushTest) {
description("Tests Flush calls");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
typedef std::unique_lock<std::mutex> ULock;
char mURL[512], info[512];
std::ifstream eleStream, eleInfo;
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(mCompName, mURL, info);
eleInfo.open(info);
@@ -753,8 +716,7 @@
bitStreamInfo[0] = 8000;
bitStreamInfo[1] = 1;
} else {
- ASSERT_NO_FATAL_FAILURE(
- getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
}
if (!setupConfigParam(mComponent, bitStreamInfo)) {
std::cout << "[ WARN ] Test Skipped \n";
@@ -768,29 +730,25 @@
// frame after this so that the below section can be covered for all
// components
uint32_t numFramesFlushed = 128;
- ASSERT_NO_FATAL_FAILURE(decodeNFrames(
- mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
- mLinearPool, eleStream, &Info, 0, numFramesFlushed, false));
+ ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+ numFramesFlushed, false));
// flush
std::list<std::unique_ptr<C2Work>> flushedWork;
- c2_status_t err =
- mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+ c2_status_t err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
ASSERT_EQ(err, C2_OK);
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
- (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+ (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
uint64_t frameIndex;
{
- //Update mFlushedIndices based on the index received from flush()
+ // Update mFlushedIndices based on the index received from flush()
ULock l(mQueueLock);
for (std::unique_ptr<C2Work>& work : flushedWork) {
ASSERT_NE(work, nullptr);
frameIndex = work->input.ordinal.frameIndex.peeku();
std::list<uint64_t>::iterator frameIndexIt =
- std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
- frameIndex);
- if (!mFlushedIndices.empty() &&
- (frameIndexIt != mFlushedIndices.end())) {
+ std::find(mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
+ if (!mFlushedIndices.empty() && (frameIndexIt != mFlushedIndices.end())) {
mFlushedIndices.erase(frameIndexIt);
work->input.buffers.clear();
work->worklets.clear();
@@ -814,29 +772,24 @@
index++;
}
if (keyFrame) {
- ASSERT_NO_FATAL_FAILURE(
- decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mLinearPool, eleStream, &Info, index,
- (int)Info.size() - index));
+ ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mLinearPool, eleStream, &Info, index,
+ (int)Info.size() - index));
}
eleStream.close();
- err =
- mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+ err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
ASSERT_EQ(err, C2_OK);
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
- (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+ (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
{
- //Update mFlushedIndices based on the index received from flush()
+ // Update mFlushedIndices based on the index received from flush()
ULock l(mQueueLock);
for (std::unique_ptr<C2Work>& work : flushedWork) {
ASSERT_NE(work, nullptr);
frameIndex = work->input.ordinal.frameIndex.peeku();
std::list<uint64_t>::iterator frameIndexIt =
- std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
- frameIndex);
- if (!mFlushedIndices.empty() &&
- (frameIndexIt != mFlushedIndices.end())) {
+ std::find(mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
+ if (!mFlushedIndices.empty() && (frameIndexIt != mFlushedIndices.end())) {
mFlushedIndices.erase(frameIndexIt);
work->input.buffers.clear();
work->worklets.clear();
@@ -848,15 +801,15 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) {
+TEST_P(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) {
description("Decode with multiple empty input frames");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
char mURL[512], info[512];
std::ifstream eleStream, eleInfo;
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(mCompName, mURL, info);
eleInfo.open(info);
@@ -871,15 +824,16 @@
// and empty input frames at an interval of 5 frames.
while (1) {
if (!(frameId % 5)) {
- if (!(frameId % 20)) flags = 32;
- else flags = 0;
+ 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;
+ codecConfig = flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
}
Info.push_back({bytesCount, flags, timestamp});
frameId++;
@@ -890,8 +844,7 @@
bitStreamInfo[0] = 8000;
bitStreamInfo[1] = 1;
} else {
- ASSERT_NO_FATAL_FAILURE(
- getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
+ ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
}
if (!setupConfigParam(mComponent, bitStreamInfo)) {
std::cout << "[ WARN ] Test Skipped \n";
@@ -901,40 +854,59 @@
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()));
+ 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));
+ 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());
+ ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived, Info.size());
ASSERT_TRUE(false);
}
ASSERT_EQ(mComponent->stop(), C2_OK);
}
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioDecHidlTest, testing::ValuesIn(kTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
+// DecodeTest with StreamIndex and EOS / No EOS
+INSTANTIATE_TEST_SUITE_P(StreamIndexAndEOS, Codec2AudioDecDecodeTest,
+ testing::ValuesIn(kDecodeTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
} // anonymous namespace
int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::AddGlobalTestEnvironment(gEnv);
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "C2 Test result = " << status;
+ kTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_DECODER);
+ for (auto params : kTestParameters) {
+ kDecodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "false"));
+ kDecodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "true"));
+ kDecodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "1", "false"));
+ kDecodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "1", "true"));
}
- return status;
-}
+
+ // Set the resource directory based on command line args.
+ // Test will fail to set up if the argument is not set.
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+ sResourceDir = argv[i + 1];
+ break;
+ }
+ }
+
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
new file mode 100644
index 0000000..a22f8cf
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the"License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an"AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalMediaC2V1_0TargetAudioDecTest.">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="vts_media_c2_v1_0_audio_dec_test" value="/data/local/tmp/vts_media_c2_v1_0_audio_dec_test" />
+
+ <!-- Files used for audio testing -->
+ <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.aac" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.aac" />
+ <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz.info" />
+ <option name="push-file" key="bbb_aac_stereo_128kbps_48000hz_multi_frame.info" value="/data/local/tmp/media/bbb_aac_stereo_128kbps_48000hz_multi_frame.info" />
+ <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.amrwb" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.amrwb" />
+ <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz.info" />
+ <option name="push-file" key="bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info" value="/data/local/tmp/media/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info" />
+ <option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.flac" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.flac" />
+ <option name="push-file" key="bbb_flac_stereo_680kbps_48000hz.info" value="/data/local/tmp/media/bbb_flac_stereo_680kbps_48000hz.info" />
+ <option name="push-file" key="bbb_g711alaw_1ch_8khz.info" value="/data/local/tmp/media/bbb_g711alaw_1ch_8khz.info" />
+ <option name="push-file" key="bbb_g711alaw_1ch_8khz.raw" value="/data/local/tmp/media/bbb_g711alaw_1ch_8khz.raw" />
+ <option name="push-file" key="bbb_g711mulaw_1ch_8khz.info" value="/data/local/tmp/media/bbb_g711mulaw_1ch_8khz.info" />
+ <option name="push-file" key="bbb_g711mulaw_1ch_8khz.raw" value="/data/local/tmp/media/bbb_g711mulaw_1ch_8khz.raw" />
+ <option name="push-file" key="bbb_gsm_1ch_8khz_13kbps.info" value="/data/local/tmp/media/bbb_gsm_1ch_8khz_13kbps.info" />
+ <option name="push-file" key="bbb_gsm_1ch_8khz_13kbps.raw" value="/data/local/tmp/media/bbb_gsm_1ch_8khz_13kbps.raw" />
+ <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.info" />
+ <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz.mp3" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz.mp3" />
+ <option name="push-file" key="bbb_mp3_stereo_192kbps_48000hz_multi_frame.info" value="/data/local/tmp/media/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info" />
+ <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.info" />
+ <option name="push-file" key="bbb_opus_stereo_128kbps_48000hz.opus" value="/data/local/tmp/media/bbb_opus_stereo_128kbps_48000hz.opus" />
+ <option name="push-file" key="bbb_raw_1ch_8khz_s32le.info" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.info" />
+ <option name="push-file" key="bbb_raw_1ch_8khz_s32le.raw" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s32le.raw" />
+ <option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.info" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.info" />
+ <option name="push-file" key="bbb_vorbis_stereo_128kbps_48000hz.vorbis" value="/data/local/tmp/media/bbb_vorbis_stereo_128kbps_48000hz.vorbis" />
+ <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.amrnb" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.amrnb" />
+ <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz.info" />
+ <option name="push-file" key="sine_amrnb_1ch_12kbps_8000hz_multi_frame.info" value="/data/local/tmp/media/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info" />
+
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="vts_media_c2_v1_0_audio_dec_test" />
+ <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+ </test>
+</configuration>
\ No newline at end of file
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 ab6bfb2..5f3ae41 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
@@ -19,74 +19,60 @@
#include <android-base/logging.h>
#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
#include <stdio.h>
-#include <fstream>
#include <algorithm>
+#include <fstream>
-#include <codec2/hidl/client.h>
#include <C2AllocatorIon.h>
-#include <C2Config.h>
-#include <C2Debug.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <codec2/hidl/client.h>
using android::C2AllocatorIon;
-#include <VtsHalHidlTargetTestBase.h>
-#include "media_c2_audio_hidl_test_common.h"
#include "media_c2_hidl_test_common.h"
-class LinearBuffer : public C2Buffer {
- public:
- explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
- : C2Buffer(
- {block->share(block->offset(), block->size(), ::C2Fence())}) {}
-};
+static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
+ kEncodeTestParameters;
-static ComponentTestEnvironment* gEnv = nullptr;
+// Resource directory
+static std::string sResourceDir = "";
+
+class LinearBuffer : public C2Buffer {
+ public:
+ explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
+ : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
+};
namespace {
-class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
-
- public:
- ::std::string getTestCaseInfo() const override {
- return ::std::string() +
- "Component: " + gEnv->getComponent().c_str() + " | " +
- "Instance: " + gEnv->getInstance().c_str() + " | " +
- "Res: " + gEnv->getRes().c_str();
- }
-
+class Codec2AudioEncHidlTestBase : public ::testing::Test {
+ public:
// google.codec2 Audio test setup
virtual void SetUp() override {
- Super::SetUp();
+ getParams();
mDisableTest = false;
ALOGV("Codec2AudioEncHidlTest SetUp");
mClient = android::Codec2Client::CreateFromService(
- gEnv->getInstance().c_str(),
- !bool(android::Codec2Client::CreateFromService("default", true)));
+ mInstanceName.c_str(),
+ !bool(android::Codec2Client::CreateFromService("default", true)));
ASSERT_NE(mClient, nullptr);
- mListener.reset(new CodecListener(
- [this](std::list<std::unique_ptr<C2Work>>& workItems) {
- handleWorkDone(workItems);
- }));
+ mListener.reset(new CodecListener([this](std::list<std::unique_ptr<C2Work>>& workItems) {
+ handleWorkDone(workItems);
+ }));
ASSERT_NE(mListener, nullptr);
for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
mWorkQueue.emplace_back(new C2Work);
}
- mClient->createComponent(gEnv->getComponent().c_str(), mListener,
- &mComponent);
+ mClient->createComponent(mComponentName, mListener, &mComponent);
ASSERT_NE(mComponent, nullptr);
- std::shared_ptr<C2AllocatorStore> store =
- android::GetCodec2PlatformAllocatorStore();
- CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR,
- &mLinearAllocator),
- C2_OK);
- mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator,
- mBlockPoolId++);
+ std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+ CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator), C2_OK);
+ mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
ASSERT_NE(mLinearPool, nullptr);
mCompName = unknown_comp;
@@ -95,19 +81,13 @@
standardComp CompName;
};
const StringToName kStringToName[] = {
- {"aac", aac},
- {"flac", flac},
- {"opus", opus},
- {"amrnb", amrnb},
- {"amrwb", amrwb},
+ {"aac", aac}, {"flac", flac}, {"opus", opus}, {"amrnb", amrnb}, {"amrwb", amrwb},
};
- const size_t kNumStringToName =
- sizeof(kStringToName) / sizeof(kStringToName[0]);
+ const size_t kNumStringToName = sizeof(kStringToName) / sizeof(kStringToName[0]);
// Find the component type
- std::string comp = std::string(gEnv->getComponent());
for (size_t i = 0; i < kNumStringToName; ++i) {
- if (strcasestr(comp.c_str(), kStringToName[i].Name)) {
+ if (strcasestr(mComponentName.c_str(), kStringToName[i].Name)) {
mCompName = kStringToName[i].CompName;
break;
}
@@ -126,15 +106,17 @@
mComponent->release();
mComponent = nullptr;
}
- Super::TearDown();
}
+
+ // Get the test parameters from GetParam call.
+ virtual void getParams() {}
+
// callback function to process onWorkDone received by Listener
void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
for (std::unique_ptr<C2Work>& work : workItems) {
if (!work->worklets.empty()) {
- workDone(mComponent, work, mFlushedIndices, mQueueLock,
- mQueueCondition, mWorkQueue, mEos, mCsd,
- mFramesReceived);
+ workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue,
+ mEos, mCsd, mFramesReceived);
}
}
}
@@ -147,6 +129,8 @@
unknown_comp,
};
+ std::string mInstanceName;
+ std::string mComponentName;
bool mEos;
bool mCsd;
bool mDisableTest;
@@ -167,7 +151,7 @@
std::shared_ptr<android::Codec2Client::Listener> mListener;
std::shared_ptr<android::Codec2Client::Component> mComponent;
- protected:
+ protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
@@ -176,9 +160,8 @@
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);
+ 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);
@@ -191,12 +174,19 @@
}
mInputMaxBufSize = bitStreamInfo[0];
}
-
};
-void validateComponent(
- const std::shared_ptr<android::Codec2Client::Component>& component,
- Codec2AudioEncHidlTest::standardComp compName, bool& disableTest) {
+class Codec2AudioEncHidlTest
+ : public Codec2AudioEncHidlTestBase,
+ public ::testing::WithParamInterface<std::tuple<std::string, std::string>> {
+ void getParams() {
+ mInstanceName = std::get<0>(GetParam());
+ mComponentName = std::get<1>(GetParam());
+ }
+};
+
+void validateComponent(const std::shared_ptr<android::Codec2Client::Component>& component,
+ Codec2AudioEncHidlTest::standardComp compName, bool& disableTest) {
// Validate its a C2 Component
if (component->getName().find("c2") == std::string::npos) {
ALOGE("Not a c2 component");
@@ -211,14 +201,12 @@
return;
}
std::vector<std::unique_ptr<C2Param>> queried;
- c2_status_t c2err =
- component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
- C2_DONT_BLOCK, &queried);
+ c2_status_t c2err = component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
+ C2_DONT_BLOCK, &queried);
if (c2err != C2_OK && queried.size() == 0) {
ALOGE("Query media type failed => %d", c2err);
} else {
- std::string inputDomain =
- ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
+ std::string inputDomain = ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
if (inputDomain.find("audio/") == std::string::npos) {
ALOGE("Expected Audio Component");
disableTest = true;
@@ -236,16 +224,14 @@
}
// Set Default config param.
-bool setupConfigParam(
- const std::shared_ptr<android::Codec2Client::Component>& component,
- int32_t nChannels, int32_t nSampleRate) {
+bool setupConfigParam(const std::shared_ptr<android::Codec2Client::Component>& component,
+ int32_t nChannels, int32_t nSampleRate) {
std::vector<std::unique_ptr<C2SettingResult>> failures;
C2StreamSampleRateInfo::input sampleRateInfo(0u, nSampleRate);
C2StreamChannelCountInfo::input channelCountInfo(0u, nChannels);
std::vector<C2Param*> configParam{&sampleRateInfo, &channelCountInfo};
- c2_status_t status =
- component->config(configParam, C2_DONT_BLOCK, &failures);
+ c2_status_t status = component->config(configParam, C2_DONT_BLOCK, &failures);
if (status == C2_OK && failures.size() == 0u) return true;
return false;
}
@@ -257,16 +243,11 @@
const char* mURL;
};
static const CompToURL kCompToURL[] = {
- {Codec2AudioEncHidlTest::standardComp::aac,
- "bbb_raw_2ch_48khz_s16le.raw"},
- {Codec2AudioEncHidlTest::standardComp::amrnb,
- "bbb_raw_1ch_8khz_s16le.raw"},
- {Codec2AudioEncHidlTest::standardComp::amrwb,
- "bbb_raw_1ch_16khz_s16le.raw"},
- {Codec2AudioEncHidlTest::standardComp::flac,
- "bbb_raw_2ch_48khz_s16le.raw"},
- {Codec2AudioEncHidlTest::standardComp::opus,
- "bbb_raw_2ch_48khz_s16le.raw"},
+ {Codec2AudioEncHidlTest::standardComp::aac, "bbb_raw_2ch_48khz_s16le.raw"},
+ {Codec2AudioEncHidlTest::standardComp::amrnb, "bbb_raw_1ch_8khz_s16le.raw"},
+ {Codec2AudioEncHidlTest::standardComp::amrwb, "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) {
@@ -278,21 +259,18 @@
}
void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
- std::mutex &queueLock, std::condition_variable& queueCondition,
+ std::mutex& queueLock, std::condition_variable& queueCondition,
std::list<std::unique_ptr<C2Work>>& workQueue,
- std::list<uint64_t>& flushedIndices,
- std::shared_ptr<C2BlockPool>& linearPool,
- std::ifstream& eleStream, uint32_t nFrames,
- int32_t samplesPerFrame, int32_t nChannels,
- int32_t nSampleRate, bool flushed = false,
+ std::list<uint64_t>& flushedIndices, std::shared_ptr<C2BlockPool>& linearPool,
+ std::ifstream& eleStream, uint32_t nFrames, int32_t samplesPerFrame,
+ int32_t nChannels, int32_t nSampleRate, bool flushed = false,
bool signalEOS = true) {
typedef std::unique_lock<std::mutex> ULock;
uint32_t frameID = 0;
uint32_t maxRetry = 0;
int bytesCount = samplesPerFrame * nChannels * 2;
- int32_t timestampIncr =
- (int)(((float)samplesPerFrame / nSampleRate) * 1000000);
+ int32_t timestampIncr = (int)(((float)samplesPerFrame / nSampleRate) * 1000000);
uint64_t timestamp = 0;
while (1) {
if (nFrames == 0) break;
@@ -312,8 +290,7 @@
if (!work && (maxRetry >= MAX_RETRY)) {
ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
}
- if (signalEOS && (nFrames == 1))
- flags |= C2FrameData::FLAG_END_OF_STREAM;
+ if (signalEOS && (nFrames == 1)) flags |= C2FrameData::FLAG_END_OF_STREAM;
if (flushed) {
flags |= SYNC_FRAME;
flushed = false;
@@ -330,10 +307,9 @@
eleStream.read(data, bytesCount);
ASSERT_EQ(eleStream.gcount(), bytesCount);
std::shared_ptr<C2LinearBlock> block;
- ASSERT_EQ(C2_OK, linearPool->fetchLinearBlock(
- bytesCount, {C2MemoryUsage::CPU_READ,
- C2MemoryUsage::CPU_WRITE},
- &block));
+ ASSERT_EQ(C2_OK,
+ linearPool->fetchLinearBlock(
+ bytesCount, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
ASSERT_TRUE(block);
// Write View
C2WriteView view = block->map().get();
@@ -365,27 +341,33 @@
}
}
-TEST_F(Codec2AudioEncHidlTest, validateCompName) {
- if (mDisableTest) return;
+TEST_P(Codec2AudioEncHidlTest, validateCompName) {
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
ALOGV("Checks if the given component is a valid audio component");
validateComponent(mComponent, mCompName, mDisableTest);
ASSERT_EQ(mDisableTest, false);
}
class Codec2AudioEncEncodeTest
- : public Codec2AudioEncHidlTest,
- public ::testing::WithParamInterface<std::pair<bool, int32_t>> {
+ : public Codec2AudioEncHidlTestBase,
+ public ::testing::WithParamInterface<
+ std::tuple<std::string, std::string, std::string, std::string>> {
+ void getParams() {
+ mInstanceName = std::get<0>(GetParam());
+ mComponentName = std::get<1>(GetParam());
+ }
};
TEST_P(Codec2AudioEncEncodeTest, EncodeTest) {
ALOGV("EncodeTest");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
char mURL[512];
- strcpy(mURL, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
GetURLForComponent(mCompName, mURL);
- bool signalEOS = GetParam().first;
+ bool signalEOS = !std::get<2>(GetParam()).compare("true");
// Ratio w.r.t to mInputMaxBufSize
- int32_t inputMaxBufRatio = GetParam().second;
+ int32_t inputMaxBufRatio = std::stoi(std::get<3>(GetParam()));
+ ;
// Setting default sampleRate
int32_t nChannels = 2;
@@ -414,10 +396,9 @@
default:
ASSERT_TRUE(false);
}
- int32_t samplesPerFrame =
- ((mInputMaxBufSize / inputMaxBufRatio) / (nChannels * 2));
- ALOGV("signalEOS %d mInputMaxBufSize %d samplesPerFrame %d", signalEOS,
- mInputMaxBufSize, samplesPerFrame);
+ int32_t samplesPerFrame = ((mInputMaxBufSize / inputMaxBufRatio) / (nChannels * 2));
+ ALOGV("signalEOS %d mInputMaxBufSize %d samplesPerFrame %d", signalEOS, mInputMaxBufSize,
+ samplesPerFrame);
if (!setupConfigParam(mComponent, nChannels, nSampleRate)) {
std::cout << "[ WARN ] Test Skipped \n";
@@ -429,26 +410,21 @@
eleStream.open(mURL, std::ifstream::binary);
ASSERT_EQ(eleStream.is_open(), true);
ALOGV("mURL : %s", mURL);
- ASSERT_NO_FATAL_FAILURE(
- encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mLinearPool, eleStream, numFrames,
- samplesPerFrame, nChannels, nSampleRate, false,
- signalEOS));
+ ASSERT_NO_FATAL_FAILURE(encodeNFrames(
+ mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices, mLinearPool,
+ eleStream, numFrames, samplesPerFrame, nChannels, nSampleRate, false, signalEOS));
// If EOS is not sent, sending empty input with EOS flag
if (!signalEOS) {
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
- ASSERT_NO_FATAL_FAILURE(
- testInputBuffer(mComponent, mQueueLock, mWorkQueue,
- C2FrameData::FLAG_END_OF_STREAM, false));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
+ ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
+ C2FrameData::FLAG_END_OF_STREAM, false));
numFrames += 1;
}
// blocking call to ensures application to Wait till all the inputs are
// consumed
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
eleStream.close();
if (mFramesReceived != numFrames) {
ALOGE("Input buffer count and Output buffer count mismatch");
@@ -465,18 +441,9 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-// EncodeTest with EOS / No EOS and inputMaxBufRatio
-// inputMaxBufRatio is ratio w.r.t. to mInputMaxBufSize
-INSTANTIATE_TEST_CASE_P(EncodeTest, Codec2AudioEncEncodeTest,
- ::testing::Values(std::make_pair(false, 1),
- std::make_pair(false, 2),
- std::make_pair(true, 1),
- std::make_pair(true, 2)));
-
-
-TEST_F(Codec2AudioEncHidlTest, EOSTest) {
+TEST_P(Codec2AudioEncHidlTest, EOSTest) {
description("Test empty input buffer with EOS flag");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
ASSERT_EQ(mComponent->start(), C2_OK);
typedef std::unique_lock<std::mutex> ULock;
@@ -514,13 +481,13 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2AudioEncHidlTest, FlushTest) {
+TEST_P(Codec2AudioEncHidlTest, FlushTest) {
description("Test Request for flush");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
typedef std::unique_lock<std::mutex> ULock;
char mURL[512];
- strcpy(mURL, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
GetURLForComponent(mCompName, mURL);
// Setting default configuration
@@ -570,29 +537,24 @@
eleStream.open(mURL, std::ifstream::binary);
ASSERT_EQ(eleStream.is_open(), true);
ALOGV("mURL : %s", mURL);
- ASSERT_NO_FATAL_FAILURE(
- encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mLinearPool, eleStream, numFramesFlushed,
- samplesPerFrame, nChannels, nSampleRate));
+ ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mLinearPool, eleStream, numFramesFlushed,
+ samplesPerFrame, nChannels, nSampleRate));
std::list<std::unique_ptr<C2Work>> flushedWork;
- c2_status_t err =
- mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+ c2_status_t err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
ASSERT_EQ(err, C2_OK);
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
- (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+ (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
uint64_t frameIndex;
{
- //Update mFlushedIndices based on the index received from flush()
+ // Update mFlushedIndices based on the index received from flush()
ULock l(mQueueLock);
for (std::unique_ptr<C2Work>& work : flushedWork) {
ASSERT_NE(work, nullptr);
frameIndex = work->input.ordinal.frameIndex.peeku();
std::list<uint64_t>::iterator frameIndexIt =
- std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
- frameIndex);
- if (!mFlushedIndices.empty() &&
- (frameIndexIt != mFlushedIndices.end())) {
+ std::find(mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
+ if (!mFlushedIndices.empty() && (frameIndexIt != mFlushedIndices.end())) {
mFlushedIndices.erase(frameIndexIt);
work->input.buffers.clear();
work->worklets.clear();
@@ -601,29 +563,24 @@
}
}
mFlushedIndices.clear();
- ASSERT_NO_FATAL_FAILURE(
- encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mLinearPool, eleStream,
- numFrames - numFramesFlushed, samplesPerFrame,
- nChannels, nSampleRate, true));
+ ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mLinearPool, eleStream,
+ numFrames - numFramesFlushed, samplesPerFrame, nChannels,
+ nSampleRate, true));
eleStream.close();
- err =
- mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+ err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
ASSERT_EQ(err, C2_OK);
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
- (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+ (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
{
- //Update mFlushedIndices based on the index received from flush()
+ // Update mFlushedIndices based on the index received from flush()
ULock l(mQueueLock);
for (std::unique_ptr<C2Work>& work : flushedWork) {
ASSERT_NE(work, nullptr);
frameIndex = work->input.ordinal.frameIndex.peeku();
std::list<uint64_t>::iterator frameIndexIt =
- std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
- frameIndex);
- if (!mFlushedIndices.empty() &&
- (frameIndexIt != mFlushedIndices.end())) {
+ std::find(mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
+ if (!mFlushedIndices.empty() && (frameIndexIt != mFlushedIndices.end())) {
mFlushedIndices.erase(frameIndexIt);
work->input.buffers.clear();
work->worklets.clear();
@@ -635,17 +592,39 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioEncHidlTest, testing::ValuesIn(kTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
+// EncodeTest with EOS / No EOS and inputMaxBufRatio
+// inputMaxBufRatio is ratio w.r.t. to mInputMaxBufSize
+INSTANTIATE_TEST_SUITE_P(EncodeTest, Codec2AudioEncEncodeTest,
+ testing::ValuesIn(kEncodeTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
} // anonymous namespace
int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::AddGlobalTestEnvironment(gEnv);
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "C2 Test result = " << status;
+ kTestParameters = getTestParameters(C2Component::DOMAIN_AUDIO, C2Component::KIND_ENCODER);
+ for (auto params : kTestParameters) {
+ kEncodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "false", "1"));
+ kEncodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "false", "2"));
+ kEncodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "true", "1"));
+ kEncodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "true", "2"));
}
- return status;
+
+ // Set the resource directory based on command line args.
+ // Test will fail to set up if the argument is not set.
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+ sResourceDir = argv[i + 1];
+ break;
+ }
+ }
+
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
}
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.xml b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.xml
new file mode 100644
index 0000000..2e37111
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the"License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an"AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalMediaC2V1_0TargetAudioEncTest.">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="vts_media_c2_v1_0_audio_enc_test" value="/data/local/tmp/vts_media_c2_v1_0_audio_enc_test" />
+
+ <!-- Files used for audio testing -->
+ <option name="push-file" key="bbb_raw_2ch_48khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_2ch_48khz_s16le.raw" />
+ <option name="push-file" key="bbb_raw_1ch_8khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_1ch_8khz_s16le.raw" />
+ <option name="push-file" key="bbb_raw_1ch_16khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_1ch_16khz_s16le.raw" />
+ <option name="push-file" key="bbb_raw_2ch_48khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_2ch_48khz_s16le.raw" />
+ <option name="push-file" key="bbb_raw_2ch_48khz_s16le.raw" value="/data/local/tmp/media/bbb_raw_2ch_48khz_s16le.raw" />
+
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="vts_media_c2_v1_0_audio_enc_test" />
+ <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/media_c2_audio_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/audio/media_c2_audio_hidl_test_common.h
deleted file mode 100644
index 4d773ce..0000000
--- a/media/codec2/hidl/1.0/vts/functional/audio/media_c2_audio_hidl_test_common.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
-#define MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
-
-
-#endif // MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
diff --git a/media/codec2/hidl/1.0/vts/functional/common/Android.bp b/media/codec2/hidl/1.0/vts/functional/common/Android.bp
index 3b4e232..f9ec5ae 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/common/Android.bp
@@ -1,7 +1,7 @@
cc_library_static {
name: "VtsHalMediaC2V1_0CommonUtil",
defaults: [
- "Vts10HalTargetTestDefaults",
+ "VtsHalTargetTestDefaults",
"libcodec2-hidl-client-defaults",
],
@@ -19,15 +19,19 @@
cc_defaults {
name: "VtsHalMediaC2V1_0Defaults",
defaults: [
- "Vts10HalTargetTestDefaults",
+ "VtsHalTargetTestDefaults",
"libcodec2-hidl-client-defaults",
],
static_libs: [
+ "libgtest",
"VtsHalMediaC2V1_0CommonUtil",
],
shared_libs: [
"libcodec2_client",
],
+ test_suites: [
+ "vts",
+ ],
}
diff --git a/media/codec2/hidl/1.0/vts/functional/common/README.md b/media/codec2/hidl/1.0/vts/functional/common/README.md
index f2f579c..ac510c5 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/README.md
+++ b/media/codec2/hidl/1.0/vts/functional/common/README.md
@@ -3,34 +3,22 @@
## master :
Functionality of master is to enumerate all the Codec2 components available in C2 media service.
-usage: `VtsHalMediaC2V1_0TargetMasterTest -I default`
+usage: `atest VtsHalMediaC2V1_0TargetMasterTest`
## component :
Functionality of component test is to validate common functionality across all the Codec2 components available in C2 media service. For a standard C2 component, these tests are expected to pass.
-usage: `VtsHalMediaC2V1_0TargetComponentTest -I software -C <comp name>`
-
-example: `VtsHalMediaC2V1_0TargetComponentTest -I software -C c2.android.vorbis.decoder`
+usage: `atest VtsHalMediaC2V1_0TargetComponentTest`
## audio :
Functionality of audio test is to validate audio specific functionality of Codec2 components. The resource files for this test are taken from `frameworks/av/media/codec2/hidl/1.0/vts/functional/res`. The path to these files on the device can be specified with `-P`. (If the device path is omitted, `/data/local/tmp/media/` is the default value.)
-usage: `VtsHalMediaC2V1_0TargetAudioDecTest -I default -C <comp name> -P <path to resource files>`
+usage: `atest VtsHalMediaC2V1_0TargetAudioDecTest`
-usage: `VtsHalMediaC2V1_0TargetAudioEncTest -I software -C <comp name> -P <path to resource files>`
-
-example: `VtsHalMediaC2V1_0TargetAudioDecTest -I software -C c2.android.flac.decoder -P /data/local/tmp/media/`
-
-example: `VtsHalMediaC2V1_0TargetAudioEncTest -I software -C c2.android.opus.encoder -P /data/local/tmp/media/`
+usage: `atest VtsHalMediaC2V1_0TargetAudioEncTest`
## video :
Functionality of video test is to validate video specific functionality of Codec2 components. The resource files for this test are taken from `frameworks/av/media/codec2/hidl/1.0/vts/functional/res`. The path to these files on the device can be specified with `-P`. (If the device path is omitted, `/data/local/tmp/media/` is the default value.)
-usage: `VtsHalMediaC2V1_0TargetVideoDecTest -I default -C <comp name> -P <path to resource files>`
-
-usage: `VtsHalMediaC2V1_0TargetVideoEncTest -I software -C <comp name> -P <path to resource files>`
-
-example: `VtsHalMediaC2V1_0TargetVideoDecTest -I software -C c2.android.avc.decoder -P /data/local/tmp/media/`
-
-example: `VtsHalMediaC2V1_0TargetVideoEncTest -I software -C c2.android.vp9.encoder -P /data/local/tmp/media/`
-
+usage: `atest VtsHalMediaC2V1_0TargetVideoDecTest`
+usage: `atest VtsHalMediaC2V1_0TargetVideoEncTest`
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
index 2f02913..5d4b001 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
@@ -22,16 +22,10 @@
#include <android/hardware/media/c2/1.0/IComponentStore.h>
-void ComponentTestEnvironment::registerTestServices() {
- registerTestService<::android::hardware::media::c2::V1_0::
- IComponentStore>();
-}
-
// 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) {
+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;
@@ -61,10 +55,8 @@
}
// 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) {
+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;
@@ -85,29 +77,25 @@
}
// 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) {
+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::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() == C2StreamInitDataInfo::output::PARAM_TYPE) {
csd = true;
- } else if ((param->index() ==
- C2StreamSampleRateInfo::output::PARAM_TYPE) ||
- (param->index() ==
- C2StreamChannelCountInfo::output::PARAM_TYPE) ||
- (param->index() ==
- C2StreamPictureSizeInfo::output::PARAM_TYPE)) {
+ } else if ((param->index() == C2StreamSampleRateInfo::output::PARAM_TYPE) ||
+ (param->index() == C2StreamChannelCountInfo::output::PARAM_TYPE) ||
+ (param->index() == C2StreamPictureSizeInfo::output::PARAM_TYPE)) {
configParam.push_back(param);
}
}
@@ -116,8 +104,7 @@
}
if (work->worklets.front()->output.flags != C2FrameData::FLAG_INCOMPLETE) {
framesReceived++;
- eos = (work->worklets.front()->output.flags &
- C2FrameData::FLAG_END_OF_STREAM) != 0;
+ 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",
@@ -143,3 +130,33 @@
return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
}
+
+// Return all test parameters, a list of tuple of <instance, component>
+const std::vector<std::tuple<std::string, std::string>>& getTestParameters() {
+ return getTestParameters(C2Component::DOMAIN_OTHER, C2Component::KIND_OTHER);
+}
+
+// Return all test parameters, a list of tuple of <instance, component> with matching domain and
+// kind.
+const std::vector<std::tuple<std::string, std::string>>& getTestParameters(
+ C2Component::domain_t domain, C2Component::kind_t kind) {
+ static std::vector<std::tuple<std::string, std::string>> parameters;
+
+ auto instances = android::Codec2Client::GetServiceNames();
+ for (std::string instance : instances) {
+ std::shared_ptr<android::Codec2Client> client =
+ android::Codec2Client::CreateFromService(instance.c_str());
+ std::vector<C2Component::Traits> components = client->listComponents();
+ for (C2Component::Traits traits : components) {
+ if (instance.compare(traits.owner)) continue;
+ if (domain != C2Component::DOMAIN_OTHER &&
+ (traits.domain != domain || traits.kind != kind)) {
+ continue;
+ }
+
+ parameters.push_back(std::make_tuple(instance, traits.name));
+ }
+ }
+
+ return parameters;
+}
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index 23e332a..4b5e0a6 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -22,31 +22,34 @@
#include <codec2/hidl/client.h>
#include <getopt.h>
+#include <gtest/gtest.h>
#include <hidl/HidlSupport.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include <chrono>
#define MAX_RETRY 20
#define TIME_OUT 400ms
#define MAX_INPUT_BUFFERS 8
-using ::android::hardware::Void;
-using ::android::hardware::Return;
-using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using namespace ::std::chrono;
+
+static std::vector<std::tuple<std::string, std::string>> kTestParameters;
/*
* Handle Callback functions onWorkDone(), onTripped(),
* onError(), onDeath(), onFramesRendered()
*/
struct CodecListener : public android::Codec2Client::Listener {
- public:
+ public:
CodecListener(
- const std::function<void(std::list<std::unique_ptr<C2Work>>& workItems)> fn =
- nullptr)
+ const std::function<void(std::list<std::unique_ptr<C2Work>>& workItems)> fn = nullptr)
: callBack(fn) {}
- virtual void onWorkDone(
- const std::weak_ptr<android::Codec2Client::Component>& comp,
- std::list<std::unique_ptr<C2Work>>& workItems) override {
+ virtual void onWorkDone(const std::weak_ptr<android::Codec2Client::Component>& comp,
+ std::list<std::unique_ptr<C2Work>>& workItems) override {
/* TODO */
ALOGD("onWorkDone called");
(void)comp;
@@ -54,40 +57,34 @@
}
virtual void onTripped(
- const std::weak_ptr<android::Codec2Client::Component>& comp,
- const std::vector<std::shared_ptr<C2SettingResult>>& settingResults)
- override {
+ const std::weak_ptr<android::Codec2Client::Component>& comp,
+ const std::vector<std::shared_ptr<C2SettingResult>>& settingResults) override {
/* TODO */
(void)comp;
(void)settingResults;
}
- virtual void onError(
- const std::weak_ptr<android::Codec2Client::Component>& comp,
- uint32_t errorCode) override {
+ virtual void onError(const std::weak_ptr<android::Codec2Client::Component>& comp,
+ uint32_t errorCode) override {
/* TODO */
(void)comp;
ALOGD("onError called");
if (errorCode != 0) ALOGE("Error : %u", errorCode);
}
- virtual void onDeath(
- const std::weak_ptr<android::Codec2Client::Component>& comp) override {
+ virtual void onDeath(const std::weak_ptr<android::Codec2Client::Component>& comp) override {
/* TODO */
(void)comp;
}
- virtual void onInputBufferDone(
- uint64_t frameIndex, size_t arrayIndex) override {
+ virtual void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex) override {
/* TODO */
(void)frameIndex;
(void)arrayIndex;
}
- virtual void onFrameRendered(
- uint64_t bufferQueueId,
- int32_t slotId,
- int64_t timestampNs) override {
+ virtual void onFrameRendered(uint64_t bufferQueueId, int32_t slotId,
+ int64_t timestampNs) override {
/* TODO */
(void)bufferQueueId;
(void)slotId;
@@ -99,96 +96,30 @@
std::function<void(std::list<std::unique_ptr<C2Work>>& workItems)> callBack;
};
-// A class for test environment setup
-class ComponentTestEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestEnvBase Super;
+// Return all test parameters, a list of tuple of <instance, component>.
+const std::vector<std::tuple<std::string, std::string>>& getTestParameters();
- public:
- virtual void registerTestServices() override;
-
- ComponentTestEnvironment() : res("/data/local/tmp/media/") {}
-
- void setComponent(const char* _component) { component = _component; }
-
- void setInstance(const char* _instance) { instance = _instance; }
-
- void setRes(const char* _res) { res = _res; }
-
- const hidl_string getInstance() const { return instance; }
-
- const hidl_string getComponent() const { return component; }
-
- const hidl_string getRes() const { return res; }
-
- int initFromOptions(int argc, char** argv) {
- static struct option options[] = {
- {"instance", required_argument, 0, 'I'},
- {"component", required_argument, 0, 'C'},
- {"res", required_argument, 0, 'P'},
- {0, 0, 0, 0}};
-
- while (true) {
- int index = 0;
- int c = getopt_long(argc, argv, "I:C:P:", options, &index);
- if (c == -1) {
- break;
- }
-
- switch (c) {
- case 'I':
- setInstance(optarg);
- break;
- case 'C':
- setComponent(optarg);
- break;
- case 'P':
- setRes(optarg);
- break;
- case '?':
- break;
- }
- }
-
- if (optind < argc) {
- fprintf(stderr,
- "unrecognized option: %s\n\n"
- "usage: %s <gtest options> <test options>\n\n"
- "test options are:\n\n"
- "-I, --instance: software for C2 components, else default\n"
- "-C, --component: C2 component to test\n"
- "-P, --res: Resource files directory location\n",
- argv[optind ?: 1], argv[0]);
- return 2;
- }
- return 0;
- }
-
- private:
- hidl_string instance;
- hidl_string component;
- hidl_string res;
-};
+// Return all test parameters, a list of tuple of <instance, component> with matching domain and
+// kind.
+const std::vector<std::tuple<std::string, std::string>>& getTestParameters(
+ C2Component::domain_t domain, C2Component::kind_t kind);
/*
* common functions declarations
*/
-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 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,
+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);
+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);
int64_t getNowUs();
diff --git a/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
index 9dc541c..119ce14 100644
--- a/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
@@ -19,11 +19,11 @@
#include <android-base/logging.h>
#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
#include <C2Config.h>
#include <codec2/hidl/client.h>
-#include <VtsHalHidlTargetTestBase.h>
#include "media_c2_hidl_test_common.h"
/* Time_Out for start(), stop(), reset(), release(), flush(), queue() are
@@ -31,50 +31,45 @@
* extra in case of timeout is 500ms, 1ms extra in case timeout is 1ms/5ms. All
* timeout is calculated in us.
*/
-#define START_TIME_OUT 550000
-#define STOP_TIME_OUT 550000
-#define RESET_TIME_OUT 550000
-#define RELEASE_TIME_OUT 550000
-#define FLUSH_TIME_OUT 6000
-#define QUEUE_TIME_OUT 2000
+#define START_TIME_OUT 550000
+#define STOP_TIME_OUT 550000
+#define RESET_TIME_OUT 550000
+#define RELEASE_TIME_OUT 550000
+#define FLUSH_TIME_OUT 6000
+#define QUEUE_TIME_OUT 2000
// Time_Out for config(), query(), querySupportedParams() are defined in
// hardware/interfaces/media/c2/1.0/IConfigurable.hal.
-#define CONFIG_TIME_OUT 6000
-#define QUERY_TIME_OUT 6000
-#define QUERYSUPPORTEDPARAMS_TIME_OUT 2000
+#define CONFIG_TIME_OUT 6000
+#define QUERY_TIME_OUT 6000
+#define QUERYSUPPORTEDPARAMS_TIME_OUT 2000
-#define CHECK_TIMEOUT(timeConsumed, TIME_OUT, FuncName) \
- if (timeConsumed > TIME_OUT) { \
- ALOGW( \
- "TIMED_OUT %s timeConsumed=%" PRId64 " us is " \
- "greater than threshold %d us", \
- FuncName, timeConsumed, TIME_OUT); \
+#define CHECK_TIMEOUT(timeConsumed, TIME_OUT, FuncName) \
+ if (timeConsumed > TIME_OUT) { \
+ ALOGW("TIMED_OUT %s timeConsumed=%" PRId64 \
+ " us is " \
+ "greater than threshold %d us", \
+ FuncName, timeConsumed, TIME_OUT); \
}
-static ComponentTestEnvironment* gEnv = nullptr;
-
namespace {
-// google.codec2 Component test setup
-class Codec2ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
+static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
+ kInputTestParameters;
- public:
+// google.codec2 Component test setup
+class Codec2ComponentHidlTestBase : public ::testing::Test {
+ public:
virtual void SetUp() override {
- Super::SetUp();
+ getParams();
mEos = false;
- mClient = android::Codec2Client::CreateFromService(
- gEnv->getInstance().c_str());
+ mClient = android::Codec2Client::CreateFromService(mInstanceName.c_str());
ASSERT_NE(mClient, nullptr);
- mListener.reset(new CodecListener(
- [this](std::list<std::unique_ptr<C2Work>>& workItems) {
- handleWorkDone(workItems);
- }));
+ mListener.reset(new CodecListener([this](std::list<std::unique_ptr<C2Work>>& workItems) {
+ handleWorkDone(workItems);
+ }));
ASSERT_NE(mListener, nullptr);
- mClient->createComponent(gEnv->getComponent().c_str(), mListener,
- &mComponent);
+ mClient->createComponent(mComponentName.c_str(), mListener, &mComponent);
ASSERT_NE(mComponent, nullptr);
for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
mWorkQueue.emplace_back(new C2Work);
@@ -90,8 +85,11 @@
mComponent->release();
mComponent = nullptr;
}
- Super::TearDown();
}
+
+ // Get the test parameters from GetParam call.
+ virtual void getParams() {}
+
// callback function to process onWorkDone received by Listener
void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
for (std::unique_ptr<C2Work>& work : workItems) {
@@ -99,12 +97,14 @@
bool mCsd = false;
uint32_t mFramesReceived = 0;
std::list<uint64_t> mFlushedIndices;
- workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition,
- mWorkQueue, mEos, mCsd, mFramesReceived);
+ workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue,
+ mEos, mCsd, mFramesReceived);
}
}
}
+ std::string mInstanceName;
+ std::string mComponentName;
bool mEos;
std::mutex mQueueLock;
std::condition_variable mQueueCondition;
@@ -114,14 +114,23 @@
std::shared_ptr<android::Codec2Client::Listener> mListener;
std::shared_ptr<android::Codec2Client::Component> mComponent;
- protected:
+ protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
};
+class Codec2ComponentHidlTest
+ : public Codec2ComponentHidlTestBase,
+ public ::testing::WithParamInterface<std::tuple<std::string, std::string>> {
+ void getParams() {
+ mInstanceName = std::get<0>(GetParam());
+ mComponentName = std::get<1>(GetParam());
+ }
+};
+
// Test Empty Flush
-TEST_F(Codec2ComponentHidlTest, EmptyFlush) {
+TEST_P(Codec2ComponentHidlTest, EmptyFlush) {
ALOGV("Empty Flush Test");
c2_status_t err = mComponent->start();
ASSERT_EQ(err, C2_OK);
@@ -137,7 +146,7 @@
}
// Test Queue Empty Work
-TEST_F(Codec2ComponentHidlTest, QueueEmptyWork) {
+TEST_P(Codec2ComponentHidlTest, QueueEmptyWork) {
ALOGV("Queue Empty Work Test");
c2_status_t err = mComponent->start();
ASSERT_EQ(err, C2_OK);
@@ -151,7 +160,7 @@
}
// Test Component Configuration
-TEST_F(Codec2ComponentHidlTest, Config) {
+TEST_P(Codec2ComponentHidlTest, Config) {
ALOGV("Configuration Test");
C2String name = mComponent->getName();
@@ -180,7 +189,7 @@
}
// Test Multiple Start Stop Reset Test
-TEST_F(Codec2ComponentHidlTest, MultipleStartStopReset) {
+TEST_P(Codec2ComponentHidlTest, MultipleStartStopReset) {
ALOGV("Multiple Start Stop and Reset Test");
for (size_t i = 0; i < MAX_RETRY; i++) {
@@ -202,21 +211,21 @@
}
// Test Component Release API
-TEST_F(Codec2ComponentHidlTest, MultipleRelease) {
+TEST_P(Codec2ComponentHidlTest, MultipleRelease) {
ALOGV("Multiple Release Test");
c2_status_t err = mComponent->start();
ASSERT_EQ(err, C2_OK);
// Query Component Domain Type
std::vector<std::unique_ptr<C2Param>> queried;
- err = mComponent->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
- C2_DONT_BLOCK, &queried);
+ err = mComponent->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE}, C2_DONT_BLOCK,
+ &queried);
EXPECT_NE(queried.size(), 0u);
// Configure Component Domain
std::vector<std::unique_ptr<C2SettingResult>> failures;
C2PortMediaTypeSetting::input* portMediaType =
- C2PortMediaTypeSetting::input::From(queried[0].get());
+ C2PortMediaTypeSetting::input::From(queried[0].get());
err = mComponent->config({portMediaType}, C2_DONT_BLOCK, &failures);
ASSERT_EQ(err, C2_OK);
ASSERT_EQ(failures.size(), 0u);
@@ -226,40 +235,8 @@
}
}
-class Codec2ComponentInputTests : public Codec2ComponentHidlTest,
- public ::testing::WithParamInterface<std::pair<uint32_t, bool> > {
-};
-
-TEST_P(Codec2ComponentInputTests, InputBufferTest) {
- description("Tests for different inputs");
-
- uint32_t flags = GetParam().first;
- bool isNullBuffer = GetParam().second;
- if (isNullBuffer) ALOGD("Testing for null input buffer with flag : %u", flags);
- else ALOGD("Testing for empty input buffer with flag : %u", flags);
- mEos = false;
- ASSERT_EQ(mComponent->start(), C2_OK);
- ASSERT_NO_FATAL_FAILURE(testInputBuffer(
- mComponent, mQueueLock, mWorkQueue, flags, isNullBuffer));
-
- ALOGD("Waiting for input consumption");
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
-
- if (flags == C2FrameData::FLAG_END_OF_STREAM) ASSERT_EQ(mEos, true);
- ASSERT_EQ(mComponent->stop(), C2_OK);
- ASSERT_EQ(mComponent->reset(), C2_OK);
-}
-
-INSTANTIATE_TEST_CASE_P(NonStdInputs, Codec2ComponentInputTests, ::testing::Values(
- std::make_pair(0, true),
- std::make_pair(C2FrameData::FLAG_END_OF_STREAM, true),
- std::make_pair(0, false),
- std::make_pair(C2FrameData::FLAG_CODEC_CONFIG, false),
- std::make_pair(C2FrameData::FLAG_END_OF_STREAM, false)));
-
// Test API's Timeout
-TEST_F(Codec2ComponentHidlTest, Timeout) {
+TEST_P(Codec2ComponentHidlTest, Timeout) {
ALOGV("Timeout Test");
c2_status_t err = C2_OK;
@@ -285,10 +262,8 @@
startTime = getNowUs();
err = mComponent->querySupportedParams(¶ms);
timeConsumed = getNowUs() - startTime;
- CHECK_TIMEOUT(timeConsumed, QUERYSUPPORTEDPARAMS_TIME_OUT,
- "querySupportedParams()");
- ALOGV("mComponent->querySupportedParams() timeConsumed=%" PRId64 " us",
- timeConsumed);
+ CHECK_TIMEOUT(timeConsumed, QUERYSUPPORTEDPARAMS_TIME_OUT, "querySupportedParams()");
+ ALOGV("mComponent->querySupportedParams() timeConsumed=%" PRId64 " us", timeConsumed);
ASSERT_EQ(err, C2_OK);
std::vector<std::unique_ptr<C2Param>> queried;
@@ -301,8 +276,8 @@
CHECK_TIMEOUT(timeConsumed, QUERY_TIME_OUT, "query()");
EXPECT_NE(queried.size(), 0u);
EXPECT_EQ(err, C2_OK);
- ALOGV("mComponent->query() for %s timeConsumed=%" PRId64 " us",
- p->name().c_str(), timeConsumed);
+ ALOGV("mComponent->query() for %s timeConsumed=%" PRId64 " us", p->name().c_str(),
+ timeConsumed);
startTime = getNowUs();
err = mComponent->config({queried[0].get()}, C2_DONT_BLOCK, &failures);
@@ -310,8 +285,8 @@
CHECK_TIMEOUT(timeConsumed, CONFIG_TIME_OUT, "config()");
ASSERT_EQ(err, C2_OK);
ASSERT_EQ(failures.size(), 0u);
- ALOGV("mComponent->config() for %s timeConsumed=%" PRId64 " us",
- p->name().c_str(), timeConsumed);
+ ALOGV("mComponent->config() for %s timeConsumed=%" PRId64 " us", p->name().c_str(),
+ timeConsumed);
}
std::list<std::unique_ptr<C2Work>> workList;
@@ -340,22 +315,68 @@
ALOGV("mComponent->release() timeConsumed=%" PRId64 " us", timeConsumed);
CHECK_TIMEOUT(timeConsumed, RELEASE_TIME_OUT, "release()");
ASSERT_EQ(err, C2_OK);
-
}
+class Codec2ComponentInputTests
+ : public Codec2ComponentHidlTestBase,
+ public ::testing::WithParamInterface<
+ std::tuple<std::string, std::string, std::string, std::string>> {
+ void getParams() {
+ mInstanceName = std::get<0>(GetParam());
+ mComponentName = std::get<1>(GetParam());
+ }
+};
+
+TEST_P(Codec2ComponentInputTests, InputBufferTest) {
+ description("Tests for different inputs");
+
+ uint32_t flags = std::stol(std::get<2>(GetParam()));
+ bool isNullBuffer = !std::get<3>(GetParam()).compare("true");
+ if (isNullBuffer)
+ ALOGD("Testing for null input buffer with flag : %u", flags);
+ else
+ ALOGD("Testing for empty input buffer with flag : %u", flags);
+ mEos = false;
+ ASSERT_EQ(mComponent->start(), C2_OK);
+ ASSERT_NO_FATAL_FAILURE(
+ testInputBuffer(mComponent, mQueueLock, mWorkQueue, flags, isNullBuffer));
+
+ ALOGD("Waiting for input consumption");
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+
+ if (flags == C2FrameData::FLAG_END_OF_STREAM) ASSERT_EQ(mEos, true);
+ ASSERT_EQ(mComponent->stop(), C2_OK);
+ ASSERT_EQ(mComponent->reset(), C2_OK);
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2ComponentHidlTest, testing::ValuesIn(kTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
+INSTANTIATE_TEST_CASE_P(NonStdInputs, Codec2ComponentInputTests,
+ testing::ValuesIn(kInputTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
} // anonymous namespace
// TODO: Add test for Invalid work,
// TODO: Add test for Invalid states
int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::AddGlobalTestEnvironment(gEnv);
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- status = RUN_ALL_TESTS();
- LOG(INFO) << "C2 Test result = " << status;
+ kTestParameters = getTestParameters();
+ for (auto params : kTestParameters) {
+ kInputTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "true"));
+ kInputTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params),
+ std::to_string(C2FrameData::FLAG_END_OF_STREAM), "true"));
+ kInputTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "false"));
+ kInputTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params),
+ std::to_string(C2FrameData::FLAG_CODEC_CONFIG), "false"));
+ kInputTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params),
+ std::to_string(C2FrameData::FLAG_END_OF_STREAM), "false"));
}
- return status;
+
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
}
diff --git a/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp b/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
index e88fbc7..fb1c291 100644
--- a/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
@@ -19,30 +19,25 @@
#include <android-base/logging.h>
#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
#include <codec2/hidl/client.h>
#include <VtsHalHidlTargetTestBase.h>
#include "media_c2_hidl_test_common.h"
-static ComponentTestEnvironment* gEnv = nullptr;
-
namespace {
// google.codec2 Master test setup
-class Codec2MasterHalTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
-
- public:
+class Codec2MasterHalTest : public ::testing::TestWithParam<std::string> {
+ public:
virtual void SetUp() override {
- Super::SetUp();
- mClient = android::Codec2Client::CreateFromService(
- gEnv->getInstance().c_str());
+ mClient = android::Codec2Client::CreateFromService(GetParam().c_str());
ASSERT_NE(mClient, nullptr);
}
- protected:
+ protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
@@ -58,15 +53,14 @@
}
// List Components
-TEST_F(Codec2MasterHalTest, ListComponents) {
+TEST_P(Codec2MasterHalTest, ListComponents) {
ALOGV("ListComponents Test");
C2String name = mClient->getName();
EXPECT_NE(name.empty(), true) << "Invalid Codec2Client Name";
// Get List of components from all known services
- const std::vector<C2Component::Traits> listTraits =
- mClient->ListComponents();
+ const std::vector<C2Component::Traits> listTraits = mClient->ListComponents();
if (listTraits.size() == 0)
ALOGE("Warning, ComponentInfo list empty");
@@ -79,24 +73,16 @@
ASSERT_NE(listener, nullptr);
// Create component from all known services
- component = mClient->CreateComponentByName(
- listTraits[i].name.c_str(), listener, &mClient);
- ASSERT_NE(component, nullptr) << "Create component failed for "
- << listTraits[i].name.c_str();
+ component =
+ mClient->CreateComponentByName(listTraits[i].name.c_str(), listener, &mClient);
+ ASSERT_NE(component, nullptr)
+ << "Create component failed for " << listTraits[i].name.c_str();
}
}
}
} // anonymous namespace
-int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- status = RUN_ALL_TESTS();
- LOG(INFO) << "C2 Test result = " << status;
- }
- return status;
-}
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2MasterHalTest,
+ testing::ValuesIn(android::Codec2Client::GetServiceNames()),
+ android::hardware::PrintInstanceNameToString);
diff --git a/media/codec2/hidl/1.0/vts/functional/video/Android.bp b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
index b737323..760f4da 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
@@ -16,6 +16,7 @@
cc_test {
name: "VtsHalMediaC2V1_0TargetVideoDecTest",
+ stem: "vts_media_c2_v1_0_video_dec_test",
defaults: ["VtsHalMediaC2V1_0Defaults"],
srcs: ["VtsHalMediaC2V1_0TargetVideoDecTest.cpp"],
header_libs: [
@@ -26,11 +27,16 @@
"libgui",
"libutils",
],
+ data: [":media_c2_v1_video_decode_res"],
+ test_config: "VtsHalMediaC2V1_0TargetVideoDecTest.xml",
}
cc_test {
name: "VtsHalMediaC2V1_0TargetVideoEncTest",
+ stem: "vts_media_c2_v1_0_video_enc_test",
defaults: ["VtsHalMediaC2V1_0Defaults"],
srcs: ["VtsHalMediaC2V1_0TargetVideoEncTest.cpp"],
+ data: [":media_c2_v1_video_encode_res"],
+ test_config: "VtsHalMediaC2V1_0TargetVideoEncTest.xml",
}
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 256603c..ec3fd7b 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
@@ -19,15 +19,16 @@
#include <android-base/logging.h>
#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
#include <stdio.h>
#include <fstream>
-#include <codec2/hidl/client.h>
#include <C2AllocatorIon.h>
-#include <C2Config.h>
-#include <C2Debug.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <codec2/hidl/client.h>
#include <gui/BufferQueue.h>
#include <gui/IConsumerListener.h>
#include <gui/IProducerListener.h>
@@ -35,9 +36,8 @@
using android::C2AllocatorIon;
-#include <VtsHalHidlTargetTestBase.h>
-#include "media_c2_video_hidl_test_common.h"
#include "media_c2_hidl_test_common.h"
+#include "media_c2_video_hidl_test_common.h"
struct FrameInfo {
int bytesCount;
@@ -45,61 +45,47 @@
int64_t timestamp;
};
+static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
+ kDecodeTestParameters;
+
+// Resource directory
+static std::string sResourceDir = "";
+
class LinearBuffer : public C2Buffer {
- public:
+ public:
explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block)
- : C2Buffer(
- {block->share(block->offset(), block->size(), ::C2Fence())}) {}
+ : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
explicit LinearBuffer(const std::shared_ptr<C2LinearBlock>& block, size_t size)
- : C2Buffer(
- {block->share(block->offset(), size, ::C2Fence())}) {}
+ : C2Buffer({block->share(block->offset(), size, ::C2Fence())}) {}
};
-static ComponentTestEnvironment* gEnv = nullptr;
-
namespace {
-class Codec2VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
-
- public:
- ::std::string getTestCaseInfo() const override {
- return ::std::string() +
- "Component: " + gEnv->getComponent().c_str() + " | " +
- "Instance: " + gEnv->getInstance().c_str() + " | " +
- "Res: " + gEnv->getRes().c_str();
- }
-
+class Codec2VideoDecHidlTestBase : public ::testing::Test {
+ public:
// google.codec2 Video test setup
virtual void SetUp() override {
- Super::SetUp();
+ getParams();
mDisableTest = false;
ALOGV("Codec2VideoDecHidlTest SetUp");
mClient = android::Codec2Client::CreateFromService(
- gEnv->getInstance().c_str(),
- !bool(android::Codec2Client::CreateFromService("default", true)));
+ mInstanceName.c_str(),
+ !bool(android::Codec2Client::CreateFromService("default", true)));
ASSERT_NE(mClient, nullptr);
- mListener.reset(new CodecListener(
- [this](std::list<std::unique_ptr<C2Work>>& workItems) {
- handleWorkDone(workItems);
- }));
+ mListener.reset(new CodecListener([this](std::list<std::unique_ptr<C2Work>>& workItems) {
+ handleWorkDone(workItems);
+ }));
ASSERT_NE(mListener, nullptr);
for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
mWorkQueue.emplace_back(new C2Work);
}
- mClient->createComponent(gEnv->getComponent().c_str(), mListener,
- &mComponent);
+ mClient->createComponent(mComponentName, mListener, &mComponent);
ASSERT_NE(mComponent, nullptr);
- std::shared_ptr<C2AllocatorStore> store =
- android::GetCodec2PlatformAllocatorStore();
- CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR,
- &mLinearAllocator),
- C2_OK);
- mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator,
- mBlockPoolId++);
+ std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+ CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator), C2_OK);
+ mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
ASSERT_NE(mLinearPool, nullptr);
mCompName = unknown_comp;
@@ -109,17 +95,15 @@
};
const StringToName kStringToName[] = {
- {"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
- {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9}, {"av1", av1},
+ {"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
+ {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9}, {"av1", av1},
};
- const size_t kNumStringToName =
- sizeof(kStringToName) / sizeof(kStringToName[0]);
+ const size_t kNumStringToName = sizeof(kStringToName) / sizeof(kStringToName[0]);
// Find the component type
- std::string comp = std::string(gEnv->getComponent());
for (size_t i = 0; i < kNumStringToName; ++i) {
- if (strcasestr(comp.c_str(), kStringToName[i].Name)) {
+ if (strcasestr(mComponentName.c_str(), kStringToName[i].Name)) {
mCompName = kStringToName[i].CompName;
break;
}
@@ -131,7 +115,7 @@
if (mCompName == unknown_comp) mDisableTest = true;
C2SecureModeTuning secureModeTuning{};
- mComponent->query({ &secureModeTuning }, {}, C2_MAY_BLOCK, nullptr);
+ mComponent->query({&secureModeTuning}, {}, C2_MAY_BLOCK, nullptr);
if (secureModeTuning.value == C2Config::SM_READ_PROTECTED) {
mDisableTest = true;
}
@@ -145,9 +129,11 @@
mComponent->release();
mComponent = nullptr;
}
- Super::TearDown();
}
+ // Get the test parameters from GetParam call.
+ virtual void getParams() {}
+
// callback function to process onWorkDone received by Listener
void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
for (std::unique_ptr<C2Work>& work : workItems) {
@@ -157,13 +143,10 @@
typedef std::unique_lock<std::mutex> ULock;
bool codecConfig = ((work->worklets.front()->output.flags &
C2FrameData::FLAG_CODEC_CONFIG) != 0);
- if (!codecConfig &&
- !work->worklets.front()->output.buffers.empty()) {
- EXPECT_GE(
- (work->worklets.front()->output.ordinal.timestamp.peeku()),
- mTimestampUs);
- mTimestampUs =
- work->worklets.front()->output.ordinal.timestamp.peeku();
+ if (!codecConfig && !work->worklets.front()->output.buffers.empty()) {
+ EXPECT_GE((work->worklets.front()->output.ordinal.timestamp.peeku()),
+ mTimestampUs);
+ mTimestampUs = work->worklets.front()->output.ordinal.timestamp.peeku();
ULock l(mQueueLock);
if (mTimestampDevTest) {
@@ -179,8 +162,7 @@
}
if (tsHit == false) {
if (mTimestampUslist.empty() == false) {
- EXPECT_EQ(tsHit, true)
- << "TimeStamp not recognized";
+ EXPECT_EQ(tsHit, true) << "TimeStamp not recognized";
} else {
std::cout << "[ INFO ] Received non-zero "
"output / TimeStamp not recognized \n";
@@ -189,9 +171,8 @@
}
}
bool mCsd;
- workDone(mComponent, work, mFlushedIndices, mQueueLock,
- mQueueCondition, mWorkQueue, mEos, mCsd,
- mFramesReceived);
+ workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue,
+ mEos, mCsd, mFramesReceived);
(void)mCsd;
}
}
@@ -209,6 +190,9 @@
unknown_comp,
};
+ std::string mInstanceName;
+ std::string mComponentName;
+
bool mEos;
bool mDisableTest;
bool mTimestampDevTest;
@@ -229,15 +213,23 @@
std::shared_ptr<android::Codec2Client::Listener> mListener;
std::shared_ptr<android::Codec2Client::Component> mComponent;
- protected:
+ protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
};
-void validateComponent(
- const std::shared_ptr<android::Codec2Client::Component>& component,
- Codec2VideoDecHidlTest::standardComp compName, bool& disableTest) {
+class Codec2VideoDecHidlTest
+ : public Codec2VideoDecHidlTestBase,
+ public ::testing::WithParamInterface<std::tuple<std::string, std::string>> {
+ void getParams() {
+ mInstanceName = std::get<0>(GetParam());
+ mComponentName = std::get<1>(GetParam());
+ }
+};
+
+void validateComponent(const std::shared_ptr<android::Codec2Client::Component>& component,
+ Codec2VideoDecHidlTest::standardComp compName, bool& disableTest) {
// Validate its a C2 Component
if (component->getName().find("c2") == std::string::npos) {
ALOGE("Not a c2 component");
@@ -252,14 +244,12 @@
return;
}
std::vector<std::unique_ptr<C2Param>> queried;
- c2_status_t c2err =
- component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
- C2_DONT_BLOCK, &queried);
+ c2_status_t c2err = component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
+ C2_DONT_BLOCK, &queried);
if (c2err != C2_OK && queried.size() == 0) {
ALOGE("Query media type failed => %d", c2err);
} else {
- std::string inputDomain =
- ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
+ std::string inputDomain = ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
if (inputDomain.find("video/") == std::string::npos) {
ALOGE("Expected Video Component");
disableTest = true;
@@ -279,8 +269,8 @@
// number of elementary streams per component
#define STREAM_COUNT 2
// LookUpTable of clips and metadata for component testing
-void GetURLForComponent(Codec2VideoDecHidlTest::standardComp comp, char* mURL,
- char* info, size_t streamIndex = 1) {
+void GetURLForComponent(Codec2VideoDecHidlTest::standardComp comp, char* mURL, char* info,
+ size_t streamIndex = 1) {
struct CompToURL {
Codec2VideoDecHidlTest::standardComp comp;
const char mURL[STREAM_COUNT][512];
@@ -289,42 +279,30 @@
ASSERT_TRUE(streamIndex < STREAM_COUNT);
static const CompToURL kCompToURL[] = {
- {Codec2VideoDecHidlTest::standardComp::avc,
- {"bbb_avc_176x144_300kbps_60fps.h264",
- "bbb_avc_640x360_768kbps_30fps.h264"},
- {"bbb_avc_176x144_300kbps_60fps.info",
- "bbb_avc_640x360_768kbps_30fps.info"}},
- {Codec2VideoDecHidlTest::standardComp::hevc,
- {"bbb_hevc_176x144_176kbps_60fps.hevc",
- "bbb_hevc_640x360_1600kbps_30fps.hevc"},
- {"bbb_hevc_176x144_176kbps_60fps.info",
- "bbb_hevc_640x360_1600kbps_30fps.info"}},
- {Codec2VideoDecHidlTest::standardComp::mpeg2,
- {"bbb_mpeg2_176x144_105kbps_25fps.m2v",
- "bbb_mpeg2_352x288_1mbps_60fps.m2v"},
- {"bbb_mpeg2_176x144_105kbps_25fps.info",
- "bbb_mpeg2_352x288_1mbps_60fps.info"}},
- {Codec2VideoDecHidlTest::standardComp::h263,
- {"", "bbb_h263_352x288_300kbps_12fps.h263"},
- {"", "bbb_h263_352x288_300kbps_12fps.info"}},
- {Codec2VideoDecHidlTest::standardComp::mpeg4,
- {"", "bbb_mpeg4_352x288_512kbps_30fps.m4v"},
- {"", "bbb_mpeg4_352x288_512kbps_30fps.info"}},
- {Codec2VideoDecHidlTest::standardComp::vp8,
- {"bbb_vp8_176x144_240kbps_60fps.vp8",
- "bbb_vp8_640x360_2mbps_30fps.vp8"},
- {"bbb_vp8_176x144_240kbps_60fps.info",
- "bbb_vp8_640x360_2mbps_30fps.info"}},
- {Codec2VideoDecHidlTest::standardComp::vp9,
- {"bbb_vp9_176x144_285kbps_60fps.vp9",
- "bbb_vp9_640x360_1600kbps_30fps.vp9"},
- {"bbb_vp9_176x144_285kbps_60fps.info",
- "bbb_vp9_640x360_1600kbps_30fps.info"}},
- {Codec2VideoDecHidlTest::standardComp::av1,
- {"bbb_av1_640_360.av1",
- "bbb_av1_176_144.av1"},
- {"bbb_av1_640_360.info",
- "bbb_av1_176_144.info"}},
+ {Codec2VideoDecHidlTest::standardComp::avc,
+ {"bbb_avc_176x144_300kbps_60fps.h264", "bbb_avc_640x360_768kbps_30fps.h264"},
+ {"bbb_avc_176x144_300kbps_60fps.info", "bbb_avc_640x360_768kbps_30fps.info"}},
+ {Codec2VideoDecHidlTest::standardComp::hevc,
+ {"bbb_hevc_176x144_176kbps_60fps.hevc", "bbb_hevc_640x360_1600kbps_30fps.hevc"},
+ {"bbb_hevc_176x144_176kbps_60fps.info", "bbb_hevc_640x360_1600kbps_30fps.info"}},
+ {Codec2VideoDecHidlTest::standardComp::mpeg2,
+ {"bbb_mpeg2_176x144_105kbps_25fps.m2v", "bbb_mpeg2_352x288_1mbps_60fps.m2v"},
+ {"bbb_mpeg2_176x144_105kbps_25fps.info", "bbb_mpeg2_352x288_1mbps_60fps.info"}},
+ {Codec2VideoDecHidlTest::standardComp::h263,
+ {"", "bbb_h263_352x288_300kbps_12fps.h263"},
+ {"", "bbb_h263_352x288_300kbps_12fps.info"}},
+ {Codec2VideoDecHidlTest::standardComp::mpeg4,
+ {"", "bbb_mpeg4_352x288_512kbps_30fps.m4v"},
+ {"", "bbb_mpeg4_352x288_512kbps_30fps.info"}},
+ {Codec2VideoDecHidlTest::standardComp::vp8,
+ {"bbb_vp8_176x144_240kbps_60fps.vp8", "bbb_vp8_640x360_2mbps_30fps.vp8"},
+ {"bbb_vp8_176x144_240kbps_60fps.info", "bbb_vp8_640x360_2mbps_30fps.info"}},
+ {Codec2VideoDecHidlTest::standardComp::vp9,
+ {"bbb_vp9_176x144_285kbps_60fps.vp9", "bbb_vp9_640x360_1600kbps_30fps.vp9"},
+ {"bbb_vp9_176x144_285kbps_60fps.info", "bbb_vp9_640x360_1600kbps_30fps.info"}},
+ {Codec2VideoDecHidlTest::standardComp::av1,
+ {"bbb_av1_640_360.av1", "bbb_av1_176_144.av1"},
+ {"bbb_av1_640_360.info", "bbb_av1_176_144.info"}},
};
for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
@@ -337,13 +315,11 @@
}
void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
- std::mutex &queueLock, std::condition_variable& queueCondition,
+ std::mutex& queueLock, std::condition_variable& queueCondition,
std::list<std::unique_ptr<C2Work>>& workQueue,
- std::list<uint64_t>& flushedIndices,
- std::shared_ptr<C2BlockPool>& linearPool,
- std::ifstream& eleStream,
- android::Vector<FrameInfo>* Info,
- int offset, int range, bool signalEOS = true) {
+ std::list<uint64_t>& flushedIndices, std::shared_ptr<C2BlockPool>& linearPool,
+ std::ifstream& eleStream, android::Vector<FrameInfo>* Info, int offset,
+ int range, bool signalEOS = true) {
typedef std::unique_lock<std::mutex> ULock;
int frameID = offset;
int maxRetry = 0;
@@ -367,8 +343,7 @@
}
int64_t timestamp = (*Info)[frameID].timestamp;
if ((*Info)[frameID].flags) flags = (1 << ((*Info)[frameID].flags - 1));
- if (signalEOS && ((frameID == (int)Info->size() - 1) ||
- (frameID == (offset + range - 1))))
+ if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1))))
flags |= C2FrameData::FLAG_END_OF_STREAM;
work->input.flags = (C2FrameData::flags_t)flags;
@@ -390,10 +365,9 @@
auto alignedSize = ALIGN(size, PAGE_SIZE);
if (size) {
std::shared_ptr<C2LinearBlock> block;
- ASSERT_EQ(C2_OK,
- linearPool->fetchLinearBlock(
- alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
- &block));
+ ASSERT_EQ(C2_OK, linearPool->fetchLinearBlock(
+ alignedSize,
+ {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block));
ASSERT_TRUE(block);
// Write View
@@ -424,16 +398,16 @@
}
}
-TEST_F(Codec2VideoDecHidlTest, validateCompName) {
- if (mDisableTest) return;
+TEST_P(Codec2VideoDecHidlTest, validateCompName) {
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
ALOGV("Checks if the given component is a valid video component");
validateComponent(mComponent, mCompName, mDisableTest);
ASSERT_EQ(mDisableTest, false);
}
-TEST_F(Codec2VideoDecHidlTest, configureTunnel) {
+TEST_P(Codec2VideoDecHidlTest, configureTunnel) {
description("Attempts to configure tunneling");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
ALOGV("Checks if the component can be configured for tunneling");
native_handle_t* sidebandStream{};
c2_status_t err = mComponent->configureVideoTunnel(0, &sidebandStream);
@@ -449,7 +423,7 @@
BufferQueue::createBufferQueue(&producer, &consumer);
class DummyConsumerListener : public BnConsumerListener {
- public:
+ public:
DummyConsumerListener() : BnConsumerListener() {}
void onFrameAvailable(const BufferItem&) override {}
void onBuffersReleased() override {}
@@ -458,37 +432,39 @@
consumer->consumerConnect(new DummyConsumerListener(), false);
class DummyProducerListener : public BnProducerListener {
- public:
+ public:
DummyProducerListener() : BnProducerListener() {}
virtual void onBufferReleased() override {}
virtual bool needsReleaseNotify() override { return false; }
virtual void onBuffersDiscarded(const std::vector<int32_t>&) override {}
};
IGraphicBufferProducer::QueueBufferOutput qbo{};
- producer->connect(new DummyProducerListener(),
- NATIVE_WINDOW_API_MEDIA,
- false,
- &qbo);
+ producer->connect(new DummyProducerListener(), NATIVE_WINDOW_API_MEDIA, false, &qbo);
ASSERT_EQ(producer->setSidebandStream(nativeHandle), NO_ERROR);
}
class Codec2VideoDecDecodeTest
- : public Codec2VideoDecHidlTest,
- public ::testing::WithParamInterface<std::pair<int32_t, bool>> {
+ : public Codec2VideoDecHidlTestBase,
+ public ::testing::WithParamInterface<
+ std::tuple<std::string, std::string, std::string, std::string>> {
+ void getParams() {
+ mInstanceName = std::get<0>(GetParam());
+ mComponentName = std::get<1>(GetParam());
+ }
};
// Bitstream Test
TEST_P(Codec2VideoDecDecodeTest, DecodeTest) {
description("Decodes input file");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
- uint32_t streamIndex = GetParam().first;
- bool signalEOS = GetParam().second;
+ uint32_t streamIndex = std::stoi(std::get<2>(GetParam()));
+ bool signalEOS = !std::get<2>(GetParam()).compare("true");
char mURL[512], info[512];
std::ifstream eleStream, eleInfo;
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(mCompName, mURL, info, streamIndex);
eleInfo.open(info);
@@ -504,10 +480,8 @@
if (!(eleInfo >> bytesCount)) break;
eleInfo >> flags;
eleInfo >> timestamp;
- bool codecConfig = flags ?
- ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
- if (mTimestampDevTest && !codecConfig)
- mTimestampUslist.push_back(timestamp);
+ bool codecConfig = flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+ if (mTimestampDevTest && !codecConfig) mTimestampUslist.push_back(timestamp);
Info.push_back({bytesCount, flags, timestamp});
}
eleInfo.close();
@@ -519,52 +493,42 @@
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(), signalEOS));
+ ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+ (int)Info.size(), signalEOS));
// If EOS is not sent, sending empty input with EOS flag
size_t infoSize = Info.size();
if (!signalEOS) {
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
- ASSERT_NO_FATAL_FAILURE(
- testInputBuffer(mComponent, mQueueLock, mWorkQueue,
- C2FrameData::FLAG_END_OF_STREAM, false));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
+ ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
+ C2FrameData::FLAG_END_OF_STREAM, false));
infoSize += 1;
}
// 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));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
}
eleStream.close();
if (mFramesReceived != infoSize) {
ALOGE("Input buffer count and Output buffer count mismatch");
- ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived,
- infoSize);
+ ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived, infoSize);
ASSERT_TRUE(false);
}
if (mTimestampDevTest) EXPECT_EQ(mTimestampUslist.empty(), true);
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-// DecodeTest with StreamIndex and EOS / No EOS
-INSTANTIATE_TEST_CASE_P(StreamIndexAndEOS, Codec2VideoDecDecodeTest,
- ::testing::Values(std::make_pair(0, false),
- std::make_pair(0, true),
- std::make_pair(1, false),
- std::make_pair(1, true)));
// Adaptive Test
-TEST_F(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
+TEST_P(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
description("Adaptive Decode Test");
- if (mDisableTest) return;
- if (!(mCompName == avc || mCompName == hevc || mCompName == vp8 ||
- mCompName == vp9 || mCompName == mpeg2))
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
+ if (!(mCompName == avc || mCompName == hevc || mCompName == vp8 || mCompName == vp9 ||
+ mCompName == mpeg2))
return;
typedef std::unique_lock<std::mutex> ULock;
@@ -578,8 +542,8 @@
char mURL[512], info[512];
std::ifstream eleStream, eleInfo;
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(mCompName, mURL, info, i % STREAM_COUNT);
eleInfo.open(info);
@@ -594,13 +558,12 @@
eleInfo >> timestamp;
timestamp += timestampOffset;
Info.push_back({bytesCount, flags, timestamp});
- bool codecConfig = flags ?
- ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+ bool codecConfig =
+ flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
{
ULock l(mQueueLock);
- if (mTimestampDevTest && !codecConfig)
- mTimestampUslist.push_back(timestamp);
+ if (mTimestampDevTest && !codecConfig) mTimestampUslist.push_back(timestamp);
}
if (timestampMax < timestamp) timestampMax = timestamp;
}
@@ -612,10 +575,9 @@
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,
- offset, (int)(Info.size() - offset), false));
+ ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mLinearPool, eleStream, &Info,
+ offset, (int)(Info.size() - offset), false));
eleStream.close();
offset = (int)Info.size();
@@ -650,13 +612,11 @@
// blocking call to ensures application to Wait till all the inputs are
// consumed
ALOGV("Waiting for input consumption");
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
if (mFramesReceived != ((Info.size()) + 1)) {
ALOGE("Input buffer count and Output buffer count mismatch");
- ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived,
- Info.size() + 1);
+ ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived, Info.size() + 1);
ASSERT_TRUE(false);
}
@@ -664,15 +624,15 @@
}
// thumbnail test
-TEST_F(Codec2VideoDecHidlTest, ThumbnailTest) {
+TEST_P(Codec2VideoDecHidlTest, ThumbnailTest) {
description("Test Request for thumbnail");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
char mURL[512], info[512];
std::ifstream eleStream, eleInfo;
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(mCompName, mURL, info);
eleInfo.open(info);
@@ -703,11 +663,10 @@
} while (!(flags & SYNC_FRAME));
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, j + 1));
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+ ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+ j + 1));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
eleStream.close();
EXPECT_GE(mFramesReceived, 1U);
ASSERT_EQ(mEos, true);
@@ -716,9 +675,9 @@
ASSERT_EQ(mComponent->release(), C2_OK);
}
-TEST_F(Codec2VideoDecHidlTest, EOSTest) {
+TEST_P(Codec2VideoDecHidlTest, EOSTest) {
description("Test empty input buffer with EOS flag");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
typedef std::unique_lock<std::mutex> ULock;
ASSERT_EQ(mComponent->start(), C2_OK);
std::unique_ptr<C2Work> work;
@@ -756,16 +715,16 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2VideoDecHidlTest, FlushTest) {
+TEST_P(Codec2VideoDecHidlTest, FlushTest) {
description("Tests Flush calls");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
typedef std::unique_lock<std::mutex> ULock;
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());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(mCompName, mURL, info);
eleInfo.open(info);
@@ -790,28 +749,24 @@
// frame after this so that the below section can be covered for all
// components
uint32_t numFramesFlushed = 128;
- ASSERT_NO_FATAL_FAILURE(decodeNFrames(
- mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
- mLinearPool, eleStream, &Info, 0, numFramesFlushed, false));
+ ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mLinearPool, eleStream, &Info, 0,
+ numFramesFlushed, false));
// flush
std::list<std::unique_ptr<C2Work>> flushedWork;
- c2_status_t err =
- mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+ c2_status_t err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
ASSERT_EQ(err, C2_OK);
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
- (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+ (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
{
// Update mFlushedIndices based on the index received from flush()
ULock l(mQueueLock);
for (std::unique_ptr<C2Work>& work : flushedWork) {
ASSERT_NE(work, nullptr);
- auto frameIndexIt =
- std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
- work->input.ordinal.frameIndex.peeku());
- if (!mFlushedIndices.empty() &&
- (frameIndexIt != mFlushedIndices.end())) {
+ auto frameIndexIt = std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
+ work->input.ordinal.frameIndex.peeku());
+ if (!mFlushedIndices.empty() && (frameIndexIt != mFlushedIndices.end())) {
mFlushedIndices.erase(frameIndexIt);
work->input.buffers.clear();
work->worklets.clear();
@@ -835,27 +790,24 @@
index++;
}
if (keyFrame) {
- ASSERT_NO_FATAL_FAILURE(
- decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mLinearPool, eleStream, &Info, index,
- (int)Info.size() - index));
+ ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mLinearPool, eleStream, &Info, index,
+ (int)Info.size() - index));
}
eleStream.close();
err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
ASSERT_EQ(err, C2_OK);
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
- (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+ (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
{
// Update mFlushedIndices based on the index received from flush()
ULock l(mQueueLock);
for (std::unique_ptr<C2Work>& work : flushedWork) {
ASSERT_NE(work, nullptr);
uint64_t frameIndex = work->input.ordinal.frameIndex.peeku();
- std::list<uint64_t>::iterator frameIndexIt = std::find(
- mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
- if (!mFlushedIndices.empty() &&
- (frameIndexIt != mFlushedIndices.end())) {
+ std::list<uint64_t>::iterator frameIndexIt =
+ std::find(mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
+ if (!mFlushedIndices.empty() && (frameIndexIt != mFlushedIndices.end())) {
mFlushedIndices.erase(frameIndexIt);
work->input.buffers.clear();
work->worklets.clear();
@@ -867,15 +819,15 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2VideoDecHidlTest, DecodeTestEmptyBuffersInserted) {
+TEST_P(Codec2VideoDecHidlTest, DecodeTestEmptyBuffersInserted) {
description("Decode with multiple empty input frames");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
char mURL[512], info[512];
std::ifstream eleStream, eleInfo;
- strcpy(mURL, gEnv->getRes().c_str());
- strcpy(info, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
+ strcpy(info, sResourceDir.c_str());
GetURLForComponent(mCompName, mURL, info);
eleInfo.open(info);
@@ -890,15 +842,16 @@
// and empty input frames at an interval of 5 frames.
while (1) {
if (!(frameId % 5)) {
- if (!(frameId % 20)) flags = 32;
- else flags = 0;
+ 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;
+ codecConfig = flags ? ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
}
Info.push_back({bytesCount, flags, timestamp});
frameId++;
@@ -909,39 +862,58 @@
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()));
+ 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));
+ 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());
+ ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived, Info.size());
ASSERT_TRUE(false);
}
}
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoDecHidlTest, testing::ValuesIn(kTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
+// DecodeTest with StreamIndex and EOS / No EOS
+INSTANTIATE_TEST_SUITE_P(StreamIndexAndEOS, Codec2VideoDecDecodeTest,
+ testing::ValuesIn(kDecodeTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
} // anonymous namespace
// TODO : Video specific configuration Test
int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::AddGlobalTestEnvironment(gEnv);
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "C2 Test result = " << status;
+ kTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER);
+ for (auto params : kTestParameters) {
+ kDecodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "false"));
+ kDecodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "0", "true"));
+ kDecodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "1", "false"));
+ kDecodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "1", "true"));
}
- return status;
-}
+
+ // Set the resource directory based on command line args.
+ // Test will fail to set up if the argument is not set.
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+ sResourceDir = argv[i + 1];
+ break;
+ }
+ }
+
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.xml b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.xml
new file mode 100644
index 0000000..8761797
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the"License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an"AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalMediaC2V1_0TargetVideoDecTest.">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="vts_media_c2_v1_0_video_dec_test" value="/data/local/tmp/vts_media_c2_v1_0_video_dec_test" />
+
+ <!-- Files used for video testing -->
+ <option name="push-file" key="bbb_avc_176x144_300kbps_60fps.h264" value="/data/local/tmp/media/bbb_avc_176x144_300kbps_60fps.h264" />
+ <option name="push-file" key="bbb_avc_640x360_768kbps_30fps.h264" value="/data/local/tmp/media/bbb_avc_640x360_768kbps_30fps.h264" />
+ <option name="push-file" key="bbb_avc_176x144_300kbps_60fps.info" value="/data/local/tmp/media/bbb_avc_176x144_300kbps_60fps.info" />
+ <option name="push-file" key="bbb_avc_640x360_768kbps_30fps.info" value="/data/local/tmp/media/bbb_avc_640x360_768kbps_30fps.info" />
+ <option name="push-file" key="bbb_hevc_176x144_176kbps_60fps.hevc" value="/data/local/tmp/media/bbb_hevc_176x144_176kbps_60fps.hevc" />
+ <option name="push-file" key="bbb_hevc_640x360_1600kbps_30fps.hevc" value="/data/local/tmp/media/bbb_hevc_640x360_1600kbps_30fps.hevc" />
+ <option name="push-file" key="bbb_hevc_176x144_176kbps_60fps.info" value="/data/local/tmp/media/bbb_hevc_176x144_176kbps_60fps.info" />
+ <option name="push-file" key="bbb_hevc_640x360_1600kbps_30fps.info" value="/data/local/tmp/media/bbb_hevc_640x360_1600kbps_30fps.info" />
+ <option name="push-file" key="bbb_mpeg2_176x144_105kbps_25fps.m2v" value="/data/local/tmp/media/bbb_mpeg2_176x144_105kbps_25fps.m2v" />
+ <option name="push-file" key="bbb_mpeg2_352x288_1mbps_60fps.m2v" value="/data/local/tmp/media/bbb_mpeg2_352x288_1mbps_60fps.m2v" />
+ <option name="push-file" key="bbb_mpeg2_176x144_105kbps_25fps.info" value="/data/local/tmp/media/bbb_mpeg2_176x144_105kbps_25fps.info" />
+ <option name="push-file" key="bbb_mpeg2_352x288_1mbps_60fps.info" value="/data/local/tmp/media/bbb_mpeg2_352x288_1mbps_60fps.info" />
+ <option name="push-file" key="bbb_h263_352x288_300kbps_12fps.h263" value="/data/local/tmp/media/bbb_h263_352x288_300kbps_12fps.h263" />
+ <option name="push-file" key="bbb_h263_352x288_300kbps_12fps.info" value="/data/local/tmp/media/bbb_h263_352x288_300kbps_12fps.info" />
+ <option name="push-file" key="bbb_mpeg4_352x288_512kbps_30fps.m4v" value="/data/local/tmp/media/bbb_mpeg4_352x288_512kbps_30fps.m4v" />
+ <option name="push-file" key="bbb_mpeg4_352x288_512kbps_30fps.info" value="/data/local/tmp/media/bbb_mpeg4_352x288_512kbps_30fps.info" />
+ <option name="push-file" key="bbb_vp8_176x144_240kbps_60fps.vp8" value="/data/local/tmp/media/bbb_vp8_176x144_240kbps_60fps.vp8" />
+ <option name="push-file" key="bbb_vp8_640x360_2mbps_30fps.vp8" value="/data/local/tmp/media/bbb_vp8_640x360_2mbps_30fps.vp8" />
+ <option name="push-file" key="bbb_vp8_176x144_240kbps_60fps.info" value="/data/local/tmp/media/bbb_vp8_176x144_240kbps_60fps.info" />
+ <option name="push-file" key="bbb_vp8_640x360_2mbps_30fps.info" value="/data/local/tmp/media/bbb_vp8_640x360_2mbps_30fps.info" />
+ <option name="push-file" key="bbb_vp9_176x144_285kbps_60fps.vp9" value="/data/local/tmp/media/bbb_vp9_176x144_285kbps_60fps.vp9" />
+ <option name="push-file" key="bbb_vp9_640x360_1600kbps_30fps.vp9" value="/data/local/tmp/media/bbb_vp9_640x360_1600kbps_30fps.vp9" />
+ <option name="push-file" key="bbb_vp9_176x144_285kbps_60fps.info" value="/data/local/tmp/media/bbb_vp9_176x144_285kbps_60fps.info" />
+ <option name="push-file" key="bbb_vp9_640x360_1600kbps_30fps.info" value="/data/local/tmp/media/bbb_vp9_640x360_1600kbps_30fps.info" />
+ <option name="push-file" key="bbb_av1_640_360.av1" value="/data/local/tmp/media/bbb_av1_640_360.av1" />
+ <option name="push-file" key="bbb_av1_176_144.av1" value="/data/local/tmp/media/bbb_av1_176_144.av1" />
+ <option name="push-file" key="bbb_av1_640_360.info" value="/data/local/tmp/media/bbb_av1_640_360.info" />
+ <option name="push-file" key="bbb_av1_176_144.info" value="/data/local/tmp/media/bbb_av1_176_144.info" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="vts_media_c2_v1_0_video_dec_test" />
+ <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+ </test>
+</configuration>
\ No newline at end of file
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 15f6acd..be97383 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
@@ -19,73 +19,62 @@
#include <android-base/logging.h>
#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
#include <stdio.h>
#include <fstream>
-#include <codec2/hidl/client.h>
#include <C2AllocatorIon.h>
-#include <C2Config.h>
-#include <C2Debug.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <codec2/hidl/client.h>
using android::C2AllocatorIon;
-#include <VtsHalHidlTargetTestBase.h>
-#include "media_c2_video_hidl_test_common.h"
#include "media_c2_hidl_test_common.h"
+#include "media_c2_video_hidl_test_common.h"
class GraphicBuffer : public C2Buffer {
-public:
- explicit GraphicBuffer(const std::shared_ptr<C2GraphicBlock> &block)
- : C2Buffer({block->share(C2Rect(block->width(), block->height()),
- ::C2Fence())}) {}
+ public:
+ explicit GraphicBuffer(const std::shared_ptr<C2GraphicBlock>& block)
+ : C2Buffer({block->share(C2Rect(block->width(), block->height()), ::C2Fence())}) {}
};
-static ComponentTestEnvironment* gEnv = nullptr;
+static std::vector<std::tuple<std::string, std::string, std::string>> kEncodeTestParameters;
+static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
+ kEncodeResolutionTestParameters;
+
+// Resource directory
+static std::string sResourceDir = "";
namespace {
-class Codec2VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- private:
- typedef ::testing::VtsHalHidlTargetTestBase Super;
-
- public:
- ::std::string getTestCaseInfo() const override {
- return ::std::string() +
- "Component: " + gEnv->getComponent().c_str() + " | " +
- "Instance: " + gEnv->getInstance().c_str() + " | " +
- "Res: " + gEnv->getRes().c_str();
- }
-
+class Codec2VideoEncHidlTestBase : public ::testing::Test {
+ public:
// google.codec2 Video test setup
virtual void SetUp() override {
- Super::SetUp();
+ getParams();
mDisableTest = false;
ALOGV("Codec2VideoEncHidlTest SetUp");
mClient = android::Codec2Client::CreateFromService(
- gEnv->getInstance().c_str(),
- !bool(android::Codec2Client::CreateFromService("default", true)));
+ mInstanceName.c_str(),
+ !bool(android::Codec2Client::CreateFromService("default", true)));
ASSERT_NE(mClient, nullptr);
- mListener.reset(new CodecListener(
- [this](std::list<std::unique_ptr<C2Work>>& workItems) {
- handleWorkDone(workItems);
- }));
+ mListener.reset(new CodecListener([this](std::list<std::unique_ptr<C2Work>>& workItems) {
+ handleWorkDone(workItems);
+ }));
ASSERT_NE(mListener, nullptr);
for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
mWorkQueue.emplace_back(new C2Work);
}
- mClient->createComponent(gEnv->getComponent().c_str(), mListener,
- &mComponent);
+ mClient->createComponent(mComponentName, mListener, &mComponent);
ASSERT_NE(mComponent, nullptr);
- std::shared_ptr<C2AllocatorStore> store =
- android::GetCodec2PlatformAllocatorStore();
- CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC,
- &mGraphicAllocator),
+ std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+ CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &mGraphicAllocator),
C2_OK);
- mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator,
- mBlockPoolId++);
+ mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator, mBlockPoolId++);
ASSERT_NE(mGraphicPool, nullptr);
mCompName = unknown_comp;
@@ -95,17 +84,15 @@
};
const StringToName kStringToName[] = {
- {"h263", h263}, {"avc", avc}, {"mpeg4", mpeg4},
- {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
+ {"h263", h263}, {"avc", avc}, {"mpeg4", mpeg4},
+ {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
};
- const size_t kNumStringToName =
- sizeof(kStringToName) / sizeof(kStringToName[0]);
+ const size_t kNumStringToName = sizeof(kStringToName) / sizeof(kStringToName[0]);
// Find the component type
- std::string comp = std::string(gEnv->getComponent());
for (size_t i = 0; i < kNumStringToName; ++i) {
- if (strcasestr(comp.c_str(), kStringToName[i].Name)) {
+ if (strcasestr(mComponentName.c_str(), kStringToName[i].Name)) {
mCompName = kStringToName[i].CompName;
break;
}
@@ -126,9 +113,11 @@
mComponent->release();
mComponent = nullptr;
}
- Super::TearDown();
}
+ // Get the test parameters from GetParam call.
+ virtual void getParams() {}
+
bool setupConfigParam(int32_t nWidth, int32_t nHeight);
// callback function to process onWorkDone received by Listener
@@ -139,11 +128,9 @@
// previous timestamp
typedef std::unique_lock<std::mutex> ULock;
if (!mTimestampUslist.empty()) {
- EXPECT_GE((work->worklets.front()
- ->output.ordinal.timestamp.peeku()),
+ EXPECT_GE((work->worklets.front()->output.ordinal.timestamp.peeku()),
mTimestampUs);
- mTimestampUs = work->worklets.front()
- ->output.ordinal.timestamp.peeku();
+ mTimestampUs = work->worklets.front()->output.ordinal.timestamp.peeku();
// Currently this lock is redundant as no mTimestampUslist is only initialized
// before queuing any work to component. Once AdaptiveTest is added similar to
// the one in video decoders, this is needed.
@@ -151,8 +138,7 @@
if (mTimestampDevTest) {
bool tsHit = false;
- std::list<uint64_t>::iterator it =
- mTimestampUslist.begin();
+ std::list<uint64_t>::iterator it = mTimestampUslist.begin();
while (it != mTimestampUslist.end()) {
if (*it == mTimestampUs) {
mTimestampUslist.erase(it);
@@ -163,21 +149,18 @@
}
if (tsHit == false) {
if (mTimestampUslist.empty() == false) {
- EXPECT_EQ(tsHit, true)
- << "TimeStamp not recognized";
+ EXPECT_EQ(tsHit, true) << "TimeStamp not recognized";
} else {
- std::cout
- << "[ INFO ] Received non-zero "
- "output / TimeStamp not recognized \n";
+ std::cout << "[ INFO ] Received non-zero "
+ "output / TimeStamp not recognized \n";
}
}
}
}
if (work->result != C2_OK) mFailedWorkReceived++;
- workDone(mComponent, work, mFlushedIndices, mQueueLock,
- mQueueCondition, mWorkQueue, mEos, mCsd,
- mFramesReceived);
+ workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue,
+ mEos, mCsd, mFramesReceived);
}
}
}
@@ -192,6 +175,8 @@
unknown_comp,
};
+ std::string mInstanceName;
+ std::string mComponentName;
bool mEos;
bool mCsd;
bool mDisableTest;
@@ -217,15 +202,23 @@
std::shared_ptr<android::Codec2Client::Listener> mListener;
std::shared_ptr<android::Codec2Client::Component> mComponent;
- protected:
+ protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
};
-void validateComponent(
- const std::shared_ptr<android::Codec2Client::Component>& component,
- Codec2VideoEncHidlTest::standardComp compName, bool& disableTest) {
+class Codec2VideoEncHidlTest
+ : public Codec2VideoEncHidlTestBase,
+ public ::testing::WithParamInterface<std::tuple<std::string, std::string>> {
+ void getParams() {
+ mInstanceName = std::get<0>(GetParam());
+ mComponentName = std::get<1>(GetParam());
+ }
+};
+
+void validateComponent(const std::shared_ptr<android::Codec2Client::Component>& component,
+ Codec2VideoEncHidlTest::standardComp compName, bool& disableTest) {
// Validate its a C2 Component
if (component->getName().find("c2") == std::string::npos) {
ALOGE("Not a c2 component");
@@ -240,14 +233,12 @@
return;
}
std::vector<std::unique_ptr<C2Param>> queried;
- c2_status_t c2err =
- component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
- C2_DONT_BLOCK, &queried);
+ c2_status_t c2err = component->query({}, {C2PortMediaTypeSetting::input::PARAM_TYPE},
+ C2_DONT_BLOCK, &queried);
if (c2err != C2_OK && queried.size() == 0) {
ALOGE("Query media type failed => %d", c2err);
} else {
- std::string inputDomain =
- ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
+ std::string inputDomain = ((C2StreamMediaTypeSetting::input*)queried[0].get())->m.value;
if (inputDomain.find("video/") == std::string::npos) {
ALOGE("Expected Video Component");
disableTest = true;
@@ -265,12 +256,11 @@
}
// Set Default config param.
-bool Codec2VideoEncHidlTest::setupConfigParam(int32_t nWidth, int32_t nHeight) {
+bool Codec2VideoEncHidlTestBase::setupConfigParam(int32_t nWidth, int32_t nHeight) {
std::vector<std::unique_ptr<C2SettingResult>> failures;
C2StreamPictureSizeInfo::input inputSize(0u, nWidth, nHeight);
std::vector<C2Param*> configParam{&inputSize};
- c2_status_t status =
- mComponent->config(configParam, C2_DONT_BLOCK, &failures);
+ c2_status_t status = mComponent->config(configParam, C2_DONT_BLOCK, &failures);
if (status == C2_OK && failures.size() == 0u) return true;
return false;
}
@@ -281,13 +271,11 @@
}
void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
- std::mutex &queueLock, std::condition_variable& queueCondition,
+ std::mutex& queueLock, std::condition_variable& queueCondition,
std::list<std::unique_ptr<C2Work>>& workQueue,
- std::list<uint64_t>& flushedIndices,
- std::shared_ptr<C2BlockPool>& graphicPool,
- std::ifstream& eleStream, bool& disableTest,
- uint32_t frameID, uint32_t nFrames, uint32_t nWidth,
- int32_t nHeight, bool flushed = false, bool signalEOS = true) {
+ std::list<uint64_t>& flushedIndices, std::shared_ptr<C2BlockPool>& graphicPool,
+ std::ifstream& eleStream, bool& disableTest, uint32_t frameID, uint32_t nFrames,
+ uint32_t nWidth, int32_t nHeight, bool flushed = false, bool signalEOS = true) {
typedef std::unique_lock<std::mutex> ULock;
uint32_t maxRetry = 0;
@@ -313,8 +301,7 @@
if (!work && (maxRetry >= MAX_RETRY)) {
ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout";
}
- if (signalEOS && (nFrames == 1))
- flags |= C2FrameData::FLAG_END_OF_STREAM;
+ if (signalEOS && (nFrames == 1)) flags |= C2FrameData::FLAG_END_OF_STREAM;
if (flushed) {
flags |= SYNC_FRAME;
flushed = false;
@@ -335,9 +322,9 @@
ASSERT_EQ(eleStream.gcount(), bytesCount);
}
std::shared_ptr<C2GraphicBlock> block;
- err = graphicPool->fetchGraphicBlock(
- nWidth, nHeight, HAL_PIXEL_FORMAT_YV12,
- {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+ err = graphicPool->fetchGraphicBlock(nWidth, nHeight, HAL_PIXEL_FORMAT_YV12,
+ {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
+ &block);
if (err != C2_OK) {
fprintf(stderr, "fetchGraphicBlock failed : %d\n", err);
disableTest = true;
@@ -380,27 +367,32 @@
}
}
-TEST_F(Codec2VideoEncHidlTest, validateCompName) {
- if (mDisableTest) return;
+TEST_P(Codec2VideoEncHidlTest, validateCompName) {
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
ALOGV("Checks if the given component is a valid video component");
validateComponent(mComponent, mCompName, mDisableTest);
ASSERT_EQ(mDisableTest, false);
}
-class Codec2VideoEncEncodeTest : public Codec2VideoEncHidlTest,
- public ::testing::WithParamInterface<bool> {
+class Codec2VideoEncEncodeTest
+ : public Codec2VideoEncHidlTestBase,
+ public ::testing::WithParamInterface<std::tuple<std::string, std::string, std::string>> {
+ void getParams() {
+ mInstanceName = std::get<0>(GetParam());
+ mComponentName = std::get<1>(GetParam());
+ }
};
TEST_P(Codec2VideoEncEncodeTest, EncodeTest) {
description("Encodes input file");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
char mURL[512];
int32_t nWidth = ENC_DEFAULT_FRAME_WIDTH;
int32_t nHeight = ENC_DEFAULT_FRAME_HEIGHT;
- bool signalEOS = GetParam();
+ bool signalEOS = !std::get<2>(GetParam()).compare("true");
- strcpy(mURL, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
GetURLForComponent(mURL);
std::ifstream eleStream;
@@ -425,10 +417,9 @@
return;
}
ASSERT_EQ(mComponent->start(), C2_OK);
- ASSERT_NO_FATAL_FAILURE(
- encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
- 0, ENC_NUM_FRAMES, nWidth, nHeight, false, signalEOS));
+ ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest, 0,
+ ENC_NUM_FRAMES, nWidth, nHeight, false, signalEOS));
// mDisableTest will be set if buffer was not fetched properly.
// This may happen when resolution is not proper but config suceeded
// In this cases, we skip encoding the input stream
@@ -441,25 +432,21 @@
// If EOS is not sent, sending empty input with EOS flag
inputFrames = ENC_NUM_FRAMES;
if (!signalEOS) {
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
- ASSERT_NO_FATAL_FAILURE(
- testInputBuffer(mComponent, mQueueLock, mWorkQueue,
- C2FrameData::FLAG_END_OF_STREAM, false));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue, 1));
+ ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
+ C2FrameData::FLAG_END_OF_STREAM, false));
inputFrames += 1;
}
// blocking call to ensures application to Wait till all the inputs are
// consumed
ALOGD("Waiting for input consumption");
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
eleStream.close();
if (mFramesReceived != inputFrames) {
ALOGE("Input buffer count and Output buffer count mismatch");
- ALOGE("framesReceived : %d inputFrames : %d", mFramesReceived,
- inputFrames);
+ ALOGE("framesReceived : %d inputFrames : %d", mFramesReceived, inputFrames);
ASSERT_TRUE(false);
}
@@ -475,13 +462,9 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-// EncodeTest with EOS / No EOS
-INSTANTIATE_TEST_CASE_P(EncodeTestwithEOS, Codec2VideoEncEncodeTest,
- ::testing::Values(true, false));
-
-TEST_F(Codec2VideoEncHidlTest, EOSTest) {
+TEST_P(Codec2VideoEncHidlTest, EOSTest) {
description("Test empty input buffer with EOS flag");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
ASSERT_EQ(mComponent->start(), C2_OK);
typedef std::unique_lock<std::mutex> ULock;
@@ -519,15 +502,15 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2VideoEncHidlTest, FlushTest) {
+TEST_P(Codec2VideoEncHidlTest, FlushTest) {
description("Test Request for flush");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
typedef std::unique_lock<std::mutex> ULock;
char mURL[512];
int32_t nWidth = ENC_DEFAULT_FRAME_WIDTH;
int32_t nHeight = ENC_DEFAULT_FRAME_HEIGHT;
- strcpy(mURL, gEnv->getRes().c_str());
+ strcpy(mURL, sResourceDir.c_str());
GetURLForComponent(mURL);
if (!setupConfigParam(nWidth, nHeight)) {
@@ -544,10 +527,9 @@
eleStream.open(mURL, std::ifstream::binary);
ASSERT_EQ(eleStream.is_open(), true);
ALOGV("mURL : %s", mURL);
- ASSERT_NO_FATAL_FAILURE(
- encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
- 0, numFramesFlushed, nWidth, nHeight));
+ ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest, 0,
+ numFramesFlushed, nWidth, nHeight));
// mDisableTest will be set if buffer was not fetched properly.
// This may happen when resolution is not proper but config suceeded
// In this cases, we skip encoding the input stream
@@ -558,23 +540,20 @@
}
std::list<std::unique_ptr<C2Work>> flushedWork;
- c2_status_t err =
- mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
+ c2_status_t err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
ASSERT_EQ(err, C2_OK);
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
- (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+ (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
uint64_t frameIndex;
{
- //Update mFlushedIndices based on the index received from flush()
+ // Update mFlushedIndices based on the index received from flush()
ULock l(mQueueLock);
for (std::unique_ptr<C2Work>& work : flushedWork) {
ASSERT_NE(work, nullptr);
frameIndex = work->input.ordinal.frameIndex.peeku();
- std::list<uint64_t>::iterator frameIndexIt = std::find(
- mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
- if (!mFlushedIndices.empty() &&
- (frameIndexIt != mFlushedIndices.end())) {
+ std::list<uint64_t>::iterator frameIndexIt =
+ std::find(mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
+ if (!mFlushedIndices.empty() && (frameIndexIt != mFlushedIndices.end())) {
mFlushedIndices.erase(frameIndexIt);
work->input.buffers.clear();
work->worklets.clear();
@@ -583,11 +562,10 @@
}
}
mFlushedIndices.clear();
- ASSERT_NO_FATAL_FAILURE(
- encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
- numFramesFlushed, numFrames - numFramesFlushed,
- nWidth, nHeight, true));
+ ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
+ numFramesFlushed, numFrames - numFramesFlushed, nWidth,
+ nHeight, true));
eleStream.close();
// mDisableTest will be set if buffer was not fetched properly.
// This may happen when resolution is not proper but config suceeded
@@ -600,19 +578,17 @@
err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
ASSERT_EQ(err, C2_OK);
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
- (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
+ (size_t)MAX_INPUT_BUFFERS - flushedWork.size()));
{
- //Update mFlushedIndices based on the index received from flush()
+ // Update mFlushedIndices based on the index received from flush()
ULock l(mQueueLock);
for (std::unique_ptr<C2Work>& work : flushedWork) {
ASSERT_NE(work, nullptr);
frameIndex = work->input.ordinal.frameIndex.peeku();
- std::list<uint64_t>::iterator frameIndexIt = std::find(
- mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
- if (!mFlushedIndices.empty() &&
- (frameIndexIt != mFlushedIndices.end())) {
+ std::list<uint64_t>::iterator frameIndexIt =
+ std::find(mFlushedIndices.begin(), mFlushedIndices.end(), frameIndex);
+ if (!mFlushedIndices.empty() && (frameIndexIt != mFlushedIndices.end())) {
mFlushedIndices.erase(frameIndexIt);
work->input.buffers.clear();
work->worklets.clear();
@@ -624,9 +600,9 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2VideoEncHidlTest, InvalidBufferTest) {
+TEST_P(Codec2VideoEncHidlTest, InvalidBufferTest) {
description("Tests feeding larger/smaller input buffer");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
std::ifstream eleStream;
int32_t nWidth = ENC_DEFAULT_FRAME_WIDTH / 2;
@@ -638,28 +614,24 @@
}
ASSERT_EQ(mComponent->start(), C2_OK);
- ASSERT_NO_FATAL_FAILURE(
- encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
- 0, 1, nWidth, nHeight, false, false));
+ ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest, 0,
+ 1, nWidth, nHeight, false, false));
// Feed larger input buffer.
- ASSERT_NO_FATAL_FAILURE(
- encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
- 1, 1, nWidth*2, nHeight*2, false, false));
+ ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest, 1,
+ 1, nWidth * 2, nHeight * 2, false, false));
// Feed smaller input buffer.
- ASSERT_NO_FATAL_FAILURE(
- encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
- 2, 1, nWidth/2, nHeight/2, false, true));
+ ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest, 2,
+ 1, nWidth / 2, nHeight / 2, false, true));
// blocking call to ensures application to Wait till all the inputs are
// consumed
ALOGD("Waiting for input consumption");
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
if (mFramesReceived != 3) {
std::cout << "[ WARN ] Component didn't receive all buffers back \n";
@@ -674,17 +646,23 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-class Codec2VideoEncResolutionTest : public Codec2VideoEncHidlTest,
- public ::testing::WithParamInterface<std::pair<int32_t, int32_t> > {
+class Codec2VideoEncResolutionTest
+ : public Codec2VideoEncHidlTestBase,
+ public ::testing::WithParamInterface<
+ std::tuple<std::string, std::string, std::string, std::string>> {
+ void getParams() {
+ mInstanceName = std::get<0>(GetParam());
+ mComponentName = std::get<1>(GetParam());
+ }
};
TEST_P(Codec2VideoEncResolutionTest, ResolutionTest) {
description("Tests encoding at different resolutions");
- if (mDisableTest) return;
+ if (mDisableTest) GTEST_SKIP() << "Test is disabled";
std::ifstream eleStream;
- int32_t nWidth = GetParam().first;
- int32_t nHeight = GetParam().second;
+ int32_t nWidth = std::stoi(std::get<2>(GetParam()));
+ int32_t nHeight = std::stoi(std::get<3>(GetParam()));
ALOGD("Trying encode for width %d height %d", nWidth, nHeight);
mEos = false;
@@ -694,10 +672,9 @@
}
ASSERT_EQ(mComponent->start(), C2_OK);
- ASSERT_NO_FATAL_FAILURE(
- encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
- mFlushedIndices, mGraphicPool, eleStream, mDisableTest,
- 0, MAX_INPUT_BUFFERS, nWidth, nHeight, false, true));
+ ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
+ mFlushedIndices, mGraphicPool, eleStream, mDisableTest, 0,
+ MAX_INPUT_BUFFERS, nWidth, nHeight, false, true));
// mDisableTest will be set if buffer was not fetched properly.
// This may happen when resolution is not proper but config suceeded
@@ -709,31 +686,52 @@
}
ALOGD("Waiting for input consumption");
- ASSERT_NO_FATAL_FAILURE(
- waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+ ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
ASSERT_EQ(mEos, true);
ASSERT_EQ(mComponent->stop(), C2_OK);
ASSERT_EQ(mComponent->reset(), C2_OK);
}
-INSTANTIATE_TEST_CASE_P(NonStdSizes, Codec2VideoEncResolutionTest, ::testing::Values(
- std::make_pair(52, 18),
- std::make_pair(365, 365),
- std::make_pair(484, 362),
- std::make_pair(244, 488)));
+INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoEncHidlTest, testing::ValuesIn(kTestParameters),
+ android::hardware::PrintInstanceTupleNameToString<>);
+
+INSTANTIATE_TEST_SUITE_P(NonStdSizes, Codec2VideoEncResolutionTest,
+ ::testing::ValuesIn(kEncodeResolutionTestParameters));
+
+// EncodeTest with EOS / No EOS
+INSTANTIATE_TEST_SUITE_P(EncodeTestwithEOS, Codec2VideoEncEncodeTest,
+ ::testing::ValuesIn(kEncodeTestParameters));
} // anonymous namespace
int main(int argc, char** argv) {
- gEnv = new ComponentTestEnvironment();
- ::testing::AddGlobalTestEnvironment(gEnv);
- ::testing::InitGoogleTest(&argc, argv);
- gEnv->init(&argc, argv);
- int status = gEnv->initFromOptions(argc, argv);
- if (status == 0) {
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "C2 Test result = " << status;
+ kTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_ENCODER);
+ for (auto params : kTestParameters) {
+ kEncodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "true"));
+ kEncodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "false"));
+
+ kEncodeResolutionTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "52", "18"));
+ kEncodeResolutionTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "365", "365"));
+ kEncodeResolutionTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "484", "362"));
+ kEncodeResolutionTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), "244", "488"));
}
- return status;
-}
+
+ // Set the resource directory based on command line args.
+ // Test will fail to set up if the argument is not set.
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
+ sResourceDir = argv[i + 1];
+ break;
+ }
+ }
+
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.xml b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.xml
new file mode 100644
index 0000000..260a616
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the"License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an"AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VtsHalMediaC2V1_0TargetVideoEncTest.">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push-file" key="vts_media_c2_v1_0_video_enc_test" value="/data/local/tmp/vts_media_c2_v1_0_video_enc_test" />
+
+ <!-- Files used for video testing -->
+ <option name="push-file" key="bbb_352x288_420p_30fps_32frames.yuv" value="/data/local/tmp/media/bbb_352x288_420p_30fps_32frames.yuv" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="vts_media_c2_v1_0_video_enc_test" />
+ <option name="native-test-flag" value="-P /data/local/tmp/media/" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h
index e37ca38..d3a693b 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/functional/video/media_c2_video_hidl_test_common.h
@@ -29,5 +29,4 @@
* Common video utils
*/
-
#endif // MEDIA_C2_VIDEO_HIDL_TEST_COMMON_H
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index cc132de..01d106f 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1948,6 +1948,13 @@
inputSurface->getHalInterface()));
}
+static void MaybeLogUnrecognizedName(const char *func, const std::string &name) {
+ thread_local std::set<std::string> sLogged{};
+ if (sLogged.insert(name).second) {
+ ALOGW("%s: Unrecognized interface name: %s", func, name.c_str());
+ }
+}
+
static status_t GetCommonAllocatorIds(
const std::vector<std::string> &names,
C2Allocator::type_t type,
@@ -1961,26 +1968,33 @@
if (names.empty()) {
return OK;
}
- std::shared_ptr<Codec2Client::Interface> intf{
- Codec2Client::CreateInterfaceByName(names[0].c_str())};
- std::vector<std::unique_ptr<C2Param>> params;
- c2_status_t err = intf->query(
- {}, {C2PortAllocatorsTuning::input::PARAM_TYPE}, C2_MAY_BLOCK, ¶ms);
- if (err == C2_OK && params.size() == 1u) {
- C2PortAllocatorsTuning::input *allocators =
- C2PortAllocatorsTuning::input::From(params[0].get());
- if (allocators && allocators->flexCount() > 0) {
- ids->insert(allocators->m.values, allocators->m.values + allocators->flexCount());
+ bool firstIteration = true;
+ for (const std::string &name : names) {
+ std::shared_ptr<Codec2Client::Interface> intf{
+ Codec2Client::CreateInterfaceByName(name.c_str())};
+ if (!intf) {
+ MaybeLogUnrecognizedName(__FUNCTION__, name);
+ continue;
}
- }
- if (ids->empty()) {
- // The component does not advertise allocators. Use default.
- ids->insert(defaultAllocatorId);
- }
- for (size_t i = 1; i < names.size(); ++i) {
- intf = Codec2Client::CreateInterfaceByName(names[i].c_str());
- err = intf->query(
+ std::vector<std::unique_ptr<C2Param>> params;
+ c2_status_t err = intf->query(
{}, {C2PortAllocatorsTuning::input::PARAM_TYPE}, C2_MAY_BLOCK, ¶ms);
+ if (firstIteration) {
+ firstIteration = false;
+ if (err == C2_OK && params.size() == 1u) {
+ C2PortAllocatorsTuning::input *allocators =
+ C2PortAllocatorsTuning::input::From(params[0].get());
+ if (allocators && allocators->flexCount() > 0) {
+ ids->insert(allocators->m.values,
+ allocators->m.values + allocators->flexCount());
+ }
+ }
+ if (ids->empty()) {
+ // The component does not advertise allocators. Use default.
+ ids->insert(defaultAllocatorId);
+ }
+ continue;
+ }
bool filtered = false;
if (err == C2_OK && params.size() == 1u) {
C2PortAllocatorsTuning::input *allocators =
@@ -2033,6 +2047,10 @@
for (const std::string &name : names) {
std::shared_ptr<Codec2Client::Interface> intf{
Codec2Client::CreateInterfaceByName(name.c_str())};
+ if (!intf) {
+ MaybeLogUnrecognizedName(__FUNCTION__, name);
+ continue;
+ }
std::vector<C2FieldSupportedValuesQuery> fields;
fields.push_back(C2FieldSupportedValuesQuery::Possible(
C2ParamField{&sUsage, &sUsage.value}));
diff --git a/media/codec2/vndk/util/C2InterfaceUtils.cpp b/media/codec2/vndk/util/C2InterfaceUtils.cpp
index 61ec911..0c1729b 100644
--- a/media/codec2/vndk/util/C2InterfaceUtils.cpp
+++ b/media/codec2/vndk/util/C2InterfaceUtils.cpp
@@ -216,9 +216,14 @@
if (limit.contains(minMask) && contains(minMask)) {
values[0] = minMask;
// keep only flags that are covered by limit
- std::remove_if(values.begin(), values.end(), [&limit, minMask](const C2Value::Primitive &v) -> bool {
- T value = v.ref<ValueType>() | minMask;
- return value == minMask || !limit.contains(value); });
+ values.erase(std::remove_if(values.begin(), values.end(),
+ [&limit, minMask](
+ const C2Value::Primitive &v) -> bool {
+ T value = v.ref<ValueType>() | minMask;
+ return value == minMask ||
+ !limit.contains(value);
+ }),
+ values.end());
// we also need to do it vice versa
for (const C2Value::Primitive &v : _mValues) {
T value = v.ref<ValueType>() | minMask;
@@ -264,24 +269,33 @@
template<typename T>
C2SupportedValueSet<T> C2SupportedValueSet<T>::limitedTo(const C2SupportedValueSet<T> &limit) const {
std::vector<C2Value::Primitive> values = _mValues; // make a copy
- std::remove_if(values.begin(), values.end(), [&limit](const C2Value::Primitive &v) -> bool {
- return !limit.contains(v.ref<ValueType>()); });
+ values.erase(std::remove_if(values.begin(), values.end(),
+ [&limit](const C2Value::Primitive &v) -> bool {
+ return !limit.contains(v.ref<ValueType>());
+ }),
+ values.end());
return C2SupportedValueSet(std::move(values));
}
template<typename T>
C2SupportedValueSet<T> C2SupportedValueSet<T>::limitedTo(const C2SupportedRange<T> &limit) const {
std::vector<C2Value::Primitive> values = _mValues; // make a copy
- std::remove_if(values.begin(), values.end(), [&limit](const C2Value::Primitive &v) -> bool {
- return !limit.contains(v.ref<ValueType>()); });
+ values.erase(std::remove_if(values.begin(), values.end(),
+ [&limit](const C2Value::Primitive &v) -> bool {
+ return !limit.contains(v.ref<ValueType>());
+ }),
+ values.end());
return C2SupportedValueSet(std::move(values));
}
template<typename T>
C2SupportedValueSet<T> C2SupportedValueSet<T>::limitedTo(const C2SupportedFlags<T> &limit) const {
std::vector<C2Value::Primitive> values = _mValues; // make a copy
- std::remove_if(values.begin(), values.end(), [&limit](const C2Value::Primitive &v) -> bool {
- return !limit.contains(v.ref<ValueType>()); });
+ values.erase(std::remove_if(values.begin(), values.end(),
+ [&limit](const C2Value::Primitive &v) -> bool {
+ return !limit.contains(v.ref<ValueType>());
+ }),
+ values.end());
return C2SupportedValueSet(std::move(values));
}
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 1cb81a6..39f5bb6 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -1906,11 +1906,15 @@
//ALOGV("\tReverb_command cmdCode Case: "
// "EFFECT_CMD_GET_PARAM start");
effect_param_t *p = (effect_param_t *)pCmdData;
+ if (pCmdData == nullptr) {
+ ALOGW("\tLVM_ERROR : pCmdData is NULL");
+ return -EINVAL;
+ }
if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) {
android_errorWriteLog(0x534e4554, "26347509");
return -EINVAL;
}
- if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) ||
+ if (cmdSize < sizeof(effect_param_t) ||
cmdSize < (sizeof(effect_param_t) + p->psize) ||
pReplyData == NULL || replySize == NULL ||
*replySize < (sizeof(effect_param_t) + p->psize)) {
diff --git a/media/libmediametrics/MediaMetricsItem.cpp b/media/libmediametrics/MediaMetricsItem.cpp
index 4371668..7cdbe5f 100644
--- a/media/libmediametrics/MediaMetricsItem.cpp
+++ b/media/libmediametrics/MediaMetricsItem.cpp
@@ -25,6 +25,7 @@
#include <set>
#include <binder/Parcel.h>
+#include <cutils/properties.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/SortedVector.h>
diff --git a/media/libmediametrics/include/media/MediaMetricsItem.h b/media/libmediametrics/include/media/MediaMetricsItem.h
index 8477f8d..303343f 100644
--- a/media/libmediametrics/include/media/MediaMetricsItem.h
+++ b/media/libmediametrics/include/media/MediaMetricsItem.h
@@ -27,12 +27,8 @@
#include <variant>
#include <binder/Parcel.h>
-#include <cutils/properties.h>
#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-#include <utils/StrongPointer.h>
-#include <utils/Timers.h>
+#include <utils/Timers.h> // nsecs_t
namespace android {
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 425468f..e97f6eb 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -107,20 +107,6 @@
}
}
-ID3::ID3(DataSourceBase *source, bool ignoreV1, off64_t offset)
- : mIsValid(false),
- mData(NULL),
- mSize(0),
- mFirstFrameOffset(0),
- mVersion(ID3_UNKNOWN),
- mRawSize(0) {
- mIsValid = parseV2(source, offset);
-
- if (!mIsValid && !ignoreV1) {
- mIsValid = parseV1(source);
- }
-}
-
ID3::ID3(const uint8_t *data, size_t size, bool ignoreV1)
: mIsValid(false),
mData(NULL),
@@ -247,44 +233,14 @@
return false;
}
- if (header.version_major == 4) {
- void *copy = malloc(size);
- if (copy == NULL) {
- free(mData);
- mData = NULL;
- ALOGE("b/24623447, no more memory");
- return false;
- }
-
- memcpy(copy, mData, size);
-
- bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
- if (!success) {
- memcpy(mData, copy, size);
- mSize = size;
-
- success = removeUnsynchronizationV2_4(true /* iTunesHack */);
-
- if (success) {
- ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
- }
- }
-
- free(copy);
- copy = NULL;
-
- if (!success) {
- free(mData);
- mData = NULL;
-
- return false;
- }
- } else if (header.flags & 0x80) {
+ // first handle global unsynchronization
+ if (header.flags & 0x80) {
ALOGV("removing unsynchronization");
removeUnsynchronization();
}
+ // handle extended header, if present
mFirstFrameOffset = 0;
if (header.version_major == 3 && (header.flags & 0x40)) {
// Version 2.3 has an optional extended header.
@@ -296,6 +252,7 @@
return false;
}
+ // v2.3 does not have syncsafe integers
size_t extendedHeaderSize = U32_AT(&mData[0]);
if (extendedHeaderSize > SIZE_MAX - 4) {
free(mData);
@@ -367,6 +324,48 @@
mFirstFrameOffset = ext_size;
}
+ // Handle any v2.4 per-frame unsynchronization
+ // The id3 spec isn't clear about what should happen if the global
+ // unsynchronization flag is combined with per-frame unsynchronization,
+ // or whether that's even allowed, so this code assumes id3 writing
+ // tools do the right thing and not apply double-unsynchronization,
+ // but will honor the flags if they are set.
+ if (header.version_major == 4) {
+ void *copy = malloc(size);
+ if (copy == NULL) {
+ free(mData);
+ mData = NULL;
+ ALOGE("b/24623447, no more memory");
+ return false;
+ }
+
+ memcpy(copy, mData, size);
+
+ bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
+ if (!success) {
+ memcpy(mData, copy, size);
+ mSize = size;
+
+ success = removeUnsynchronizationV2_4(true /* iTunesHack */);
+
+ if (success) {
+ ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
+ }
+ }
+
+ free(copy);
+ copy = NULL;
+
+ if (!success) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+ }
+
+
+
if (header.version_major == 2) {
mVersion = ID3_V2_2;
} else if (header.version_major == 3) {
@@ -411,7 +410,7 @@
bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
size_t oldSize = mSize;
- size_t offset = 0;
+ size_t offset = mFirstFrameOffset;
while (mSize >= 10 && offset <= mSize - 10) {
if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
break;
@@ -445,7 +444,7 @@
}
if ((flags & 2) && (dataSize >= 2)) {
- // This file has "unsynchronization", so we have to replace occurrences
+ // This frame has "unsynchronization", so we have to replace occurrences
// of 0xff 0x00 with just 0xff in order to get the real data.
size_t readOffset = offset + 11;
diff --git a/media/libstagefright/id3/test/ID3Test.cpp b/media/libstagefright/id3/test/ID3Test.cpp
index a8f1470..cd5cd9e 100644
--- a/media/libstagefright/id3/test/ID3Test.cpp
+++ b/media/libstagefright/id3/test/ID3Test.cpp
@@ -24,6 +24,7 @@
#include <datasource/FileSource.h>
#include <media/stagefright/foundation/hexdump.h>
+#include <media/MediaExtractorPluginHelper.h>
#include <ID3.h>
#include "ID3TestEnvironment.h"
@@ -42,7 +43,8 @@
string path = gEnv->getRes() + GetParam();
sp<FileSource> file = new FileSource(path.c_str());
ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n";
- ID3 tag(file.get());
+ DataSourceHelper helper(file->wrap());
+ ID3 tag(&helper);
ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n";
ID3::Iterator it(tag, nullptr);
@@ -61,7 +63,8 @@
sp<android::FileSource> file = new FileSource(path.c_str());
ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n";
- ID3 tag(file.get());
+ DataSourceHelper helper(file->wrap());
+ ID3 tag(&helper);
ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n";
ASSERT_TRUE(tag.version() >= versionNumber)
<< "Expected version: " << tag.version() << " Found version: " << versionNumber;
@@ -73,7 +76,8 @@
sp<android::FileSource> file = new FileSource(path.c_str());
ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n";
- ID3 tag(file.get());
+ DataSourceHelper helper(file->wrap());
+ ID3 tag(&helper);
ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n";
int countTextFrames = 0;
ID3::Iterator it(tag, nullptr);
@@ -99,7 +103,8 @@
sp<android::FileSource> file = new FileSource(path.c_str());
ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n";
- ID3 tag(file.get());
+ DataSourceHelper helper(file->wrap());
+ ID3 tag(&helper);
ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n";
size_t dataSize;
String8 mime;
@@ -124,7 +129,8 @@
sp<android::FileSource> file = new FileSource(path.c_str());
ASSERT_EQ(file->initCheck(), (status_t)OK) << "File initialization failed! \n";
- ID3 tag(file.get());
+ DataSourceHelper helper(file->wrap());
+ ID3 tag(&helper);
ASSERT_TRUE(tag.isValid()) << "No valid ID3 tag found for " << path.c_str() << "\n";
int count = 0;
ID3::Iterator it(tag, nullptr);
diff --git a/media/libstagefright/id3/testid3.cpp b/media/libstagefright/id3/testid3.cpp
index 9984d85..5cd51cf 100644
--- a/media/libstagefright/id3/testid3.cpp
+++ b/media/libstagefright/id3/testid3.cpp
@@ -24,6 +24,7 @@
#include <binder/ProcessState.h>
#include <datasource/FileSource.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/MediaExtractorPluginHelper.h>
#define MAXPATHLEN 256
@@ -72,7 +73,8 @@
sp<FileSource> file = new FileSource(path);
CHECK_EQ(file->initCheck(), (status_t)OK);
- ID3 tag(file.get());
+ DataSourceHelper helper(file->wrap());
+ ID3 tag(&helper);
if (!tag.isValid()) {
printf("FAIL %s\n", path);
} else {
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index 2843a7a..0be5896 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -37,7 +37,6 @@
};
explicit ID3(DataSourceHelper *source, bool ignoreV1 = false, off64_t offset = 0);
- explicit ID3(DataSourceBase *source, bool ignoreV1 = false, off64_t offset = 0);
ID3(const uint8_t *data, size_t size, bool ignoreV1 = false);
~ID3();
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index a720bc9..8c186c9 100644
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -34,12 +34,7 @@
const char *mRole;
} kComponents[] = {
- // two choices for aac decoding.
- // configurable in media/libstagefright/data/media_codecs_google_audio.xml
- // default implementation
{ "OMX.google.aac.decoder", "aacdec", "audio_decoder.aac" },
- // alternate implementation
- { "OMX.google.xaac.decoder", "xaacdec", "audio_decoder.aac" },
{ "OMX.google.aac.encoder", "aacenc", "audio_encoder.aac" },
{ "OMX.google.amrnb.decoder", "amrdec", "audio_decoder.amrnb" },
{ "OMX.google.amrnb.encoder", "amrnbenc", "audio_encoder.amrnb" },
diff --git a/media/libstagefright/tests/extractorFactory/Android.bp b/media/libstagefright/tests/extractorFactory/Android.bp
new file mode 100644
index 0000000..e3e61d7
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/Android.bp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+ name: "ExtractorFactoryTest",
+ gtest: true,
+
+ srcs: [
+ "ExtractorFactoryTest.cpp",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libbase",
+ "libutils",
+ "libmedia",
+ "libbinder",
+ "libcutils",
+ "libdl_android",
+ "libdatasource",
+ "libmediametrics",
+ ],
+
+ static_libs: [
+ "libstagefright",
+ "libstagefright_foundation",
+ ],
+
+ include_dirs: [
+ "frameworks/av/media/libstagefright",
+ ],
+
+ // TODO: (b/150181583)
+ compile_multilib: "first",
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ sanitize: {
+ cfi: true,
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ },
+}
diff --git a/media/libstagefright/tests/extractorFactory/AndroidTest.xml b/media/libstagefright/tests/extractorFactory/AndroidTest.xml
new file mode 100644
index 0000000..3aa6392
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Test module config for extractor factory unit tests">
+ <option name="test-suite-tag" value="ExtractorFactoryTest" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="ExtractorFactoryTest->/data/local/tmp/ExtractorFactoryTest" />
+ <option name="push-file"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip?unzip=true"
+ value="/data/local/tmp/ExtractorFactoryTestRes/" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="ExtractorFactoryTest" />
+ <option name="native-test-flag" value="-P /data/local/tmp/ExtractorFactoryTestRes/" />
+ </test>
+</configuration>
diff --git a/media/libstagefright/tests/extractorFactory/ExtractorFactoryTest.cpp b/media/libstagefright/tests/extractorFactory/ExtractorFactoryTest.cpp
new file mode 100644
index 0000000..d155caa
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/ExtractorFactoryTest.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ExtractorFactoryTest"
+#include <utils/Log.h>
+
+#include <binder/ProcessState.h>
+
+#include <datasource/FileSource.h>
+#include <media/stagefright/MediaExtractorFactory.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+
+#include "ExtractorFactoryTestEnvironment.h"
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/exFactoryLogs"
+
+using namespace android;
+
+static ExtractorFactoryTestEnvironment *gEnv = nullptr;
+
+class ExtractorFactoryTest : public ::testing::TestWithParam<pair<string, string>> {
+ public:
+ ExtractorFactoryTest() : mDataSource(nullptr), mExtractor(nullptr) {}
+
+ ~ExtractorFactoryTest() {
+ if (mDataSource) {
+ mDataSource.clear();
+ mDataSource = nullptr;
+ }
+ if (mExtractor) {
+ mExtractor.clear();
+ mExtractor = nullptr;
+ }
+ }
+
+ int32_t createDataSource(string inputFileName);
+ int32_t createExtractor(bool createFromService, string inputMime);
+
+ sp<DataSource> mDataSource;
+ sp<IMediaExtractor> mExtractor;
+};
+
+int32_t ExtractorFactoryTest::createDataSource(string inputFileName) {
+ FILE *mInputFp = fopen(inputFileName.c_str(), "rb");
+ if (!mInputFp) {
+ ALOGE("Unable to open input file : %s for reading", inputFileName.c_str());
+ return -1;
+ }
+ struct stat buf;
+ int32_t status = stat(inputFileName.c_str(), &buf);
+ if (status != 0) {
+ ALOGE("Failed to read file properties for input file : %s", inputFileName.c_str());
+ return -1;
+ }
+ int32_t fd = fileno(mInputFp);
+ if (fd < 0) {
+ ALOGE("Invalid file descriptor for input file : %s", inputFileName.c_str());
+ return -1;
+ }
+ mDataSource = new FileSource(dup(fd), 0, buf.st_size);
+ if (!mDataSource) return -1;
+ return 0;
+}
+
+int32_t ExtractorFactoryTest::createExtractor(bool createFromService, string inputMime) {
+ ALOGV("Creating extractor for mime : %s", inputMime.c_str());
+ if (createFromService) {
+ mExtractor = MediaExtractorFactory::CreateFromService(mDataSource, inputMime.c_str());
+ } else {
+ mExtractor = MediaExtractorFactory::Create(mDataSource);
+ }
+ if (mExtractor == nullptr) return -1;
+ return 0;
+}
+
+TEST_F(ExtractorFactoryTest, ListExtractorsTest) {
+ MediaExtractorFactory::LoadExtractors();
+ vector<std::string> supportedTypes = MediaExtractorFactory::getSupportedTypes();
+ ASSERT_GT(supportedTypes.size(), 0) << " MediaExtractorFactory doesn't suuport any extractor";
+
+ FILE *outputLog = fopen(OUTPUT_FILE_NAME, "wb");
+ ASSERT_NE(outputLog, nullptr) << "Unable to open output file - " << OUTPUT_FILE_NAME
+ << " for writing";
+
+ int32_t fd = fileno(outputLog);
+ ASSERT_GE(fd, 0);
+
+ Vector<String16> args;
+ int32_t status = MediaExtractorFactory::dump(fd, args);
+ ASSERT_EQ(status, OK) << "MediaExtractorFactory dump failed";
+ fclose(outputLog);
+}
+
+TEST_P(ExtractorFactoryTest, ExtractorFactoryApiTest) {
+ string inputMime = GetParam().second;
+ string inputFileName = gEnv->getRes() + GetParam().first;
+
+ MediaExtractorFactory::LoadExtractors();
+ bool createMode[] = {true, false};
+ for (bool createFromService : createMode) {
+ int32_t status = createDataSource(inputFileName);
+ ASSERT_EQ(status, 0) << "create data source failed";
+
+ status = createExtractor(createFromService, inputMime);
+ ASSERT_EQ(status, 0) << "Extractor creation failed for input: " << inputFileName;
+
+ int32_t numTracks = mExtractor->countTracks();
+ ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+
+ sp<MetaData> meta = mExtractor->getMetaData();
+ ASSERT_NE(meta, nullptr) << "getMetaData returned null";
+
+ const char *mime;
+ bool valueFound = meta->findCString(kKeyMIMEType, &mime);
+ ASSERT_TRUE(valueFound) << "Extractor did not provide MIME type";
+ ASSERT_EQ(mime, inputMime) << "Extractor factory returned invalid mime type";
+ mExtractor.clear();
+ mDataSource.clear();
+ }
+}
+
+// TODO: (b/150111966)
+// Replace mime strings with appropriate definitions
+INSTANTIATE_TEST_SUITE_P(
+ ExtractorFactoryTestAll, ExtractorFactoryTest,
+ ::testing::Values(make_pair("loudsoftaac.aac", MEDIA_MIMETYPE_AUDIO_AAC_ADTS),
+ make_pair("testamr.amr", "audio/amr"),
+ make_pair("amrwb.wav", MEDIA_MIMETYPE_AUDIO_AMR_WB),
+ make_pair("john_cage.ogg", MEDIA_MIMETYPE_CONTAINER_OGG),
+ make_pair("monotestgsm.wav", MEDIA_MIMETYPE_CONTAINER_WAV),
+ make_pair("segment000001.ts", MEDIA_MIMETYPE_CONTAINER_MPEG2TS),
+ make_pair("sinesweepflac.flac", MEDIA_MIMETYPE_AUDIO_FLAC),
+ make_pair("testopus.opus", MEDIA_MIMETYPE_CONTAINER_OGG),
+ make_pair("midi_a.mid", MEDIA_MIMETYPE_AUDIO_MIDI),
+ make_pair("sinesweepvorbis.mkv", MEDIA_MIMETYPE_CONTAINER_MATROSKA),
+ make_pair("sinesweepoggmp4.mp4", "audio/mp4"),
+ make_pair("sinesweepmp3lame.mp3", MEDIA_MIMETYPE_AUDIO_MPEG),
+ make_pair("swirl_144x136_vp9.webm", "video/webm"),
+ make_pair("swirl_144x136_vp8.webm", "video/webm"),
+ make_pair("swirl_132x130_mpeg4.mp4", MEDIA_MIMETYPE_CONTAINER_MPEG4)));
+
+int main(int argc, char **argv) {
+ ProcessState::self()->startThreadPool();
+ gEnv = new ExtractorFactoryTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGV("Test result = %d\n", status);
+ }
+ return status;
+}
diff --git a/media/libstagefright/tests/extractorFactory/ExtractorFactoryTestEnvironment.h b/media/libstagefright/tests/extractorFactory/ExtractorFactoryTestEnvironment.h
new file mode 100644
index 0000000..0fad4d3
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/ExtractorFactoryTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __EXTRACTOR_FACTORY_TEST_ENVIRONMENT_H__
+#define __EXTRACTOR_FACTORY_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class ExtractorFactoryTestEnvironment : public ::testing::Environment {
+ public:
+ ExtractorFactoryTestEnvironment() : res("/data/local/tmp/") {}
+
+ // Parses the command line arguments
+ int initFromOptions(int argc, char **argv);
+
+ void setRes(const char *_res) { res = _res; }
+
+ const string getRes() const { return res; }
+
+ private:
+ string res;
+};
+
+int ExtractorFactoryTestEnvironment::initFromOptions(int argc, char **argv) {
+ static struct option options[] = {{"res", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+ while (true) {
+ int index = 0;
+ int c = getopt_long(argc, argv, "P:", options, &index);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'P':
+ setRes(optarg);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "unrecognized option: %s\n\n"
+ "usage: %s <gtest options> <test options>\n\n"
+ "test options are:\n\n"
+ "-P, --path: Resource files directory location\n",
+ argv[optind ?: 1], argv[0]);
+ return 2;
+ }
+ return 0;
+}
+
+#endif // __EXTRACTOR_FACTORY_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/tests/extractorFactory/README.md b/media/libstagefright/tests/extractorFactory/README.md
new file mode 100644
index 0000000..aaa71aa
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/README.md
@@ -0,0 +1,37 @@
+## Media Testing ##
+---
+#### Writer :
+The Writer Test Suite validates the writers available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/libstagefright/tests/writer/
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+
+adb push ${OUT}/data/nativetest64/ExtractorFactoryTest/ExtractorFactoryTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+
+adb push ${OUT}/data/nativetest/ExtractorFactoryTest/ExtractorFactoryTest /data/local/tmp/
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip).
+Download, unzip and push these files into device for testing.
+
+```
+adb push extractor /data/local/tmp/
+```
+
+usage: ExtractorFactoryTest -P \<path_to_res_folder\>
+```
+adb shell /data/local/tmp/ExtractorFactoryTest -P /data/local/tmp/extractor/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest ExtractorFactoryTest -- --enable-module-dynamic-download=true
+```
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 03c16f3..de7ae40 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -135,7 +135,7 @@
static sp<os::IExternalVibratorService> getExternalVibratorService() {
if (sExternalVibratorService == 0) {
- sp <IBinder> binder = defaultServiceManager()->getService(
+ sp<IBinder> binder = defaultServiceManager()->getService(
String16("external_vibrator_service"));
if (binder != 0) {
sExternalVibratorService =
@@ -411,6 +411,7 @@
status_t AudioFlinger::addEffectToHal(audio_port_handle_t deviceId,
audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+ AutoMutex lock(mHardwareLock);
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId);
if (audioHwDevice == nullptr) {
return NO_INIT;
@@ -420,6 +421,7 @@
status_t AudioFlinger::removeEffectFromHal(audio_port_handle_t deviceId,
audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+ AutoMutex lock(mHardwareLock);
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId);
if (audioHwDevice == nullptr) {
return NO_INIT;
@@ -439,6 +441,7 @@
{
// if module is 0, the request comes from an old policy manager and we should load
// well known modules
+ AutoMutex lock(mHardwareLock);
if (module == 0) {
ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
for (size_t i = 0; i < arraysize(audio_interfaces); i++) {
@@ -1079,17 +1082,18 @@
mMasterVolume = value;
// Set master volume in the HALs which support it.
- for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ {
AutoMutex lock(mHardwareLock);
- AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
- mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
- if (dev->canSetMasterVolume()) {
- dev->hwDevice()->setMasterVolume(value);
+ mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+ if (dev->canSetMasterVolume()) {
+ dev->hwDevice()->setMasterVolume(value);
+ }
+ mHardwareStatus = AUDIO_HW_IDLE;
}
- mHardwareStatus = AUDIO_HW_IDLE;
}
-
// Now set the master volume in each playback thread. Playback threads
// assigned to HALs which do not have master volume support will apply
// master volume during the mix operation. Threads with HALs which do
@@ -1156,6 +1160,9 @@
{ // scope for the lock
AutoMutex lock(mHardwareLock);
+ if (mPrimaryHardwareDev == nullptr) {
+ return INVALID_OPERATION;
+ }
sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
mHardwareStatus = AUDIO_HW_SET_MODE;
ret = dev->setMode(mode);
@@ -1185,6 +1192,9 @@
}
AutoMutex lock(mHardwareLock);
+ if (mPrimaryHardwareDev == nullptr) {
+ return INVALID_OPERATION;
+ }
sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
if (primaryDev == nullptr) {
ALOGW("%s: no primary HAL device", __func__);
@@ -1210,6 +1220,9 @@
return false;
}
AutoMutex lock(mHardwareLock);
+ if (mPrimaryHardwareDev == nullptr) {
+ return false;
+ }
sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
if (primaryDev == nullptr) {
ALOGW("%s: no primary HAL device", __func__);
@@ -1252,15 +1265,17 @@
mMasterMute = muted;
// Set master mute in the HALs which support it.
- for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ {
AutoMutex lock(mHardwareLock);
- AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
- mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
- if (dev->canSetMasterMute()) {
- dev->hwDevice()->setMasterMute(muted);
+ mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
+ if (dev->canSetMasterMute()) {
+ dev->hwDevice()->setMasterMute(muted);
+ }
+ mHardwareStatus = AUDIO_HW_IDLE;
}
- mHardwareStatus = AUDIO_HW_IDLE;
}
// Now set the master mute in each playback thread. Playback threads
@@ -1591,16 +1606,13 @@
if (ioHandle == AUDIO_IO_HANDLE_NONE) {
String8 out_s8;
+ AutoMutex lock(mHardwareLock);
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
String8 s;
- status_t result;
- {
- AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_GET_PARAMETER;
sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
- result = dev->getParameters(keys, &s);
+ status_t result = dev->getParameters(keys, &s);
mHardwareStatus = AUDIO_HW_IDLE;
- }
if (result == OK) out_s8 += s;
}
return out_s8;
@@ -1633,6 +1645,9 @@
}
AutoMutex lock(mHardwareLock);
+ if (mPrimaryHardwareDev == nullptr) {
+ return 0;
+ }
mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
@@ -1718,6 +1733,9 @@
}
AutoMutex lock(mHardwareLock);
+ if (mPrimaryHardwareDev == nullptr) {
+ return INVALID_OPERATION;
+ }
sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
ret = dev->setVoiceVolume(value);
@@ -2126,10 +2144,11 @@
return AUDIO_MODULE_HANDLE_NONE;
}
Mutex::Autolock _l(mLock);
+ AutoMutex lock(mHardwareLock);
return loadHwModule_l(name);
}
-// loadHwModule_l() must be called with AudioFlinger::mLock held
+// loadHwModule_l() must be called with AudioFlinger::mLock and AudioFlinger::mHardwareLock held
audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
{
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
@@ -2161,44 +2180,49 @@
// master mute and volume settings.
AudioHwDevice::Flags flags = static_cast<AudioHwDevice::Flags>(0);
- { // scope for auto-lock pattern
- AutoMutex lock(mHardwareLock);
-
- if (0 == mAudioHwDevs.size()) {
- mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
- float mv;
- if (OK == dev->getMasterVolume(&mv)) {
- mMasterVolume = mv;
- }
-
- mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
- bool mm;
- if (OK == dev->getMasterMute(&mm)) {
- mMasterMute = mm;
- }
+ if (0 == mAudioHwDevs.size()) {
+ mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
+ float mv;
+ if (OK == dev->getMasterVolume(&mv)) {
+ mMasterVolume = mv;
}
- mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
- if (OK == dev->setMasterVolume(mMasterVolume)) {
- flags = static_cast<AudioHwDevice::Flags>(flags |
- AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
+ mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
+ bool mm;
+ if (OK == dev->getMasterMute(&mm)) {
+ mMasterMute = mm;
}
-
- mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
- if (OK == dev->setMasterMute(mMasterMute)) {
- flags = static_cast<AudioHwDevice::Flags>(flags |
- AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
- }
-
- mHardwareStatus = AUDIO_HW_IDLE;
}
+
+ mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+ if (OK == dev->setMasterVolume(mMasterVolume)) {
+ flags = static_cast<AudioHwDevice::Flags>(flags |
+ AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
+ }
+
+ mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
+ if (OK == dev->setMasterMute(mMasterMute)) {
+ flags = static_cast<AudioHwDevice::Flags>(flags |
+ AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
+ }
+
+ mHardwareStatus = AUDIO_HW_IDLE;
+
if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_MSD) == 0) {
// An MSD module is inserted before hardware modules in order to mix encoded streams.
flags = static_cast<AudioHwDevice::Flags>(flags | AudioHwDevice::AHWD_IS_INSERT);
}
audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);
- mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
+ AudioHwDevice *audioDevice = new AudioHwDevice(handle, name, dev, flags);
+ if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_PRIMARY) == 0) {
+ mPrimaryHardwareDev = audioDevice;
+ mHardwareStatus = AUDIO_HW_SET_MODE;
+ mPrimaryHardwareDev->hwDevice()->setMode(mMode);
+ mHardwareStatus = AUDIO_HW_IDLE;
+ }
+
+ mAudioHwDevs.add(handle, audioDevice);
ALOGI("loadHwModule() Loaded %s audio interface, handle %d", name, handle);
@@ -2284,6 +2308,7 @@
}
Mutex::Autolock _l(mLock);
+ AutoMutex lock(mHardwareLock);
ssize_t index = mAudioHwDevs.indexOfKey(module);
if (index < 0) {
ALOGW("%s() bad hw module %d", __func__, module);
@@ -2305,8 +2330,15 @@
return mHwAvSyncIds.valueAt(index);
}
- sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
- if (dev == NULL) {
+ sp<DeviceHalInterface> dev;
+ {
+ AutoMutex lock(mHardwareLock);
+ if (mPrimaryHardwareDev == nullptr) {
+ return AUDIO_HW_SYNC_INVALID;
+ }
+ dev = mPrimaryHardwareDev->hwDevice();
+ }
+ if (dev == nullptr) {
return AUDIO_HW_SYNC_INVALID;
}
String8 reply;
@@ -2374,8 +2406,21 @@
status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfo> *microphones)
{
AutoMutex lock(mHardwareLock);
- sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
- status_t status = dev->getMicrophones(microphones);
+ status_t status = INVALID_OPERATION;
+
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ std::vector<media::MicrophoneInfo> mics;
+ AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
+ mHardwareStatus = AUDIO_HW_GET_MICROPHONES;
+ status_t devStatus = dev->hwDevice()->getMicrophones(&mics);
+ mHardwareStatus = AUDIO_HW_IDLE;
+ if (devStatus == NO_ERROR) {
+ microphones->insert(microphones->begin(), mics.begin(), mics.end());
+ // report success if at least one HW module supports the function.
+ status = NO_ERROR;
+ }
+ }
+
return status;
}
@@ -2522,12 +2567,13 @@
// notify client processes of the new output creation
playbackThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
- // the first primary output opened designates the primary hw device
- if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
+ // the first primary output opened designates the primary hw device if no HW module
+ // named "primary" was already loaded.
+ AutoMutex lock(mHardwareLock);
+ if ((mPrimaryHardwareDev == nullptr) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
ALOGI("Using module %d as the primary audio interface", module);
mPrimaryHardwareDev = playbackThread->getOutput()->audioHwDev;
- AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_MODE;
mPrimaryHardwareDev->hwDevice()->setMode(mMode);
mHardwareStatus = AUDIO_HW_IDLE;
@@ -3196,6 +3242,10 @@
AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
{
+ AutoMutex lock(mHardwareLock);
+ if (mPrimaryHardwareDev == nullptr) {
+ return nullptr;
+ }
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
if(thread->isDuplicating()) {
@@ -3206,7 +3256,7 @@
return thread;
}
}
- return NULL;
+ return nullptr;
}
DeviceTypeSet AudioFlinger::primaryOutputDevice_l() const
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 5c20a2d..6afbd4f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -835,10 +835,11 @@
// NOTE: If both mLock and mHardwareLock mutexes must be held,
// always take mLock before mHardwareLock
- // These two fields are immutable after onFirstRef(), so no lock needed to access
- AudioHwDevice* mPrimaryHardwareDev; // mAudioHwDevs[0] or NULL
+ // guarded by mHardwareLock
+ AudioHwDevice* mPrimaryHardwareDev;
DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs;
+ // These two fields are immutable after onFirstRef(), so no lock needed to access
sp<DevicesFactoryHalInterface> mDevicesFactoryHal;
sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback;
@@ -865,6 +866,7 @@
AUDIO_HW_GET_PARAMETER, // get_parameters
AUDIO_HW_SET_MASTER_MUTE, // set_master_mute
AUDIO_HW_GET_MASTER_MUTE, // get_master_mute
+ AUDIO_HW_GET_MICROPHONES, // getMicrophones
};
mutable hardware_call_state mHardwareStatus; // for dump only
diff --git a/services/mediametrics/TimeMachine.h b/services/mediametrics/TimeMachine.h
index b138233..6861c78 100644
--- a/services/mediametrics/TimeMachine.h
+++ b/services/mediametrics/TimeMachine.h
@@ -138,7 +138,7 @@
if (timeSequence.empty() // no elements
|| property.back() == AMEDIAMETRICS_PROP_SUFFIX_CHAR_DUPLICATES_ALLOWED
|| timeSequence.rbegin()->second != el) { // value changed
- timeSequence.emplace(time, std::move(el));
+ timeSequence.emplace_hint(timeSequence.end(), time, std::move(el));
if (timeSequence.size() > kTimeSequenceMaxElements) {
ALOGV("%s: restricting maximum elements (discarding oldest) for %s",
diff --git a/services/mediametrics/TransactionLog.h b/services/mediametrics/TransactionLog.h
index d64acf3..8a22826 100644
--- a/services/mediametrics/TransactionLog.h
+++ b/services/mediametrics/TransactionLog.h
@@ -94,8 +94,8 @@
std::lock_guard lock(mLock);
(void)gc(garbage);
- mLog.emplace(time, item);
- mItemMap[key].emplace(time, item);
+ mLog.emplace_hint(mLog.end(), time, item);
+ mItemMap[key].emplace_hint(mItemMap[key].end(), time, item);
return NO_ERROR; // no errors for now.
}