Merge "Omx vts test." into oc-dev
This commit is contained in:
commit
9a9c8da39b
16 changed files with 1722 additions and 1067 deletions
|
@ -3,6 +3,7 @@ subdirs = [
|
|||
"1.0",
|
||||
"omx/1.0",
|
||||
"omx/1.0/vts/functional/audio",
|
||||
"omx/1.0/vts/functional/common",
|
||||
"omx/1.0/vts/functional/component",
|
||||
"omx/1.0/vts/functional/master",
|
||||
"omx/1.0/vts/functional/video",
|
||||
|
|
|
@ -34,7 +34,8 @@ cc_test {
|
|||
"android.hidl.memory@1.0",
|
||||
"android.hardware.media.omx@1.0",
|
||||
],
|
||||
static_libs: ["VtsHalHidlTargetTestBase"],
|
||||
static_libs: ["VtsHalHidlTargetTestBase",
|
||||
"VtsHalMediaOmxV1_0CommonUtil"],
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-g",
|
||||
|
@ -65,7 +66,8 @@ cc_test {
|
|||
"android.hidl.memory@1.0",
|
||||
"android.hardware.media.omx@1.0",
|
||||
],
|
||||
static_libs: ["VtsHalHidlTargetTestBase"],
|
||||
static_libs: ["VtsHalHidlTargetTestBase",
|
||||
"VtsHalMediaOmxV1_0CommonUtil"],
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-g",
|
||||
|
|
|
@ -30,6 +30,7 @@ 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;
|
||||
|
@ -136,7 +137,9 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
gEnv->getInstance());
|
||||
ASSERT_NE(omx, nullptr);
|
||||
observer =
|
||||
new CodecObserver([this](Message msg) { handleMessage(msg); });
|
||||
new CodecObserver([this](Message msg, const BufferInfo* buffer) {
|
||||
handleMessage(msg, buffer);
|
||||
});
|
||||
ASSERT_NE(observer, nullptr);
|
||||
if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
|
||||
disableTest = true;
|
||||
|
@ -218,7 +221,8 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
|
||||
// callback function to process messages received by onMessages() from IL
|
||||
// client.
|
||||
void handleMessage(Message msg) {
|
||||
void handleMessage(Message msg, const BufferInfo* buffer) {
|
||||
(void)buffer;
|
||||
if (msg.type == Message::Type::FILL_BUFFER_DONE) {
|
||||
if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
|
||||
eosFlag = true;
|
||||
|
@ -254,13 +258,26 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
#define WRITE_OUTPUT 0
|
||||
#if WRITE_OUTPUT
|
||||
static int count = 0;
|
||||
FILE* ofp = nullptr;
|
||||
if (count)
|
||||
ofp = fopen("out.bin", "ab");
|
||||
else
|
||||
ofp = fopen("out.bin", "wb");
|
||||
if (ofp != nullptr) {
|
||||
fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
|
||||
sizeof(char),
|
||||
msg.data.extendedBufferData.rangeLength, ofp);
|
||||
fclose(ofp);
|
||||
count++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testEOS(android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, bool signalEOS = false);
|
||||
|
||||
enum standardComp {
|
||||
mp3,
|
||||
amrnb,
|
||||
|
@ -294,44 +311,6 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
}
|
||||
};
|
||||
|
||||
// end of stream test for audio decoder components
|
||||
void AudioDecHidlTest::testEOS(android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
bool signalEOS) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
size_t i = 0;
|
||||
if (signalEOS) {
|
||||
if ((i = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
|
||||
// signal an empty buffer with flag set to EOS
|
||||
dispatchInputBuffer(omxNode, iBuffer, i, 0, OMX_BUFFERFLAG_EOS, 0);
|
||||
} else {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
// Dispatch all client owned output buffers to recover remaining frames
|
||||
while (1) {
|
||||
if ((i = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, i);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (1) {
|
||||
Message msg;
|
||||
status =
|
||||
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
EXPECT_EQ(status,
|
||||
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
for (; i < iBuffer->size(); i++) {
|
||||
if ((*iBuffer)[i].owner != client) break;
|
||||
}
|
||||
if (i == iBuffer->size()) break;
|
||||
}
|
||||
// test for flag
|
||||
EXPECT_EQ(eosFlag, true);
|
||||
eosFlag = false;
|
||||
}
|
||||
|
||||
// Set Default port param.
|
||||
void setDefaultPortParam(
|
||||
sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding,
|
||||
|
@ -580,8 +559,9 @@ void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
int timeOut = TIMEOUT_COUNTER;
|
||||
|
||||
while (1) {
|
||||
while (timeOut--) {
|
||||
size_t i = 0;
|
||||
status =
|
||||
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
|
@ -603,6 +583,7 @@ void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, index);
|
||||
}
|
||||
timeOut--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -642,6 +623,8 @@ void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
frameID++;
|
||||
}
|
||||
|
||||
int timeOut = TIMEOUT_COUNTER;
|
||||
bool stall = false;
|
||||
while (1) {
|
||||
status =
|
||||
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
|
@ -672,9 +655,21 @@ void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
(*Info)[frameID].bytesCount, flags,
|
||||
(*Info)[frameID].timestamp);
|
||||
frameID++;
|
||||
}
|
||||
stall = false;
|
||||
} else
|
||||
stall = true;
|
||||
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, index);
|
||||
stall = false;
|
||||
} else
|
||||
stall = true;
|
||||
if (stall)
|
||||
timeOut--;
|
||||
else
|
||||
timeOut = TIMEOUT_COUNTER;
|
||||
if (timeOut == 0) {
|
||||
EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -778,7 +773,7 @@ TEST_F(AudioDecHidlTest, DecodeTest) {
|
|||
eleStream.close();
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
testEOS(&iBuffer, &oBuffer);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
|
||||
EXPECT_EQ(timestampUslist.empty(), true);
|
||||
// set state to idle
|
||||
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
|
||||
|
@ -825,7 +820,7 @@ TEST_F(AudioDecHidlTest, EOSTest_M) {
|
|||
changeStateIdletoExecute(omxNode, observer);
|
||||
|
||||
// request EOS at the start
|
||||
testEOS(&iBuffer, &oBuffer, true);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag);
|
||||
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput);
|
||||
EXPECT_GE(framesReceived, 0U);
|
||||
|
@ -908,7 +903,7 @@ TEST_F(AudioDecHidlTest, ThumbnailTest) {
|
|||
eleStream.close();
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
testEOS(&iBuffer, &oBuffer);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
|
||||
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput);
|
||||
EXPECT_GE(framesReceived, 1U);
|
||||
|
@ -924,7 +919,7 @@ TEST_F(AudioDecHidlTest, ThumbnailTest) {
|
|||
eleStream.close();
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
testEOS(&iBuffer, &oBuffer, true);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag);
|
||||
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput);
|
||||
EXPECT_GE(framesReceived, 1U);
|
||||
|
@ -1004,7 +999,7 @@ TEST_F(AudioDecHidlTest, SimpleEOSTest) {
|
|||
eleStream.close();
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
testEOS(&iBuffer, &oBuffer);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
|
||||
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput);
|
||||
framesReceived = 0;
|
||||
|
|
|
@ -30,6 +30,7 @@ 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;
|
||||
|
@ -135,7 +136,10 @@ class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>(
|
||||
gEnv->getInstance());
|
||||
ASSERT_NE(omx, nullptr);
|
||||
observer = new CodecObserver([this](Message msg) { (void)msg; });
|
||||
observer =
|
||||
new CodecObserver([this](Message msg, const BufferInfo* buffer) {
|
||||
handleMessage(msg, buffer);
|
||||
});
|
||||
ASSERT_NE(observer, nullptr);
|
||||
if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
|
||||
disableTest = true;
|
||||
|
@ -191,6 +195,7 @@ class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
}
|
||||
}
|
||||
if (i == kNumCompToCoding) disableTest = true;
|
||||
eosFlag = false;
|
||||
if (disableTest) std::cerr << "[ ] Warning ! Test Disabled\n";
|
||||
}
|
||||
|
||||
|
@ -201,6 +206,36 @@ class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
// callback function to process messages received by onMessages() from IL
|
||||
// client.
|
||||
void handleMessage(Message msg, const BufferInfo* buffer) {
|
||||
(void)buffer;
|
||||
|
||||
if (msg.type == Message::Type::FILL_BUFFER_DONE) {
|
||||
if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
|
||||
eosFlag = true;
|
||||
}
|
||||
if (msg.data.extendedBufferData.rangeLength != 0) {
|
||||
#define WRITE_OUTPUT 0
|
||||
#if WRITE_OUTPUT
|
||||
static int count = 0;
|
||||
FILE* ofp = nullptr;
|
||||
if (count)
|
||||
ofp = fopen("out.bin", "ab");
|
||||
else
|
||||
ofp = fopen("out.bin", "wb");
|
||||
if (ofp != nullptr) {
|
||||
fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
|
||||
sizeof(char),
|
||||
msg.data.extendedBufferData.rangeLength, ofp);
|
||||
fclose(ofp);
|
||||
count++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum standardComp {
|
||||
amrnb,
|
||||
amrwb,
|
||||
|
@ -215,6 +250,7 @@ class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
standardComp compName;
|
||||
OMX_AUDIO_CODINGTYPE eEncoding;
|
||||
bool disableTest;
|
||||
bool eosFlag;
|
||||
|
||||
protected:
|
||||
static void description(const std::string& description) {
|
||||
|
@ -289,12 +325,44 @@ void GetURLForComponent(AudioEncHidlTest::standardComp comp, char* mURL) {
|
|||
}
|
||||
}
|
||||
|
||||
// blocking call to ensures application to Wait till all the inputs are consumed
|
||||
void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
int timeOut = TIMEOUT_COUNTER;
|
||||
|
||||
while (timeOut--) {
|
||||
size_t i = 0;
|
||||
status =
|
||||
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
EXPECT_EQ(status,
|
||||
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
// status == TIMED_OUT, it could be due to process time being large
|
||||
// than DEFAULT_TIMEOUT or component needs output buffers to start
|
||||
// processing.
|
||||
for (; i < iBuffer->size(); i++) {
|
||||
if ((*iBuffer)[i].owner != client) break;
|
||||
}
|
||||
if (i == iBuffer->size()) break;
|
||||
|
||||
// Dispatch an output buffer assuming outQueue.empty() is true
|
||||
size_t index;
|
||||
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, index);
|
||||
}
|
||||
timeOut--;
|
||||
}
|
||||
}
|
||||
|
||||
// Encode N Frames
|
||||
void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, uint32_t nFrames,
|
||||
int32_t samplesPerFrame, int32_t nChannels,
|
||||
int32_t nSampleRate, std::ifstream& eleStream) {
|
||||
int32_t nSampleRate, std::ifstream& eleStream,
|
||||
bool signalEOS = true) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
|
@ -307,6 +375,7 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
int32_t timestampIncr =
|
||||
(int)(((float)samplesPerFrame / nSampleRate) * 1000000);
|
||||
uint64_t timestamp = 0;
|
||||
uint32_t flags = 0;
|
||||
for (size_t i = 0; i < iBuffer->size() && nFrames != 0; i++) {
|
||||
char* ipBuffer = static_cast<char*>(
|
||||
static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
|
||||
|
@ -314,11 +383,14 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
static_cast<int>((*iBuffer)[i].mMemory->getSize()));
|
||||
eleStream.read(ipBuffer, bytesCount);
|
||||
if (eleStream.gcount() != bytesCount) break;
|
||||
dispatchInputBuffer(omxNode, iBuffer, i, bytesCount, 0, timestamp);
|
||||
if (signalEOS && (nFrames == 1)) flags = OMX_BUFFERFLAG_EOS;
|
||||
dispatchInputBuffer(omxNode, iBuffer, i, bytesCount, flags, timestamp);
|
||||
timestamp += timestampIncr;
|
||||
nFrames--;
|
||||
}
|
||||
|
||||
int timeOut = TIMEOUT_COUNTER;
|
||||
bool stall = false;
|
||||
while (1) {
|
||||
status =
|
||||
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
|
@ -337,14 +409,27 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
static_cast<int>((*iBuffer)[index].mMemory->getSize()));
|
||||
eleStream.read(ipBuffer, bytesCount);
|
||||
if (eleStream.gcount() != bytesCount) break;
|
||||
dispatchInputBuffer(omxNode, iBuffer, index, bytesCount, 0,
|
||||
if (signalEOS && (nFrames == 1)) flags = OMX_BUFFERFLAG_EOS;
|
||||
dispatchInputBuffer(omxNode, iBuffer, index, bytesCount, flags,
|
||||
timestamp);
|
||||
timestamp += timestampIncr;
|
||||
nFrames--;
|
||||
}
|
||||
stall = false;
|
||||
} else
|
||||
stall = true;
|
||||
// Dispatch output buffer
|
||||
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, index);
|
||||
stall = false;
|
||||
} else
|
||||
stall = true;
|
||||
if (stall)
|
||||
timeOut--;
|
||||
else
|
||||
timeOut = TIMEOUT_COUNTER;
|
||||
if (timeOut == 0) {
|
||||
EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -380,8 +465,8 @@ TEST_F(AudioEncHidlTest, EnumeratePortFormat) {
|
|||
}
|
||||
|
||||
// test raw stream encode
|
||||
TEST_F(AudioEncHidlTest, EncodeTest) {
|
||||
description("Tests Encode");
|
||||
TEST_F(AudioEncHidlTest, SimpleEncodeTest) {
|
||||
description("Tests Basic encoding and EOS");
|
||||
if (disableTest) return;
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
||||
|
@ -399,8 +484,6 @@ TEST_F(AudioEncHidlTest, EncodeTest) {
|
|||
GetURLForComponent(compName, mURL);
|
||||
|
||||
std::ifstream eleStream;
|
||||
eleStream.open(mURL, std::ifstream::binary);
|
||||
ASSERT_EQ(eleStream.is_open(), true);
|
||||
|
||||
// Configure input port
|
||||
int32_t nChannels = 2;
|
||||
|
@ -449,16 +532,19 @@ TEST_F(AudioEncHidlTest, EncodeTest) {
|
|||
// set state to executing
|
||||
changeStateIdletoExecute(omxNode, observer);
|
||||
|
||||
encodeNFrames(omxNode, observer, &iBuffer, &oBuffer, 1024, samplesPerFrame,
|
||||
eleStream.open(mURL, std::ifstream::binary);
|
||||
ASSERT_EQ(eleStream.is_open(), true);
|
||||
encodeNFrames(omxNode, observer, &iBuffer, &oBuffer, 128, samplesPerFrame,
|
||||
nChannels, nSampleRate, eleStream);
|
||||
eleStream.close();
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
|
||||
|
||||
// set state to idle
|
||||
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
|
||||
// set state to executing
|
||||
changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
|
||||
eleStream.close();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
|
|
@ -30,6 +30,7 @@ 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;
|
||||
|
@ -45,277 +46,6 @@ using ::android::sp;
|
|||
#include <media_hidl_test_common.h>
|
||||
#include <memory>
|
||||
|
||||
// allocate buffers needed on a component port
|
||||
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.get(), 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 = false;
|
||||
allocator->allocate(
|
||||
portDef.nBufferSize,
|
||||
[&success, &buffer](bool _s,
|
||||
::android::hardware::hidl_memory const& mem) {
|
||||
success = _s;
|
||||
buffer.omxBuffer.sharedMemory = mem;
|
||||
});
|
||||
ASSERT_EQ(success, true);
|
||||
ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(), portDef.nBufferSize);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// State Transition : Loaded -> Idle
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateLoadedtoIdle(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;
|
||||
|
||||
// set state to idle
|
||||
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
||||
OMX_StateIdle);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
||||
|
||||
// Dont switch states until the ports are populated
|
||||
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
|
||||
// allocate buffers on input port
|
||||
allocatePortBuffers(omxNode, iBuffer, kPortIndexInput);
|
||||
|
||||
// Dont switch states until the ports are populated
|
||||
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
|
||||
// allocate buffers on output port
|
||||
allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput);
|
||||
|
||||
// As the ports are populated, check if the state transition is complete
|
||||
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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Idle -> Loaded
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateIdletoLoaded(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;
|
||||
|
||||
// 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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Idle -> Execute
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateIdletoExecute(sp<IOmxNode> omxNode,
|
||||
sp<CodecObserver> observer) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
// set state to execute
|
||||
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);
|
||||
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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Execute -> Idle
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
// 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);
|
||||
|
||||
// test if client got all its buffers back
|
||||
for (size_t i = 0; i < oBuffer->size(); ++i) {
|
||||
EXPECT_EQ((*oBuffer)[i].owner, client);
|
||||
}
|
||||
for (size_t i = 0; i < iBuffer->size(); ++i) {
|
||||
EXPECT_EQ((*iBuffer)[i].owner, client);
|
||||
}
|
||||
}
|
||||
|
||||
// get empty buffer index
|
||||
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();
|
||||
}
|
||||
|
||||
// dispatch buffer to output port
|
||||
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;
|
||||
}
|
||||
|
||||
// dispatch buffer to input port
|
||||
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;
|
||||
}
|
||||
|
||||
// Flush input and output ports
|
||||
void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
|
||||
OMX_U32 kPortIndexOutput, int64_t timeoutUs) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
// Flush input port
|
||||
status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
|
||||
kPortIndexInput);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = observer->dequeueMessage(&msg, timeoutUs, 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);
|
||||
}
|
||||
|
||||
// Flush output port
|
||||
status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
|
||||
kPortIndexOutput);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = observer->dequeueMessage(&msg, timeoutUs, 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);
|
||||
}
|
||||
}
|
||||
|
||||
Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
|
||||
sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding) {
|
||||
OMX_U32 index = 0;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2016, The Android Open Source Project
|
||||
* 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.
|
||||
|
@ -18,6 +18,7 @@
|
|||
#define MEDIA_AUDIO_HIDL_TEST_COMMON_H
|
||||
|
||||
#include <media_hidl_test_common.h>
|
||||
|
||||
/*
|
||||
* Random Index used for monkey testing while get/set parameters
|
||||
*/
|
||||
|
@ -26,42 +27,6 @@
|
|||
/*
|
||||
* Common audio utils
|
||||
*/
|
||||
void allocatePortBuffers(sp<IOmxNode> omxNode,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
OMX_U32 portIndex);
|
||||
|
||||
void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput);
|
||||
|
||||
void changeStateIdletoLoaded(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput);
|
||||
|
||||
void changeStateIdletoExecute(sp<IOmxNode> omxNode, sp<CodecObserver> observer);
|
||||
|
||||
void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer);
|
||||
|
||||
size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray);
|
||||
|
||||
void dispatchOutputBuffer(sp<IOmxNode> omxNode,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
size_t bufferIndex);
|
||||
|
||||
void dispatchInputBuffer(sp<IOmxNode> omxNode,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
size_t bufferIndex, int bytesCount, uint32_t flags,
|
||||
uint64_t timestamp);
|
||||
|
||||
void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
|
||||
OMX_U32 kPortIndexOutput, int64_t timeoutUs = DEFAULT_TIMEOUT);
|
||||
|
||||
Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
|
||||
sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding);
|
||||
|
||||
|
|
33
media/omx/1.0/vts/functional/common/Android.bp
Executable file
33
media/omx/1.0/vts/functional/common/Android.bp
Executable file
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// 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_library_static {
|
||||
name: "VtsHalMediaOmxV1_0CommonUtil",
|
||||
defaults: ["hidl_defaults"],
|
||||
srcs: ["media_hidl_test_common.cpp"],
|
||||
shared_libs: [
|
||||
"liblog",
|
||||
"libhidlmemory",
|
||||
"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/",
|
||||
],
|
||||
}
|
435
media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
Executable file
435
media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
Executable file
|
@ -0,0 +1,435 @@
|
|||
/*
|
||||
* 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_video_test_common"
|
||||
|
||||
#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 <hidlmemory/mapping.h>
|
||||
#include <media/hardware/HardwareAPI.h>
|
||||
#include <media_hidl_test_common.h>
|
||||
#include <memory>
|
||||
|
||||
// allocate buffers needed on a component port
|
||||
void allocatePortBuffers(sp<IOmxNode> omxNode,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
OMX_U32 portIndex, PortMode portMode) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
OMX_PARAM_PORTDEFINITIONTYPE portDef;
|
||||
|
||||
buffArray->clear();
|
||||
|
||||
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
|
||||
&portDef);
|
||||
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
|
||||
if (portMode == PortMode::PRESET_SECURE_BUFFER) {
|
||||
for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
|
||||
BufferInfo buffer;
|
||||
buffer.owner = client;
|
||||
buffer.omxBuffer.type = CodecBuffer::Type::NATIVE_HANDLE;
|
||||
omxNode->allocateSecureBuffer(
|
||||
portIndex, portDef.nBufferSize,
|
||||
[&status, &buffer](
|
||||
android::hardware::media::omx::V1_0::Status _s, uint32_t id,
|
||||
::android::hardware::hidl_handle const& nativeHandle) {
|
||||
status = _s;
|
||||
buffer.id = id;
|
||||
buffer.omxBuffer.nativeHandle = nativeHandle;
|
||||
});
|
||||
buffArray->push(buffer);
|
||||
ASSERT_EQ(status,
|
||||
::android::hardware::media::omx::V1_0::Status::OK);
|
||||
}
|
||||
} else if (portMode == PortMode::PRESET_BYTE_BUFFER ||
|
||||
portMode == PortMode::DYNAMIC_ANW_BUFFER) {
|
||||
sp<IAllocator> allocator = IAllocator::getService("ashmem");
|
||||
EXPECT_NE(allocator.get(), nullptr);
|
||||
|
||||
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 = false;
|
||||
if (portMode != PortMode::PRESET_BYTE_BUFFER) {
|
||||
portDef.nBufferSize = sizeof(android::VideoNativeMetadata);
|
||||
}
|
||||
allocator->allocate(
|
||||
portDef.nBufferSize,
|
||||
[&success, &buffer](
|
||||
bool _s, ::android::hardware::hidl_memory const& mem) {
|
||||
success = _s;
|
||||
buffer.omxBuffer.sharedMemory = mem;
|
||||
});
|
||||
ASSERT_EQ(success, true);
|
||||
ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(),
|
||||
portDef.nBufferSize);
|
||||
buffer.mMemory = mapMemory(buffer.omxBuffer.sharedMemory);
|
||||
ASSERT_NE(buffer.mMemory, nullptr);
|
||||
if (portMode == PortMode::DYNAMIC_ANW_BUFFER) {
|
||||
android::VideoNativeMetadata* metaData =
|
||||
static_cast<android::VideoNativeMetadata*>(
|
||||
static_cast<void*>(buffer.mMemory->getPointer()));
|
||||
metaData->nFenceFd = -1;
|
||||
buffer.slot = -1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// State Transition : Loaded -> Idle
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
|
||||
PortMode* portMode) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
PortMode defaultPortMode[2], *pm;
|
||||
|
||||
defaultPortMode[0] = PortMode::PRESET_BYTE_BUFFER;
|
||||
defaultPortMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
||||
pm = portMode ? portMode : defaultPortMode;
|
||||
|
||||
// set state to idle
|
||||
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
||||
OMX_StateIdle);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
||||
|
||||
// Dont switch states until the ports are populated
|
||||
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
|
||||
// allocate buffers on input port
|
||||
allocatePortBuffers(omxNode, iBuffer, kPortIndexInput, pm[0]);
|
||||
|
||||
// Dont switch states until the ports are populated
|
||||
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
|
||||
// allocate buffers on output port
|
||||
allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput, pm[1]);
|
||||
|
||||
// As the ports are populated, check if the state transition is complete
|
||||
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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Idle -> Loaded
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateIdletoLoaded(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;
|
||||
|
||||
// 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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Idle -> Execute
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateIdletoExecute(sp<IOmxNode> omxNode,
|
||||
sp<CodecObserver> observer) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
// set state to execute
|
||||
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);
|
||||
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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Execute -> Idle
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
// 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);
|
||||
|
||||
// test if client got all its buffers back
|
||||
for (size_t i = 0; i < oBuffer->size(); ++i) {
|
||||
EXPECT_EQ((*oBuffer)[i].owner, client);
|
||||
}
|
||||
for (size_t i = 0; i < iBuffer->size(); ++i) {
|
||||
EXPECT_EQ((*iBuffer)[i].owner, client);
|
||||
}
|
||||
}
|
||||
|
||||
// get empty buffer index
|
||||
size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray) {
|
||||
android::Vector<BufferInfo>::iterator it = buffArray->begin();
|
||||
while (it != buffArray->end()) {
|
||||
if (it->owner == client) {
|
||||
// This block of code ensures that all buffers allocated at init
|
||||
// time are utilized
|
||||
BufferInfo backup = *it;
|
||||
buffArray->erase(it);
|
||||
buffArray->push_back(backup);
|
||||
return buffArray->size() - 1;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
return buffArray->size();
|
||||
}
|
||||
|
||||
// dispatch buffer to output port
|
||||
void dispatchOutputBuffer(sp<IOmxNode> omxNode,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
size_t bufferIndex, PortMode portMode) {
|
||||
if (portMode == PortMode::DYNAMIC_ANW_BUFFER) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
CodecBuffer t = (*buffArray)[bufferIndex].omxBuffer;
|
||||
t.type = CodecBuffer::Type::ANW_BUFFER;
|
||||
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;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// dispatch buffer to input port
|
||||
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;
|
||||
}
|
||||
|
||||
// Flush input and output ports
|
||||
void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
|
||||
OMX_U32 kPortIndexOutput, int64_t timeoutUs) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
// Flush input port
|
||||
status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
|
||||
kPortIndexInput);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = observer->dequeueMessage(&msg, timeoutUs, 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);
|
||||
}
|
||||
|
||||
// Flush output port
|
||||
status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
|
||||
kPortIndexOutput);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = observer->dequeueMessage(&msg, timeoutUs, 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);
|
||||
}
|
||||
}
|
||||
|
||||
// dispatch an empty input buffer with eos flag set if requested.
|
||||
// This call assumes that all input buffers are processed completely.
|
||||
// feed output buffers till we receive a buffer with eos flag set
|
||||
void testEOS(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, bool signalEOS,
|
||||
bool& eosFlag, PortMode* portMode) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
PortMode defaultPortMode[2], *pm;
|
||||
|
||||
defaultPortMode[0] = PortMode::PRESET_BYTE_BUFFER;
|
||||
defaultPortMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
||||
pm = portMode ? portMode : defaultPortMode;
|
||||
|
||||
size_t i = 0;
|
||||
if (signalEOS) {
|
||||
if ((i = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
|
||||
// signal an empty buffer with flag set to EOS
|
||||
dispatchInputBuffer(omxNode, iBuffer, i, 0, OMX_BUFFERFLAG_EOS, 0);
|
||||
} else {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
|
||||
int timeOut = TIMEOUT_COUNTER;
|
||||
while (timeOut--) {
|
||||
// Dispatch all client owned output buffers to recover remaining frames
|
||||
while (1) {
|
||||
if ((i = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, i, pm[1]);
|
||||
// if dispatch is successful, perhaps there is a latency
|
||||
// in the component. Dont be in a haste to leave. reset timeout
|
||||
// counter
|
||||
timeOut = TIMEOUT_COUNTER;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Message msg;
|
||||
status =
|
||||
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
EXPECT_EQ(status,
|
||||
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
if (eosFlag == true) break;
|
||||
}
|
||||
// test for flag
|
||||
EXPECT_EQ(eosFlag, true);
|
||||
eosFlag = false;
|
||||
}
|
|
@ -33,9 +33,19 @@
|
|||
#include <media/openmax/OMX_AudioExt.h>
|
||||
#include <media/openmax/OMX_VideoExt.h>
|
||||
|
||||
#define DEFAULT_TIMEOUT 40000
|
||||
#define TIMEOUT_COUNTER (10000000 / DEFAULT_TIMEOUT)
|
||||
|
||||
enum bufferOwner {
|
||||
client,
|
||||
component,
|
||||
unknown,
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO: Borrowed from Conversion.h. This is not the ideal way to do it.
|
||||
* Loose these definitions once you include Conversion.h
|
||||
* TODO: below definitions are 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);
|
||||
|
@ -57,22 +67,14 @@ inline uint32_t toRawCommandType(OMX_COMMANDTYPE l) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Handle Callback functions EmptythisBuffer(), FillthisBuffer(),
|
||||
* EventHandler()
|
||||
* struct definitions
|
||||
*/
|
||||
#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;
|
||||
int32_t slot;
|
||||
};
|
||||
|
||||
struct FrameData {
|
||||
|
@ -81,9 +83,14 @@ struct FrameData {
|
|||
uint32_t timestamp;
|
||||
};
|
||||
|
||||
/*
|
||||
* Handle Callback functions EmptythisBuffer(), FillthisBuffer(),
|
||||
* EventHandler()
|
||||
*/
|
||||
struct CodecObserver : public IOmxObserver {
|
||||
public:
|
||||
CodecObserver(std::function<void(Message)> fn) : callBack(fn) {}
|
||||
CodecObserver(std::function<void(Message, const BufferInfo*)> fn)
|
||||
: callBack(fn) {}
|
||||
Return<void> onMessages(const hidl_vec<Message>& messages) override {
|
||||
android::Mutex::Autolock autoLock(msgLock);
|
||||
for (hidl_vec<Message>::const_iterator it = messages.begin();
|
||||
|
@ -114,7 +121,7 @@ struct CodecObserver : public IOmxObserver {
|
|||
for (i = 0; i < oBuffers->size(); ++i) {
|
||||
if ((*oBuffers)[i].id ==
|
||||
it->data.bufferData.buffer) {
|
||||
if (callBack) callBack(*it);
|
||||
if (callBack) callBack(*it, &(*oBuffers)[i]);
|
||||
oBuffers->editItemAt(i).owner = client;
|
||||
msgQueue.erase(it);
|
||||
break;
|
||||
|
@ -129,6 +136,7 @@ struct CodecObserver : public IOmxObserver {
|
|||
for (i = 0; i < iBuffers->size(); ++i) {
|
||||
if ((*iBuffers)[i].id ==
|
||||
it->data.bufferData.buffer) {
|
||||
if (callBack) callBack(*it, &(*iBuffers)[i]);
|
||||
iBuffers->editItemAt(i).owner = client;
|
||||
msgQueue.erase(it);
|
||||
break;
|
||||
|
@ -154,7 +162,7 @@ struct CodecObserver : public IOmxObserver {
|
|||
android::List<Message> msgQueue;
|
||||
android::Mutex msgLock;
|
||||
android::Condition msgCondition;
|
||||
std::function<void(Message)> callBack;
|
||||
std::function<void(Message, const BufferInfo*)> callBack;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -245,4 +253,51 @@ Return<android::hardware::media::omx::V1_0::Status> setPortConfig(
|
|||
inHidlBytes(params, sizeof(*params)));
|
||||
}
|
||||
|
||||
/*
|
||||
* common functions declarations
|
||||
*/
|
||||
void allocatePortBuffers(sp<IOmxNode> omxNode,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
OMX_U32 portIndex,
|
||||
PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
|
||||
|
||||
void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
|
||||
PortMode* portMode = nullptr);
|
||||
|
||||
void changeStateIdletoLoaded(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput);
|
||||
|
||||
void changeStateIdletoExecute(sp<IOmxNode> omxNode, sp<CodecObserver> observer);
|
||||
|
||||
void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer);
|
||||
|
||||
size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray);
|
||||
|
||||
void dispatchOutputBuffer(sp<IOmxNode> omxNode,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
size_t bufferIndex,
|
||||
PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
|
||||
|
||||
void dispatchInputBuffer(sp<IOmxNode> omxNode,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
size_t bufferIndex, int bytesCount, uint32_t flags,
|
||||
uint64_t timestamp);
|
||||
|
||||
void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
|
||||
OMX_U32 kPortIndexOutput, int64_t timeoutUs = DEFAULT_TIMEOUT);
|
||||
|
||||
void testEOS(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, bool signalEOS,
|
||||
bool& eosFlag, PortMode* portMode = nullptr);
|
||||
|
||||
#endif // MEDIA_HIDL_TEST_COMMON_H
|
||||
|
|
|
@ -23,6 +23,7 @@ cc_test {
|
|||
"liblog",
|
||||
"libcutils",
|
||||
"libhidlbase",
|
||||
"libhidlmemory",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"libnativehelper",
|
||||
|
@ -32,7 +33,8 @@ cc_test {
|
|||
"android.hidl.memory@1.0",
|
||||
"android.hardware.media.omx@1.0",
|
||||
],
|
||||
static_libs: ["VtsHalHidlTargetTestBase"],
|
||||
static_libs: ["VtsHalHidlTargetTestBase",
|
||||
"VtsHalMediaOmxV1_0CommonUtil"],
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-g",
|
||||
|
|
|
@ -30,6 +30,7 @@ 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;
|
||||
|
@ -196,268 +197,6 @@ class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
// Random Index used for monkey testing while get/set parameters
|
||||
#define RANDOM_INDEX 1729
|
||||
|
||||
// allocate buffers needed on a component port
|
||||
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.get(), 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 = false;
|
||||
allocator->allocate(
|
||||
portDef.nBufferSize,
|
||||
[&success, &buffer](bool _s,
|
||||
::android::hardware::hidl_memory const& mem) {
|
||||
success = _s;
|
||||
buffer.omxBuffer.sharedMemory = mem;
|
||||
});
|
||||
ASSERT_EQ(success, true);
|
||||
ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(), portDef.nBufferSize);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// State Transition : Loaded -> Idle
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateLoadedtoIdle(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;
|
||||
|
||||
// set state to idle
|
||||
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
||||
OMX_StateIdle);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
||||
|
||||
// Dont switch states until the ports are populated
|
||||
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
|
||||
// allocate buffers on input port
|
||||
allocatePortBuffers(omxNode, iBuffer, kPortIndexInput);
|
||||
|
||||
// Dont switch states until the ports are populated
|
||||
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
|
||||
// allocate buffers on output port
|
||||
allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput);
|
||||
|
||||
// As the ports are populated, check if the state transition is complete
|
||||
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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Idle -> Loaded
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateIdletoLoaded(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;
|
||||
|
||||
// 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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Idle -> Execute
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateIdletoExecute(sp<IOmxNode> omxNode,
|
||||
sp<CodecObserver> observer) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
// set state to execute
|
||||
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);
|
||||
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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Execute -> Idle
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
// 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);
|
||||
|
||||
// test if client got all its buffers back
|
||||
for (size_t i = 0; i < oBuffer->size(); ++i) {
|
||||
EXPECT_EQ((*oBuffer)[i].owner, client);
|
||||
}
|
||||
for (size_t i = 0; i < iBuffer->size(); ++i) {
|
||||
EXPECT_EQ((*iBuffer)[i].owner, client);
|
||||
}
|
||||
}
|
||||
|
||||
// dispatch buffer to output port
|
||||
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;
|
||||
}
|
||||
|
||||
// dispatch buffer to input port
|
||||
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;
|
||||
}
|
||||
|
||||
// Flush input and output ports
|
||||
void flushPorts(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 input port
|
||||
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);
|
||||
}
|
||||
|
||||
// Flush output port
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// get/set video component port format
|
||||
Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
|
||||
sp<IOmxNode> omxNode, OMX_U32 portIndex,
|
||||
|
|
|
@ -33,8 +33,12 @@ cc_test {
|
|||
"android.hidl.allocator@1.0",
|
||||
"android.hidl.memory@1.0",
|
||||
"android.hardware.media.omx@1.0",
|
||||
"android.hardware.graphics.allocator@2.0",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
"android.hardware.graphics.common@1.0",
|
||||
],
|
||||
static_libs: ["VtsHalHidlTargetTestBase"],
|
||||
static_libs: ["VtsHalHidlTargetTestBase",
|
||||
"VtsHalMediaOmxV1_0CommonUtil"],
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-g",
|
||||
|
@ -59,13 +63,17 @@ cc_test {
|
|||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"libnativehelper",
|
||||
"libnativewindow",
|
||||
"libutils",
|
||||
"libstagefright_foundation",
|
||||
"android.hidl.allocator@1.0",
|
||||
"android.hidl.memory@1.0",
|
||||
"android.hardware.media.omx@1.0",
|
||||
"android.hardware.graphics.bufferqueue@1.0",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
],
|
||||
static_libs: ["VtsHalHidlTargetTestBase"],
|
||||
static_libs: ["VtsHalHidlTargetTestBase",
|
||||
"VtsHalMediaOmxV1_0CommonUtil"],
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-g",
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#define LOG_TAG "media_omx_hidl_video_dec_test"
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
|
||||
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
|
||||
#include <android/hardware/graphics/mapper/2.0/types.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>
|
||||
|
@ -25,11 +28,14 @@
|
|||
#include <android/hidl/memory/1.0/IMapper.h>
|
||||
#include <android/hidl/memory/1.0/IMemory.h>
|
||||
|
||||
using ::android::hardware::graphics::common::V1_0::BufferUsage;
|
||||
using ::android::hardware::graphics::common::V1_0::PixelFormat;
|
||||
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;
|
||||
|
@ -136,7 +142,9 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
gEnv->getInstance());
|
||||
ASSERT_NE(omx, nullptr);
|
||||
observer =
|
||||
new CodecObserver([this](Message msg) { handleMessage(msg); });
|
||||
new CodecObserver([this](Message msg, const BufferInfo* buffer) {
|
||||
handleMessage(msg, buffer);
|
||||
});
|
||||
ASSERT_NE(observer, nullptr);
|
||||
if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
|
||||
disableTest = true;
|
||||
|
@ -193,10 +201,19 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
}
|
||||
}
|
||||
if (i == kNumCompToCompression) disableTest = true;
|
||||
portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
||||
eosFlag = false;
|
||||
framesReceived = 0;
|
||||
timestampUs = 0;
|
||||
timestampDevTest = false;
|
||||
isSecure = 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 (isSecure) disableTest = true;
|
||||
if (disableTest) std::cerr << "[ ] Warning ! Test Disabled\n";
|
||||
}
|
||||
|
||||
|
@ -209,7 +226,8 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
|
||||
// callback function to process messages received by onMessages() from IL
|
||||
// client.
|
||||
void handleMessage(Message msg) {
|
||||
void handleMessage(Message msg, const BufferInfo* buffer) {
|
||||
(void)buffer;
|
||||
if (msg.type == Message::Type::FILL_BUFFER_DONE) {
|
||||
if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
|
||||
eosFlag = true;
|
||||
|
@ -245,13 +263,27 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
#define WRITE_OUTPUT 0
|
||||
#if WRITE_OUTPUT
|
||||
static int count = 0;
|
||||
FILE* ofp = nullptr;
|
||||
if (count)
|
||||
ofp = fopen("out.bin", "ab");
|
||||
else
|
||||
ofp = fopen("out.bin", "wb");
|
||||
if (ofp != nullptr &&
|
||||
portMode[1] == PortMode::PRESET_BYTE_BUFFER) {
|
||||
fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
|
||||
sizeof(char),
|
||||
msg.data.extendedBufferData.rangeLength, ofp);
|
||||
fclose(ofp);
|
||||
count++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testEOS(android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, bool signalEOS = false);
|
||||
|
||||
enum standardComp {
|
||||
h263,
|
||||
avc,
|
||||
|
@ -269,11 +301,13 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
standardComp compName;
|
||||
OMX_VIDEO_CODINGTYPE eCompressionFormat;
|
||||
bool disableTest;
|
||||
PortMode portMode[2];
|
||||
bool eosFlag;
|
||||
uint32_t framesReceived;
|
||||
uint64_t timestampUs;
|
||||
::android::List<uint64_t> timestampUslist;
|
||||
bool timestampDevTest;
|
||||
bool isSecure;
|
||||
|
||||
protected:
|
||||
static void description(const std::string& description) {
|
||||
|
@ -281,44 +315,6 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
}
|
||||
};
|
||||
|
||||
// end of stream test for video decoder components
|
||||
void VideoDecHidlTest::testEOS(android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
bool signalEOS) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
size_t i = 0;
|
||||
if (signalEOS) {
|
||||
if ((i = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
|
||||
// signal an empty buffer with flag set to EOS
|
||||
dispatchInputBuffer(omxNode, iBuffer, i, 0, OMX_BUFFERFLAG_EOS, 0);
|
||||
} else {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
// Dispatch all client owned output buffers to recover remaining frames
|
||||
while (1) {
|
||||
if ((i = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, i);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (1) {
|
||||
Message msg;
|
||||
status =
|
||||
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
EXPECT_EQ(status,
|
||||
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
for (; i < iBuffer->size(); i++) {
|
||||
if ((*iBuffer)[i].owner != client) break;
|
||||
}
|
||||
if (i == iBuffer->size()) break;
|
||||
}
|
||||
// test for flag
|
||||
EXPECT_EQ(eosFlag, true);
|
||||
eosFlag = false;
|
||||
}
|
||||
|
||||
// Set Default port param.
|
||||
void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
|
||||
OMX_VIDEO_CODINGTYPE eCompressionFormat,
|
||||
|
@ -399,12 +395,85 @@ void GetURLForComponent(VideoDecHidlTest::standardComp comp, char* mURL,
|
|||
}
|
||||
}
|
||||
|
||||
void allocateGraphicBuffers(sp<IOmxNode> omxNode, OMX_U32 portIndex,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
uint32_t nFrameWidth, uint32_t nFrameHeight,
|
||||
int32_t* nStride, uint32_t count) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator =
|
||||
android::hardware::graphics::allocator::V2_0::IAllocator::getService();
|
||||
ASSERT_NE(nullptr, allocator.get());
|
||||
|
||||
sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
|
||||
android::hardware::graphics::mapper::V2_0::IMapper::getService();
|
||||
ASSERT_NE(mapper.get(), nullptr);
|
||||
|
||||
android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo
|
||||
descriptorInfo;
|
||||
uint32_t usage;
|
||||
|
||||
descriptorInfo.width = nFrameWidth;
|
||||
descriptorInfo.height = nFrameHeight;
|
||||
descriptorInfo.layerCount = 1;
|
||||
descriptorInfo.format = PixelFormat::RGBA_8888;
|
||||
descriptorInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN);
|
||||
omxNode->getGraphicBufferUsage(
|
||||
portIndex,
|
||||
[&status, &usage](android::hardware::media::omx::V1_0::Status _s,
|
||||
uint32_t _n1) {
|
||||
status = _s;
|
||||
usage = _n1;
|
||||
});
|
||||
if (status == android::hardware::media::omx::V1_0::Status::OK) {
|
||||
descriptorInfo.usage |= usage;
|
||||
}
|
||||
|
||||
::android::hardware::hidl_vec<uint32_t> descriptor;
|
||||
android::hardware::graphics::mapper::V2_0::Error error;
|
||||
mapper->createDescriptor(
|
||||
descriptorInfo, [&error, &descriptor](
|
||||
android::hardware::graphics::mapper::V2_0::Error _s,
|
||||
::android::hardware::hidl_vec<uint32_t> _n1) {
|
||||
error = _s;
|
||||
descriptor = _n1;
|
||||
});
|
||||
EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
|
||||
|
||||
EXPECT_EQ(buffArray->size(), count);
|
||||
allocator->allocate(
|
||||
descriptor, count,
|
||||
[&](android::hardware::graphics::mapper::V2_0::Error _s, uint32_t _n1,
|
||||
const ::android::hardware::hidl_vec<
|
||||
::android::hardware::hidl_handle>& _n2) {
|
||||
ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE,
|
||||
_s);
|
||||
*nStride = _n1;
|
||||
ASSERT_EQ(count, _n2.size());
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
buffArray->editItemAt(i).omxBuffer.nativeHandle = _n2[i];
|
||||
buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.width =
|
||||
nFrameWidth;
|
||||
buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.height =
|
||||
nFrameHeight;
|
||||
buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.stride = _n1;
|
||||
buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.format =
|
||||
descriptorInfo.format;
|
||||
buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.usage =
|
||||
descriptorInfo.usage;
|
||||
buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.layerCount =
|
||||
descriptorInfo.layerCount;
|
||||
buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.id =
|
||||
(*buffArray)[i].id;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// port settings reconfiguration during runtime. reconfigures frame dimensions
|
||||
void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
|
||||
Message msg) {
|
||||
Message msg, PortMode oPortMode) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
|
||||
if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
|
||||
|
@ -461,7 +530,8 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
status,
|
||||
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
|
||||
allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput);
|
||||
allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput,
|
||||
oPortMode);
|
||||
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
|
||||
iBuffer, oBuffer);
|
||||
ASSERT_EQ(status,
|
||||
|
@ -472,7 +542,7 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
|
||||
// dispatch output buffers
|
||||
for (size_t i = 0; i < oBuffer->size(); i++) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, i);
|
||||
dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode);
|
||||
}
|
||||
} else {
|
||||
ASSERT_TRUE(false);
|
||||
|
@ -499,18 +569,21 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput) {
|
||||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
|
||||
PortMode oPortMode) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
int timeOut = TIMEOUT_COUNTER;
|
||||
|
||||
while (1) {
|
||||
while (timeOut--) {
|
||||
size_t i = 0;
|
||||
status =
|
||||
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
if (status == android::hardware::media::omx::V1_0::Status::OK) {
|
||||
EXPECT_EQ(msg.type, Message::Type::EVENT);
|
||||
portReconfiguration(omxNode, observer, iBuffer, oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput, msg);
|
||||
kPortIndexInput, kPortIndexOutput, msg,
|
||||
oPortMode);
|
||||
}
|
||||
// status == TIMED_OUT, it could be due to process time being large
|
||||
// than DEFAULT_TIMEOUT or component needs output buffers to start
|
||||
|
@ -523,8 +596,9 @@ void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
// Dispatch an output buffer assuming outQueue.empty() is true
|
||||
size_t index;
|
||||
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, index);
|
||||
dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode);
|
||||
}
|
||||
timeOut--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,13 +608,14 @@ void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
android::Vector<BufferInfo>* oBuffer,
|
||||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
|
||||
std::ifstream& eleStream, android::Vector<FrameData>* Info,
|
||||
int offset, int range, bool signalEOS = true) {
|
||||
int offset, int range, PortMode oPortMode,
|
||||
bool signalEOS = true) {
|
||||
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);
|
||||
dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode);
|
||||
}
|
||||
// dispatch input buffers
|
||||
uint32_t flags = 0;
|
||||
|
@ -563,6 +638,8 @@ void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
frameID++;
|
||||
}
|
||||
|
||||
int timeOut = TIMEOUT_COUNTER;
|
||||
bool stall = false;
|
||||
while (1) {
|
||||
status =
|
||||
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
|
@ -571,7 +648,8 @@ void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
if (status == android::hardware::media::omx::V1_0::Status::OK &&
|
||||
msg.type == Message::Type::EVENT) {
|
||||
portReconfiguration(omxNode, observer, iBuffer, oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput, msg);
|
||||
kPortIndexInput, kPortIndexOutput, msg,
|
||||
oPortMode);
|
||||
}
|
||||
|
||||
if (frameID == (int)Info->size() || frameID == (offset + range)) break;
|
||||
|
@ -593,9 +671,21 @@ void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
(*Info)[frameID].bytesCount, flags,
|
||||
(*Info)[frameID].timestamp);
|
||||
frameID++;
|
||||
}
|
||||
stall = false;
|
||||
} else
|
||||
stall = true;
|
||||
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, index);
|
||||
dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode);
|
||||
stall = false;
|
||||
} else
|
||||
stall = true;
|
||||
if (stall)
|
||||
timeOut--;
|
||||
else
|
||||
timeOut = TIMEOUT_COUNTER;
|
||||
if (timeOut == 0) {
|
||||
EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -675,6 +765,28 @@ TEST_F(VideoDecHidlTest, DecodeTest) {
|
|||
}
|
||||
eleInfo.close();
|
||||
|
||||
// set port mode
|
||||
if (isSecure) {
|
||||
portMode[0] = PortMode::PRESET_SECURE_BUFFER;
|
||||
portMode[1] = PortMode::DYNAMIC_ANW_BUFFER;
|
||||
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);
|
||||
} else {
|
||||
portMode[0] = PortMode::PRESET_BYTE_BUFFER;
|
||||
portMode[1] = PortMode::DYNAMIC_ANW_BUFFER;
|
||||
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
||||
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
||||
if (status != ::android::hardware::media::omx::V1_0::Status::OK) {
|
||||
portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
||||
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
||||
ASSERT_EQ(status,
|
||||
::android::hardware::media::omx::V1_0::Status::OK);
|
||||
}
|
||||
}
|
||||
|
||||
// set Port Params
|
||||
uint32_t nFrameWidth, nFrameHeight, xFramerate;
|
||||
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
|
||||
|
@ -682,23 +794,38 @@ TEST_F(VideoDecHidlTest, DecodeTest) {
|
|||
&xFramerate);
|
||||
setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
|
||||
eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
|
||||
omxNode->prepareForAdaptivePlayback(kPortIndexOutput, false, 1920, 1080);
|
||||
|
||||
android::Vector<BufferInfo> iBuffer, oBuffer;
|
||||
|
||||
// set state to idle
|
||||
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
kPortIndexInput, kPortIndexOutput, portMode);
|
||||
// set state to executing
|
||||
changeStateIdletoExecute(omxNode, observer);
|
||||
|
||||
if (portMode[1] != PortMode::PRESET_BYTE_BUFFER) {
|
||||
OMX_PARAM_PORTDEFINITIONTYPE portDef;
|
||||
|
||||
status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
|
||||
kPortIndexOutput, &portDef);
|
||||
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
allocateGraphicBuffers(
|
||||
omxNode, kPortIndexOutput, &oBuffer,
|
||||
portDef.format.video.nFrameWidth, portDef.format.video.nFrameHeight,
|
||||
&portDef.format.video.nStride, portDef.nBufferCountActual);
|
||||
}
|
||||
|
||||
// Port Reconfiguration
|
||||
eleStream.open(mURL, std::ifstream::binary);
|
||||
ASSERT_EQ(eleStream.is_open(), true);
|
||||
decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput, eleStream, &Info, 0, (int)Info.size());
|
||||
kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(),
|
||||
portMode[1]);
|
||||
eleStream.close();
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
testEOS(&iBuffer, &oBuffer);
|
||||
kPortIndexInput, kPortIndexOutput, portMode[1]);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode);
|
||||
EXPECT_EQ(timestampUslist.empty(), true);
|
||||
// set state to idle
|
||||
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
|
||||
|
@ -730,18 +857,25 @@ TEST_F(VideoDecHidlTest, EOSTest_M) {
|
|||
&xFramerate);
|
||||
setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
|
||||
eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
|
||||
omxNode->prepareForAdaptivePlayback(kPortIndexOutput, false, 1920, 1080);
|
||||
|
||||
// set port mode
|
||||
PortMode portMode[2];
|
||||
portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
||||
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);
|
||||
|
||||
android::Vector<BufferInfo> iBuffer, oBuffer;
|
||||
|
||||
// set state to idle
|
||||
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
kPortIndexInput, kPortIndexOutput, portMode);
|
||||
// set state to executing
|
||||
changeStateIdletoExecute(omxNode, observer);
|
||||
|
||||
// request EOS at the start
|
||||
testEOS(&iBuffer, &oBuffer, true);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode);
|
||||
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput);
|
||||
EXPECT_GE(framesReceived, 0U);
|
||||
|
@ -798,13 +932,20 @@ TEST_F(VideoDecHidlTest, ThumbnailTest) {
|
|||
&xFramerate);
|
||||
setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
|
||||
eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
|
||||
omxNode->prepareForAdaptivePlayback(kPortIndexOutput, false, 1920, 1080);
|
||||
|
||||
// set port mode
|
||||
PortMode portMode[2];
|
||||
portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
||||
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);
|
||||
|
||||
android::Vector<BufferInfo> iBuffer, oBuffer;
|
||||
|
||||
// set state to idle
|
||||
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
kPortIndexInput, kPortIndexOutput, portMode);
|
||||
// set state to executing
|
||||
changeStateIdletoExecute(omxNode, observer);
|
||||
|
||||
|
@ -814,11 +955,11 @@ TEST_F(VideoDecHidlTest, ThumbnailTest) {
|
|||
eleStream.open(mURL, std::ifstream::binary);
|
||||
ASSERT_EQ(eleStream.is_open(), true);
|
||||
decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput, eleStream, &Info, 0, i + 1);
|
||||
kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1]);
|
||||
eleStream.close();
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
testEOS(&iBuffer, &oBuffer);
|
||||
kPortIndexInput, kPortIndexOutput, portMode[1]);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode);
|
||||
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput);
|
||||
EXPECT_GE(framesReceived, 1U);
|
||||
|
@ -828,11 +969,12 @@ TEST_F(VideoDecHidlTest, ThumbnailTest) {
|
|||
eleStream.open(mURL, std::ifstream::binary);
|
||||
ASSERT_EQ(eleStream.is_open(), true);
|
||||
decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput, eleStream, &Info, 0, i + 1, false);
|
||||
kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1],
|
||||
false);
|
||||
eleStream.close();
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
testEOS(&iBuffer, &oBuffer, true);
|
||||
kPortIndexInput, kPortIndexOutput, portMode[1]);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode);
|
||||
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput);
|
||||
EXPECT_GE(framesReceived, 1U);
|
||||
|
@ -889,13 +1031,20 @@ TEST_F(VideoDecHidlTest, SimpleEOSTest) {
|
|||
&xFramerate);
|
||||
setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
|
||||
eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
|
||||
omxNode->prepareForAdaptivePlayback(kPortIndexOutput, false, 1920, 1080);
|
||||
|
||||
// set port mode
|
||||
PortMode portMode[2];
|
||||
portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
||||
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);
|
||||
|
||||
android::Vector<BufferInfo> iBuffer, oBuffer;
|
||||
|
||||
// set state to idle
|
||||
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
kPortIndexInput, kPortIndexOutput, portMode);
|
||||
// set state to executing
|
||||
changeStateIdletoExecute(omxNode, observer);
|
||||
|
||||
|
@ -903,11 +1052,12 @@ TEST_F(VideoDecHidlTest, SimpleEOSTest) {
|
|||
eleStream.open(mURL, std::ifstream::binary);
|
||||
ASSERT_EQ(eleStream.is_open(), true);
|
||||
decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput, eleStream, &Info, 0, (int)Info.size());
|
||||
kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(),
|
||||
portMode[1]);
|
||||
eleStream.close();
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
testEOS(&iBuffer, &oBuffer);
|
||||
kPortIndexInput, kPortIndexOutput, portMode[1]);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode);
|
||||
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput);
|
||||
framesReceived = 0;
|
||||
|
@ -964,11 +1114,19 @@ TEST_F(VideoDecHidlTest, FlushTest) {
|
|||
setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
|
||||
eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
|
||||
|
||||
// set port mode
|
||||
PortMode portMode[2];
|
||||
portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
||||
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);
|
||||
|
||||
android::Vector<BufferInfo> iBuffer, oBuffer;
|
||||
|
||||
// set state to idle
|
||||
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
kPortIndexInput, kPortIndexOutput, portMode);
|
||||
// set state to executing
|
||||
changeStateIdletoExecute(omxNode, observer);
|
||||
|
||||
|
@ -979,7 +1137,8 @@ TEST_F(VideoDecHidlTest, FlushTest) {
|
|||
eleStream.open(mURL, std::ifstream::binary);
|
||||
ASSERT_EQ(eleStream.is_open(), true);
|
||||
decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput, eleStream, &Info, 0, nFrames, false);
|
||||
kPortIndexOutput, eleStream, &Info, 0, nFrames, portMode[1],
|
||||
false);
|
||||
// Note: Assumes 200 ms is enough to end any decode call that started
|
||||
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput, 200000);
|
||||
|
@ -1001,7 +1160,7 @@ TEST_F(VideoDecHidlTest, FlushTest) {
|
|||
if (keyFrame) {
|
||||
decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
kPortIndexOutput, eleStream, &Info, index,
|
||||
Info.size() - index, false);
|
||||
Info.size() - index, portMode[1], false);
|
||||
}
|
||||
// Note: Assumes 200 ms is enough to end any decode call that started
|
||||
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
|
||||
#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
|
||||
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
|
||||
#include <android/hardware/graphics/mapper/2.0/types.h>
|
||||
#include <android/hardware/media/omx/1.0/IGraphicBufferSource.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>
|
||||
|
@ -29,11 +34,17 @@
|
|||
#include <android/hidl/memory/1.0/IMapper.h>
|
||||
#include <android/hidl/memory/1.0/IMemory.h>
|
||||
|
||||
using ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer;
|
||||
using ::android::hardware::graphics::bufferqueue::V1_0::IProducerListener;
|
||||
using ::android::hardware::graphics::common::V1_0::BufferUsage;
|
||||
using ::android::hardware::graphics::common::V1_0::PixelFormat;
|
||||
using ::android::hardware::media::omx::V1_0::IGraphicBufferSource;
|
||||
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;
|
||||
|
@ -48,6 +59,7 @@ using ::android::sp;
|
|||
#include <media/hardware/HardwareAPI.h>
|
||||
#include <media_hidl_test_common.h>
|
||||
#include <media_video_hidl_test_common.h>
|
||||
#include <system/window.h>
|
||||
#include <fstream>
|
||||
|
||||
// A class for test environment setup
|
||||
|
@ -140,7 +152,10 @@ class VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>(
|
||||
gEnv->getInstance());
|
||||
ASSERT_NE(omx, nullptr);
|
||||
observer = new CodecObserver([this](Message msg) { (void)msg; });
|
||||
observer =
|
||||
new CodecObserver([this](Message msg, const BufferInfo* buffer) {
|
||||
handleMessage(msg, buffer);
|
||||
});
|
||||
ASSERT_NE(observer, nullptr);
|
||||
if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
|
||||
disableTest = true;
|
||||
|
@ -196,6 +211,19 @@ class VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
}
|
||||
}
|
||||
if (i == kNumCompToCompression) disableTest = true;
|
||||
eosFlag = false;
|
||||
prependSPSPPS = false;
|
||||
timestampDevTest = false;
|
||||
producer = nullptr;
|
||||
source = nullptr;
|
||||
isSecure = 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 (isSecure) disableTest = true;
|
||||
if (disableTest) std::cerr << "[ ] Warning ! Test Disabled\n";
|
||||
}
|
||||
|
||||
|
@ -206,6 +234,63 @@ class VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
// callback function to process messages received by onMessages() from IL
|
||||
// client.
|
||||
void handleMessage(Message msg, const BufferInfo* buffer) {
|
||||
(void)buffer;
|
||||
|
||||
if (msg.type == Message::Type::FILL_BUFFER_DONE) {
|
||||
if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
|
||||
eosFlag = true;
|
||||
}
|
||||
if (msg.data.extendedBufferData.rangeLength != 0) {
|
||||
// Test if current timestamp is among the list of queued
|
||||
// timestamps
|
||||
if (timestampDevTest && (prependSPSPPS ||
|
||||
(msg.data.extendedBufferData.flags &
|
||||
OMX_BUFFERFLAG_CODECCONFIG) == 0)) {
|
||||
bool tsHit = false;
|
||||
android::List<uint64_t>::iterator it =
|
||||
timestampUslist.begin();
|
||||
while (it != timestampUslist.end()) {
|
||||
if (*it == msg.data.extendedBufferData.timestampUs) {
|
||||
timestampUslist.erase(it);
|
||||
tsHit = true;
|
||||
break;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
if (tsHit == false) {
|
||||
if (timestampUslist.empty() == false) {
|
||||
EXPECT_EQ(tsHit, true)
|
||||
<< "TimeStamp not recognized";
|
||||
} else {
|
||||
std::cerr
|
||||
<< "[ ] Warning ! Received non-zero "
|
||||
"output / TimeStamp not recognized \n";
|
||||
}
|
||||
}
|
||||
}
|
||||
#define WRITE_OUTPUT 0
|
||||
#if WRITE_OUTPUT
|
||||
static int count = 0;
|
||||
FILE* ofp = nullptr;
|
||||
if (count)
|
||||
ofp = fopen("out.bin", "ab");
|
||||
else
|
||||
ofp = fopen("out.bin", "wb");
|
||||
if (ofp != nullptr) {
|
||||
fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
|
||||
sizeof(char),
|
||||
msg.data.extendedBufferData.rangeLength, ofp);
|
||||
fclose(ofp);
|
||||
count++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum standardComp {
|
||||
h263,
|
||||
avc,
|
||||
|
@ -222,6 +307,13 @@ class VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
standardComp compName;
|
||||
OMX_VIDEO_CODINGTYPE eCompressionFormat;
|
||||
bool disableTest;
|
||||
bool eosFlag;
|
||||
bool prependSPSPPS;
|
||||
::android::List<uint64_t> timestampUslist;
|
||||
bool timestampDevTest;
|
||||
bool isSecure;
|
||||
sp<IGraphicBufferProducer> producer;
|
||||
sp<IGraphicBufferSource> source;
|
||||
|
||||
protected:
|
||||
static void description(const std::string& description) {
|
||||
|
@ -229,6 +321,30 @@ class VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
|||
}
|
||||
};
|
||||
|
||||
// CodecProducerListener class
|
||||
struct CodecProducerListener : public IProducerListener {
|
||||
public:
|
||||
CodecProducerListener(int a, int b)
|
||||
: freeBuffers(a), minUnDequeuedCount(b) {}
|
||||
virtual ::android::hardware::Return<void> onBufferReleased() override {
|
||||
android::Mutex::Autolock autoLock(bufferLock);
|
||||
freeBuffers += 1;
|
||||
return Void();
|
||||
}
|
||||
virtual ::android::hardware::Return<bool> needsReleaseNotify() override {
|
||||
return true;
|
||||
}
|
||||
void reduceCount() {
|
||||
android::Mutex::Autolock autoLock(bufferLock);
|
||||
freeBuffers -= 1;
|
||||
EXPECT_GE(freeBuffers, minUnDequeuedCount);
|
||||
}
|
||||
|
||||
size_t freeBuffers;
|
||||
size_t minUnDequeuedCount;
|
||||
android::Mutex bufferLock;
|
||||
};
|
||||
|
||||
// request VOP refresh
|
||||
void requestIDR(sp<IOmxNode> omxNode, OMX_U32 portIndex) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
|
@ -375,13 +491,313 @@ void GetURLForComponent(char* URL) {
|
|||
strcat(URL, "bbb_352x288_420p_30fps_32frames.yuv");
|
||||
}
|
||||
|
||||
// blocking call to ensures application to Wait till all the inputs are consumed
|
||||
void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
bool inputDataIsMeta = false,
|
||||
sp<CodecProducerListener> listener = nullptr) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
int timeOut = TIMEOUT_COUNTER;
|
||||
|
||||
while (timeOut--) {
|
||||
size_t i = 0;
|
||||
status =
|
||||
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
EXPECT_EQ(status,
|
||||
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
// status == TIMED_OUT, it could be due to process time being large
|
||||
// than DEFAULT_TIMEOUT or component needs output buffers to start
|
||||
// processing.
|
||||
if (inputDataIsMeta) {
|
||||
if (listener->freeBuffers == iBuffer->size()) break;
|
||||
} else {
|
||||
for (; i < iBuffer->size(); i++) {
|
||||
if ((*iBuffer)[i].owner != client) break;
|
||||
}
|
||||
if (i == iBuffer->size()) break;
|
||||
}
|
||||
|
||||
// Dispatch an output buffer assuming outQueue.empty() is true
|
||||
size_t index;
|
||||
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int colorFormatConversion(BufferInfo* buffer, void* buff, PixelFormat format,
|
||||
std::ifstream& eleStream) {
|
||||
sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
|
||||
android::hardware::graphics::mapper::V2_0::IMapper::getService();
|
||||
EXPECT_NE(mapper.get(), nullptr);
|
||||
if (mapper.get() == nullptr) return 1;
|
||||
|
||||
android::hardware::hidl_handle fence;
|
||||
android::hardware::graphics::mapper::V2_0::IMapper::Rect rect;
|
||||
android::hardware::graphics::mapper::V2_0::YCbCrLayout ycbcrLayout;
|
||||
android::hardware::graphics::mapper::V2_0::Error error;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.width = buffer->omxBuffer.attr.anwBuffer.width;
|
||||
rect.height = buffer->omxBuffer.attr.anwBuffer.height;
|
||||
|
||||
if (format == PixelFormat::YV12) {
|
||||
mapper->lockYCbCr(
|
||||
buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, fence,
|
||||
[&](android::hardware::graphics::mapper::V2_0::Error _e,
|
||||
android::hardware::graphics::mapper::V2_0::YCbCrLayout _n1) {
|
||||
error = _e;
|
||||
ycbcrLayout = _n1;
|
||||
});
|
||||
EXPECT_EQ(error,
|
||||
android::hardware::graphics::mapper::V2_0::Error::NONE);
|
||||
if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
|
||||
return 1;
|
||||
|
||||
EXPECT_EQ(ycbcrLayout.chromaStep, 1U);
|
||||
char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
|
||||
for (size_t y = rect.height; y > 0; --y) {
|
||||
eleStream.read(ipBuffer, rect.width);
|
||||
if (eleStream.gcount() != rect.width) return 1;
|
||||
ipBuffer += ycbcrLayout.yStride;
|
||||
}
|
||||
ipBuffer = static_cast<char*>(ycbcrLayout.cb);
|
||||
for (size_t y = rect.height >> 1; y > 0; --y) {
|
||||
eleStream.read(ipBuffer, rect.width >> 1);
|
||||
if (eleStream.gcount() != rect.width >> 1) return 1;
|
||||
ipBuffer += ycbcrLayout.cStride;
|
||||
}
|
||||
ipBuffer = static_cast<char*>(ycbcrLayout.cr);
|
||||
for (size_t y = rect.height >> 1; y > 0; --y) {
|
||||
eleStream.read(ipBuffer, rect.width >> 1);
|
||||
if (eleStream.gcount() != rect.width >> 1) return 1;
|
||||
ipBuffer += ycbcrLayout.cStride;
|
||||
}
|
||||
|
||||
mapper->unlock(buff,
|
||||
[&](android::hardware::graphics::mapper::V2_0::Error _e,
|
||||
android::hardware::hidl_handle _n1) {
|
||||
error = _e;
|
||||
fence = _n1;
|
||||
});
|
||||
EXPECT_EQ(error,
|
||||
android::hardware::graphics::mapper::V2_0::Error::NONE);
|
||||
if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
|
||||
return 1;
|
||||
} else if (format == PixelFormat::YCBCR_420_888) {
|
||||
void* data;
|
||||
mapper->lock(buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, fence,
|
||||
[&](android::hardware::graphics::mapper::V2_0::Error _e,
|
||||
void* _n1) {
|
||||
error = _e;
|
||||
data = _n1;
|
||||
});
|
||||
EXPECT_EQ(error,
|
||||
android::hardware::graphics::mapper::V2_0::Error::NONE);
|
||||
if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
|
||||
return 1;
|
||||
|
||||
ycbcrLayout.chromaStep = 1;
|
||||
ycbcrLayout.yStride = buffer->omxBuffer.attr.anwBuffer.stride;
|
||||
ycbcrLayout.cStride = ycbcrLayout.yStride >> 1;
|
||||
ycbcrLayout.y = data;
|
||||
ycbcrLayout.cb = static_cast<char*>(ycbcrLayout.y) +
|
||||
(ycbcrLayout.yStride * rect.height);
|
||||
ycbcrLayout.cr = static_cast<char*>(ycbcrLayout.cb) +
|
||||
((ycbcrLayout.yStride * rect.height) >> 2);
|
||||
|
||||
char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
|
||||
for (size_t y = rect.height; y > 0; --y) {
|
||||
eleStream.read(ipBuffer, rect.width);
|
||||
if (eleStream.gcount() != rect.width) return 1;
|
||||
ipBuffer += ycbcrLayout.yStride;
|
||||
}
|
||||
ipBuffer = static_cast<char*>(ycbcrLayout.cb);
|
||||
for (size_t y = rect.height >> 1; y > 0; --y) {
|
||||
eleStream.read(ipBuffer, rect.width >> 1);
|
||||
if (eleStream.gcount() != rect.width >> 1) return 1;
|
||||
ipBuffer += ycbcrLayout.cStride;
|
||||
}
|
||||
ipBuffer = static_cast<char*>(ycbcrLayout.cr);
|
||||
for (size_t y = rect.height >> 1; y > 0; --y) {
|
||||
eleStream.read(ipBuffer, rect.width >> 1);
|
||||
if (eleStream.gcount() != rect.width >> 1) return 1;
|
||||
ipBuffer += ycbcrLayout.cStride;
|
||||
}
|
||||
|
||||
mapper->unlock(buff,
|
||||
[&](android::hardware::graphics::mapper::V2_0::Error _e,
|
||||
android::hardware::hidl_handle _n1) {
|
||||
error = _e;
|
||||
fence = _n1;
|
||||
});
|
||||
EXPECT_EQ(error,
|
||||
android::hardware::graphics::mapper::V2_0::Error::NONE);
|
||||
if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
|
||||
return 1;
|
||||
} else {
|
||||
EXPECT_TRUE(false) << "un expected pixel format";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fillGraphicBuffer(BufferInfo* buffer, PixelFormat format,
|
||||
std::ifstream& eleStream) {
|
||||
sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
|
||||
android::hardware::graphics::mapper::V2_0::IMapper::getService();
|
||||
EXPECT_NE(mapper.get(), nullptr);
|
||||
if (mapper.get() == nullptr) return 1;
|
||||
|
||||
void* buff = nullptr;
|
||||
android::hardware::graphics::mapper::V2_0::Error error;
|
||||
mapper->importBuffer(
|
||||
buffer->omxBuffer.nativeHandle,
|
||||
[&](android::hardware::graphics::mapper::V2_0::Error _e, void* _n1) {
|
||||
error = _e;
|
||||
buff = _n1;
|
||||
});
|
||||
EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
|
||||
if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
|
||||
return 1;
|
||||
|
||||
if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
|
||||
|
||||
error = mapper->freeBuffer(buff);
|
||||
EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
|
||||
if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dispatchGraphicBuffer(sp<IOmxNode> omxNode,
|
||||
sp<IGraphicBufferProducer> producer,
|
||||
sp<CodecProducerListener> listener,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
OMX_U32 portIndex, std::ifstream& eleStream,
|
||||
uint64_t timestamp) {
|
||||
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);
|
||||
if (status != ::android::hardware::media::omx::V1_0::Status::OK) return 1;
|
||||
|
||||
enum {
|
||||
// A flag returned by dequeueBuffer when the client needs to call
|
||||
// requestBuffer immediately thereafter.
|
||||
BUFFER_NEEDS_REALLOCATION = 0x1,
|
||||
// A flag returned by dequeueBuffer when all mirrored slots should be
|
||||
// released by the client. This flag should always be processed first.
|
||||
RELEASE_ALL_BUFFERS = 0x2,
|
||||
};
|
||||
|
||||
int32_t slot;
|
||||
int32_t result;
|
||||
::android::hardware::hidl_handle fence;
|
||||
IGraphicBufferProducer::FrameEventHistoryDelta outTimestamps;
|
||||
::android::hardware::media::V1_0::AnwBuffer AnwBuffer;
|
||||
PixelFormat format = PixelFormat::YV12;
|
||||
producer->dequeueBuffer(
|
||||
portDef.format.video.nFrameWidth, portDef.format.video.nFrameHeight,
|
||||
format, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
|
||||
true, [&](int32_t _s, int32_t const& _n1,
|
||||
::android::hardware::hidl_handle const& _n2,
|
||||
IGraphicBufferProducer::FrameEventHistoryDelta const& _n3) {
|
||||
result = _s;
|
||||
slot = _n1;
|
||||
fence = _n2;
|
||||
outTimestamps = _n3;
|
||||
});
|
||||
if (result & BUFFER_NEEDS_REALLOCATION) {
|
||||
producer->requestBuffer(
|
||||
slot, [&](int32_t _s,
|
||||
::android::hardware::media::V1_0::AnwBuffer const& _n1) {
|
||||
result = _s;
|
||||
AnwBuffer = _n1;
|
||||
});
|
||||
EXPECT_EQ(result, 0);
|
||||
if (result != 0) return 1;
|
||||
size_t i;
|
||||
for (i = 0; i < buffArray->size(); i++) {
|
||||
if ((*buffArray)[i].slot == -1) {
|
||||
buffArray->editItemAt(i).slot = slot;
|
||||
buffArray->editItemAt(i).omxBuffer.nativeHandle =
|
||||
AnwBuffer.nativeHandle;
|
||||
buffArray->editItemAt(i).omxBuffer.attr.anwBuffer =
|
||||
AnwBuffer.attr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPECT_NE(i, buffArray->size());
|
||||
if (i == buffArray->size()) return 1;
|
||||
}
|
||||
EXPECT_EQ(result, 0);
|
||||
if (result != 0) return 1;
|
||||
|
||||
// fill Buffer
|
||||
BufferInfo buffer;
|
||||
size_t i;
|
||||
for (i = 0; i < buffArray->size(); i++) {
|
||||
if ((*buffArray)[i].slot == slot) {
|
||||
buffer = (*buffArray)[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPECT_NE(i, buffArray->size());
|
||||
if (i == buffArray->size()) return 1;
|
||||
if (fillGraphicBuffer(&buffer, format, eleStream)) return 1;
|
||||
|
||||
// queue Buffer
|
||||
IGraphicBufferProducer::QueueBufferOutput output;
|
||||
IGraphicBufferProducer::QueueBufferInput input;
|
||||
android::hardware::media::V1_0::Rect rect;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = buffer.omxBuffer.attr.anwBuffer.width;
|
||||
rect.bottom = buffer.omxBuffer.attr.anwBuffer.height;
|
||||
input.timestamp = timestamp;
|
||||
input.isAutoTimestamp = false;
|
||||
input.dataSpace =
|
||||
android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN;
|
||||
input.crop = rect;
|
||||
input.scalingMode = 0;
|
||||
input.transform = 0;
|
||||
input.stickyTransform = 0;
|
||||
input.fence = android::hardware::hidl_handle();
|
||||
input.surfaceDamage =
|
||||
android::hardware::hidl_vec<android::hardware::media::V1_0::Rect>{rect};
|
||||
input.getFrameTimestamps = false;
|
||||
producer->queueBuffer(
|
||||
buffer.slot, input,
|
||||
[&](int32_t _s, const IGraphicBufferProducer::QueueBufferOutput& _n1) {
|
||||
result = _s;
|
||||
output = _n1;
|
||||
});
|
||||
EXPECT_EQ(result, 0);
|
||||
if (result != 0) return 1;
|
||||
|
||||
listener->reduceCount();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Encode N Frames
|
||||
void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
OMX_U32 portIndexOutput,
|
||||
OMX_U32 portIndexInput, OMX_U32 portIndexOutput,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, uint32_t nFrames,
|
||||
uint32_t xFramerate, int bytesCount,
|
||||
std::ifstream& eleStream) {
|
||||
std::ifstream& eleStream,
|
||||
::android::List<uint64_t>* timestampUslist = nullptr,
|
||||
bool signalEOS = true, bool inputDataIsMeta = false,
|
||||
sp<IGraphicBufferProducer> producer = nullptr,
|
||||
sp<CodecProducerListener> listener = nullptr) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
uint32_t ipCount = 0;
|
||||
|
@ -398,20 +814,39 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
}
|
||||
// dispatch input buffers
|
||||
int32_t timestampIncr = (int)((float)1000000 / (xFramerate >> 16));
|
||||
// timestamp scale = Nano sec
|
||||
if (inputDataIsMeta) timestampIncr *= 1000;
|
||||
uint64_t timestamp = 0;
|
||||
uint32_t flags = 0;
|
||||
for (size_t i = 0; i < iBuffer->size() && nFrames != 0; i++) {
|
||||
char* ipBuffer = static_cast<char*>(
|
||||
static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
|
||||
ASSERT_LE(bytesCount,
|
||||
static_cast<int>((*iBuffer)[i].mMemory->getSize()));
|
||||
eleStream.read(ipBuffer, bytesCount);
|
||||
if (eleStream.gcount() != bytesCount) break;
|
||||
dispatchInputBuffer(omxNode, iBuffer, i, bytesCount, 0, timestamp);
|
||||
timestamp += timestampIncr;
|
||||
nFrames--;
|
||||
ipCount++;
|
||||
if (inputDataIsMeta) {
|
||||
if (listener->freeBuffers > listener->minUnDequeuedCount) {
|
||||
if (dispatchGraphicBuffer(omxNode, producer, listener, iBuffer,
|
||||
portIndexInput, eleStream, timestamp))
|
||||
break;
|
||||
timestamp += timestampIncr;
|
||||
nFrames--;
|
||||
ipCount++;
|
||||
}
|
||||
} else {
|
||||
char* ipBuffer = static_cast<char*>(
|
||||
static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
|
||||
ASSERT_LE(bytesCount,
|
||||
static_cast<int>((*iBuffer)[i].mMemory->getSize()));
|
||||
eleStream.read(ipBuffer, bytesCount);
|
||||
if (eleStream.gcount() != bytesCount) break;
|
||||
if (signalEOS && (nFrames == 1)) flags = OMX_BUFFERFLAG_EOS;
|
||||
dispatchInputBuffer(omxNode, iBuffer, i, bytesCount, flags,
|
||||
timestamp);
|
||||
if (timestampUslist) timestampUslist->push_back(timestamp);
|
||||
timestamp += timestampIncr;
|
||||
nFrames--;
|
||||
ipCount++;
|
||||
}
|
||||
}
|
||||
|
||||
int timeOut = TIMEOUT_COUNTER;
|
||||
bool stall = false;
|
||||
while (1) {
|
||||
status =
|
||||
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
|
@ -422,6 +857,9 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
ASSERT_EQ(msg.data.eventData.data1, portIndexOutput);
|
||||
ASSERT_EQ(msg.data.eventData.data2,
|
||||
OMX_IndexConfigAndroidIntraRefresh);
|
||||
} else if (msg.data.eventData.event == OMX_EventError) {
|
||||
EXPECT_TRUE(false) << "Received OMX_EventError, not sure why";
|
||||
break;
|
||||
} else {
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
|
@ -431,21 +869,51 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|||
|
||||
// Dispatch input buffer
|
||||
size_t index = 0;
|
||||
if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
|
||||
char* ipBuffer = static_cast<char*>(
|
||||
static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
|
||||
ASSERT_LE(bytesCount,
|
||||
static_cast<int>((*iBuffer)[index].mMemory->getSize()));
|
||||
eleStream.read(ipBuffer, bytesCount);
|
||||
if (eleStream.gcount() != bytesCount) break;
|
||||
dispatchInputBuffer(omxNode, iBuffer, index, bytesCount, 0,
|
||||
timestamp);
|
||||
timestamp += timestampIncr;
|
||||
nFrames--;
|
||||
ipCount++;
|
||||
if (inputDataIsMeta) {
|
||||
if (listener->freeBuffers > listener->minUnDequeuedCount) {
|
||||
if (dispatchGraphicBuffer(omxNode, producer, listener, iBuffer,
|
||||
portIndexInput, eleStream, timestamp))
|
||||
break;
|
||||
timestamp += timestampIncr;
|
||||
nFrames--;
|
||||
ipCount++;
|
||||
stall = false;
|
||||
} else {
|
||||
stall = true;
|
||||
}
|
||||
} else {
|
||||
if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
|
||||
char* ipBuffer = static_cast<char*>(static_cast<void*>(
|
||||
(*iBuffer)[index].mMemory->getPointer()));
|
||||
ASSERT_LE(
|
||||
bytesCount,
|
||||
static_cast<int>((*iBuffer)[index].mMemory->getSize()));
|
||||
eleStream.read(ipBuffer, bytesCount);
|
||||
if (eleStream.gcount() != bytesCount) break;
|
||||
if (signalEOS && (nFrames == 1)) flags = OMX_BUFFERFLAG_EOS;
|
||||
dispatchInputBuffer(omxNode, iBuffer, index, bytesCount, flags,
|
||||
timestamp);
|
||||
if (timestampUslist) timestampUslist->push_back(timestamp);
|
||||
timestamp += timestampIncr;
|
||||
nFrames--;
|
||||
ipCount++;
|
||||
stall = false;
|
||||
} else {
|
||||
stall = true;
|
||||
}
|
||||
}
|
||||
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
||||
dispatchOutputBuffer(omxNode, oBuffer, index);
|
||||
stall = false;
|
||||
} else
|
||||
stall = true;
|
||||
if (stall)
|
||||
timeOut--;
|
||||
else
|
||||
timeOut = TIMEOUT_COUNTER;
|
||||
if (timeOut == 0) {
|
||||
EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
|
||||
break;
|
||||
}
|
||||
if (ipCount == 15) {
|
||||
changeBitrate(omxNode, portIndexOutput, 768000);
|
||||
|
@ -491,7 +959,7 @@ TEST_F(VideoEncHidlTest, EnumeratePortFormat) {
|
|||
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
}
|
||||
|
||||
// test raw stream encode
|
||||
// test raw stream encode (input is byte buffers)
|
||||
TEST_F(VideoEncHidlTest, EncodeTest) {
|
||||
description("Test Encode");
|
||||
if (disableTest) return;
|
||||
|
@ -511,8 +979,8 @@ TEST_F(VideoEncHidlTest, EncodeTest) {
|
|||
GetURLForComponent(mURL);
|
||||
|
||||
std::ifstream eleStream;
|
||||
eleStream.open(mURL, std::ifstream::binary);
|
||||
ASSERT_EQ(eleStream.is_open(), true);
|
||||
|
||||
timestampDevTest = true;
|
||||
|
||||
// Configure input port
|
||||
uint32_t nFrameWidth = 352;
|
||||
|
@ -526,6 +994,7 @@ TEST_F(VideoEncHidlTest, EncodeTest) {
|
|||
setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat, nBitRate,
|
||||
xFramerate);
|
||||
setRefreshPeriod(omxNode, kPortIndexOutput, 0);
|
||||
|
||||
unsigned int index;
|
||||
omxNode->getExtensionIndex(
|
||||
"OMX.google.android.index.prependSPSPPSToIDRFrames",
|
||||
|
@ -542,24 +1011,299 @@ TEST_F(VideoEncHidlTest, EncodeTest) {
|
|||
if (status != ::android::hardware::media::omx::V1_0::Status::OK)
|
||||
std::cerr
|
||||
<< "[ ] Warning ! unable to prependSPSPPSToIDRFrames\n";
|
||||
else
|
||||
prependSPSPPS = true;
|
||||
|
||||
// set port mode
|
||||
PortMode portMode[2];
|
||||
portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
||||
if (isSecure && prependSPSPPS) portMode[1] = PortMode::PRESET_SECURE_BUFFER;
|
||||
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);
|
||||
|
||||
android::Vector<BufferInfo> iBuffer, oBuffer;
|
||||
|
||||
// set state to idle
|
||||
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
kPortIndexInput, kPortIndexOutput, portMode);
|
||||
// set state to executing
|
||||
changeStateIdletoExecute(omxNode, observer);
|
||||
|
||||
encodeNFrames(omxNode, observer, kPortIndexOutput, &iBuffer, &oBuffer, 1024,
|
||||
xFramerate, (nFrameWidth * nFrameHeight * 3) >> 1, eleStream);
|
||||
eleStream.open(mURL, std::ifstream::binary);
|
||||
ASSERT_EQ(eleStream.is_open(), true);
|
||||
encodeNFrames(omxNode, observer, kPortIndexInput, kPortIndexOutput,
|
||||
&iBuffer, &oBuffer, 32, xFramerate,
|
||||
(nFrameWidth * nFrameHeight * 3) >> 1, eleStream,
|
||||
×tampUslist);
|
||||
eleStream.close();
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
|
||||
EXPECT_EQ(timestampUslist.empty(), true);
|
||||
|
||||
// set state to idle
|
||||
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
|
||||
// set state to executing
|
||||
changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
}
|
||||
|
||||
// test raw stream encode (input is ANW buffers)
|
||||
TEST_F(VideoEncHidlTest, EncodeTestBufferMetaModes) {
|
||||
description("Test Encode Input buffer metamodes");
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
// Configure input port
|
||||
uint32_t nFrameWidth = 352;
|
||||
uint32_t nFrameHeight = 288;
|
||||
uint32_t xFramerate = (30U << 16);
|
||||
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatAndroidOpaque;
|
||||
setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
|
||||
xFramerate, eColorFormat);
|
||||
|
||||
// CreateInputSurface
|
||||
EXPECT_TRUE(omx->createInputSurface(
|
||||
[&](android::hardware::media::omx::V1_0::Status _s,
|
||||
sp<IGraphicBufferProducer> const& _nl,
|
||||
sp<IGraphicBufferSource> const& _n2) {
|
||||
status = _s;
|
||||
producer = _nl;
|
||||
source = _n2;
|
||||
})
|
||||
.isOk());
|
||||
ASSERT_NE(producer, nullptr);
|
||||
ASSERT_NE(source, nullptr);
|
||||
|
||||
// Do setInputSurface()
|
||||
// enable MetaMode on input port
|
||||
status = source->configure(
|
||||
omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
|
||||
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
|
||||
// setMaxDequeuedBufferCount
|
||||
int32_t returnval;
|
||||
int32_t value;
|
||||
producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
|
||||
[&returnval, &value](int32_t _s, int32_t _n1) {
|
||||
returnval = _s;
|
||||
value = _n1;
|
||||
});
|
||||
ASSERT_EQ(returnval, 0);
|
||||
OMX_PARAM_PORTDEFINITIONTYPE portDef;
|
||||
status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
|
||||
kPortIndexInput, &portDef);
|
||||
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
ASSERT_EQ(::android::OK,
|
||||
producer->setMaxDequeuedBufferCount(portDef.nBufferCountActual));
|
||||
|
||||
// Connect :: Mock Producer Listener
|
||||
IGraphicBufferProducer::QueueBufferOutput qbo;
|
||||
sp<CodecProducerListener> listener =
|
||||
new CodecProducerListener(portDef.nBufferCountActual + value, value);
|
||||
producer->connect(
|
||||
listener, NATIVE_WINDOW_API_CPU, false,
|
||||
[&](int32_t _s, IGraphicBufferProducer::QueueBufferOutput const& _n1) {
|
||||
returnval = _s;
|
||||
qbo = _n1;
|
||||
});
|
||||
ASSERT_EQ(returnval, 0);
|
||||
|
||||
portDef.nBufferCountActual = portDef.nBufferCountActual + value;
|
||||
status = setPortParam(omxNode, OMX_IndexParamPortDefinition,
|
||||
kPortIndexInput, &portDef);
|
||||
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
|
||||
// set port mode
|
||||
PortMode portMode[2];
|
||||
portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
|
||||
portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
||||
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);
|
||||
|
||||
char mURL[512];
|
||||
strcpy(mURL, gEnv->getRes().c_str());
|
||||
GetURLForComponent(mURL);
|
||||
|
||||
std::ifstream eleStream;
|
||||
|
||||
status = source->setSuspend(false, 0);
|
||||
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = source->setRepeatPreviousFrameDelayUs(100000);
|
||||
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = source->setMaxFps(24.0f);
|
||||
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = source->setTimeLapseConfig(24.0, 24.0);
|
||||
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = source->setTimeOffsetUs(-100);
|
||||
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = source->setStartTimeUs(10);
|
||||
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = source->setStopTimeUs(1000000);
|
||||
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
::android::hardware::media::omx::V1_0::ColorAspects aspects;
|
||||
aspects.range =
|
||||
::android::hardware::media::omx::V1_0::ColorAspects::Range::UNSPECIFIED;
|
||||
aspects.primaries = ::android::hardware::media::omx::V1_0::ColorAspects::
|
||||
Primaries::UNSPECIFIED;
|
||||
aspects.transfer = ::android::hardware::media::omx::V1_0::ColorAspects::
|
||||
Transfer::UNSPECIFIED;
|
||||
aspects.matrixCoeffs = ::android::hardware::media::omx::V1_0::ColorAspects::
|
||||
MatrixCoeffs::UNSPECIFIED;
|
||||
status = source->setColorAspects(aspects);
|
||||
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
int64_t stopTimeOffsetUs;
|
||||
source->getStopTimeOffsetUs(
|
||||
[&](android::hardware::media::omx::V1_0::Status _s, int64_t _n1) {
|
||||
status = _s;
|
||||
stopTimeOffsetUs = _n1;
|
||||
});
|
||||
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
|
||||
android::Vector<BufferInfo> iBuffer, oBuffer;
|
||||
// set state to idle
|
||||
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput, portMode);
|
||||
// set state to executing
|
||||
changeStateIdletoExecute(omxNode, observer);
|
||||
|
||||
eleStream.open(mURL, std::ifstream::binary);
|
||||
ASSERT_EQ(eleStream.is_open(), true);
|
||||
encodeNFrames(omxNode, observer, kPortIndexInput, kPortIndexOutput,
|
||||
&iBuffer, &oBuffer, 1024, xFramerate,
|
||||
(nFrameWidth * nFrameHeight * 3) >> 1, eleStream, nullptr,
|
||||
false, true, producer, listener);
|
||||
eleStream.close();
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, true,
|
||||
listener);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
|
||||
|
||||
// set state to idle
|
||||
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
|
||||
EXPECT_EQ(portDef.nBufferCountActual, listener->freeBuffers);
|
||||
// set state to executing
|
||||
changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
|
||||
returnval = producer->disconnect(
|
||||
NATIVE_WINDOW_API_CPU, IGraphicBufferProducer::DisconnectMode::API);
|
||||
ASSERT_EQ(returnval, 0);
|
||||
}
|
||||
|
||||
// Test end of stream
|
||||
TEST_F(VideoEncHidlTest, EncodeTestEOS) {
|
||||
description("Test EOS");
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
// CreateInputSurface
|
||||
EXPECT_TRUE(omx->createInputSurface(
|
||||
[&](android::hardware::media::omx::V1_0::Status _s,
|
||||
sp<IGraphicBufferProducer> const& _nl,
|
||||
sp<IGraphicBufferSource> const& _n2) {
|
||||
status = _s;
|
||||
producer = _nl;
|
||||
source = _n2;
|
||||
})
|
||||
.isOk());
|
||||
ASSERT_NE(producer, nullptr);
|
||||
ASSERT_NE(source, nullptr);
|
||||
|
||||
// Do setInputSurface()
|
||||
// enable MetaMode on input port
|
||||
status = source->configure(
|
||||
omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
|
||||
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
|
||||
// setMaxDequeuedBufferCount
|
||||
int32_t returnval;
|
||||
int32_t value;
|
||||
producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
|
||||
[&returnval, &value](int32_t _s, int32_t _n1) {
|
||||
returnval = _s;
|
||||
value = _n1;
|
||||
});
|
||||
ASSERT_EQ(returnval, 0);
|
||||
OMX_PARAM_PORTDEFINITIONTYPE portDef;
|
||||
status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
|
||||
kPortIndexInput, &portDef);
|
||||
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
ASSERT_EQ(::android::OK,
|
||||
producer->setMaxDequeuedBufferCount(portDef.nBufferCountActual));
|
||||
|
||||
// Connect :: Mock Producer Listener
|
||||
IGraphicBufferProducer::QueueBufferOutput qbo;
|
||||
sp<CodecProducerListener> listener =
|
||||
new CodecProducerListener(portDef.nBufferCountActual + value, value);
|
||||
producer->connect(
|
||||
listener, NATIVE_WINDOW_API_CPU, false,
|
||||
[&](int32_t _s, IGraphicBufferProducer::QueueBufferOutput const& _n1) {
|
||||
returnval = _s;
|
||||
qbo = _n1;
|
||||
});
|
||||
ASSERT_EQ(returnval, 0);
|
||||
|
||||
portDef.nBufferCountActual = portDef.nBufferCountActual + value;
|
||||
status = setPortParam(omxNode, OMX_IndexParamPortDefinition,
|
||||
kPortIndexInput, &portDef);
|
||||
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
|
||||
// set port mode
|
||||
PortMode portMode[2];
|
||||
portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
|
||||
portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
||||
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);
|
||||
|
||||
android::Vector<BufferInfo> iBuffer, oBuffer;
|
||||
// set state to idle
|
||||
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput, portMode);
|
||||
// set state to executing
|
||||
changeStateIdletoExecute(omxNode, observer);
|
||||
|
||||
// send EOS
|
||||
status = source->signalEndOfInputStream();
|
||||
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
||||
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, true,
|
||||
listener);
|
||||
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
|
||||
|
||||
// set state to idle
|
||||
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
|
||||
EXPECT_EQ(portDef.nBufferCountActual, listener->freeBuffers);
|
||||
// set state to executing
|
||||
changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
|
||||
kPortIndexInput, kPortIndexOutput);
|
||||
|
||||
returnval = producer->disconnect(
|
||||
NATIVE_WINDOW_API_CPU, IGraphicBufferProducer::DisconnectMode::API);
|
||||
ASSERT_EQ(returnval, 0);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
|
|
@ -15,6 +15,11 @@
|
|||
*/
|
||||
|
||||
#define LOG_TAG "media_omx_hidl_video_test_common"
|
||||
|
||||
#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>
|
||||
|
@ -30,6 +35,7 @@ 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;
|
||||
|
@ -41,281 +47,11 @@ using ::android::sp;
|
|||
|
||||
#include <VtsHalHidlTargetTestBase.h>
|
||||
#include <hidlmemory/mapping.h>
|
||||
#include <media/hardware/HardwareAPI.h>
|
||||
#include <media_hidl_test_common.h>
|
||||
#include <media_video_hidl_test_common.h>
|
||||
#include <memory>
|
||||
|
||||
// allocate buffers needed on a component port
|
||||
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.get(), 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 = false;
|
||||
allocator->allocate(
|
||||
portDef.nBufferSize,
|
||||
[&success, &buffer](bool _s,
|
||||
::android::hardware::hidl_memory const& mem) {
|
||||
success = _s;
|
||||
buffer.omxBuffer.sharedMemory = mem;
|
||||
});
|
||||
ASSERT_EQ(success, true);
|
||||
ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(), portDef.nBufferSize);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// State Transition : Loaded -> Idle
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateLoadedtoIdle(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;
|
||||
|
||||
// set state to idle
|
||||
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
|
||||
OMX_StateIdle);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
||||
|
||||
// Dont switch states until the ports are populated
|
||||
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
|
||||
// allocate buffers on input port
|
||||
allocatePortBuffers(omxNode, iBuffer, kPortIndexInput);
|
||||
|
||||
// Dont switch states until the ports are populated
|
||||
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
||||
|
||||
// allocate buffers on output port
|
||||
allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput);
|
||||
|
||||
// As the ports are populated, check if the state transition is complete
|
||||
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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Idle -> Loaded
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateIdletoLoaded(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;
|
||||
|
||||
// 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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Idle -> Execute
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateIdletoExecute(sp<IOmxNode> omxNode,
|
||||
sp<CodecObserver> observer) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
// set state to execute
|
||||
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);
|
||||
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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// State Transition : Execute -> Idle
|
||||
// Note: This function does not make any background checks for this transition.
|
||||
// The callee holds the reponsibility to ensure the legality of the transition.
|
||||
void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
// 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);
|
||||
|
||||
// test if client got all its buffers back
|
||||
for (size_t i = 0; i < oBuffer->size(); ++i) {
|
||||
EXPECT_EQ((*oBuffer)[i].owner, client);
|
||||
}
|
||||
for (size_t i = 0; i < iBuffer->size(); ++i) {
|
||||
EXPECT_EQ((*iBuffer)[i].owner, client);
|
||||
}
|
||||
}
|
||||
|
||||
// get empty buffer index
|
||||
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();
|
||||
}
|
||||
|
||||
// dispatch buffer to output port
|
||||
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;
|
||||
}
|
||||
|
||||
// dispatch buffer to input port
|
||||
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;
|
||||
}
|
||||
|
||||
// Flush input and output ports
|
||||
void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
|
||||
OMX_U32 kPortIndexOutput, int64_t timeoutUs) {
|
||||
android::hardware::media::omx::V1_0::Status status;
|
||||
Message msg;
|
||||
|
||||
// Flush input port
|
||||
status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
|
||||
kPortIndexInput);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = observer->dequeueMessage(&msg, timeoutUs, 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);
|
||||
}
|
||||
|
||||
// Flush output port
|
||||
status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
|
||||
kPortIndexOutput);
|
||||
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
||||
status = observer->dequeueMessage(&msg, timeoutUs, 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);
|
||||
}
|
||||
}
|
||||
|
||||
Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
|
||||
sp<IOmxNode> omxNode, OMX_U32 portIndex,
|
||||
OMX_VIDEO_CODINGTYPE eCompressionFormat, OMX_COLOR_FORMATTYPE eColorFormat,
|
||||
|
|
|
@ -25,41 +25,6 @@
|
|||
/*
|
||||
* Common video utils
|
||||
*/
|
||||
void allocatePortBuffers(sp<IOmxNode> omxNode,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
OMX_U32 portIndex);
|
||||
|
||||
void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput);
|
||||
|
||||
void changeStateIdletoLoaded(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer,
|
||||
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput);
|
||||
|
||||
void changeStateIdletoExecute(sp<IOmxNode> omxNode, sp<CodecObserver> observer);
|
||||
|
||||
void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer);
|
||||
|
||||
size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray);
|
||||
|
||||
void dispatchOutputBuffer(sp<IOmxNode> omxNode,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
size_t bufferIndex);
|
||||
|
||||
void dispatchInputBuffer(sp<IOmxNode> omxNode,
|
||||
android::Vector<BufferInfo>* buffArray,
|
||||
size_t bufferIndex, int bytesCount, uint32_t flags,
|
||||
uint64_t timestamp);
|
||||
|
||||
void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
||||
android::Vector<BufferInfo>* iBuffer,
|
||||
android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
|
||||
OMX_U32 kPortIndexOutput, int64_t timeoutUs = DEFAULT_TIMEOUT);
|
||||
|
||||
Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
|
||||
sp<IOmxNode> omxNode, OMX_U32 portIndex,
|
||||
|
|
Loading…
Reference in a new issue