media.omx VTS test baseline

Change-Id: I0cb1997e9cc0427fdfe8091de84e8cb75c7bab14

Test GetPortIndices

Tests support for omx index type: OMX_IndexParamAudioInit,
OMX_IndexParamImageInit, OMX_IndexParamVideoInit, OMX_IndexParamOtherInit.

Change-Id: I50c7c70c8e000684ef02a6e372be32f9c178e74d

Test Port Enabling/Disabling

Enumerate the list of ports available on the component.
Test if they can be disabled and enabled. This test is carried
when the component is in Loaded state. Also, omx-il specification
allows enabling and disabling all ports at once by passing the
argument OMX_ALL. The behavior of the component on this argument
is tested. Disable and enable a port index that is not supported
by the component is also tested.

Change-Id: I1ab3cc3652a63d05bd0c3ceae92e01ebd4aae12d

Test State Transitions

Change the states of the component from loaded->idle->execute->idle->loaded
While the component is switching states, make sure the below dependencies are met.
1. When the component is switching from Loaded to Idle,
ensure this transition does not take place until the supplier has provided
the ports their necessary buffers
2. When the component is switching from Idle to execute,
change the buffer owner from Client to Component.
3. When the component is switching from execute to Idle,
ensure the client got all the buffers it supplied to the component back.
4. When the component is switching from Idle to loaded,
ensure this transition takes place only after freeing all the buffers

Change-Id: I7c3f6f65adf3afda4e54ca7cafb5bb7799a5b2d6

Test for Flush

When the component is in execute state and as buffers are being
exchanged between client and component, call a flush. Test that all
the unprocessed buffers are returned to the client

Change-Id: I00f4c356df0e832aecc457a53163532e82ead9a3

Fix object labels for master and component

This changes maintains consistency across Vts test folders

Change-Id: I0f3e40db04876a3dab170936037c42f994d67c18

Audio_enc/Audio_dec folders are removed.

The current folders needs work. We will revisit this again

Change-Id: Ic8287288d0727f1384e096b846e0066b2ec9f95f

Fix Object labels for common

Change-Id: I8f19a339983aa81d581ed3d55780180f8d976382

Test Port Definition structures

Tests support for omx index type OMX_IndexParamPortDefinition

Change-Id: I45d82199c6cf20f24aa42d9fea69bd1c88a51757

Bug fix : Pass i/o buffer structure information while dequeueing messages

Also fixed sending false port id during freeBuffer call.

Change-Id: Id5c4f67cccea6b577880e42ee0d294cc55d534ad

Test port reconfiguration and buffer flow in audio decoder

In the current commit we have added tests for audio decoder
components. The selected component decodes an elementary stream
and in this process port reconfiguration, buffer flow and flush
are tested.

Test: mma
Change-Id: I42c8397f704f5fa69878efe91932c477ac66d1b2
This commit is contained in:
Ram Mohan M 2017-03-29 14:52:20 +05:30 committed by Zhuoyao Zhang
parent 59bfe719d2
commit 527cf97159
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;
}