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:
parent
59bfe719d2
commit
527cf97159
11 changed files with 3048 additions and 0 deletions
3
media/Android.bp
Normal file → Executable file
3
media/Android.bp
Normal file → Executable 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",
|
||||
]
|
||||
|
|
79
media/omx/1.0/vts/functional/audio/Android.bp
Normal file
79
media/omx/1.0/vts/functional/audio/Android.bp
Normal 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",
|
||||
],
|
||||
}
|
||||
|
||||
|
|
@ -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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶ms);
|
||||
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, ¶ms);
|
||||
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;
|
||||
}
|
|
@ -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, ¶ms);
|
||||
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;
|
||||
}
|
|
@ -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, ¶ms);
|
||||
}
|
||||
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
}
|
|
@ -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
|
206
media/omx/1.0/vts/functional/common/media_hidl_test_common.h
Normal file
206
media/omx/1.0/vts/functional/common/media_hidl_test_common.h
Normal 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, ¶ms](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, ¶ms](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
|
45
media/omx/1.0/vts/functional/component/Android.bp
Normal file
45
media/omx/1.0/vts/functional/component/Android.bp
Normal 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
38
media/omx/1.0/vts/functional/master/Android.bp
Normal file
38
media/omx/1.0/vts/functional/master/Android.bp
Normal 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",
|
||||
],
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue