Merge "Convert VtsHalMediaC2V1_0HostTest to individual gtest" into rvc-dev

gugelfrei
Dan Shi 4 years ago committed by Android (Google) Code Review
commit 5dfd0a2360

@ -5,5 +5,4 @@ taklee@google.com
wonsik@google.com
# VTS team
yim@google.com
zhuoyao@google.com
dshi@google.com

@ -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",
],
}

@ -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",
}

@ -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 @@ struct FrameInfo {
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())}) {}
};
static ComponentTestEnvironment* gEnv = nullptr;
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 @@ class Codec2AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
// 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 @@ class Codec2AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
unknown_comp,
};
std::string mInstanceName;
std::string mComponentName;
bool mEos;
bool mDisableTest;
bool mTimestampDevTest;
@ -218,15 +200,23 @@ class Codec2AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ void validateComponent(
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 @@ void validateComponent(
}
// 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 @@ bool setupConfigParam(
// 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 @@ void getInputChannelInfo(
#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 @@ void GetURLForComponent(Codec2AudioDecHidlTest::standardComp comp, char* mURL,
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 GetURLForComponent(Codec2AudioDecHidlTest::standardComp comp, char* mURL,
}
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 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
}
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 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
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 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
}
}
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 @@ TEST_P(Codec2AudioDecDecodeTest, DecodeTest) {
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 @@ TEST_P(Codec2AudioDecDecodeTest, DecodeTest) {
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 @@ TEST_P(Codec2AudioDecDecodeTest, DecodeTest) {
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 @@ TEST_P(Codec2AudioDecDecodeTest, DecodeTest) {
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 @@ TEST_P(Codec2AudioDecDecodeTest, DecodeTest) {
}
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 @@ TEST_F(Codec2AudioDecHidlTest, ThumbnailTest) {
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 @@ TEST_F(Codec2AudioDecHidlTest, ThumbnailTest) {
} 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 @@ TEST_F(Codec2AudioDecHidlTest, EOSTest) {
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 @@ TEST_F(Codec2AudioDecHidlTest, FlushTest) {
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 @@ TEST_F(Codec2AudioDecHidlTest, FlushTest) {
// 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 @@ TEST_F(Codec2AudioDecHidlTest, FlushTest) {
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 @@ TEST_F(Codec2AudioDecHidlTest, FlushTest) {
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 @@ TEST_F(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) {
// 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 @@ TEST_F(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) {
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 @@ TEST_F(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) {
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"));
}
// 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;
}
}
return status;
}
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -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>

@ -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"
static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
kEncodeTestParameters;
// 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())}) {}
};
static ComponentTestEnvironment* gEnv = nullptr;
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 @@ class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
unknown_comp,
};
std::string mInstanceName;
std::string mComponentName;
bool mEos;
bool mCsd;
bool mDisableTest;
@ -167,7 +151,7 @@ class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
}
mInputMaxBufSize = bitStreamInfo[0];
}
};
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) {
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 @@ void validateComponent(
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 @@ void validateComponent(
}
// 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 @@ void GetURLForComponent(Codec2AudioEncHidlTest::standardComp comp, char* mURL) {
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 GetURLForComponent(Codec2AudioEncHidlTest::standardComp comp, char* mURL) {
}
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 @@ void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
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 @@ void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
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 @@ void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
}
}
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 @@ TEST_P(Codec2AudioEncEncodeTest, EncodeTest) {
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 @@ TEST_P(Codec2AudioEncEncodeTest, EncodeTest) {
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 @@ TEST_P(Codec2AudioEncEncodeTest, EncodeTest) {
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 @@ TEST_F(Codec2AudioEncHidlTest, EOSTest) {
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 @@ TEST_F(Codec2AudioEncHidlTest, FlushTest) {
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 @@ TEST_F(Codec2AudioEncHidlTest, FlushTest) {
}
}
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 @@ TEST_F(Codec2AudioEncHidlTest, FlushTest) {
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"));
}
// 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;
}
}
return status;
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -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>

@ -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

@ -1,7 +1,7 @@
cc_library_static {
name: "VtsHalMediaC2V1_0CommonUtil",
defaults: [
"Vts10HalTargetTestDefaults",
"VtsHalTargetTestDefaults",
"libcodec2-hidl-client-defaults",
],
@ -19,15 +19,19 @@ cc_library_static {
cc_defaults {
name: "VtsHalMediaC2V1_0Defaults",
defaults: [
"Vts10HalTargetTestDefaults",
"VtsHalTargetTestDefaults",
"libcodec2-hidl-client-defaults",
],
static_libs: [
"libgtest",
"VtsHalMediaC2V1_0CommonUtil",
],
shared_libs: [
"libcodec2_client",
],
test_suites: [
"vts",
],
}

@ -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: `VtsHalMediaC2V1_0TargetAudioEncTest -I software -C <comp name> -P <path to resource files>`
usage: `atest VtsHalMediaC2V1_0TargetAudioDecTest`
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`

@ -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 @@ void testInputBuffer(
}
// 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 @@ void waitOnInputConsumption(std::mutex& queueLock,
}
// 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 @@ void workDone(
}
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 @@ int64_t getNowUs() {
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;
}

@ -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 @@ struct CodecListener : public android::Codec2Client::Listener {
}
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 @@ struct CodecListener : public android::Codec2Client::Listener {
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;
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;
}
// Return all test parameters, a list of tuple of <instance, component>.
const std::vector<std::tuple<std::string, std::string>>& getTestParameters();
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();

@ -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 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 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); \
}
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 @@ class Codec2ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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_F(Codec2ComponentHidlTest, EmptyFlush) {
}
// 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_F(Codec2ComponentHidlTest, QueueEmptyWork) {
}
// Test Component Configuration
TEST_F(Codec2ComponentHidlTest, Config) {
TEST_P(Codec2ComponentHidlTest, Config) {
ALOGV("Configuration Test");
C2String name = mComponent->getName();
@ -180,7 +189,7 @@ TEST_F(Codec2ComponentHidlTest, Config) {
}
// 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_F(Codec2ComponentHidlTest, MultipleStartStopReset) {
}
// 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 @@ TEST_F(Codec2ComponentHidlTest, MultipleRelease) {
}
}
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 @@ TEST_F(Codec2ComponentHidlTest, Timeout) {
startTime = getNowUs();
err = mComponent->querySupportedParams(&params);
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 @@ TEST_F(Codec2ComponentHidlTest, Timeout) {
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 @@ TEST_F(Codec2ComponentHidlTest, Timeout) {
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 @@ TEST_F(Codec2ComponentHidlTest, Timeout) {
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();
}

@ -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 @@ void displayComponentInfo(const std::vector<C2Component::Traits>& compList) {
}
// 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 @@ TEST_F(Codec2MasterHalTest, ListComponents) {
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);

@ -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 @@ cc_test {
"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",
}

@ -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 @@ struct FrameInfo {
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 @@ class Codec2VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
};
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 @@ class Codec2VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
}
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 @@ class Codec2VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
}
}
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 @@ class Codec2VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
unknown_comp,
};
std::string mInstanceName;
std::string mComponentName;
bool mEos;
bool mDisableTest;
bool mTimestampDevTest;
@ -229,15 +213,23 @@ class Codec2VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ void validateComponent(
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 @@ void validateComponent(
// 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 @@ void GetURLForComponent(Codec2VideoDecHidlTest::standardComp comp, char* mURL,
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 GetURLForComponent(Codec2VideoDecHidlTest::standardComp comp, char* mURL,
}
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 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
}
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 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
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 @@ void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
}
}
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 @@ TEST_F(Codec2VideoDecHidlTest, configureTunnel) {
BufferQueue::createBufferQueue(&producer, &consumer);
class DummyConsumerListener : public BnConsumerListener {
public:
public:
DummyConsumerListener() : BnConsumerListener() {}
void onFrameAvailable(const BufferItem&) override {}
void onBuffersReleased() override {}
@ -458,37 +432,39 @@ TEST_F(Codec2VideoDecHidlTest, configureTunnel) {
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 @@ TEST_P(Codec2VideoDecDecodeTest, DecodeTest) {
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 @@ TEST_P(Codec2VideoDecDecodeTest, DecodeTest) {
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 @@ TEST_F(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
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 @@ TEST_F(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
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 @@ TEST_F(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
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 @@ TEST_F(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
// 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 @@ TEST_F(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
}
// 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 @@ TEST_F(Codec2VideoDecHidlTest, ThumbnailTest) {
} 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 @@ TEST_F(Codec2VideoDecHidlTest, ThumbnailTest) {
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 @@ TEST_F(Codec2VideoDecHidlTest, EOSTest) {
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 @@ TEST_F(Codec2VideoDecHidlTest, FlushTest) {
// 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 @@ TEST_F(Codec2VideoDecHidlTest, FlushTest) {
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 @@ TEST_F(Codec2VideoDecHidlTest, FlushTest) {
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 @@ TEST_F(Codec2VideoDecHidlTest, DecodeTestEmptyBuffersInserted) {
// 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 @@ TEST_F(Codec2VideoDecHidlTest, DecodeTestEmptyBuffersInserted) {
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"));
}
// 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;
}
}
return status;
}
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -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>

@ -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;
namespace {
class Codec2VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
private:
typedef ::testing::VtsHalHidlTargetTestBase Super;
// Resource directory
static std::string sResourceDir = "";
public:
::std::string getTestCaseInfo() const override {
return ::std::string() +
"Component: " + gEnv->getComponent().c_str() + " | " +
"Instance: " + gEnv->getInstance().c_str() + " | " +
"Res: " + gEnv->getRes().c_str();
}
namespace {
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 @@ class Codec2VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
};
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 @@ class Codec2VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
// 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 @@ class Codec2VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ class Codec2VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
}
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 @@ class Codec2VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
unknown_comp,
};
std::string mInstanceName;
std::string mComponentName;
bool mEos;
bool mCsd;
bool mDisableTest;
@ -217,15 +202,23 @@ class Codec2VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
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 @@ void validateComponent(
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 @@ void validateComponent(
}
// 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 GetURLForComponent(char* URL) {
}
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 @@ void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
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 @@ void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
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 @@ void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& comp
}
}
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 @@ TEST_P(Codec2VideoEncEncodeTest, EncodeTest) {
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 @@ TEST_P(Codec2VideoEncEncodeTest, EncodeTest) {
// 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 @@ TEST_P(Codec2VideoEncEncodeTest, EncodeTest) {
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 @@ TEST_F(Codec2VideoEncHidlTest, EOSTest) {
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 @@ TEST_F(Codec2VideoEncHidlTest, FlushTest) {
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 @@ TEST_F(Codec2VideoEncHidlTest, FlushTest) {
}
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 @@ TEST_F(Codec2VideoEncHidlTest, FlushTest) {
}
}
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 @@ TEST_F(Codec2VideoEncHidlTest, FlushTest) {
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 @@ TEST_F(Codec2VideoEncHidlTest, FlushTest) {
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 @@ TEST_F(Codec2VideoEncHidlTest, InvalidBufferTest) {
}
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 @@ TEST_F(Codec2VideoEncHidlTest, InvalidBufferTest) {
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 @@ TEST_P(Codec2VideoEncResolutionTest, ResolutionTest) {
}
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 @@ TEST_P(Codec2VideoEncResolutionTest, ResolutionTest) {
}
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();
}

@ -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>

@ -29,5 +29,4 @@
* Common video utils
*/
#endif // MEDIA_C2_VIDEO_HIDL_TEST_COMMON_H

Loading…
Cancel
Save