Merge "media.omx VTS test baseline" into oc-dev

This commit is contained in:
Zhuoyao Zhang
2017-04-13 19:24:28 +00:00
committed by Android (Google) Code Review
11 changed files with 3048 additions and 0 deletions

3
media/Android.bp Normal file → Executable file
View File

@@ -2,4 +2,7 @@
subdirs = [
"1.0",
"omx/1.0",
"omx/1.0/vts/functional/master",
"omx/1.0/vts/functional/component",
"omx/1.0/vts/functional/audio",
]

View File

@@ -0,0 +1,79 @@
//
// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
cc_test {
name: "VtsHalMediaOmxV1_0TargetAudioEncTest",
defaults: ["hidl_defaults"],
srcs: ["VtsHalMediaOmxV1_0TargetAudioEncTest.cpp",
"media_audio_hidl_test_common.cpp"],
shared_libs: [
"libbase",
"liblog",
"libcutils",
"libhidlbase",
"libhidlmemory",
"libhidltransport",
"libhwbinder",
"libnativehelper",
"libutils",
"libstagefright_foundation",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"android.hardware.media.omx@1.0",
],
static_libs: ["VtsHalHidlTargetTestBase"],
cflags: [
"-O0",
"-g",
],
include_dirs: [
"frameworks/native/include/media/openmax/",
"hardware/interfaces/media/omx/1.0/vts/functional/common",
],
}
cc_test {
name: "VtsHalMediaOmxV1_0TargetAudioDecTest",
defaults: ["hidl_defaults"],
srcs: ["VtsHalMediaOmxV1_0TargetAudioDecTest.cpp",
"media_audio_hidl_test_common.cpp"],
shared_libs: [
"libbase",
"liblog",
"libcutils",
"libhidlbase",
"libhidlmemory",
"libhidltransport",
"libhwbinder",
"libnativehelper",
"libutils",
"libstagefright_foundation",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"android.hardware.media.omx@1.0",
],
static_libs: ["VtsHalHidlTargetTestBase"],
cflags: [
"-O0",
"-g",
],
include_dirs: [
"frameworks/native/include/media/openmax/",
"hardware/interfaces/media/omx/1.0/vts/functional/common",
],
}

View File

@@ -0,0 +1,687 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "media_omx_hidl_audio_dec_test"
#include <android-base/logging.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <android/hardware/media/omx/1.0/IOmxObserver.h>
#include <android/hardware/media/omx/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::media::omx::V1_0::IOmxObserver;
using ::android::hardware::media::omx::V1_0::IOmxNode;
using ::android::hardware::media::omx::V1_0::Message;
using ::android::hardware::media::omx::V1_0::CodecBuffer;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::hidl::memory::V1_0::IMapper;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;
#include <VtsHalHidlTargetTestBase.h>
#include <getopt.h>
#include <media_audio_hidl_test_common.h>
#include <media_hidl_test_common.h>
#include <fstream>
// A class for test environment setup
class ComponentTestEnvironment : public ::testing::Environment {
public:
virtual void SetUp() {}
virtual void TearDown() {}
ComponentTestEnvironment() : instance("default") {}
void setInstance(const char* _instance) { instance = _instance; }
void setComponent(const char* _component) { component = _component; }
void setRole(const char* _role) { role = _role; }
void setQuirks(int _quirks) { quirks = _quirks; }
const hidl_string getInstance() const { return instance; }
const hidl_string getComponent() const { return component; }
const hidl_string getRole() const { return role; }
int getQuirks() const { return quirks; }
int initFromOptions(int argc, char** argv) {
static struct option options[] = {
{"instance", required_argument, 0, 'I'},
{"component", required_argument, 0, 'C'},
{"role", required_argument, 0, 'R'},
{"quirks", required_argument, 0, 'Q'},
{0, 0, 0, 0}};
while (true) {
int index = 0;
int c = getopt_long(argc, argv, "I:C:Q:R:", options, &index);
if (c == -1) {
break;
}
switch (c) {
case 'I':
setInstance(optarg);
break;
case 'C':
setComponent(optarg);
break;
case 'Q':
setQuirks(atoi(optarg));
break;
case 'R':
setRole(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: HAL instance to test\n"
"-C, --component: OMX component to test\n"
"-R, --Role: OMX component Role\n"
"-Q, --quirks: Component quirks\n",
argv[optind ?: 1], argv[0]);
return 2;
}
return 0;
}
private:
hidl_string instance;
hidl_string component;
hidl_string role;
// to be removed when IOmxNode::setQuirks is removed
int quirks;
};
static ComponentTestEnvironment* gEnv = nullptr;
class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
public:
virtual void SetUp() override {
android::hardware::media::omx::V1_0::Status status;
omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>(
gEnv->getInstance());
ASSERT_NE(omx, nullptr);
observer = new CodecObserver();
ASSERT_NE(observer, nullptr);
ASSERT_EQ(strncmp(gEnv->getComponent().c_str(), "OMX.", 4), 0)
<< "Invalid Component Name";
EXPECT_TRUE(omx->allocateNode(
gEnv->getComponent(), observer,
[&](android::hardware::media::omx::V1_0::Status _s,
sp<IOmxNode> const& _nl) {
status = _s;
this->omxNode = _nl;
})
.isOk());
ASSERT_NE(omxNode, nullptr);
ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
struct StringToName {
const char* Name;
standardComp CompName;
};
const StringToName kStringToName[] = {
{"mp3", mp3}, {"amrnb", amrnb}, {"amrwb", amrwb},
{"aac", aac}, {"vorbis", vorbis}, {"opus", opus},
{"pcm", pcm}, {"flac", flac},
};
const size_t kNumStringToName =
sizeof(kStringToName) / sizeof(kStringToName[0]);
const char* pch;
char substring[OMX_MAX_STRINGNAME_SIZE];
strcpy(substring, gEnv->getRole().c_str());
pch = strchr(substring, '.');
ASSERT_NE(pch, nullptr);
compName = unknown_comp;
for (size_t i = 0; i < kNumStringToName; ++i) {
if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
compName = kStringToName[i].CompName;
break;
}
}
ASSERT_NE(compName, unknown_comp);
struct CompToCoding {
standardComp CompName;
OMX_AUDIO_CODINGTYPE eEncoding;
};
static const CompToCoding kCompToCoding[] = {
{mp3, OMX_AUDIO_CodingMP3},
{amrnb, OMX_AUDIO_CodingAMR},
{amrwb, OMX_AUDIO_CodingAMR},
{aac, OMX_AUDIO_CodingAAC},
{vorbis, OMX_AUDIO_CodingVORBIS},
{pcm, OMX_AUDIO_CodingPCM},
{opus, (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS},
{flac, OMX_AUDIO_CodingFLAC},
};
static const size_t kNumCompToCoding =
sizeof(kCompToCoding) / sizeof(kCompToCoding[0]);
size_t i;
for (i = 0; i < kNumCompToCoding; ++i) {
if (kCompToCoding[i].CompName == compName) {
eEncoding = kCompToCoding[i].eEncoding;
break;
}
}
ASSERT_NE(i, kNumCompToCoding);
}
virtual void TearDown() override {
if (omxNode != nullptr) {
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
}
enum standardComp {
mp3,
amrnb,
amrwb,
aac,
vorbis,
opus,
pcm,
flac,
unknown_comp,
};
sp<IOmx> omx;
sp<CodecObserver> observer;
sp<IOmxNode> omxNode;
standardComp compName;
OMX_AUDIO_CODINGTYPE eEncoding;
};
void setDefaultPortParam(
sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding,
int32_t nChannels = 2, int32_t nSampleRate = 44100,
OMX_NUMERICALDATATYPE eNumData = OMX_NumericalDataSigned,
int32_t nBitPerSample = 16) {
android::hardware::media::omx::V1_0::Status status;
OMX_PARAM_PORTDEFINITIONTYPE portDef;
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
&portDef);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
portDef.format.audio.bFlagErrorConcealment = OMX_TRUE;
portDef.format.audio.eEncoding = eEncoding;
status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
&portDef);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
switch ((int)eEncoding) {
case OMX_AUDIO_CodingPCM:
setupPCMPort(omxNode, portIndex, nChannels, eNumData, nBitPerSample,
nSampleRate);
break;
default:
ASSERT_TRUE(false);
break;
}
}
void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
OMX_AUDIO_CODINGTYPE eEncoding, int32_t* nChannels,
int32_t* nSampleRate) {
*nChannels = 0;
*nSampleRate = 0;
android::hardware::media::omx::V1_0::Status status;
switch ((int)eEncoding) {
case OMX_AUDIO_CodingPCM: {
OMX_AUDIO_PARAM_PCMMODETYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioPcm,
kPortIndexInput, &param);
ASSERT_EQ(status,
::android::hardware::media::omx::V1_0::Status::OK);
*nChannels = param.nChannels;
*nSampleRate = param.nSamplingRate;
break;
}
case OMX_AUDIO_CodingMP3: {
OMX_AUDIO_PARAM_MP3TYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioMp3,
kPortIndexInput, &param);
ASSERT_EQ(status,
::android::hardware::media::omx::V1_0::Status::OK);
*nChannels = param.nChannels;
*nSampleRate = param.nSampleRate;
break;
}
case OMX_AUDIO_CodingFLAC: {
OMX_AUDIO_PARAM_FLACTYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioFlac,
kPortIndexInput, &param);
ASSERT_EQ(status,
::android::hardware::media::omx::V1_0::Status::OK);
*nChannels = param.nChannels;
*nSampleRate = param.nSampleRate;
break;
}
case OMX_AUDIO_CodingAndroidOPUS: {
OMX_AUDIO_PARAM_ANDROID_OPUSTYPE param;
status = getPortParam(omxNode,
(OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
kPortIndexInput, &param);
ASSERT_EQ(status,
::android::hardware::media::omx::V1_0::Status::OK);
*nChannels = param.nChannels;
*nSampleRate = param.nSampleRate;
break;
}
case OMX_AUDIO_CodingVORBIS: {
OMX_AUDIO_PARAM_VORBISTYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioVorbis,
kPortIndexInput, &param);
ASSERT_EQ(status,
::android::hardware::media::omx::V1_0::Status::OK);
*nChannels = param.nChannels;
*nSampleRate = param.nSampleRate;
break;
}
case OMX_AUDIO_CodingAMR: {
OMX_AUDIO_PARAM_AMRTYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioAmr,
kPortIndexInput, &param);
ASSERT_EQ(status,
::android::hardware::media::omx::V1_0::Status::OK);
*nChannels = param.nChannels;
*nSampleRate = 8000;
break;
}
case OMX_AUDIO_CodingAAC: {
OMX_AUDIO_PARAM_AACPROFILETYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioAac,
kPortIndexInput, &param);
ASSERT_EQ(status,
::android::hardware::media::omx::V1_0::Status::OK);
*nChannels = param.nChannels;
*nSampleRate = param.nSampleRate;
break;
}
default:
ASSERT_TRUE(false);
break;
}
}
void GetURLForComponent(AudioDecHidlTest::standardComp comp, const char** mURL,
const char** info) {
struct CompToURL {
AudioDecHidlTest::standardComp comp;
const char* mURL;
const char* info;
};
static const CompToURL kCompToURL[] = {
{AudioDecHidlTest::standardComp::mp3,
"/sdcard/raw/MP3_48KHz_128kbps_s_1_17_CBR.audio.mp3",
"/sdcard/raw/MP3_48KHz_128kbps_s_1_17_CBR.audio.info"},
{AudioDecHidlTest::standardComp::aac,
"/sdcard/raw/H264_500_AAC_128.audio.aac",
"/sdcard/raw/H264_500_AAC_128.audio.info"},
{AudioDecHidlTest::standardComp::amrnb,
"/sdcard/raw/H264_320_AMRNB_6.audio.amr",
"/sdcard/raw/H264_320_AMRNB_6.audio.info"},
{AudioDecHidlTest::standardComp::amrwb, "", ""},
{AudioDecHidlTest::standardComp::vorbis, "", ""},
{AudioDecHidlTest::standardComp::opus, "", ""},
{AudioDecHidlTest::standardComp::flac, "", ""},
};
for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
if (kCompToURL[i].comp == comp) {
*mURL = kCompToURL[i].mURL;
*info = kCompToURL[i].info;
return;
}
}
}
void flushAllPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
android::Vector<BufferInfo>* iBuffer,
android::Vector<BufferInfo>* oBuffer,
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput) {
android::hardware::media::omx::V1_0::Status status;
Message msg;
// Flush
status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
kPortIndexInput);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandFlush);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexInput);
// test if client got all its buffers back
for (size_t i = 0; i < iBuffer->size(); ++i) {
EXPECT_EQ((*iBuffer)[i].owner, client);
}
status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
kPortIndexOutput);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandFlush);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
// test if client got all its buffers back
for (size_t i = 0; i < oBuffer->size(); ++i) {
EXPECT_EQ((*oBuffer)[i].owner, client);
}
}
void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
android::Vector<BufferInfo>* iBuffer,
android::Vector<BufferInfo>* oBuffer,
OMX_AUDIO_CODINGTYPE eEncoding, OMX_U32 kPortIndexInput,
OMX_U32 kPortIndexOutput, uint32_t nFrames,
std::ifstream& eleStream, std::ifstream& eleInfo) {
android::hardware::media::omx::V1_0::Status status;
Message msg;
// dispatch output buffers
for (size_t i = 0; i < oBuffer->size(); i++) {
dispatchOutputBuffer(omxNode, oBuffer, i);
}
// dispatch input buffers
int bytesCount = 0;
for (size_t i = 0; i < iBuffer->size(); i++) {
char* ipBuffer = static_cast<char*>(
static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
if (!(eleInfo >> bytesCount)) break;
eleStream.read(ipBuffer, bytesCount);
ASSERT_EQ(eleStream.gcount(), bytesCount);
dispatchInputBuffer(omxNode, iBuffer, i, bytesCount, 0, 0);
}
while (nFrames != 0) {
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
if (status == android::hardware::media::omx::V1_0::Status::OK &&
msg.type == Message::Type::EVENT &&
msg.data.eventData.event == OMX_EventPortSettingsChanged) {
ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
status = omxNode->sendCommand(
toRawCommandType(OMX_CommandPortDisable), kPortIndexOutput);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
oBuffer);
if (status ==
android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
for (size_t i = 0; i < oBuffer->size(); ++i) {
// test if client got all its buffers back
EXPECT_EQ((*oBuffer)[i].owner, client);
// free the buffers
status =
omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
}
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
// Port Reconfigurations
int32_t nChannels;
int32_t nSampleRate;
getInputChannelInfo(omxNode, kPortIndexInput, eEncoding,
&nChannels, &nSampleRate);
setDefaultPortParam(omxNode, kPortIndexOutput,
OMX_AUDIO_CodingPCM, nChannels,
nSampleRate);
// If you can disable a port, then you should be able to enable
// it as well
status = omxNode->sendCommand(
toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
// do not enable the port until all the buffers are supplied
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(
status,
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
// dispatch output buffers
for (size_t i = 0; i < oBuffer->size(); i++) {
dispatchOutputBuffer(omxNode, oBuffer, i);
}
} else {
ASSERT_TRUE(false);
}
continue;
}
size_t index = 0;
if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
char* ipBuffer = static_cast<char*>(
static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
if (!(eleInfo >> bytesCount)) break;
eleStream.read(ipBuffer, bytesCount);
ASSERT_EQ(eleStream.gcount(), bytesCount);
dispatchInputBuffer(omxNode, iBuffer, index, bytesCount, 0, 0);
}
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
dispatchOutputBuffer(omxNode, oBuffer, index);
}
nFrames--;
}
}
// Set Component Role
TEST_F(AudioDecHidlTest, SetRole) {
android::hardware::media::omx::V1_0::Status status;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// Enumerate Port Format
TEST_F(AudioDecHidlTest, EnumeratePortFormat) {
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
ASSERT_EQ(params.nPorts, 2U);
kPortIndexInput = params.nStartPortNumber;
kPortIndexOutput = kPortIndexInput + 1;
}
status = setAudioPortFormat(omxNode, kPortIndexInput, eEncoding);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
status = setAudioPortFormat(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// Decode Test
TEST_F(AudioDecHidlTest, DecodeTest) {
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
ASSERT_EQ(params.nPorts, 2U);
kPortIndexInput = params.nStartPortNumber;
kPortIndexOutput = kPortIndexInput + 1;
}
const char *mURL = nullptr, *info = nullptr;
GetURLForComponent(compName, &mURL, &info);
EXPECT_NE(mURL, nullptr);
EXPECT_NE(info, nullptr);
std::ifstream eleStream, eleInfo;
eleStream.open(mURL, std::ifstream::binary);
ASSERT_EQ(eleStream.is_open(), true);
eleInfo.open(info);
ASSERT_EQ(eleInfo.is_open(), true);
if (eEncoding == OMX_AUDIO_CodingPCM)
setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
int32_t nChannels;
int32_t nSampleRate;
getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
&nSampleRate);
setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
nChannels, nSampleRate);
Message msg;
android::Vector<BufferInfo> iBuffer, oBuffer;
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateIdle);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
allocatePortBuffers(omxNode, &iBuffer, kPortIndexInput);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
allocatePortBuffers(omxNode, &oBuffer, kPortIndexOutput);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle);
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateExecuting);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateExecuting);
// Port Reconfiguration
decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
kPortIndexInput, kPortIndexOutput, (1 << 12), eleStream,
eleInfo);
// flush
flushAllPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
kPortIndexOutput);
// set state to Idle
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateIdle);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle);
// set state to Loaded
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateLoaded);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
// dont change state until all buffers are freed
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
for (size_t i = 0; i < iBuffer.size(); ++i) {
status = omxNode->freeBuffer(kPortIndexInput, iBuffer[i].id);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
}
// dont change state until all buffers are freed
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
for (size_t i = 0; i < oBuffer.size(); ++i) {
status = omxNode->freeBuffer(kPortIndexOutput, oBuffer[i].id);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
}
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateLoaded);
eleInfo.close();
eleStream.close();
}
int main(int argc, char** argv) {
gEnv = new ComponentTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
if (status == 0) {
status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
}
return status;
}

View File

@@ -0,0 +1,263 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "media_omx_hidl_audio_enc_test"
#include <android-base/logging.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <android/hardware/media/omx/1.0/IOmxObserver.h>
#include <android/hardware/media/omx/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::media::omx::V1_0::IOmxObserver;
using ::android::hardware::media::omx::V1_0::IOmxNode;
using ::android::hardware::media::omx::V1_0::Message;
using ::android::hardware::media::omx::V1_0::CodecBuffer;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::hidl::memory::V1_0::IMapper;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;
#include <VtsHalHidlTargetTestBase.h>
#include <getopt.h>
#include <media_audio_hidl_test_common.h>
#include <media_hidl_test_common.h>
#include <fstream>
// A class for test environment setup
class ComponentTestEnvironment : public ::testing::Environment {
public:
virtual void SetUp() {}
virtual void TearDown() {}
ComponentTestEnvironment() : instance("default") {}
void setInstance(const char* _instance) { instance = _instance; }
void setComponent(const char* _component) { component = _component; }
void setRole(const char* _role) { role = _role; }
void setQuirks(int _quirks) { quirks = _quirks; }
const hidl_string getInstance() const { return instance; }
const hidl_string getComponent() const { return component; }
const hidl_string getRole() const { return role; }
int getQuirks() const { return quirks; }
int initFromOptions(int argc, char** argv) {
static struct option options[] = {
{"instance", required_argument, 0, 'I'},
{"component", required_argument, 0, 'C'},
{"role", required_argument, 0, 'R'},
{"quirks", required_argument, 0, 'Q'},
{0, 0, 0, 0}};
while (true) {
int index = 0;
int c = getopt_long(argc, argv, "I:C:Q:R:", options, &index);
if (c == -1) {
break;
}
switch (c) {
case 'I':
setInstance(optarg);
break;
case 'C':
setComponent(optarg);
break;
case 'Q':
setQuirks(atoi(optarg));
break;
case 'R':
setRole(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: HAL instance to test\n"
"-C, --component: OMX component to test\n"
"-R, --Role: OMX component Role\n"
"-Q, --quirks: Component quirks\n",
argv[optind ?: 1], argv[0]);
return 2;
}
return 0;
}
private:
hidl_string instance;
hidl_string component;
hidl_string role;
// to be removed when IOmxNode::setQuirks is removed
int quirks;
};
static ComponentTestEnvironment* gEnv = nullptr;
class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
public:
virtual void SetUp() override {
android::hardware::media::omx::V1_0::Status status;
omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>(
gEnv->getInstance());
ASSERT_NE(omx, nullptr);
observer = new CodecObserver();
ASSERT_NE(observer, nullptr);
ASSERT_EQ(strncmp(gEnv->getComponent().c_str(), "OMX.", 4), 0)
<< "Invalid Component Name";
EXPECT_TRUE(omx->allocateNode(
gEnv->getComponent(), observer,
[&](android::hardware::media::omx::V1_0::Status _s,
sp<IOmxNode> const& _nl) {
status = _s;
this->omxNode = _nl;
})
.isOk());
ASSERT_NE(omxNode, nullptr);
ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
struct StringToName {
const char* Name;
standardComp CompName;
};
const StringToName kStringToName[] = {
{"mp3", mp3}, {"amrnb", amrnb}, {"amrwb", amrwb},
{"aac", aac}, {"vorbis", vorbis}, {"opus", opus},
{"pcm", pcm}, {"flac", flac},
};
const size_t kNumStringToName =
sizeof(kStringToName) / sizeof(kStringToName[0]);
const char* pch;
char substring[OMX_MAX_STRINGNAME_SIZE];
strcpy(substring, gEnv->getRole().c_str());
pch = strchr(substring, '.');
ASSERT_NE(pch, nullptr);
compName = unknown_comp;
for (size_t i = 0; i < kNumStringToName; ++i) {
if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
compName = kStringToName[i].CompName;
break;
}
}
ASSERT_NE(compName, unknown_comp);
struct CompToCoding {
standardComp CompName;
OMX_AUDIO_CODINGTYPE eEncoding;
};
static const CompToCoding kCompToCoding[] = {
{mp3, OMX_AUDIO_CodingMP3},
{amrnb, OMX_AUDIO_CodingAMR},
{amrwb, OMX_AUDIO_CodingAMR},
{aac, OMX_AUDIO_CodingAAC},
{vorbis, OMX_AUDIO_CodingVORBIS},
{pcm, OMX_AUDIO_CodingPCM},
{opus, (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS},
{flac, OMX_AUDIO_CodingFLAC},
};
static const size_t kNumCompToCoding =
sizeof(kCompToCoding) / sizeof(kCompToCoding[0]);
size_t i;
for (i = 0; i < kNumCompToCoding; ++i) {
if (kCompToCoding[i].CompName == compName) {
eEncoding = kCompToCoding[i].eEncoding;
break;
}
}
ASSERT_NE(i, kNumCompToCoding);
}
virtual void TearDown() override {
if (omxNode != nullptr) {
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
}
enum standardComp {
mp3,
amrnb,
amrwb,
aac,
vorbis,
opus,
pcm,
flac,
unknown_comp,
};
sp<IOmx> omx;
sp<CodecObserver> observer;
sp<IOmxNode> omxNode;
standardComp compName;
OMX_AUDIO_CODINGTYPE eEncoding;
};
// Set Component Role
TEST_F(AudioEncHidlTest, SetRole) {
android::hardware::media::omx::V1_0::Status status;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// Enumerate Port Format
TEST_F(AudioEncHidlTest, EnumeratePortFormat) {
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
ASSERT_EQ(params.nPorts, 2U);
kPortIndexInput = params.nStartPortNumber;
kPortIndexOutput = kPortIndexInput + 1;
}
status = setAudioPortFormat(omxNode, kPortIndexInput, OMX_AUDIO_CodingPCM);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
status = setAudioPortFormat(omxNode, kPortIndexOutput, eEncoding);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
int main(int argc, char** argv) {
gEnv = new ComponentTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
if (status == 0) {
status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
}
return status;
}

View File

@@ -0,0 +1,316 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "media_omx_hidl_audio_test_common"
#include <android-base/logging.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <android/hardware/media/omx/1.0/IOmxObserver.h>
#include <android/hardware/media/omx/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::media::omx::V1_0::IOmxObserver;
using ::android::hardware::media::omx::V1_0::IOmxNode;
using ::android::hardware::media::omx::V1_0::Message;
using ::android::hardware::media::omx::V1_0::CodecBuffer;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::hidl::memory::V1_0::IMapper;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;
#include <VtsHalHidlTargetTestBase.h>
#include <hidlmemory/mapping.h>
#include <media_audio_hidl_test_common.h>
#include <media_hidl_test_common.h>
#include <memory>
void allocatePortBuffers(sp<IOmxNode> omxNode,
android::Vector<BufferInfo>* buffArray,
OMX_U32 portIndex) {
android::hardware::media::omx::V1_0::Status status;
OMX_PARAM_PORTDEFINITIONTYPE portDef;
buffArray->clear();
sp<IAllocator> allocator = IAllocator::getService("ashmem");
EXPECT_NE(allocator, nullptr);
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
&portDef);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
BufferInfo buffer;
buffer.owner = client;
buffer.omxBuffer.type = CodecBuffer::Type::SHARED_MEM;
buffer.omxBuffer.attr.preset.rangeOffset = 0;
buffer.omxBuffer.attr.preset.rangeLength = 0;
bool success;
allocator->allocate(
portDef.nBufferSize,
[&success, &buffer](bool _s,
::android::hardware::hidl_memory const& mem) {
success = _s;
buffer.omxBuffer.sharedMemory = mem;
});
ASSERT_EQ(success, true);
buffer.mMemory = mapMemory(buffer.omxBuffer.sharedMemory);
ASSERT_NE(buffer.mMemory, nullptr);
omxNode->useBuffer(
portIndex, buffer.omxBuffer,
[&status, &buffer](android::hardware::media::omx::V1_0::Status _s,
uint32_t id) {
status = _s;
buffer.id = id;
});
buffArray->push(buffer);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
}
size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray) {
for (size_t i = 0; i < buffArray->size(); i++) {
if ((*buffArray)[i].owner == client) return i;
}
return buffArray->size();
}
void dispatchInputBuffer(sp<IOmxNode> omxNode,
android::Vector<BufferInfo>* buffArray,
size_t bufferIndex, int bytesCount, uint32_t flags,
uint64_t timestamp) {
android::hardware::media::omx::V1_0::Status status;
CodecBuffer t;
t.sharedMemory = android::hardware::hidl_memory();
t.nativeHandle = android::hardware::hidl_handle();
t.type = CodecBuffer::Type::PRESET;
t.attr.preset.rangeOffset = 0;
t.attr.preset.rangeLength = bytesCount;
native_handle_t* fenceNh = native_handle_create(0, 0);
ASSERT_NE(fenceNh, nullptr);
status = omxNode->emptyBuffer((*buffArray)[bufferIndex].id, t, flags,
timestamp, fenceNh);
native_handle_close(fenceNh);
native_handle_delete(fenceNh);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
buffArray->editItemAt(bufferIndex).owner = component;
}
void dispatchOutputBuffer(sp<IOmxNode> omxNode,
android::Vector<BufferInfo>* buffArray,
size_t bufferIndex) {
android::hardware::media::omx::V1_0::Status status;
CodecBuffer t;
t.sharedMemory = android::hardware::hidl_memory();
t.nativeHandle = android::hardware::hidl_handle();
t.type = CodecBuffer::Type::PRESET;
t.attr.preset.rangeOffset = 0;
t.attr.preset.rangeLength = 0;
native_handle_t* fenceNh = native_handle_create(0, 0);
ASSERT_NE(fenceNh, nullptr);
status = omxNode->fillBuffer((*buffArray)[bufferIndex].id, t, fenceNh);
native_handle_close(fenceNh);
native_handle_delete(fenceNh);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
buffArray->editItemAt(bufferIndex).owner = component;
}
Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE encoding) {
OMX_U32 index = 0;
OMX_AUDIO_PARAM_PORTFORMATTYPE portFormat;
std::vector<OMX_AUDIO_CODINGTYPE> eEncoding;
android::hardware::media::omx::V1_0::Status status;
while (1) {
portFormat.nIndex = index;
status = getPortParam(omxNode, OMX_IndexParamAudioPortFormat, portIndex,
&portFormat);
if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
eEncoding.push_back(portFormat.eEncoding);
index++;
if (index == 512) {
EXPECT_LE(index, 512U)
<< "Expecting OMX_ErrorNoMore but not received";
break;
}
}
if (!index) return status;
for (index = 0; index < eEncoding.size(); index++) {
if (eEncoding[index] == encoding) {
portFormat.eEncoding = eEncoding[index];
break;
}
}
if (index == eEncoding.size()) {
ALOGI("setting default Port format");
portFormat.eEncoding = eEncoding[0];
}
// In setParam call nIndex shall be ignored as per omx-il specification.
// see how this holds up by corrupting nIndex
portFormat.nIndex = RANDOM_INDEX;
status = setPortParam(omxNode, OMX_IndexParamAudioPortFormat, portIndex,
&portFormat);
return status;
}
Return<android::hardware::media::omx::V1_0::Status> setRole(
sp<IOmxNode> omxNode, const char* role) {
OMX_PARAM_COMPONENTROLETYPE params;
strcpy((char*)params.cRole, role);
return setParam(omxNode, OMX_IndexParamStandardComponentRole, &params);
}
void setupPCMPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
OMX_NUMERICALDATATYPE eNumData, int32_t nBitPerSample,
int32_t nSamplingRate) {
OMX_AUDIO_PARAM_PCMMODETYPE param;
android::hardware::media::omx::V1_0::Status status;
status = getPortParam(omxNode, OMX_IndexParamAudioPcm, portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
param.nChannels = nChannels;
param.eNumData = eNumData;
param.eEndian = OMX_EndianBig;
param.bInterleaved = OMX_TRUE;
param.nBitPerSample = nBitPerSample;
param.nSamplingRate = nSamplingRate;
param.ePCMMode = OMX_AUDIO_PCMModeLinear;
switch (nChannels) {
case 1:
param.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
break;
case 2:
param.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
param.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
break;
default:
EXPECT_TRUE(false);
}
status = setPortParam(omxNode, OMX_IndexParamAudioPcm, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupMP3Port(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_AUDIO_MP3STREAMFORMATTYPE eFormat, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, bool isEncoder) {
if (isEncoder == false) return;
OMX_AUDIO_PARAM_MP3TYPE param;
android::hardware::media::omx::V1_0::Status status;
status = getPortParam(omxNode, OMX_IndexParamAudioMp3, portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
param.nChannels = nChannels;
param.nBitRate = nBitRate;
param.nSampleRate = nSampleRate;
param.nAudioBandWidth = 0;
param.eChannelMode = (nChannels == 1) ? OMX_AUDIO_ChannelModeMono
: OMX_AUDIO_ChannelModeStereo;
param.eFormat = eFormat;
status = setPortParam(omxNode, OMX_IndexParamAudioMp3, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupFLACPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nSampleRate, int32_t nCompressionLevel,
bool isEncoder) {
if (isEncoder == false) return;
android::hardware::media::omx::V1_0::Status status;
OMX_AUDIO_PARAM_FLACTYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioFlac, portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
param.nChannels = nChannels;
param.nSampleRate = nSampleRate;
param.nCompressionLevel = nCompressionLevel;
status = setPortParam(omxNode, OMX_IndexParamAudioFlac, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupOPUSPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, bool isEncoder) {
if (isEncoder == false) return;
android::hardware::media::omx::V1_0::Status status;
OMX_AUDIO_PARAM_ANDROID_OPUSTYPE param;
status =
getPortParam(omxNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
param.nChannels = nChannels;
param.nBitRate = nBitRate;
param.nSampleRate = nSampleRate;
status =
setPortParam(omxNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupAMRPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nBitRate,
OMX_AUDIO_AMRBANDMODETYPE eAMRBandMode, bool isEncoder) {
if (isEncoder == false) return;
android::hardware::media::omx::V1_0::Status status;
OMX_AUDIO_PARAM_AMRTYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioAmr, portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
param.nChannels = 1;
param.nBitRate = nBitRate;
param.eAMRBandMode = eAMRBandMode;
status = setPortParam(omxNode, OMX_IndexParamAudioAmr, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupVORBISPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, int32_t nQuality,
bool isEncoder) {
if (isEncoder == false) return;
android::hardware::media::omx::V1_0::Status status;
OMX_AUDIO_PARAM_VORBISTYPE param;
status =
getPortParam(omxNode, OMX_IndexParamAudioVorbis, portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
param.nChannels = nChannels;
param.nBitRate = nBitRate;
param.nSampleRate = nSampleRate;
param.nQuality = nQuality;
status =
setPortParam(omxNode, OMX_IndexParamAudioVorbis, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupAACPort(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_AUDIO_AACPROFILETYPE eAACProfile,
OMX_AUDIO_AACSTREAMFORMATTYPE eAACStreamFormat,
int32_t nChannels, int32_t nBitRate, int32_t nSampleRate,
bool isEncoder) {
if (isEncoder == false) return;
android::hardware::media::omx::V1_0::Status status;
OMX_AUDIO_PARAM_AACPROFILETYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioAac, portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
param.nChannels = nChannels;
param.nSampleRate = nSampleRate;
param.nBitRate = nBitRate;
param.eAACProfile = eAACProfile;
param.eAACStreamFormat = eAACStreamFormat;
param.eChannelMode = (nChannels == 1) ? OMX_AUDIO_ChannelModeMono
: OMX_AUDIO_ChannelModeStereo;
status = setPortParam(omxNode, OMX_IndexParamAudioAac, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2016, 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_AUDIO_HIDL_TEST_COMMON_H
#define MEDIA_AUDIO_HIDL_TEST_COMMON_H
#include <media_hidl_test_common.h>
/*
* Random Index used for monkey testing while get/set parameters
*/
#define RANDOM_INDEX 1729
/*
* Common audio utils
*/
void allocatePortBuffers(sp<IOmxNode> omxNode,
android::Vector<BufferInfo>* buffArray,
OMX_U32 portIndex);
size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray);
void dispatchInputBuffer(sp<IOmxNode> omxNode,
android::Vector<BufferInfo>* buffArray,
size_t bufferIndex, int bytesCount, uint32_t flags,
uint64_t timestamp);
void dispatchOutputBuffer(sp<IOmxNode> omxNode,
android::Vector<BufferInfo>* buffArray,
size_t bufferIndex);
Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE encoding);
Return<android::hardware::media::omx::V1_0::Status> setRole(
sp<IOmxNode> omxNode, const char* role);
void setupPCMPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
OMX_NUMERICALDATATYPE eNumData, int32_t nBitPerSample,
int32_t nSamplingRate);
void setupMP3Port(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_AUDIO_MP3STREAMFORMATTYPE eFormat, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, bool isEncoder);
void setupFLACPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nSampleRate, int32_t nCompressionLevel,
bool isEncoder);
void setupOPUSPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, bool isEncoder);
void setupAMRPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nBitRate,
OMX_AUDIO_AMRBANDMODETYPE eAMRBandMode, bool isEncoder);
void setupVORBISPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, int32_t nQuality,
bool isEncoder);
void setupAACPort(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_AUDIO_AACPROFILETYPE eAACProfile,
OMX_AUDIO_AACSTREAMFORMATTYPE eAACStreamFormat,
int32_t nChannels, int32_t nBitRate, int32_t nSampleRate,
bool isEncoder);
#endif // MEDIA_AUDIO_HIDL_TEST_COMMON_H

View File

@@ -0,0 +1,206 @@
/*
* Copyright 2016, 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_HIDL_TEST_COMMON_H
#define MEDIA_HIDL_TEST_COMMON_H
#include <media/stagefright/foundation/ALooper.h>
#include <utils/Condition.h>
#include <utils/List.h>
#include <utils/Mutex.h>
#include <media/openmax/OMX_Index.h>
#include <media/openmax/OMX_Core.h>
#include <media/openmax/OMX_Component.h>
#include <media/openmax/OMX_IndexExt.h>
#include <media/openmax/OMX_AudioExt.h>
/*
* TODO: Borrowed from Conversion.h. This is not the ideal way to do it.
* Loose these definitions once you include Conversion.h
*/
inline uint32_t toRawIndexType(OMX_INDEXTYPE l) {
return static_cast<uint32_t>(l);
}
inline android::hardware::media::omx::V1_0::Status toStatus(
android::status_t l) {
return static_cast<android::hardware::media::omx::V1_0::Status>(l);
}
inline hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) {
hidl_vec<uint8_t> t;
t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false);
return t;
}
inline uint32_t toRawCommandType(OMX_COMMANDTYPE l) {
return static_cast<uint32_t>(l);
}
/*
* Handle Callback functions EmptythisBuffer(), FillthisBuffer(),
* EventHandler()
*/
#define DEFAULT_TIMEOUT 40000
enum bufferOwner {
client,
component,
unknown,
};
struct BufferInfo {
uint32_t id;
bufferOwner owner;
android::hardware::media::omx::V1_0::CodecBuffer omxBuffer;
::android::sp<IMemory> mMemory;
};
struct CodecObserver : public IOmxObserver {
public:
Return<void> onMessages(const hidl_vec<Message>& messages) override {
android::Mutex::Autolock autoLock(msgLock);
for (hidl_vec<Message>::const_iterator it = messages.begin();
it != messages.end(); ++it) {
msgQueue.push_back(*it);
}
msgCondition.signal();
return Void();
}
android::hardware::media::omx::V1_0::Status dequeueMessage(
Message* msg, int64_t timeoutUs,
android::Vector<BufferInfo>* iBuffers = nullptr,
android::Vector<BufferInfo>* oBuffers = nullptr) {
int64_t finishBy = android::ALooper::GetNowUs() + timeoutUs;
for (;;) {
android::Mutex::Autolock autoLock(msgLock);
android::List<Message>::iterator it = msgQueue.begin();
while (it != msgQueue.end()) {
if (it->type ==
android::hardware::media::omx::V1_0::Message::Type::EVENT) {
*msg = *it;
msgQueue.erase(it);
return ::android::hardware::media::omx::V1_0::Status::OK;
} else if (it->type == android::hardware::media::omx::V1_0::
Message::Type::FILL_BUFFER_DONE) {
if (oBuffers) {
size_t i;
for (i = 0; i < oBuffers->size(); ++i) {
if ((*oBuffers)[i].id ==
it->data.bufferData.buffer) {
oBuffers->editItemAt(i).owner = client;
msgQueue.erase(it);
break;
}
}
EXPECT_LE(i, oBuffers->size());
}
} else if (it->type == android::hardware::media::omx::V1_0::
Message::Type::EMPTY_BUFFER_DONE) {
if (iBuffers) {
size_t i;
for (i = 0; i < iBuffers->size(); ++i) {
if ((*iBuffers)[i].id ==
it->data.bufferData.buffer) {
iBuffers->editItemAt(i).owner = client;
msgQueue.erase(it);
break;
}
}
EXPECT_LE(i, iBuffers->size());
}
}
++it;
}
android::status_t err =
(timeoutUs < 0)
? msgCondition.wait(msgLock)
: msgCondition.waitRelative(
msgLock,
(finishBy - android::ALooper::GetNowUs()) * 1000);
if (err == android::TIMED_OUT) return toStatus(err);
}
}
android::List<Message> msgQueue;
android::Mutex msgLock;
android::Condition msgCondition;
};
/*
* Useful Wrapper utilities
*/
template <class T>
void InitOMXParams(T* params) {
params->nSize = sizeof(T);
params->nVersion.s.nVersionMajor = 1;
params->nVersion.s.nVersionMinor = 0;
params->nVersion.s.nRevision = 0;
params->nVersion.s.nStep = 0;
}
template <class T>
Return<android::hardware::media::omx::V1_0::Status> getParam(
sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, T* params) {
android::hardware::media::omx::V1_0::Status status;
InitOMXParams(params);
omxNode->getParameter(
toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
[&status, &params](android::hardware::media::omx::V1_0::Status _s,
hidl_vec<uint8_t> const& outParams) {
status = _s;
std::copy(outParams.data(), outParams.data() + outParams.size(),
static_cast<uint8_t*>(static_cast<void*>(params)));
});
return status;
}
template <class T>
Return<android::hardware::media::omx::V1_0::Status> setParam(
sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, T* params) {
InitOMXParams(params);
return omxNode->setParameter(toRawIndexType(omxIdx),
inHidlBytes(params, sizeof(*params)));
}
template <class T>
Return<android::hardware::media::omx::V1_0::Status> getPortParam(
sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
android::hardware::media::omx::V1_0::Status status;
InitOMXParams(params);
params->nPortIndex = nPortIndex;
omxNode->getParameter(
toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
[&status, &params](android::hardware::media::omx::V1_0::Status _s,
hidl_vec<uint8_t> const& outParams) {
status = _s;
std::copy(outParams.data(), outParams.data() + outParams.size(),
static_cast<uint8_t*>(static_cast<void*>(params)));
});
return status;
}
template <class T>
Return<android::hardware::media::omx::V1_0::Status> setPortParam(
sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
InitOMXParams(params);
params->nPortIndex = nPortIndex;
return omxNode->setParameter(toRawIndexType(omxIdx),
inHidlBytes(params, sizeof(*params)));
}
#endif // MEDIA_HIDL_TEST_COMMON_H

View File

@@ -0,0 +1,45 @@
//
// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
cc_test {
name: "VtsHalMediaOmxV1_0TargetComponentTest",
defaults: ["hidl_defaults"],
srcs: ["VtsHalMediaOmxV1_0TargetComponentTest.cpp"],
shared_libs: [
"libbase",
"liblog",
"libcutils",
"libhidlbase",
"libhidltransport",
"libhwbinder",
"libnativehelper",
"libutils",
"libstagefright_foundation",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"android.hardware.media.omx@1.0",
],
static_libs: ["VtsHalHidlTargetTestBase"],
cflags: [
"-O0",
"-g",
],
include_dirs: [
"frameworks/native/include/media/openmax/",
"hardware/interfaces/media/omx/1.0/vts/functional/common",
],
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
//
// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
cc_test {
name: "VtsHalMediaOmxV1_0TargetMasterTest",
defaults: ["hidl_defaults"],
srcs: ["VtsHalMediaOmxV1_0TargetMasterTest.cpp"],
shared_libs: [
"libbase",
"liblog",
"libcutils",
"libhidlbase",
"libhidltransport",
"libhwbinder",
"libnativehelper",
"libutils",
"android.hardware.media.omx@1.0",
],
static_libs: ["VtsHalHidlTargetTestBase"],
cflags: [
"-O0",
"-g",
],
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "media_omx_hidl_master_test"
#include <android-base/logging.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/types.h>
#include <getopt.h>
#include <log/log.h>
#include <VtsHalHidlTargetTestBase.h>
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;
// A class for test environment setup
class ComponentTestEnvironment : public ::testing::Environment {
public:
virtual void SetUp() {}
virtual void TearDown() {}
ComponentTestEnvironment() : instance("default") {}
void setInstance(const char* _instance) { instance = _instance; }
const hidl_string getInstance() const { return instance; }
int initFromOptions(int argc, char** argv) {
static struct option options[] = {
{"instance", required_argument, 0, 'I'}, {0, 0, 0, 0}};
while (true) {
int index = 0;
int c = getopt_long(argc, argv, "I:", options, &index);
if (c == -1) {
break;
}
switch (c) {
case 'I':
setInstance(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: HAL instance to test\n",
argv[optind ?: 1], argv[0]);
return 2;
}
return 0;
}
private:
hidl_string instance;
};
static ComponentTestEnvironment* gEnv = nullptr;
class MasterHidlTest : public ::testing::VtsHalHidlTargetTestBase {
public:
virtual void SetUp() override {
omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>(
gEnv->getInstance());
ASSERT_NE(omx, nullptr);
}
virtual void TearDown() override {}
sp<IOmx> omx;
};
// enumerate list of components and roles
TEST_F(MasterHidlTest, ListNodes) {
android::hardware::media::omx::V1_0::Status status;
hidl_vec<IOmx::ComponentInfo> nodeList;
EXPECT_TRUE(
omx->listNodes([&status, &nodeList](
android::hardware::media::omx::V1_0::Status _s,
hidl_vec<IOmx::ComponentInfo> const& _nl) {
status = _s;
nodeList = _nl;
})
.isOk());
}
int main(int argc, char** argv) {
gEnv = new ComponentTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
if (status == 0) {
status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
}
return status;
}