mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Test: make vts -j99 BUILD_GOOGLE_VTS=true TARGET_PRODUCT=aosp_arm64 \ && vts-tradefed run commandAndExit vts \ --skip-all-system-status-check --primary-abi-only \ --skip-preconditions --module VtsHalMediaOmxV1_0Host \ -l INFO bug: 70933963 Change-Id: I5695820b225041f5b764506cdafacf7c95d836aa
1284 lines
56 KiB
C++
1284 lines
56 KiB
C++
/*
|
|
* 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_component_test"
|
|
#ifdef __LP64__
|
|
#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
|
|
#endif
|
|
|
|
#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::hardware::media::omx::V1_0::PortMode;
|
|
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_hidl_test_common.h>
|
|
|
|
static ComponentTestEnvironment* gEnv = nullptr;
|
|
|
|
// generic component test fixture class
|
|
class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|
private:
|
|
typedef ::testing::VtsHalHidlTargetTestBase Super;
|
|
public:
|
|
::std::string getTestCaseInfo() const override {
|
|
return ::std::string() +
|
|
"Component: " + gEnv->getComponent().c_str() + " | " +
|
|
"Role: " + gEnv->getRole().c_str() + " | " +
|
|
"Instance: " + gEnv->getInstance().c_str();
|
|
}
|
|
|
|
virtual void SetUp() override {
|
|
Super::SetUp();
|
|
disableTest = false;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
omx = Super::getService<IOmx>(gEnv->getInstance());
|
|
ASSERT_NE(omx, nullptr);
|
|
observer = new CodecObserver(nullptr);
|
|
ASSERT_NE(observer, nullptr);
|
|
if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
|
|
disableTest = true;
|
|
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());
|
|
if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
|
|
disableTest = true;
|
|
std::cout << "[ WARN ] Test Disabled, component not present\n";
|
|
return;
|
|
}
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
ASSERT_NE(omxNode, nullptr);
|
|
ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
|
|
struct StringToClass {
|
|
const char* Class;
|
|
standardCompClass CompClass;
|
|
};
|
|
const StringToClass kStringToClass[] = {
|
|
{"audio_decoder", audio_decoder},
|
|
{"audio_encoder", audio_encoder},
|
|
{"video_decoder", video_decoder},
|
|
{"video_encoder", video_encoder},
|
|
};
|
|
const size_t kNumStringToClass =
|
|
sizeof(kStringToClass) / sizeof(kStringToClass[0]);
|
|
const char* pch;
|
|
char substring[OMX_MAX_STRINGNAME_SIZE];
|
|
strcpy(substring, gEnv->getRole().c_str());
|
|
pch = strchr(substring, '.');
|
|
ASSERT_NE(pch, nullptr) << "Invalid Component Role";
|
|
substring[pch - substring] = '\0';
|
|
compClass = unknown_class;
|
|
for (size_t i = 0; i < kNumStringToClass; ++i) {
|
|
if (!strcasecmp(substring, kStringToClass[i].Class)) {
|
|
compClass = kStringToClass[i].CompClass;
|
|
break;
|
|
}
|
|
}
|
|
if (compClass == unknown_class) disableTest = true;
|
|
isSecure = false;
|
|
mTunnel = false;
|
|
size_t suffixLen = strlen(".secure");
|
|
if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
|
|
isSecure =
|
|
!strcmp(gEnv->getComponent().c_str() +
|
|
strlen(gEnv->getComponent().c_str()) - suffixLen,
|
|
".secure");
|
|
}
|
|
if (compClass == video_decoder) {
|
|
omxNode->configureVideoTunnelMode(
|
|
1, OMX_TRUE, 0,
|
|
[&](android::hardware::media::omx::V1_0::Status _s,
|
|
const ::android::hardware::hidl_handle& sidebandHandle) {
|
|
(void)sidebandHandle;
|
|
if (_s == android::hardware::media::omx::V1_0::Status::OK)
|
|
this->mTunnel = true;
|
|
});
|
|
}
|
|
// NOTES: secure components are not covered in these tests.
|
|
// we are disabling tests for them
|
|
if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
|
|
}
|
|
|
|
virtual void TearDown() override {
|
|
if (omxNode != nullptr) {
|
|
// If you have encountered a fatal failure, it is possible that
|
|
// freeNode() will not go through. Instead of hanging the app.
|
|
// let it pass through and report errors
|
|
if (::testing::Test::HasFatalFailure()) return;
|
|
EXPECT_TRUE((omxNode->freeNode()).isOk());
|
|
omxNode = nullptr;
|
|
}
|
|
Super::TearDown();
|
|
}
|
|
|
|
enum standardCompClass {
|
|
audio_decoder,
|
|
audio_encoder,
|
|
video_decoder,
|
|
video_encoder,
|
|
unknown_class,
|
|
};
|
|
|
|
sp<IOmx> omx;
|
|
sp<CodecObserver> observer;
|
|
sp<IOmxNode> omxNode;
|
|
standardCompClass compClass;
|
|
bool mTunnel;
|
|
bool isSecure;
|
|
bool disableTest;
|
|
|
|
protected:
|
|
static void description(const std::string& description) {
|
|
RecordProperty("description", description);
|
|
}
|
|
};
|
|
|
|
void initPortMode(PortMode* pm, bool isSecure,
|
|
ComponentHidlTest::standardCompClass compClass) {
|
|
pm[0] = PortMode::PRESET_BYTE_BUFFER;
|
|
pm[1] = PortMode::PRESET_BYTE_BUFFER;
|
|
if (isSecure) {
|
|
switch (compClass) {
|
|
case ComponentHidlTest::video_decoder:
|
|
pm[0] = PortMode::PRESET_SECURE_BUFFER;
|
|
break;
|
|
case ComponentHidlTest::video_encoder:
|
|
pm[1] = PortMode::PRESET_SECURE_BUFFER;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// test dispatch message API call
|
|
TEST_F(ComponentHidlTest, dispatchMsg) {
|
|
description("test dispatch message API call");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
Message msgin, msgout;
|
|
|
|
msgin.type = Message::Type::EVENT;
|
|
msgin.data.eventData.event = OMX_EventError;
|
|
msgin.data.eventData.data1 = 0xdeaf;
|
|
msgin.data.eventData.data2 = 0xd00d;
|
|
msgin.data.eventData.data3 = 0x01ce;
|
|
msgin.data.eventData.data4 = 0xfa11;
|
|
status = omxNode->dispatchMessage(msgin);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = observer->dequeueMessage(&msgout, DEFAULT_TIMEOUT);
|
|
EXPECT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
EXPECT_EQ(msgout.type, msgin.type);
|
|
EXPECT_EQ(msgout.data.eventData.event, msgin.data.eventData.event);
|
|
EXPECT_EQ(msgout.data.eventData.data1, msgin.data.eventData.data1);
|
|
EXPECT_EQ(msgout.data.eventData.data2, msgin.data.eventData.data2);
|
|
EXPECT_EQ(msgout.data.eventData.data3, msgin.data.eventData.data3);
|
|
EXPECT_EQ(msgout.data.eventData.data4, msgin.data.eventData.data4);
|
|
}
|
|
|
|
// set component role
|
|
TEST_F(ComponentHidlTest, SetRole) {
|
|
description("Test Set Component Role");
|
|
if (disableTest) return;
|
|
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);
|
|
}
|
|
|
|
// port indices enumeration
|
|
TEST_F(ComponentHidlTest, DISABLED_GetPortIndices) {
|
|
description("Test Component on Mandatory Port Parameters (Port Indices)");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_PORT_PARAM_TYPE params;
|
|
|
|
status = setRole(omxNode, gEnv->getRole().c_str());
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// Get Number of Ports and their Indices for all Domains
|
|
// (Audio/Video/Image/Other)
|
|
// All standard OMX components shall support following OMX Index types
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = getParam(omxNode, OMX_IndexParamImageInit, ¶ms);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = getParam(omxNode, OMX_IndexParamOtherInit, ¶ms);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
}
|
|
|
|
// port format enumeration
|
|
TEST_F(ComponentHidlTest, EnumeratePortFormat) {
|
|
description("Test Component on Mandatory Port Parameters (Port Format)");
|
|
if (disableTest) return;
|
|
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;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
kPortIndexInput = params.nStartPortNumber;
|
|
kPortIndexOutput = kPortIndexInput + 1;
|
|
}
|
|
|
|
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
|
|
OMX_U32 xFramerate = 24U << 16;
|
|
|
|
// Enumerate Port Format
|
|
if (compClass == audio_encoder) {
|
|
status =
|
|
setAudioPortFormat(omxNode, kPortIndexInput, OMX_AUDIO_CodingPCM);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = setAudioPortFormat(omxNode, kPortIndexOutput,
|
|
OMX_AUDIO_CodingAutoDetect);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
} else if (compClass == audio_decoder) {
|
|
status = setAudioPortFormat(omxNode, kPortIndexInput,
|
|
OMX_AUDIO_CodingAutoDetect);
|
|
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);
|
|
} else if (compClass == video_encoder) {
|
|
status =
|
|
setVideoPortFormat(omxNode, kPortIndexInput, OMX_VIDEO_CodingUnused,
|
|
eColorFormat, xFramerate);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = setVideoPortFormat(omxNode, kPortIndexOutput,
|
|
OMX_VIDEO_CodingAutoDetect,
|
|
OMX_COLOR_FormatUnused, 0U);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
} else {
|
|
status = setVideoPortFormat(omxNode, kPortIndexInput,
|
|
OMX_VIDEO_CodingAutoDetect,
|
|
OMX_COLOR_FormatUnused, 0U);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = setVideoPortFormat(omxNode, kPortIndexOutput,
|
|
OMX_VIDEO_CodingUnused, eColorFormat,
|
|
xFramerate);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
}
|
|
}
|
|
|
|
// get/set default port settings of a component
|
|
TEST_F(ComponentHidlTest, DISABLED_SetDefaultPortParams) {
|
|
description(
|
|
"Test Component on Mandatory Port Parameters (Port Definition)");
|
|
if (disableTest) return;
|
|
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;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
kPortIndexInput = params.nStartPortNumber;
|
|
kPortIndexOutput = kPortIndexInput + 1;
|
|
}
|
|
|
|
for (size_t i = kPortIndexInput; i <= kPortIndexOutput; i++) {
|
|
OMX_PARAM_PORTDEFINITIONTYPE portDef;
|
|
status =
|
|
getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
if (status == android::hardware::media::omx::V1_0::Status::OK) {
|
|
EXPECT_EQ(portDef.eDir, i - kPortIndexInput); // OMX_DirInput
|
|
EXPECT_EQ(portDef.bEnabled, OMX_TRUE);
|
|
EXPECT_EQ(portDef.bPopulated, OMX_FALSE);
|
|
EXPECT_GE(portDef.nBufferCountMin, 1U);
|
|
EXPECT_GE(portDef.nBufferCountActual, portDef.nBufferCountMin);
|
|
if (compClass == audio_encoder || compClass == audio_decoder) {
|
|
EXPECT_EQ(portDef.eDomain, OMX_PortDomainAudio);
|
|
} else if (compClass == video_encoder ||
|
|
compClass == video_decoder) {
|
|
EXPECT_EQ(portDef.eDomain, OMX_PortDomainVideo);
|
|
}
|
|
OMX_PARAM_PORTDEFINITIONTYPE mirror = portDef;
|
|
|
|
// nBufferCountActual >= nBufferCountMin
|
|
portDef.nBufferCountActual = portDef.nBufferCountMin - 1;
|
|
status = setPortParam(omxNode, OMX_IndexParamPortDefinition, i,
|
|
&portDef);
|
|
EXPECT_NE(status,
|
|
::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// Port Direction - Read Only
|
|
portDef = mirror;
|
|
portDef.eDir = static_cast<OMX_DIRTYPE>(RANDOM_INDEX);
|
|
setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
|
|
getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
|
|
if (portDef.eDir != mirror.eDir) {
|
|
std::cerr << "[ ERROR ] port direction has to be read only "
|
|
"but is changeable \n";
|
|
}
|
|
EXPECT_EQ(portDef.eDir, mirror.eDir);
|
|
setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
|
|
|
|
// Port Min BufferCount - Read Only
|
|
portDef = mirror;
|
|
portDef.nBufferCountMin += 1;
|
|
setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
|
|
getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
|
|
if (portDef.nBufferCountMin != mirror.nBufferCountMin) {
|
|
std::cerr << "[ ERROR ] port Min BufferCount has to be "
|
|
"read only but is changeable \n";
|
|
}
|
|
EXPECT_EQ(portDef.nBufferCountMin, mirror.nBufferCountMin);
|
|
setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
|
|
|
|
// Port Actual BufferCount
|
|
portDef = mirror;
|
|
portDef.nBufferCountActual += 1;
|
|
status = setPortParam(omxNode, OMX_IndexParamPortDefinition, i,
|
|
&portDef);
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, i,
|
|
&portDef);
|
|
EXPECT_EQ(portDef.nBufferCountActual,
|
|
mirror.nBufferCountActual + 1);
|
|
}
|
|
setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
|
|
|
|
// Port BufferSize is although read only as per OMX-IL 1.2, android
|
|
// doesnt abide by this.
|
|
// Decrease buffer size
|
|
portDef = mirror;
|
|
OMX_U32 nBufferSize = portDef.nBufferSize >> 1;
|
|
if (nBufferSize != 0) {
|
|
if (!strncmp(gEnv->getComponent().c_str(), "OMX.google.", 11)) {
|
|
portDef.nBufferSize = nBufferSize;
|
|
} else {
|
|
// Probable alignment requirements of vendor component
|
|
portDef.nBufferSize = ALIGN_POWER_OF_TWO(nBufferSize, 12);
|
|
nBufferSize = portDef.nBufferSize;
|
|
}
|
|
} else {
|
|
ASSERT_TRUE(false) << "Unexpected buffer size";
|
|
}
|
|
setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
|
|
getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
|
|
// SPECIAL CASE: For video decoder, allow configuration of input
|
|
// buffer size even if it is less than minimum requirement and
|
|
// similarly for encoder allow configuration of output port buffer
|
|
// size.
|
|
if ((compClass == video_encoder && i == kPortIndexOutput) ||
|
|
(compClass == video_decoder && i == kPortIndexInput)) {
|
|
double dev = (portDef.nBufferSize / (double)nBufferSize);
|
|
dev -= 1;
|
|
if (dev < 0 || dev > 0.1) {
|
|
std::cerr << "[ ERROR ] port buffer size deviation "
|
|
"larger than expected \n";
|
|
}
|
|
} else {
|
|
EXPECT_EQ(portDef.nBufferSize, mirror.nBufferSize);
|
|
}
|
|
setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
|
|
|
|
// Increase buffer size
|
|
portDef = mirror;
|
|
portDef.nBufferSize = mirror.nBufferSize << 1;
|
|
setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
|
|
getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
|
|
EXPECT_EQ(portDef.nBufferSize, (mirror.nBufferSize << 1));
|
|
}
|
|
}
|
|
}
|
|
|
|
// populate port test
|
|
TEST_F(ComponentHidlTest, DISABLED_PopulatePort) {
|
|
description("Verify bPopulated field of a component port");
|
|
if (disableTest || isSecure) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_U32 portBase = 0;
|
|
|
|
status = setRole(omxNode, gEnv->getRole().c_str());
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
portBase = params.nStartPortNumber;
|
|
}
|
|
|
|
// set state to idle
|
|
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
|
OMX_StateIdle);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
OMX_PARAM_PORTDEFINITIONTYPE portDef;
|
|
status =
|
|
getPortParam(omxNode, OMX_IndexParamPortDefinition, portBase, &portDef);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
ASSERT_EQ(portDef.bPopulated, OMX_FALSE);
|
|
|
|
android::Vector<BufferInfo> pBuffer;
|
|
pBuffer.clear();
|
|
uint32_t nBufferSize = portDef.nBufferSize >> 1;
|
|
|
|
for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
|
|
BufferInfo buffer;
|
|
ASSERT_NO_FATAL_FAILURE(allocateBuffer(omxNode, &buffer, portBase,
|
|
nBufferSize,
|
|
PortMode::PRESET_BYTE_BUFFER));
|
|
pBuffer.push(buffer);
|
|
}
|
|
|
|
status =
|
|
getPortParam(omxNode, OMX_IndexParamPortDefinition, portBase, &portDef);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
// A port is populated when all of the buffers indicated by
|
|
// nBufferCountActual with a size of at least nBufferSizehave been
|
|
// allocated on the port.
|
|
ASSERT_EQ(portDef.bPopulated, OMX_FALSE);
|
|
}
|
|
|
|
// Flush test
|
|
TEST_F(ComponentHidlTest, Flush) {
|
|
description("Test Flush");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
Message msg;
|
|
|
|
status = setRole(omxNode, gEnv->getRole().c_str());
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
kPortIndexInput = params.nStartPortNumber;
|
|
kPortIndexOutput = kPortIndexInput + 1;
|
|
}
|
|
|
|
android::Vector<BufferInfo> iBuffer, oBuffer;
|
|
|
|
// set port mode
|
|
PortMode portMode[2];
|
|
initPortMode(portMode, isSecure, compClass);
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
|
|
// dispatch buffers
|
|
for (size_t i = 0; i < oBuffer.size(); i++) {
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
dispatchOutputBuffer(omxNode, &oBuffer, i, portMode[1]));
|
|
}
|
|
// flush port
|
|
ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
|
|
kPortIndexInput, kPortIndexOutput));
|
|
#if 0
|
|
// TODO: Sending empty input buffers is slightly tricky.
|
|
// Components sometimes process input buffers even when output buffers are
|
|
// not dispatched. For instance Parsing sequence header does not require
|
|
// output buffers. In such instances sending 0 size input buffers might
|
|
// make component to send error events. so lets skip this aspect of testing.
|
|
// dispatch buffers
|
|
for (size_t i = 0; i < iBuffer.size(); i++) {
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
dispatchInputBuffer(omxNode, &iBuffer, i, 0, 0, 0, portMode[0]));
|
|
}
|
|
// flush ports
|
|
ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
|
|
kPortIndexInput, kPortIndexOutput));
|
|
#endif
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
|
|
// set state to loaded
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
|
|
&oBuffer, kPortIndexInput,
|
|
kPortIndexOutput));
|
|
}
|
|
|
|
// Flush test - monkeying
|
|
TEST_F(ComponentHidlTest, Flush_M) {
|
|
description("Test Flush monkeying");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
Message msg;
|
|
|
|
status = setRole(omxNode, gEnv->getRole().c_str());
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
kPortIndexInput = params.nStartPortNumber;
|
|
kPortIndexOutput = kPortIndexInput + 1;
|
|
}
|
|
|
|
android::Vector<BufferInfo> iBuffer, oBuffer;
|
|
|
|
// set port mode
|
|
PortMode portMode[2];
|
|
initPortMode(portMode, isSecure, compClass);
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// // Flush all ports ; receive error OMX_ErrorIncorrectStateOperation
|
|
// status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
|
|
// OMX_ALL);
|
|
// ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
|
|
// // Flush all ports ; receive error OMX_ErrorIncorrectStateOperation
|
|
// status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
|
|
// OMX_ALL);
|
|
// ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
|
|
|
|
// dispatch buffers
|
|
for (size_t i = 0; i < oBuffer.size(); i++) {
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
dispatchOutputBuffer(omxNode, &oBuffer, i, portMode[1]));
|
|
}
|
|
|
|
// // flush invalid port, expecting OMX_ErrorBadPortIndex
|
|
// status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
|
|
// RANDOM_INDEX);
|
|
// ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// Flush all ports
|
|
status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush), OMX_ALL);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
for (int j = 0; j < 2; j++) {
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_PE, &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);
|
|
if (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);
|
|
}
|
|
} else if (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);
|
|
}
|
|
} else {
|
|
EXPECT_TRUE(false) << "Bad port Index";
|
|
}
|
|
}
|
|
|
|
// SPECIAL CASE: When OMX_ALL is used as argument, Android OMX Core sends
|
|
// an additional flush event with argument OMX_ALL. This we believe is
|
|
// not recognized by OMX-IL Spec. So read this event and ignore it
|
|
status =
|
|
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_PE, &iBuffer, &oBuffer);
|
|
if (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, OMX_ALL);
|
|
}
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
|
|
// set state to loaded
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
|
|
&oBuffer, kPortIndexInput,
|
|
kPortIndexOutput));
|
|
}
|
|
|
|
// test port mode configuration when the component is in various states
|
|
TEST_F(ComponentHidlTest, PortModeConfig) {
|
|
description("Test Port Mode Configuration");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
Message msg;
|
|
|
|
status = setRole(omxNode, gEnv->getRole().c_str());
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
kPortIndexInput = params.nStartPortNumber;
|
|
kPortIndexOutput = kPortIndexInput + 1;
|
|
}
|
|
|
|
android::Vector<BufferInfo> iBuffer, oBuffer;
|
|
|
|
// set port mode
|
|
PortMode portMode[2];
|
|
initPortMode(portMode, isSecure, compClass);
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
// Only Allow Port Mode configuration in loaded state
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
|
|
// Only Allow Port Mode configuration in loaded state
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
|
|
// set state to loaded
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
|
|
&oBuffer, kPortIndexInput,
|
|
kPortIndexOutput));
|
|
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
}
|
|
|
|
// state transitions test
|
|
TEST_F(ComponentHidlTest, StateTransitions) {
|
|
description("Test State Transitions Loaded<->Idle<->Execute");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
OMX_U32 portBase = 0;
|
|
Message msg;
|
|
status = setRole(omxNode, gEnv->getRole().c_str());
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
portBase = params.nStartPortNumber;
|
|
}
|
|
kPortIndexInput = portBase;
|
|
kPortIndexOutput = portBase + 1;
|
|
|
|
android::Vector<BufferInfo> pBuffer[2];
|
|
|
|
// set port mode
|
|
PortMode portMode[2];
|
|
initPortMode(portMode, isSecure, compClass);
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to idle
|
|
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
|
OMX_StateIdle);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
for (size_t j = portBase; j < portBase + 2; j++) {
|
|
pBuffer[j - portBase].clear();
|
|
|
|
OMX_PARAM_PORTDEFINITIONTYPE def;
|
|
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, j, &def);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
for (size_t i = 0; i < def.nBufferCountActual; i++) {
|
|
// Dont switch states until the ports are populated
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
|
|
&pBuffer[0], &pBuffer[1]);
|
|
ASSERT_EQ(status,
|
|
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
|
|
|
BufferInfo buffer;
|
|
ASSERT_NO_FATAL_FAILURE(allocateBuffer(
|
|
omxNode, &buffer, j, def.nBufferSize, portMode[j - portBase]));
|
|
pBuffer[j - portBase].push(buffer);
|
|
}
|
|
}
|
|
|
|
// As the ports are populated, check if the state transition is complete
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0],
|
|
&pBuffer[1]);
|
|
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 executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
|
|
// dispatch buffers
|
|
for (size_t i = 0; i < pBuffer[1].size(); i++) {
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
dispatchOutputBuffer(omxNode, &pBuffer[1], i, portMode[1]));
|
|
}
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]));
|
|
#if 0
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
|
|
// TODO: Sending empty input buffers is slightly tricky.
|
|
// dispatch buffers
|
|
for (size_t i = 0; i < pBuffer[0].size(); i++) {
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
dispatchInputBuffer(omxNode, &pBuffer[0], i, 0, 0, 0, portMode[0]));
|
|
}
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]));
|
|
#endif
|
|
|
|
// set state to loaded
|
|
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
|
OMX_StateLoaded);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
for (size_t j = portBase; j < portBase + 2; j++) {
|
|
for (size_t i = 0; i < pBuffer[j].size(); ++i) {
|
|
// Dont switch states until the ports are populated
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
|
|
&pBuffer[0], &pBuffer[1]);
|
|
ASSERT_EQ(status,
|
|
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
|
|
|
status = omxNode->freeBuffer(j, pBuffer[j][i].id);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
}
|
|
}
|
|
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0],
|
|
&pBuffer[1]);
|
|
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);
|
|
}
|
|
|
|
// state transitions test - monkeying
|
|
TEST_F(ComponentHidlTest, DISABLED_StateTransitions_M) {
|
|
description("Test State Transitions monkeying");
|
|
if (disableTest || isSecure) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
Message msg;
|
|
|
|
status = setRole(omxNode, gEnv->getRole().c_str());
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
kPortIndexInput = params.nStartPortNumber;
|
|
kPortIndexOutput = kPortIndexInput + 1;
|
|
}
|
|
|
|
android::Vector<BufferInfo> iBuffer, oBuffer;
|
|
|
|
// set state to loaded ; receive error OMX_ErrorSameState
|
|
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
|
OMX_StateLoaded);
|
|
EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to executing ; receive error OMX_ErrorIncorrectStateTransition
|
|
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
|
OMX_StateExecuting);
|
|
EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
|
|
&oBuffer, kPortIndexInput,
|
|
kPortIndexOutput));
|
|
|
|
// set state to idle ; receive error OMX_ErrorSameState
|
|
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
|
OMX_StateIdle);
|
|
EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
|
|
|
|
// set state to executing ; receive error OMX_ErrorSameState
|
|
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
|
OMX_StateExecuting);
|
|
EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to Loaded ; receive error OMX_ErrorIncorrectStateTransition
|
|
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
|
OMX_StateLoaded);
|
|
EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
|
|
// set state to loaded
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
|
|
&oBuffer, kPortIndexInput,
|
|
kPortIndexOutput));
|
|
}
|
|
|
|
// port enable disable test
|
|
TEST_F(ComponentHidlTest, DISABLED_PortEnableDisable_Loaded) {
|
|
description("Test Port Enable and Disable (Component State :: Loaded)");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_U32 portBase = 0;
|
|
Message msg;
|
|
status = setRole(omxNode, gEnv->getRole().c_str());
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
portBase = params.nStartPortNumber;
|
|
}
|
|
|
|
for (size_t i = portBase; i < portBase + 2; i++) {
|
|
status =
|
|
omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
ASSERT_EQ(msg.type, Message::Type::EVENT);
|
|
if (msg.data.eventData.event == OMX_EventCmdComplete) {
|
|
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
|
|
ASSERT_EQ(msg.data.eventData.data2, i);
|
|
// If you can disable a port, then you should be able to enable it
|
|
// as well
|
|
status = omxNode->sendCommand(
|
|
toRawCommandType(OMX_CommandPortEnable), i);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT);
|
|
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, i);
|
|
} else if (msg.data.eventData.event == OMX_EventError) {
|
|
ALOGE("Port %d Disabling failed with error %d", (int)i,
|
|
(int)msg.data.eventData.event);
|
|
} else {
|
|
// something unexpected happened
|
|
ASSERT_TRUE(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// port enable disable test
|
|
TEST_F(ComponentHidlTest, PortEnableDisable_Idle) {
|
|
description("Test Port Enable and Disable (Component State :: Idle)");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
OMX_U32 portBase = 0;
|
|
Message msg;
|
|
status = setRole(omxNode, gEnv->getRole().c_str());
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
portBase = params.nStartPortNumber;
|
|
}
|
|
kPortIndexInput = portBase;
|
|
kPortIndexOutput = portBase + 1;
|
|
|
|
// Component State :: Idle
|
|
android::Vector<BufferInfo> pBuffer[2];
|
|
|
|
// set port mode
|
|
PortMode portMode[2];
|
|
initPortMode(portMode, isSecure, compClass);
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1],
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
int range = mTunnel ? 1 : 2;
|
|
for (size_t i = portBase; i < portBase + range; i++) {
|
|
status =
|
|
omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0],
|
|
&pBuffer[1]);
|
|
if (status == android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(msg.type, Message::Type::EVENT);
|
|
if (msg.data.eventData.event == OMX_EventCmdComplete) {
|
|
// do not disable the port until all the buffers are freed
|
|
ASSERT_TRUE(false);
|
|
} else if (msg.data.eventData.event == OMX_EventError) {
|
|
ALOGE("Port %d Disabling failed with error %d", (int)i,
|
|
(int)msg.data.eventData.event);
|
|
} else {
|
|
// something unexpected happened
|
|
ASSERT_TRUE(false);
|
|
}
|
|
} else if (status ==
|
|
android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
|
|
for (size_t j = 0; j < pBuffer[i - portBase].size(); ++j) {
|
|
status = omxNode->freeBuffer(i, pBuffer[i - portBase][j].id);
|
|
ASSERT_EQ(status,
|
|
android::hardware::media::omx::V1_0::Status::OK);
|
|
}
|
|
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
|
|
&pBuffer[0], &pBuffer[1]);
|
|
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, i);
|
|
|
|
// If you can disable a port, then you should be able to enable it
|
|
// as well
|
|
status = omxNode->sendCommand(
|
|
toRawCommandType(OMX_CommandPortEnable), i);
|
|
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,
|
|
&pBuffer[0], &pBuffer[1]);
|
|
ASSERT_EQ(status,
|
|
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
|
|
|
ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
|
|
omxNode, &pBuffer[i - portBase], i, portMode[i - portBase]));
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
|
|
&pBuffer[0], &pBuffer[1]);
|
|
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, i);
|
|
} else {
|
|
// something unexpected happened
|
|
ASSERT_TRUE(false);
|
|
}
|
|
}
|
|
|
|
// set state to Loaded
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1],
|
|
kPortIndexInput, kPortIndexOutput));
|
|
}
|
|
|
|
// port enable disable test
|
|
TEST_F(ComponentHidlTest, PortEnableDisable_Execute) {
|
|
description("Test Port Enable and Disable (Component State :: Execute)");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
OMX_U32 portBase = 0;
|
|
Message msg;
|
|
status = setRole(omxNode, gEnv->getRole().c_str());
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
portBase = params.nStartPortNumber;
|
|
}
|
|
kPortIndexInput = portBase;
|
|
kPortIndexOutput = portBase + 1;
|
|
|
|
// Component State :: Idle
|
|
android::Vector<BufferInfo> pBuffer[2];
|
|
|
|
// set port mode
|
|
PortMode portMode[2];
|
|
initPortMode(portMode, isSecure, compClass);
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1],
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
|
|
// dispatch buffers
|
|
for (size_t i = 0; i < pBuffer[1].size(); i++) {
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
dispatchOutputBuffer(omxNode, &pBuffer[1], i, portMode[1]));
|
|
}
|
|
|
|
int range = mTunnel ? 1 : 2;
|
|
for (size_t i = portBase; i < portBase + range; i++) {
|
|
status =
|
|
omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0],
|
|
&pBuffer[1]);
|
|
if (status == android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(msg.type, Message::Type::EVENT);
|
|
if (msg.data.eventData.event == OMX_EventCmdComplete) {
|
|
// do not disable the port until all the buffers are freed
|
|
ASSERT_TRUE(false);
|
|
} else if (msg.data.eventData.event == OMX_EventError) {
|
|
ALOGE("Port %d Disabling failed with error %d", (int)i,
|
|
(int)msg.data.eventData.event);
|
|
} else {
|
|
// something unexpected happened
|
|
ASSERT_TRUE(false);
|
|
}
|
|
} else if (status ==
|
|
android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
|
|
for (size_t j = 0; j < pBuffer[i - portBase].size(); ++j) {
|
|
// test if client got all its buffers back
|
|
EXPECT_EQ(pBuffer[i - portBase][j].owner, client);
|
|
// free the buffers
|
|
status = omxNode->freeBuffer(i, pBuffer[i - portBase][j].id);
|
|
ASSERT_EQ(status,
|
|
android::hardware::media::omx::V1_0::Status::OK);
|
|
}
|
|
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
|
|
&pBuffer[0], &pBuffer[1]);
|
|
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, i);
|
|
|
|
// If you can disable a port, then you should be able to enable it
|
|
// as well
|
|
status = omxNode->sendCommand(
|
|
toRawCommandType(OMX_CommandPortEnable), i);
|
|
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,
|
|
&pBuffer[0], &pBuffer[1]);
|
|
ASSERT_EQ(status,
|
|
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
|
|
|
ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
|
|
omxNode, &pBuffer[i - portBase], i, portMode[i - portBase]));
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
|
|
&pBuffer[0], &pBuffer[1]);
|
|
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, i);
|
|
} else {
|
|
// something unexpected happened
|
|
ASSERT_TRUE(false);
|
|
}
|
|
}
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]));
|
|
// set state to loaded
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1],
|
|
kPortIndexInput, kPortIndexOutput));
|
|
}
|
|
|
|
// port enable disable test - monkeying
|
|
TEST_F(ComponentHidlTest, DISABLED_PortEnableDisable_M) {
|
|
description(
|
|
"Test Port Enable and Disable Monkeying (Component State :: Loaded)");
|
|
if (disableTest || isSecure) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_U32 portBase = 0;
|
|
Message msg;
|
|
status = setRole(omxNode, gEnv->getRole().c_str());
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
if (compClass == audio_decoder || compClass == audio_encoder) {
|
|
status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
|
|
} else {
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
}
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
portBase = params.nStartPortNumber;
|
|
}
|
|
|
|
// disable invalid port, expecting OMX_ErrorBadPortIndex
|
|
status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable),
|
|
RANDOM_INDEX);
|
|
ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// enable invalid port, expecting OMX_ErrorBadPortIndex
|
|
status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortEnable),
|
|
RANDOM_INDEX);
|
|
ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// disable all ports
|
|
status =
|
|
omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), OMX_ALL);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
for (size_t i = 0; i < 2; i++) {
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
ASSERT_EQ(msg.type, Message::Type::EVENT);
|
|
if (msg.data.eventData.event == OMX_EventCmdComplete) {
|
|
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
|
|
if (msg.data.eventData.data2 != portBase ||
|
|
msg.data.eventData.data2 != portBase + 1)
|
|
EXPECT_TRUE(false);
|
|
} else if (msg.data.eventData.event == OMX_EventError) {
|
|
ALOGE("Port %d Disabling failed with error %d", (int)i,
|
|
(int)msg.data.eventData.event);
|
|
} else {
|
|
// something unexpected happened
|
|
ASSERT_TRUE(false);
|
|
}
|
|
}
|
|
|
|
// enable all ports
|
|
status =
|
|
omxNode->sendCommand(toRawCommandType(OMX_CommandPortEnable), OMX_ALL);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
for (size_t i = 0; i < 2; i++) {
|
|
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT);
|
|
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
ASSERT_EQ(msg.type, Message::Type::EVENT);
|
|
if (msg.data.eventData.event == OMX_EventCmdComplete) {
|
|
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
|
|
if (msg.data.eventData.data2 != portBase ||
|
|
msg.data.eventData.data2 != portBase + 1)
|
|
EXPECT_TRUE(false);
|
|
} else if (msg.data.eventData.event == OMX_EventError) {
|
|
ALOGE("Port %d Enabling failed with error %d", (int)i,
|
|
(int)msg.data.eventData.event);
|
|
} else {
|
|
// something unexpected happened
|
|
ASSERT_TRUE(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
gEnv = new ComponentTestEnvironment();
|
|
::testing::AddGlobalTestEnvironment(gEnv);
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
gEnv->init(&argc, argv);
|
|
int status = gEnv->initFromOptions(argc, argv);
|
|
if (status == 0) {
|
|
status = RUN_ALL_TESTS();
|
|
ALOGI("Test result = %d", status);
|
|
}
|
|
return status;
|
|
}
|