Basic audio/video encoder/decoder test.

Bug: 32023356
TODO: cleanup the test code b/37719510

ComponentTest :-
1. allocatePortBuffers cleanup
2. More than one test fixture performs State transitions
(Loaded <-> Idle <-> Execute). So, this is moved to a routine and
invoked when needed.
3. Dispatch input/output buffers code section is moved to a routine
4. Seperated Test fixtures StateTransitions_Flush
5. Added Doc string
6. Test component port population

AudioDecTest :-
1. Backport Cleanup changes from ComponentTest to AudioDecTest
2. Added elementary streams for the following codecs mp3, amr-nb &
Updated paths to elementary streams in audio decoder test

Test: Tested ComponentTest and AudioDecTest for mp3

Change-Id: I90decde4dfab55c3d456dfd88b474dd5abe8eebc

List Available components (roles) in android media framework

Change-Id: I210665843e997e60b167f2d680c87b1cc4f90c58

add README.md

Change-Id: I3a2a057d10b18f4f374928a996b8b4ea4b084770

add basic video decoder tests

for a given component test for successful decoding of an input clip

Test: tested for softavc decoder

Change-Id: I2f4c034c34a456e1ed0c2d32ef381ca48aeda8ff

add basic audio encoder tests

for a given component, test for successful encoding of an input clip

Test: tested on softaac, softamrnb, softamrwb & softflac components

Change-Id: I05f5646ffed37143a21ea72f0fd782c2bb5c4d82

add basic video encoder tests

For a given component test successful encoding of nframes of a
raw video clip

Test: tested on softavc encoder.
Change-Id: Ia1d754061e8362f6c08a2be3d6384c95589a36de
This commit is contained in:
Ram Mohan M
2017-04-19 14:31:19 +05:30
committed by Zhuoyao Zhang
parent 1fd47b29b3
commit f9c4003fcd
24 changed files with 4160 additions and 562 deletions

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

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

View File

@@ -0,0 +1,49 @@
## Codec OMX Tests
---
The current directory contains the following folders: audio, common, component, master
and video.
Besides common, all other folders contain basic OMX unit tests for testing audio and video decoder-encoder
components. common constitutes files that are used across test applications.
## master
Enumerates all the omx components (and their roles) available in android media framework.
Usage:
VtsHalMediaOmxV1\_0TargetMasterTest -I default
## component
This folder includes test fixtures that tests aspects common to all OMX compatible components. For instance, port enabling/disabling, enumerating port formats, state transitions, flush etc. stay common to all components irrespective of the service they offer. In a way this tests the OMX Core. Every standard OMX compatible component is expected to pass these tests.
Usage:
VtsHalMediaOmxV1\_0TargetComponentTest -I default -C <component name> -R <component role>
## audio
This folder includes test fixtures associated with audio encoder/decoder components such as encoding/decoding, EOS test, timestamp test etc. These tests are aimed towards testing the component specific aspects.
Usage:
VtsHalMediaOmxV1\_0TargetAudioDecTest -I default -C <component name> -R audio_decoder.<class>
VtsHalMediaOmxV1\_0TargetAudioEncTest -I default -C <component name> -R audio_encoder.<class>
## video
This folder includes test fixtures associated with video encoder/decoder components like encoding/decoding, EOS test, timestamp test etc. These tests are aimed towards testing the component specific aspects.
Usage:
VtsHalMediaOmxV1\_0TargetVideoDecTest -I default -C <component name> -R video_decoder.<class>
VtsHalMediaOmxV1\_0TargetVideoEncTest -I default -C <component name> -R video_encoder.<class>
## notes
Every component shall be tested by two applications,
* ComponentTest.
* AudioDecTest/AudioEncTest/VideoDecTest/VideoEncTest depending on the component class.

View File

@@ -155,7 +155,7 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
const StringToName kStringToName[] = {
{"mp3", mp3}, {"amrnb", amrnb}, {"amrwb", amrwb},
{"aac", aac}, {"vorbis", vorbis}, {"opus", opus},
{"pcm", pcm}, {"flac", flac},
{"pcm", pcm},
};
const size_t kNumStringToName =
sizeof(kStringToName) / sizeof(kStringToName[0]);
@@ -184,7 +184,6 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
{vorbis, OMX_AUDIO_CodingVORBIS},
{pcm, OMX_AUDIO_CodingPCM},
{opus, (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS},
{flac, OMX_AUDIO_CodingFLAC},
};
static const size_t kNumCompToCoding =
sizeof(kCompToCoding) / sizeof(kCompToCoding[0]);
@@ -213,7 +212,6 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
vorbis,
opus,
pcm,
flac,
unknown_comp,
};
@@ -222,14 +220,21 @@ class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
sp<IOmxNode> omxNode;
standardComp compName;
OMX_AUDIO_CODINGTYPE eEncoding;
protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
};
// Set Default port param.
void setDefaultPortParam(
sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding,
int32_t nChannels = 2, int32_t nSampleRate = 44100,
OMX_NUMERICALDATATYPE eNumData = OMX_NumericalDataSigned,
int32_t nBitPerSample = 16) {
android::hardware::media::omx::V1_0::Status status;
OMX_PARAM_PORTDEFINITIONTYPE portDef;
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
&portDef);
@@ -246,18 +251,25 @@ void setDefaultPortParam(
setupPCMPort(omxNode, portIndex, nChannels, eNumData, nBitPerSample,
nSampleRate);
break;
case OMX_AUDIO_CodingAAC:
setupAACPort(omxNode, portIndex, OMX_AUDIO_AACObjectNull,
OMX_AUDIO_AACStreamFormatMP4ADTS, nChannels, 0,
nSampleRate);
default:
ASSERT_TRUE(false);
break;
}
}
// In decoder components, often the input port parameters get updated upon
// parsing the header of elementary stream. Client needs to collect this
// information to reconfigure other ports that share data with this input
// port.
void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
OMX_AUDIO_CODINGTYPE eEncoding, int32_t* nChannels,
int32_t* nSampleRate) {
android::hardware::media::omx::V1_0::Status status;
*nChannels = 0;
*nSampleRate = 0;
android::hardware::media::omx::V1_0::Status status;
switch ((int)eEncoding) {
case OMX_AUDIO_CodingPCM: {
@@ -280,16 +292,6 @@ void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
*nSampleRate = param.nSampleRate;
break;
}
case OMX_AUDIO_CodingFLAC: {
OMX_AUDIO_PARAM_FLACTYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioFlac,
kPortIndexInput, &param);
ASSERT_EQ(status,
::android::hardware::media::omx::V1_0::Status::OK);
*nChannels = param.nChannels;
*nSampleRate = param.nSampleRate;
break;
}
case OMX_AUDIO_CodingAndroidOPUS: {
OMX_AUDIO_PARAM_ANDROID_OPUSTYPE param;
status = getPortParam(omxNode,
@@ -337,6 +339,7 @@ void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
}
}
// LookUpTable of clips and metadata for component testing
void GetURLForComponent(AudioDecHidlTest::standardComp comp, const char** mURL,
const char** info) {
struct CompToURL {
@@ -346,20 +349,26 @@ void GetURLForComponent(AudioDecHidlTest::standardComp comp, const char** mURL,
};
static const CompToURL kCompToURL[] = {
{AudioDecHidlTest::standardComp::mp3,
"/sdcard/raw/MP3_48KHz_128kbps_s_1_17_CBR.audio.mp3",
"/sdcard/raw/MP3_48KHz_128kbps_s_1_17_CBR.audio.info"},
"/sdcard/media/bbb_mp3_stereo_192kbps_48000hz.mp3",
"/sdcard/media/bbb_mp3_stereo_192kbps_48000hz.info"},
{AudioDecHidlTest::standardComp::aac,
"/sdcard/raw/H264_500_AAC_128.audio.aac",
"/sdcard/raw/H264_500_AAC_128.audio.info"},
"/sdcard/media/bbb_aac_stereo_128kbps_48000hz.aac",
"/sdcard/media/bbb_aac_stereo_128kbps_48000hz.info"},
{AudioDecHidlTest::standardComp::amrnb,
"/sdcard/raw/H264_320_AMRNB_6.audio.amr",
"/sdcard/raw/H264_320_AMRNB_6.audio.info"},
{AudioDecHidlTest::standardComp::amrwb, "", ""},
{AudioDecHidlTest::standardComp::vorbis, "", ""},
{AudioDecHidlTest::standardComp::opus, "", ""},
{AudioDecHidlTest::standardComp::flac, "", ""},
"/sdcard/media/sine_amrnb_1ch_12kbps_8000hz.amrnb",
"/sdcard/media/sine_amrnb_1ch_12kbps_8000hz.info"},
{AudioDecHidlTest::standardComp::amrwb,
"/sdcard/media/sine_amrwb_1ch_24kbps_16000hz.amrwb",
"/sdcard/media/sine_amrwb_1ch_24kbps_16000hz.info"},
{AudioDecHidlTest::standardComp::vorbis,
"/sdcard/media/bbb_vorbis_stereo_128kbps_48000hz.vorbis",
"/sdcard/media/bbb_vorbis_stereo_128kbps_48000hz.info"},
{AudioDecHidlTest::standardComp::opus,
"/sdcard/media/bbb_opus_stereo_128kbps_48000hz.opus",
"/sdcard/media/bbb_opus_stereo_128kbps_48000hz.info"},
};
*mURL = *info = nullptr;
for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
if (kCompToURL[i].comp == comp) {
*mURL = kCompToURL[i].mURL;
@@ -369,42 +378,7 @@ void GetURLForComponent(AudioDecHidlTest::standardComp comp, const char** mURL,
}
}
void flushAllPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
android::Vector<BufferInfo>* iBuffer,
android::Vector<BufferInfo>* oBuffer,
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput) {
android::hardware::media::omx::V1_0::Status status;
Message msg;
// Flush
status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
kPortIndexInput);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandFlush);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexInput);
// test if client got all its buffers back
for (size_t i = 0; i < iBuffer->size(); ++i) {
EXPECT_EQ((*iBuffer)[i].owner, client);
}
status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
kPortIndexOutput);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandFlush);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
// test if client got all its buffers back
for (size_t i = 0; i < oBuffer->size(); ++i) {
EXPECT_EQ((*oBuffer)[i].owner, client);
}
}
// Decode N Frames
void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
android::Vector<BufferInfo>* iBuffer,
android::Vector<BufferInfo>* oBuffer,
@@ -420,115 +394,140 @@ void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
}
// dispatch input buffers
int bytesCount = 0;
for (size_t i = 0; i < iBuffer->size(); i++) {
uint32_t flags = 0;
uint64_t timestamp = 0;
for (size_t i = 0; i < iBuffer->size() && nFrames != 0; i++) {
char* ipBuffer = static_cast<char*>(
static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
if (!(eleInfo >> bytesCount)) break;
ASSERT_LE(bytesCount,
static_cast<int>((*iBuffer)[i].mMemory->getSize()));
eleStream.read(ipBuffer, bytesCount);
ASSERT_EQ(eleStream.gcount(), bytesCount);
dispatchInputBuffer(omxNode, iBuffer, i, bytesCount, 0, 0);
eleInfo >> flags;
eleInfo >> timestamp;
dispatchInputBuffer(omxNode, iBuffer, i, bytesCount, 0, timestamp);
nFrames--;
}
while (nFrames != 0) {
while (1) {
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
// Port Reconfiguration
if (status == android::hardware::media::omx::V1_0::Status::OK &&
msg.type == Message::Type::EVENT &&
msg.data.eventData.event == OMX_EventPortSettingsChanged) {
ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
msg.type == Message::Type::EVENT) {
if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
status = omxNode->sendCommand(
toRawCommandType(OMX_CommandPortDisable), kPortIndexOutput);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status = omxNode->sendCommand(
toRawCommandType(OMX_CommandPortDisable), kPortIndexOutput);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
oBuffer);
if (status ==
android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
for (size_t i = 0; i < oBuffer->size(); ++i) {
// test if client got all its buffers back
EXPECT_EQ((*oBuffer)[i].owner, client);
// free the buffers
status =
omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
if (status ==
android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
for (size_t i = 0; i < oBuffer->size(); ++i) {
// test if client got all its buffers back
EXPECT_EQ((*oBuffer)[i].owner, client);
// free the buffers
status = omxNode->freeBuffer(kPortIndexOutput,
(*oBuffer)[i].id);
ASSERT_EQ(
status,
android::hardware::media::omx::V1_0::Status::OK);
}
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
}
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
// Port Reconfigurations
int32_t nChannels;
int32_t nSampleRate;
getInputChannelInfo(omxNode, kPortIndexInput, eEncoding,
&nChannels, &nSampleRate);
setDefaultPortParam(omxNode, kPortIndexOutput,
OMX_AUDIO_CodingPCM, nChannels,
nSampleRate);
// set Port Params
int32_t nChannels;
int32_t nSampleRate;
getInputChannelInfo(omxNode, kPortIndexInput, eEncoding,
&nChannels, &nSampleRate);
setDefaultPortParam(omxNode, kPortIndexOutput,
OMX_AUDIO_CodingPCM, nChannels,
nSampleRate);
// If you can disable a port, then you should be able to enable
// it as well
status = omxNode->sendCommand(
toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
// If you can disable a port, then you should be able to
// enable
// it as well
status = omxNode->sendCommand(
toRawCommandType(OMX_CommandPortEnable),
kPortIndexOutput);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
// do not enable the port until all the buffers are supplied
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(
status,
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
// do not enable the port until all the buffers are supplied
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(
status,
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
// dispatch output buffers
for (size_t i = 0; i < oBuffer->size(); i++) {
dispatchOutputBuffer(omxNode, oBuffer, i);
// dispatch output buffers
for (size_t i = 0; i < oBuffer->size(); i++) {
dispatchOutputBuffer(omxNode, oBuffer, i);
}
} else {
ASSERT_TRUE(false);
}
} else {
ASSERT_TRUE(false);
EXPECT_TRUE(false);
return;
}
continue;
}
if (nFrames == 0) break;
// 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()));
if (!(eleInfo >> bytesCount)) break;
ASSERT_LE(bytesCount,
static_cast<int>((*iBuffer)[index].mMemory->getSize()));
eleStream.read(ipBuffer, bytesCount);
ASSERT_EQ(eleStream.gcount(), bytesCount);
dispatchInputBuffer(omxNode, iBuffer, index, bytesCount, 0, 0);
eleInfo >> flags;
eleInfo >> timestamp;
dispatchInputBuffer(omxNode, iBuffer, index, bytesCount, 0,
timestamp);
nFrames--;
}
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
dispatchOutputBuffer(omxNode, oBuffer, index);
}
nFrames--;
}
}
// Set Component Role
TEST_F(AudioDecHidlTest, SetRole) {
description("Test Set Component Role");
android::hardware::media::omx::V1_0::Status status;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// Enumerate Port Format
TEST_F(AudioDecHidlTest, EnumeratePortFormat) {
description("Test Component on Mandatory Port Parameters (Port Format)");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
status = setRole(omxNode, gEnv->getRole().c_str());
@@ -546,8 +545,8 @@ TEST_F(AudioDecHidlTest, EnumeratePortFormat) {
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// Decode Test
TEST_F(AudioDecHidlTest, DecodeTest) {
description("Tests Port Reconfiguration and Decode");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
status = setRole(omxNode, gEnv->getRole().c_str());
@@ -570,105 +569,30 @@ TEST_F(AudioDecHidlTest, DecodeTest) {
eleInfo.open(info);
ASSERT_EQ(eleInfo.is_open(), true);
if (eEncoding == OMX_AUDIO_CodingPCM)
setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
int32_t nChannels;
int32_t nSampleRate;
int32_t nChannels, nSampleRate;
// Configure input port
setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
&nSampleRate);
// Configure output port
setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
nChannels, nSampleRate);
Message msg;
android::Vector<BufferInfo> iBuffer, oBuffer;
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateIdle);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
allocatePortBuffers(omxNode, &iBuffer, kPortIndexInput);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
allocatePortBuffers(omxNode, &oBuffer, kPortIndexOutput);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle);
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateExecuting);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateExecuting);
// set state to idle
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
// set state to executing
changeStateIdletoExecute(omxNode, observer);
// Port Reconfiguration
decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
kPortIndexInput, kPortIndexOutput, (1 << 12), eleStream,
eleInfo);
// flush
flushAllPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
kPortIndexOutput);
// set state to Idle
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateIdle);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle);
// set state to Loaded
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateLoaded);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
// dont change state until all buffers are freed
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
for (size_t i = 0; i < iBuffer.size(); ++i) {
status = omxNode->freeBuffer(kPortIndexInput, iBuffer[i].id);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
}
// dont change state until all buffers are freed
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
for (size_t i = 0; i < oBuffer.size(); ++i) {
status = omxNode->freeBuffer(kPortIndexOutput, oBuffer[i].id);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
}
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateLoaded);
kPortIndexInput, kPortIndexOutput, 1024, eleStream, eleInfo);
// set state to idle
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
// set state to executing
changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
eleInfo.close();
eleStream.close();

View File

@@ -153,9 +153,7 @@ class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
standardComp CompName;
};
const StringToName kStringToName[] = {
{"mp3", mp3}, {"amrnb", amrnb}, {"amrwb", amrwb},
{"aac", aac}, {"vorbis", vorbis}, {"opus", opus},
{"pcm", pcm}, {"flac", flac},
{"amrnb", amrnb}, {"amrwb", amrwb}, {"aac", aac}, {"flac", flac},
};
const size_t kNumStringToName =
sizeof(kStringToName) / sizeof(kStringToName[0]);
@@ -177,13 +175,9 @@ class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
OMX_AUDIO_CODINGTYPE eEncoding;
};
static const CompToCoding kCompToCoding[] = {
{mp3, OMX_AUDIO_CodingMP3},
{amrnb, OMX_AUDIO_CodingAMR},
{amrwb, OMX_AUDIO_CodingAMR},
{aac, OMX_AUDIO_CodingAAC},
{vorbis, OMX_AUDIO_CodingVORBIS},
{pcm, OMX_AUDIO_CodingPCM},
{opus, (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS},
{flac, OMX_AUDIO_CodingFLAC},
};
static const size_t kNumCompToCoding =
@@ -206,13 +200,9 @@ class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
}
enum standardComp {
mp3,
amrnb,
amrwb,
aac,
vorbis,
opus,
pcm,
flac,
unknown_comp,
};
@@ -222,17 +212,146 @@ class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
sp<IOmxNode> omxNode;
standardComp compName;
OMX_AUDIO_CODINGTYPE eEncoding;
protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
};
// Set Component Role
// Set Default port param.
void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_AUDIO_CODINGTYPE eEncoding,
AudioEncHidlTest::standardComp comp, int32_t nChannels,
int32_t nSampleRate, int32_t nBitRate) {
android::hardware::media::omx::V1_0::Status status;
OMX_PARAM_PORTDEFINITIONTYPE portDef;
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
&portDef);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
portDef.format.audio.bFlagErrorConcealment = OMX_TRUE;
portDef.format.audio.eEncoding = eEncoding;
status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
&portDef);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
switch ((int)eEncoding) {
case OMX_AUDIO_CodingFLAC:
setupFLACPort(omxNode, portIndex, nChannels, nSampleRate,
5 /* nCompressionLevel */);
break;
case OMX_AUDIO_CodingAMR:
setupAMRPort(omxNode, portIndex, nBitRate,
(comp == AudioEncHidlTest::standardComp::amrwb));
break;
case OMX_AUDIO_CodingAAC:
setupAACPort(omxNode, portIndex, OMX_AUDIO_AACObjectNull,
OMX_AUDIO_AACStreamFormatMP4FF, nChannels, nBitRate,
nSampleRate);
break;
default:
break;
}
}
// LookUpTable of clips and metadata for component testing
void GetURLForComponent(AudioEncHidlTest::standardComp comp,
const char** mURL) {
struct CompToURL {
AudioEncHidlTest::standardComp comp;
const char* mURL;
};
static const CompToURL kCompToURL[] = {
{AudioEncHidlTest::standardComp::aac,
"/sdcard/media/bbb_raw_2ch_48khz_s16le.raw"},
{AudioEncHidlTest::standardComp::amrnb,
"/sdcard/media/bbb_raw_1ch_8khz_s16le.raw"},
{AudioEncHidlTest::standardComp::amrwb,
"/sdcard/media/bbb_raw_1ch_16khz_s16le.raw"},
{AudioEncHidlTest::standardComp::flac,
"/sdcard/media/bbb_raw_2ch_48khz_s16le.raw"},
};
*mURL = nullptr;
for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
if (kCompToURL[i].comp == comp) {
*mURL = kCompToURL[i].mURL;
return;
}
}
}
// 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) {
android::hardware::media::omx::V1_0::Status status;
Message msg;
// dispatch output buffers
for (size_t i = 0; i < oBuffer->size(); i++) {
dispatchOutputBuffer(omxNode, oBuffer, i);
}
// dispatch input buffers
int bytesCount = samplesPerFrame * nChannels * 2;
int32_t timestampIncr =
(int)(((float)samplesPerFrame / nSampleRate) * 1000000);
uint64_t timestamp = 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--;
}
while (1) {
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
if (status == android::hardware::media::omx::V1_0::Status::OK)
ASSERT_TRUE(false);
if (nFrames == 0) break;
// 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--;
}
// Dispatch output buffer
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
dispatchOutputBuffer(omxNode, oBuffer, index);
}
}
}
TEST_F(AudioEncHidlTest, SetRole) {
description("Test Set Component Role");
android::hardware::media::omx::V1_0::Status status;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// Enumerate Port Format
TEST_F(AudioEncHidlTest, EnumeratePortFormat) {
description("Test Component on Mandatory Port Parameters (Port Format)");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
status = setRole(omxNode, gEnv->getRole().c_str());
@@ -250,6 +369,86 @@ TEST_F(AudioEncHidlTest, EnumeratePortFormat) {
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
TEST_F(AudioEncHidlTest, EncodeTest) {
description("Tests Encode");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
ASSERT_EQ(params.nPorts, 2U);
kPortIndexInput = params.nStartPortNumber;
kPortIndexOutput = kPortIndexInput + 1;
}
const char* mURL = nullptr;
GetURLForComponent(compName, &mURL);
EXPECT_NE(mURL, nullptr);
std::ifstream eleStream;
eleStream.open(mURL, std::ifstream::binary);
ASSERT_EQ(eleStream.is_open(), true);
// Configure input port
int32_t nChannels = 2;
int32_t nSampleRate = 44100;
int32_t samplesPerFrame = 1024;
int32_t nBitRate = 128000;
switch (compName) {
case amrnb:
nChannels = 1;
nSampleRate = 8000;
samplesPerFrame = 160;
nBitRate = 7400;
break;
case amrwb:
nChannels = 1;
nSampleRate = 16000;
samplesPerFrame = 160;
nBitRate = 15850;
break;
case aac:
nChannels = 2;
nSampleRate = 48000;
samplesPerFrame = 1024;
nBitRate = 128000;
break;
case flac:
nChannels = 2;
nSampleRate = 48000;
samplesPerFrame = 1152;
nBitRate = 128000;
break;
default:
ASSERT_TRUE(false);
}
setupPCMPort(omxNode, kPortIndexInput, nChannels, OMX_NumericalDataSigned,
16, nSampleRate);
// Configure output port
setDefaultPortParam(omxNode, kPortIndexOutput, eEncoding, compName,
nChannels, nSampleRate, nBitRate);
android::Vector<BufferInfo> iBuffer, oBuffer;
// set state to idle
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
// set state to executing
changeStateIdletoExecute(omxNode, observer);
encodeNFrames(omxNode, observer, &iBuffer, &oBuffer, 1024, samplesPerFrame,
nChannels, nSampleRate, eleStream);
// 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) {
gEnv = new ComponentTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);

View File

@@ -45,6 +45,7 @@ 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) {
@@ -54,18 +55,19 @@ void allocatePortBuffers(sp<IOmxNode> omxNode,
buffArray->clear();
sp<IAllocator> allocator = IAllocator::getService("ashmem");
EXPECT_NE(allocator, nullptr);
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;
bool success = false;
allocator->allocate(
portDef.nBufferSize,
[&success, &buffer](bool _s,
@@ -74,6 +76,7 @@ void allocatePortBuffers(sp<IOmxNode> omxNode,
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(
@@ -88,6 +91,143 @@ void allocatePortBuffers(sp<IOmxNode> omxNode,
}
}
// 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;
@@ -95,6 +235,7 @@ size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray) {
return buffArray->size();
}
// dispatch buffer to input port
void dispatchInputBuffer(sp<IOmxNode> omxNode,
android::Vector<BufferInfo>* buffArray,
size_t bufferIndex, int bytesCount, uint32_t flags,
@@ -116,6 +257,7 @@ void dispatchInputBuffer(sp<IOmxNode> omxNode,
buffArray->editItemAt(bufferIndex).owner = component;
}
// dispatch buffer to output port
void dispatchOutputBuffer(sp<IOmxNode> omxNode,
android::Vector<BufferInfo>* buffArray,
size_t bufferIndex) {
@@ -135,6 +277,45 @@ void dispatchOutputBuffer(sp<IOmxNode> omxNode,
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);
}
}
Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE encoding) {
OMX_U32 index = 0;
@@ -190,7 +371,7 @@ void setupPCMPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
param.nChannels = nChannels;
param.eNumData = eNumData;
param.eEndian = OMX_EndianBig;
param.eEndian = OMX_EndianLittle;
param.bInterleaved = OMX_TRUE;
param.nBitPerSample = nBitPerSample;
param.nSamplingRate = nSamplingRate;
@@ -207,13 +388,12 @@ void setupPCMPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
EXPECT_TRUE(false);
}
status = setPortParam(omxNode, OMX_IndexParamAudioPcm, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupMP3Port(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_AUDIO_MP3STREAMFORMATTYPE eFormat, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, bool isEncoder) {
if (isEncoder == false) return;
int32_t nBitRate, int32_t nSampleRate) {
OMX_AUDIO_PARAM_MP3TYPE param;
android::hardware::media::omx::V1_0::Status status;
status = getPortParam(omxNode, OMX_IndexParamAudioMp3, portIndex, &param);
@@ -226,13 +406,11 @@ void setupMP3Port(sp<IOmxNode> omxNode, OMX_U32 portIndex,
: OMX_AUDIO_ChannelModeStereo;
param.eFormat = eFormat;
status = setPortParam(omxNode, OMX_IndexParamAudioMp3, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupFLACPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nSampleRate, int32_t nCompressionLevel,
bool isEncoder) {
if (isEncoder == false) return;
int32_t nSampleRate, int32_t nCompressionLevel) {
android::hardware::media::omx::V1_0::Status status;
OMX_AUDIO_PARAM_FLACTYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioFlac, portIndex, &param);
@@ -241,12 +419,11 @@ void setupFLACPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
param.nSampleRate = nSampleRate;
param.nCompressionLevel = nCompressionLevel;
status = setPortParam(omxNode, OMX_IndexParamAudioFlac, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupOPUSPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, bool isEncoder) {
if (isEncoder == false) return;
int32_t nBitRate, int32_t nSampleRate) {
android::hardware::media::omx::V1_0::Status status;
OMX_AUDIO_PARAM_ANDROID_OPUSTYPE param;
status =
@@ -259,27 +436,47 @@ void setupOPUSPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
status =
setPortParam(omxNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) {
if (isAMRWB) {
if (bps <= 6600) return OMX_AUDIO_AMRBandModeWB0;
if (bps <= 8850) return OMX_AUDIO_AMRBandModeWB1;
if (bps <= 12650) return OMX_AUDIO_AMRBandModeWB2;
if (bps <= 14250) return OMX_AUDIO_AMRBandModeWB3;
if (bps <= 15850) return OMX_AUDIO_AMRBandModeWB4;
if (bps <= 18250) return OMX_AUDIO_AMRBandModeWB5;
if (bps <= 19850) return OMX_AUDIO_AMRBandModeWB6;
if (bps <= 23050) return OMX_AUDIO_AMRBandModeWB7;
return OMX_AUDIO_AMRBandModeWB8;
} else {
if (bps <= 4750) return OMX_AUDIO_AMRBandModeNB0;
if (bps <= 5150) return OMX_AUDIO_AMRBandModeNB1;
if (bps <= 5900) return OMX_AUDIO_AMRBandModeNB2;
if (bps <= 6700) return OMX_AUDIO_AMRBandModeNB3;
if (bps <= 7400) return OMX_AUDIO_AMRBandModeNB4;
if (bps <= 7950) return OMX_AUDIO_AMRBandModeNB5;
if (bps <= 10200) return OMX_AUDIO_AMRBandModeNB6;
return OMX_AUDIO_AMRBandModeNB7;
}
}
void setupAMRPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nBitRate,
OMX_AUDIO_AMRBANDMODETYPE eAMRBandMode, bool isEncoder) {
if (isEncoder == false) return;
bool isAMRWB) {
android::hardware::media::omx::V1_0::Status status;
OMX_AUDIO_PARAM_AMRTYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioAmr, portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
param.nChannels = 1;
param.nBitRate = nBitRate;
param.eAMRBandMode = eAMRBandMode;
param.eAMRBandMode = pickModeFromBitRate(isAMRWB, nBitRate);
status = setPortParam(omxNode, OMX_IndexParamAudioAmr, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupVORBISPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, int32_t nQuality,
bool isEncoder) {
if (isEncoder == false) return;
int32_t nBitRate, int32_t nSampleRate, int32_t nQuality) {
android::hardware::media::omx::V1_0::Status status;
OMX_AUDIO_PARAM_VORBISTYPE param;
status =
@@ -291,15 +488,13 @@ void setupVORBISPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
param.nQuality = nQuality;
status =
setPortParam(omxNode, OMX_IndexParamAudioVorbis, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupAACPort(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_AUDIO_AACPROFILETYPE eAACProfile,
OMX_AUDIO_AACSTREAMFORMATTYPE eAACStreamFormat,
int32_t nChannels, int32_t nBitRate, int32_t nSampleRate,
bool isEncoder) {
if (isEncoder == false) return;
int32_t nChannels, int32_t nBitRate, int32_t nSampleRate) {
android::hardware::media::omx::V1_0::Status status;
OMX_AUDIO_PARAM_AACPROFILETYPE param;
status = getPortParam(omxNode, OMX_IndexParamAudioAac, portIndex, &param);
@@ -312,5 +507,5 @@ void setupAACPort(sp<IOmxNode> omxNode, OMX_U32 portIndex,
param.eChannelMode = (nChannels == 1) ? OMX_AUDIO_ChannelModeMono
: OMX_AUDIO_ChannelModeStereo;
status = setPortParam(omxNode, OMX_IndexParamAudioAac, portIndex, &param);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}

View File

@@ -30,6 +30,22 @@ 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 dispatchInputBuffer(sp<IOmxNode> omxNode,
@@ -41,6 +57,11 @@ void dispatchOutputBuffer(sp<IOmxNode> omxNode,
android::Vector<BufferInfo>* buffArray,
size_t bufferIndex);
void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
android::Vector<BufferInfo>* iBuffer,
android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
OMX_U32 kPortIndexOutput);
Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE encoding);
@@ -53,26 +74,23 @@ void setupPCMPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
void setupMP3Port(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_AUDIO_MP3STREAMFORMATTYPE eFormat, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, bool isEncoder);
int32_t nBitRate, int32_t nSampleRate);
void setupFLACPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nSampleRate, int32_t nCompressionLevel,
bool isEncoder);
int32_t nSampleRate, int32_t nCompressionLevel);
void setupOPUSPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, bool isEncoder);
int32_t nBitRate, int32_t nSampleRate);
void setupAMRPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nBitRate,
OMX_AUDIO_AMRBANDMODETYPE eAMRBandMode, bool isEncoder);
bool isAMRWB);
void setupVORBISPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, int32_t nChannels,
int32_t nBitRate, int32_t nSampleRate, int32_t nQuality,
bool isEncoder);
int32_t nBitRate, int32_t nSampleRate, int32_t nQuality);
void setupAACPort(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_AUDIO_AACPROFILETYPE eAACProfile,
OMX_AUDIO_AACSTREAMFORMATTYPE eAACStreamFormat,
int32_t nChannels, int32_t nBitRate, int32_t nSampleRate,
bool isEncoder);
int32_t nChannels, int32_t nBitRate, int32_t nSampleRate);
#endif // MEDIA_AUDIO_HIDL_TEST_COMMON_H

View File

@@ -27,6 +27,7 @@
#include <media/openmax/OMX_Component.h>
#include <media/openmax/OMX_IndexExt.h>
#include <media/openmax/OMX_AudioExt.h>
#include <media/openmax/OMX_VideoExt.h>
/*
* TODO: Borrowed from Conversion.h. This is not the ideal way to do it.

View File

@@ -172,10 +172,6 @@ class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
}
}
ASSERT_NE(compClass, unknown_class) << "Invalid Component Class";
allocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(
"ashmem");
ASSERT_NE(allocator, nullptr);
}
virtual void TearDown() override {
@@ -196,13 +192,19 @@ class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase {
sp<IOmx> omx;
sp<CodecObserver> observer;
sp<IOmxNode> omxNode;
sp<IAllocator> allocator;
standardCompClass compClass;
protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
};
// Random Index used for monkey testing while get/set parameters
#define RANDOM_INDEX 1729
void allocatePortBuffers(sp<IOmxNode> omxNode, sp<IAllocator> allocator,
// 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;
@@ -210,16 +212,20 @@ void allocatePortBuffers(sp<IOmxNode> omxNode, sp<IAllocator> allocator,
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;
bool success = false;
allocator->allocate(
portDef.nBufferSize,
[&success, &buffer](bool _s,
@@ -228,6 +234,7 @@ void allocatePortBuffers(sp<IOmxNode> omxNode, sp<IAllocator> allocator,
buffer.omxBuffer.sharedMemory = mem;
});
ASSERT_EQ(success, true);
ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(), portDef.nBufferSize);
omxNode->useBuffer(
portIndex, buffer.omxBuffer,
@@ -241,6 +248,223 @@ void allocatePortBuffers(sp<IOmxNode> omxNode, sp<IAllocator> allocator,
}
}
// 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);
}
}
Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE compressionFormat, OMX_COLOR_FORMATTYPE colorFormat,
@@ -262,6 +486,8 @@ Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
eCompressionFormat.push_back(portFormat.eCompressionFormat);
index++;
if (index == 512) {
// enumerated way too many formats, highly unusual for this to
// happen.
EXPECT_LE(index, 512U)
<< "Expecting OMX_ErrorNoMore but not received";
break;
@@ -317,6 +543,8 @@ Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
eEncoding.push_back(portFormat.eEncoding);
index++;
if (index == 512) {
// enumerated way too many formats, highly unusual for this to
// happen.
EXPECT_LE(index, 512U)
<< "Expecting OMX_ErrorNoMore but not received";
break;
@@ -348,22 +576,23 @@ Return<android::hardware::media::omx::V1_0::Status> setRole(
return setParam(omxNode, OMX_IndexParamStandardComponentRole, &params);
}
// Set Component Role
TEST_F(ComponentHidlTest, SetRole) {
description("Test Set Component Role");
android::hardware::media::omx::V1_0::Status status;
status = setRole(omxNode, gEnv->getRole().c_str());
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// Get Number of Ports and their Indices for all Domains
// (Audio/Video/Image/Other)
TEST_F(ComponentHidlTest, GetPortIndices) {
description("Test Component on Mandatory Port Parameters (Port ID's)");
android::hardware::media::omx::V1_0::Status status;
OMX_PORT_PARAM_TYPE params;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
// Get Number of Ports and their Indices for all Domains
// (Audio/Video/Image/Other)
// All standard OMX components shall support following OMX Index types
status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
@@ -375,8 +604,8 @@ TEST_F(ComponentHidlTest, GetPortIndices) {
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
// Enumerate Port Format
TEST_F(ComponentHidlTest, EnumeratePortFormat) {
description("Test Component on Mandatory Port Parameters (Port Format)");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
@@ -397,6 +626,7 @@ TEST_F(ComponentHidlTest, EnumeratePortFormat) {
OMX_COLOR_FORMATTYPE colorFormat = OMX_COLOR_FormatYUV420Planar;
OMX_U32 frameRate = 24 << 16;
// Enumerate Port Format
if (compClass == audio_encoder) {
status =
setAudioPortFormat(omxNode, kPortIndexInput, OMX_AUDIO_CodingPCM);
@@ -432,8 +662,9 @@ TEST_F(ComponentHidlTest, EnumeratePortFormat) {
}
}
// r/w default i/o port parameters
TEST_F(ComponentHidlTest, SetDefaultPortParams) {
description(
"Test Component on Mandatory Port Parameters (Port Definition)");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
@@ -451,15 +682,15 @@ TEST_F(ComponentHidlTest, SetDefaultPortParams) {
kPortIndexOutput = kPortIndexInput + 1;
}
// r/w default i/o port parameters
OMX_PARAM_PORTDEFINITIONTYPE iPortDef;
status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
kPortIndexInput, &iPortDef);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
if (status == android::hardware::media::omx::V1_0::Status::OK) {
EXPECT_EQ(iPortDef.eDir, OMX_DirInput);
EXPECT_EQ(iPortDef.bEnabled, OMX_TRUE);
EXPECT_EQ(iPortDef.bPopulated, 0);
EXPECT_EQ(iPortDef.bPopulated, OMX_FALSE);
EXPECT_GE(iPortDef.nBufferCountMin, 1U);
EXPECT_GE(iPortDef.nBufferCountActual, iPortDef.nBufferCountMin);
if (compClass == audio_encoder || compClass == audio_decoder) {
@@ -495,12 +726,8 @@ TEST_F(ComponentHidlTest, SetDefaultPortParams) {
if ((iPortDef.eDir != OMX_DirInput) ||
(iPortDef.nBufferCountMin != dummy.nBufferCountMin) ||
(iPortDef.nBufferSize != dummy.nBufferSize)) {
ALOGI(
"Warning, Component does not seem to preserve Read-Only "
"fields");
printf(
"Warning, Component does not seem to preserve Read-Only fields "
"\n");
std::cerr << "[ ] Warning ! Component input port does not "
"preserve Read-Only fields \n";
}
}
@@ -511,7 +738,7 @@ TEST_F(ComponentHidlTest, SetDefaultPortParams) {
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
EXPECT_EQ(oPortDef.eDir, OMX_DirOutput);
EXPECT_EQ(oPortDef.bEnabled, OMX_TRUE);
EXPECT_EQ(oPortDef.bPopulated, 0);
EXPECT_EQ(oPortDef.bPopulated, OMX_FALSE);
EXPECT_GE(oPortDef.nBufferCountMin, 1U);
EXPECT_GE(oPortDef.nBufferCountActual, oPortDef.nBufferCountMin);
if (compClass == audio_encoder || compClass == audio_decoder) {
@@ -547,18 +774,82 @@ TEST_F(ComponentHidlTest, SetDefaultPortParams) {
if ((oPortDef.eDir != OMX_DirOutput) ||
(oPortDef.nBufferCountMin != dummy.nBufferCountMin) ||
(oPortDef.nBufferSize != dummy.nBufferSize)) {
ALOGI(
"Warning, Component does not seem to preserve Read-Only "
"fields");
printf(
"Warning, Component does not seem to preserve Read-Only fields "
"\n");
std::cerr << "[ ] Warning ! Component output port does "
"not preserve Read-Only fields \n";
}
}
}
// Test State Transitions & Flush
TEST_F(ComponentHidlTest, StateTransitions_Flush) {
TEST_F(ComponentHidlTest, PopulatePort) {
description("Verify bPopulated field of a component port");
android::hardware::media::omx::V1_0::Status status;
OMX_U32 portBase = 0;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
} else {
status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
}
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
ASSERT_EQ(params.nPorts, 2U);
portBase = params.nStartPortNumber;
}
sp<IAllocator> allocator = IAllocator::getService("ashmem");
EXPECT_NE(allocator.get(), nullptr);
OMX_PARAM_PORTDEFINITIONTYPE portDef;
status =
getPortParam(omxNode, OMX_IndexParamPortDefinition, portBase, &portDef);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(portDef.bPopulated, OMX_FALSE);
android::Vector<BufferInfo> pBuffer;
pBuffer.clear();
uint32_t nBufferSize = portDef.nBufferSize >> 1;
for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
BufferInfo buffer;
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(
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(), nBufferSize);
omxNode->useBuffer(
portBase, buffer.omxBuffer,
[&status, &buffer](android::hardware::media::omx::V1_0::Status _s,
uint32_t id) {
status = _s;
buffer.id = id;
});
pBuffer.push(buffer);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
status =
getPortParam(omxNode, OMX_IndexParamPortDefinition, portBase, &portDef);
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
// A port is populated when all of the buffers indicated by
// nBufferCountActual
// with a size of at least nBufferSizehave been allocated on the port.
ASSERT_EQ(portDef.bPopulated, OMX_FALSE);
}
TEST_F(ComponentHidlTest, Flush) {
description("Test Flush");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
Message msg;
@@ -580,163 +871,79 @@ TEST_F(ComponentHidlTest, StateTransitions_Flush) {
android::Vector<BufferInfo> iBuffer, oBuffer;
// 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 got their buffers
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, allocator, &iBuffer, kPortIndexInput);
// Dont switch states until the ports got their buffers
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, allocator, &oBuffer, kPortIndexOutput);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle);
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
// set state to executing
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateExecuting);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateExecuting);
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;
for (size_t i = 0; i < oBuffer.size(); ++i) {
native_handle_t* fenceNh = native_handle_create(0, 0);
status = omxNode->fillBuffer(oBuffer[i].id, t, fenceNh);
native_handle_close(fenceNh);
native_handle_delete(fenceNh);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
oBuffer.editItemAt(i).owner = component;
changeStateIdletoExecute(omxNode, observer);
// dispatch buffers
for (size_t i = 0; i < oBuffer.size(); i++) {
dispatchOutputBuffer(omxNode, &oBuffer, i);
}
// 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);
// flush port
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
kPortIndexOutput);
// dispatch buffers
for (size_t i = 0; i < iBuffer.size(); i++) {
dispatchInputBuffer(omxNode, &iBuffer, i, 0, 0, 0);
}
// set state to executing
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateExecuting);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateExecuting);
for (size_t i = 0; i < oBuffer.size(); i += 2) {
native_handle_t* fenceNh = native_handle_create(0, 0);
status = omxNode->fillBuffer(oBuffer[i].id, t, fenceNh);
native_handle_close(fenceNh);
native_handle_delete(fenceNh);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
oBuffer.editItemAt(i).owner = component;
}
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);
}
// set state to Idle
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateIdle);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle);
// set state to Loaded
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateLoaded);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
// dont change state until all buffers are freed
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
for (size_t i = 0; i < iBuffer.size(); ++i) {
status = omxNode->freeBuffer(kPortIndexInput, iBuffer[i].id);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
}
// dont change state until all buffers are freed
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT);
for (size_t i = 0; i < oBuffer.size(); ++i) {
status = omxNode->freeBuffer(kPortIndexOutput, oBuffer[i].id);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
}
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateLoaded);
// flush ports
flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
kPortIndexOutput);
// set state to idle
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
// set state to loaded
changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
}
TEST_F(ComponentHidlTest, StateTransitions) {
description("Test State Transitions");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
Message msg;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
OMX_PORT_PARAM_TYPE params;
if (compClass == audio_decoder || compClass == audio_encoder) {
status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
} else {
status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
}
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
ASSERT_EQ(params.nPorts, 2U);
kPortIndexInput = params.nStartPortNumber;
kPortIndexOutput = kPortIndexInput + 1;
}
android::Vector<BufferInfo> iBuffer, oBuffer;
// set state to idle
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
// set state to executing
changeStateIdletoExecute(omxNode, observer);
// dispatch buffers
for (size_t i = 0; i < oBuffer.size(); i++) {
dispatchOutputBuffer(omxNode, &oBuffer, i);
}
// set state to idle
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
// set state to executing
changeStateIdletoExecute(omxNode, observer);
// dispatch buffers
for (size_t i = 0; i < iBuffer.size(); i++) {
dispatchInputBuffer(omxNode, &iBuffer, i, 0, 0, 0);
}
// set state to idle
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
// set state to loaded
changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
}
// Test State Transitions
TEST_F(ComponentHidlTest, StateTransitions_M) {
description("Test State Transitions monkeying");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
Message msg;
@@ -768,21 +975,8 @@ TEST_F(ComponentHidlTest, StateTransitions_M) {
EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
// set state to idle
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateIdle);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
// allocate buffers on i/o port
allocatePortBuffers(omxNode, allocator, &iBuffer, kPortIndexInput);
allocatePortBuffers(omxNode, allocator, &oBuffer, kPortIndexOutput);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle);
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
// set state to idle ; receive error OMX_ErrorSameState
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
@@ -790,16 +984,7 @@ TEST_F(ComponentHidlTest, StateTransitions_M) {
EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
// set state to executing
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateExecuting);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &iBuffer, &oBuffer);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateExecuting);
changeStateIdletoExecute(omxNode, observer);
// set state to executing ; receive error OMX_ErrorSameState
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
@@ -812,43 +997,15 @@ TEST_F(ComponentHidlTest, StateTransitions_M) {
EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK);
// set state to Idle
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateIdle);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
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);
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
// set state to Loaded
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateLoaded);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
for (size_t i = 0; i < iBuffer.size(); ++i) {
status = omxNode->freeBuffer(kPortIndexInput, iBuffer[i].id);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
}
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);
changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
}
// Enable and Disable Input and Output ports when the component is in Loaded
// State
TEST_F(ComponentHidlTest, PortEnableDisable_Loaded) {
description("Test Port Enable and Disable (Component State :: Loaded)");
android::hardware::media::omx::V1_0::Status status;
OMX_U32 portBase = 0;
Message msg;
@@ -895,8 +1052,8 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Loaded) {
}
}
// Enable and Disable Input and Output ports when the component is in Idle State
TEST_F(ComponentHidlTest, PortEnableDisable_Idle) {
description("Test Port Enable and Disable (Component State :: Idle)");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
OMX_U32 portBase = 0;
@@ -918,22 +1075,10 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Idle) {
// Component State :: Idle
android::Vector<BufferInfo> pBuffer[2];
// set state to idle
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateIdle);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
// allocate buffers on input port
allocatePortBuffers(omxNode, allocator, &pBuffer[0], kPortIndexInput);
allocatePortBuffers(omxNode, allocator, &pBuffer[1], kPortIndexOutput);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0],
&pBuffer[1]);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle);
changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1],
kPortIndexInput, kPortIndexOutput);
for (size_t i = portBase; i < portBase + 2; i++) {
status =
@@ -982,7 +1127,7 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Idle) {
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
allocatePortBuffers(omxNode, allocator, &pBuffer[i - portBase], i);
allocatePortBuffers(omxNode, &pBuffer[i - portBase], i);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
&pBuffer[0], &pBuffer[1]);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
@@ -994,10 +1139,14 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Idle) {
ASSERT_TRUE(false);
}
}
// set state to Loaded
changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1],
kPortIndexInput, kPortIndexOutput);
}
// Enable and Disable Input and Output ports when the component is in execute
TEST_F(ComponentHidlTest, PortEnableDisable_Execute) {
description("Test Port Enable and Disable (Component State :: Execute)");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
OMX_U32 portBase = 0;
@@ -1019,48 +1168,17 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Execute) {
// Component State :: Idle
android::Vector<BufferInfo> pBuffer[2];
// set state to idle
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateIdle);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1],
kPortIndexInput, kPortIndexOutput);
// allocate buffers on input port
allocatePortBuffers(omxNode, allocator, &pBuffer[0], kPortIndexInput);
allocatePortBuffers(omxNode, allocator, &pBuffer[1], kPortIndexOutput);
// set state to executing
changeStateIdletoExecute(omxNode, observer);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0],
&pBuffer[1]);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle);
// Component State :: 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, &pBuffer[0],
&pBuffer[1]);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
ASSERT_EQ(msg.data.eventData.data2, OMX_StateExecuting);
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;
for (size_t i = 0; i < pBuffer[1].size(); ++i) {
native_handle_t* fenceNh = native_handle_create(0, 0);
status = omxNode->fillBuffer(pBuffer[1][i].id, t, fenceNh);
native_handle_close(fenceNh);
native_handle_delete(fenceNh);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
pBuffer[1].editItemAt(i).owner = component;
// dispatch buffers
for (size_t i = 0; i < pBuffer[1].size(); i++) {
dispatchOutputBuffer(omxNode, &pBuffer[1], i);
}
for (size_t i = portBase; i < portBase + 2; i++) {
@@ -1113,7 +1231,7 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Execute) {
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
allocatePortBuffers(omxNode, allocator, &pBuffer[i - portBase], i);
allocatePortBuffers(omxNode, &pBuffer[i - portBase], i);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
&pBuffer[0], &pBuffer[1]);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
@@ -1125,10 +1243,18 @@ TEST_F(ComponentHidlTest, PortEnableDisable_Execute) {
ASSERT_TRUE(false);
}
}
// set state to Idle
changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]);
// set state to Loaded
changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1],
kPortIndexInput, kPortIndexOutput);
}
// Enable and Disable Input and Output ports, (in loaded state)
TEST_F(ComponentHidlTest, PortEnableDisable_M) {
description(
"Test Port Enable and Disable Monkeying (Component State :: Loaded)");
android::hardware::media::omx::V1_0::Status status;
OMX_U32 portBase = 0;
Message msg;

View File

@@ -105,6 +105,13 @@ TEST_F(MasterHidlTest, ListNodes) {
nodeList = _nl;
})
.isOk());
for (size_t i = 0; i < nodeList.size(); i++) {
printf("%s", nodeList[i].mName.c_str());
for (size_t j = 0; j < ((nodeList[i]).mRoles).size(); j++) {
printf("\t %s", nodeList[i].mRoles[j].c_str());
}
printf("\n");
}
}
int main(int argc, char** argv) {

View File

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

View File

@@ -0,0 +1,551 @@
/*
* 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_dec_test"
#include <android-base/logging.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <android/hardware/media/omx/1.0/IOmxObserver.h>
#include <android/hardware/media/omx/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::media::omx::V1_0::IOmxObserver;
using ::android::hardware::media::omx::V1_0::IOmxNode;
using ::android::hardware::media::omx::V1_0::Message;
using ::android::hardware::media::omx::V1_0::CodecBuffer;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::hidl::memory::V1_0::IMapper;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;
#include <VtsHalHidlTargetTestBase.h>
#include <getopt.h>
#include <media_hidl_test_common.h>
#include <media_video_hidl_test_common.h>
#include <fstream>
// A class for test environment setup
class ComponentTestEnvironment : public ::testing::Environment {
public:
virtual void SetUp() {}
virtual void TearDown() {}
ComponentTestEnvironment() : instance("default") {}
void setInstance(const char* _instance) { instance = _instance; }
void setComponent(const char* _component) { component = _component; }
void setRole(const char* _role) { role = _role; }
void setQuirks(int _quirks) { quirks = _quirks; }
const hidl_string getInstance() const { return instance; }
const hidl_string getComponent() const { return component; }
const hidl_string getRole() const { return role; }
int getQuirks() const { return quirks; }
int initFromOptions(int argc, char** argv) {
static struct option options[] = {
{"instance", required_argument, 0, 'I'},
{"component", required_argument, 0, 'C'},
{"role", required_argument, 0, 'R'},
{"quirks", required_argument, 0, 'Q'},
{0, 0, 0, 0}};
while (true) {
int index = 0;
int c = getopt_long(argc, argv, "I:C:Q:R:", options, &index);
if (c == -1) {
break;
}
switch (c) {
case 'I':
setInstance(optarg);
break;
case 'C':
setComponent(optarg);
break;
case 'Q':
setQuirks(atoi(optarg));
break;
case 'R':
setRole(optarg);
break;
case '?':
break;
}
}
if (optind < argc) {
fprintf(stderr,
"unrecognized option: %s\n\n"
"usage: %s <gtest options> <test options>\n\n"
"test options are:\n\n"
"-I, --instance: HAL instance to test\n"
"-C, --component: OMX component to test\n"
"-R, --Role: OMX component Role\n"
"-Q, --quirks: Component quirks\n",
argv[optind ?: 1], argv[0]);
return 2;
}
return 0;
}
private:
hidl_string instance;
hidl_string component;
hidl_string role;
// to be removed when IOmxNode::setQuirks is removed
int quirks;
};
static ComponentTestEnvironment* gEnv = nullptr;
class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
public:
virtual void SetUp() override {
android::hardware::media::omx::V1_0::Status status;
omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>(
gEnv->getInstance());
ASSERT_NE(omx, nullptr);
observer = new CodecObserver();
ASSERT_NE(observer, nullptr);
ASSERT_EQ(strncmp(gEnv->getComponent().c_str(), "OMX.", 4), 0)
<< "Invalid Component Name";
EXPECT_TRUE(omx->allocateNode(
gEnv->getComponent(), observer,
[&](android::hardware::media::omx::V1_0::Status _s,
sp<IOmxNode> const& _nl) {
status = _s;
this->omxNode = _nl;
})
.isOk());
ASSERT_NE(omxNode, nullptr);
ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
struct StringToName {
const char* Name;
standardComp CompName;
};
const StringToName kStringToName[] = {
{"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
{"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
};
const size_t kNumStringToName =
sizeof(kStringToName) / sizeof(kStringToName[0]);
const char* pch;
char substring[OMX_MAX_STRINGNAME_SIZE];
strcpy(substring, gEnv->getRole().c_str());
pch = strchr(substring, '.');
ASSERT_NE(pch, nullptr);
compName = unknown_comp;
for (size_t i = 0; i < kNumStringToName; ++i) {
if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
compName = kStringToName[i].CompName;
break;
}
}
ASSERT_NE(compName, unknown_comp);
struct CompToCompression {
standardComp CompName;
OMX_VIDEO_CODINGTYPE eCompressionFormat;
};
static const CompToCompression kCompToCompression[] = {
{h263, OMX_VIDEO_CodingH263}, {avc, OMX_VIDEO_CodingAVC},
{mpeg2, OMX_VIDEO_CodingMPEG2}, {mpeg4, OMX_VIDEO_CodingMPEG4},
{hevc, OMX_VIDEO_CodingHEVC}, {vp8, OMX_VIDEO_CodingVP8},
{vp9, OMX_VIDEO_CodingVP9},
};
static const size_t kNumCompToCompression =
sizeof(kCompToCompression) / sizeof(kCompToCompression[0]);
size_t i;
for (i = 0; i < kNumCompToCompression; ++i) {
if (kCompToCompression[i].CompName == compName) {
eCompressionFormat = kCompToCompression[i].eCompressionFormat;
break;
}
}
ASSERT_NE(i, kNumCompToCompression);
}
virtual void TearDown() override {
if (omxNode != nullptr) {
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
}
enum standardComp {
h263,
avc,
mpeg2,
mpeg4,
hevc,
vp8,
vp9,
unknown_comp,
};
sp<IOmx> omx;
sp<CodecObserver> observer;
sp<IOmxNode> omxNode;
standardComp compName;
OMX_VIDEO_CODINGTYPE eCompressionFormat;
protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
};
// Set Default port param.
void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE eCompressionFormat,
OMX_COLOR_FORMATTYPE eColorFormat,
OMX_U32 nFrameWidth = 352, OMX_U32 nFrameHeight = 288,
OMX_U32 nBitrate = 0,
OMX_U32 xFramerate = (24U << 16)) {
switch ((int)eCompressionFormat) {
case OMX_VIDEO_CodingUnused:
setupRAWPort(omxNode, portIndex, nFrameWidth, nFrameHeight,
nBitrate, xFramerate, eColorFormat);
break;
default:
break;
}
}
// In decoder components, often the input port parameters get updated upon
// parsing the header of elementary stream. Client needs to collect this
// information to reconfigure other ports that share data with this input
// port.
void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
uint32_t* nFrameWidth, uint32_t* nFrameHeight,
uint32_t* xFramerate) {
android::hardware::media::omx::V1_0::Status status;
*nFrameWidth = 352;
*nFrameHeight = 288;
*xFramerate = (24U << 16);
OMX_PARAM_PORTDEFINITIONTYPE portDef;
status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
kPortIndexInput, &portDef);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
*nFrameWidth = portDef.format.video.nFrameWidth;
*nFrameHeight = portDef.format.video.nFrameHeight;
*xFramerate = portDef.format.video.xFramerate;
}
}
// LookUpTable of clips and metadata for component testing
void GetURLForComponent(VideoDecHidlTest::standardComp comp, const char** mURL,
const char** info) {
struct CompToURL {
VideoDecHidlTest::standardComp comp;
const char* mURL;
const char* info;
};
static const CompToURL kCompToURL[] = {
{VideoDecHidlTest::standardComp::avc,
"/sdcard/media/bbb_avc_1920x1080_5000kbps_30fps.h264",
"/sdcard/media/bbb_avc_1920x1080_5000kbps_30fps.info"},
};
*mURL = *info = nullptr;
for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
if (kCompToURL[i].comp == comp) {
*mURL = kCompToURL[i].mURL;
*info = kCompToURL[i].info;
return;
}
}
}
void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
android::Vector<BufferInfo>* iBuffer,
android::Vector<BufferInfo>* oBuffer,
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
Message msg) {
android::hardware::media::omx::V1_0::Status status;
if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
if (msg.data.eventData.data2 == 0) {
status = omxNode->sendCommand(
toRawCommandType(OMX_CommandPortDisable), kPortIndexOutput);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
oBuffer);
if (status ==
android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
for (size_t i = 0; i < oBuffer->size(); ++i) {
// test if client got all its buffers back
EXPECT_EQ((*oBuffer)[i].owner, client);
// free the buffers
status =
omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
}
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
// set Port Params
uint32_t nFrameWidth, nFrameHeight, xFramerate;
OMX_COLOR_FORMATTYPE eColorFormat =
OMX_COLOR_FormatYUV420Planar;
getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth,
&nFrameHeight, &xFramerate);
setDefaultPortParam(omxNode, kPortIndexOutput,
OMX_VIDEO_CodingUnused, eColorFormat,
nFrameWidth, nFrameHeight, 0, xFramerate);
// If you can disable a port, then you should be able to
// enable
// it as well
status = omxNode->sendCommand(
toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
// do not enable the port until all the buffers are supplied
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(
status,
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput);
status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
iBuffer, oBuffer);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
// dispatch output buffers
for (size_t i = 0; i < oBuffer->size(); i++) {
dispatchOutputBuffer(omxNode, oBuffer, i);
}
} else {
ASSERT_TRUE(false);
}
} else if (msg.data.eventData.data2 ==
OMX_IndexConfigCommonOutputCrop) {
std::cerr << "[ ] Warning ! OMX_EventPortSettingsChanged/ "
"OMX_IndexConfigCommonOutputCrop not handled \n";
} else if (msg.data.eventData.data2 == OMX_IndexVendorStartUnused + 3) {
std::cerr << "[ ] Warning ! OMX_EventPortSettingsChanged/ "
"kDescribeColorAspectsIndex not handled \n";
}
} else if (msg.data.eventData.event == OMX_EventError) {
std::cerr << "[ ] Warning ! OMX_EventError/ "
"Decode Frame Call might be failed \n";
return;
} else {
// something unexpected happened
ASSERT_TRUE(false);
}
}
// Decode N Frames
void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
android::Vector<BufferInfo>* iBuffer,
android::Vector<BufferInfo>* oBuffer,
OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
uint32_t nFrames, std::ifstream& eleStream,
std::ifstream& eleInfo) {
android::hardware::media::omx::V1_0::Status status;
Message msg;
// dispatch output buffers
for (size_t i = 0; i < oBuffer->size(); i++) {
dispatchOutputBuffer(omxNode, oBuffer, i);
}
// dispatch input buffers
int bytesCount = 0;
uint32_t sampleflags = 0, flags = 0;
uint64_t timestamp = 0;
for (size_t i = 0; i < iBuffer->size() && nFrames != 0; i++) {
char* ipBuffer = static_cast<char*>(
static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
if (!(eleInfo >> bytesCount)) break;
ASSERT_LE(bytesCount,
static_cast<int>((*iBuffer)[i].mMemory->getSize()));
eleStream.read(ipBuffer, bytesCount);
ASSERT_EQ(eleStream.gcount(), bytesCount);
eleInfo >> sampleflags;
eleInfo >> timestamp;
flags = 0;
// Map MediaExtractor flags to OMX Buffer flags
if (sampleflags & 1) flags |= OMX_BUFFERFLAG_SYNCFRAME;
dispatchInputBuffer(omxNode, iBuffer, i, bytesCount, flags, timestamp);
nFrames--;
}
while (1) {
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
// Port Reconfiguration
if (status == android::hardware::media::omx::V1_0::Status::OK &&
msg.type == Message::Type::EVENT) {
portReconfiguration(omxNode, observer, iBuffer, oBuffer,
kPortIndexInput, kPortIndexOutput, msg);
}
if (nFrames == 0) break;
// 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()));
if (!(eleInfo >> bytesCount)) break;
ASSERT_LE(bytesCount,
static_cast<int>((*iBuffer)[index].mMemory->getSize()));
eleStream.read(ipBuffer, bytesCount);
ASSERT_EQ(eleStream.gcount(), bytesCount);
eleInfo >> sampleflags;
eleInfo >> timestamp;
flags = 0;
// Map MediaExtractor flags to OMX Buffer flags
if (sampleflags & 1) flags |= OMX_BUFFERFLAG_SYNCFRAME;
dispatchInputBuffer(omxNode, iBuffer, index, bytesCount, flags,
timestamp);
nFrames--;
}
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
dispatchOutputBuffer(omxNode, oBuffer, index);
}
}
}
TEST_F(VideoDecHidlTest, SetRole) {
description("Test Set Component Role");
android::hardware::media::omx::V1_0::Status status;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
TEST_F(VideoDecHidlTest, EnumeratePortFormat) {
description("Test Component on Mandatory Port Parameters (Port Format)");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
OMX_U32 xFramerate = (24U << 16);
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, &params);
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
ASSERT_EQ(params.nPorts, 2U);
kPortIndexInput = params.nStartPortNumber;
kPortIndexOutput = kPortIndexInput + 1;
}
status = setVideoPortFormat(omxNode, kPortIndexInput, eCompressionFormat,
OMX_COLOR_FormatUnused, 0U);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
status =
setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
eColorFormat, xFramerate);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
TEST_F(VideoDecHidlTest, DecodeTest) {
description("Tests Port Reconfiguration and Decode");
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, &params);
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
ASSERT_EQ(params.nPorts, 2U);
kPortIndexInput = params.nStartPortNumber;
kPortIndexOutput = kPortIndexInput + 1;
}
const char *mURL = nullptr, *info = nullptr;
GetURLForComponent(compName, &mURL, &info);
EXPECT_NE(mURL, nullptr);
EXPECT_NE(info, nullptr);
std::ifstream eleStream, eleInfo;
eleStream.open(mURL, std::ifstream::binary);
ASSERT_EQ(eleStream.is_open(), true);
eleInfo.open(info);
ASSERT_EQ(eleInfo.is_open(), true);
// set Port Params
uint32_t nFrameWidth, nFrameHeight, xFramerate;
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
&xFramerate);
setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
android::Vector<BufferInfo> iBuffer, oBuffer;
// set state to idle
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
// set state to executing
changeStateIdletoExecute(omxNode, observer);
// Port Reconfiguration
decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
kPortIndexOutput, 1024, eleStream, eleInfo);
// set state to idle
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
// set state to executing
changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
eleInfo.close();
eleStream.close();
}
int main(int argc, char** argv) {
gEnv = new ComponentTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
if (status == 0) {
status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
}
return status;
}

View File

@@ -0,0 +1,425 @@
/*
* 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_enc_test"
#include <android-base/logging.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <android/hardware/media/omx/1.0/IOmxObserver.h>
#include <android/hardware/media/omx/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::media::omx::V1_0::IOmxObserver;
using ::android::hardware::media::omx::V1_0::IOmxNode;
using ::android::hardware::media::omx::V1_0::Message;
using ::android::hardware::media::omx::V1_0::CodecBuffer;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::hidl::memory::V1_0::IMapper;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;
#include <VtsHalHidlTargetTestBase.h>
#include <getopt.h>
#include <media_hidl_test_common.h>
#include <media_video_hidl_test_common.h>
#include <fstream>
// A class for test environment setup
class ComponentTestEnvironment : public ::testing::Environment {
public:
virtual void SetUp() {}
virtual void TearDown() {}
ComponentTestEnvironment() : instance("default") {}
void setInstance(const char* _instance) { instance = _instance; }
void setComponent(const char* _component) { component = _component; }
void setRole(const char* _role) { role = _role; }
void setQuirks(int _quirks) { quirks = _quirks; }
const hidl_string getInstance() const { return instance; }
const hidl_string getComponent() const { return component; }
const hidl_string getRole() const { return role; }
int getQuirks() const { return quirks; }
int initFromOptions(int argc, char** argv) {
static struct option options[] = {
{"instance", required_argument, 0, 'I'},
{"component", required_argument, 0, 'C'},
{"role", required_argument, 0, 'R'},
{"quirks", required_argument, 0, 'Q'},
{0, 0, 0, 0}};
while (true) {
int index = 0;
int c = getopt_long(argc, argv, "I:C:Q:R:", options, &index);
if (c == -1) {
break;
}
switch (c) {
case 'I':
setInstance(optarg);
break;
case 'C':
setComponent(optarg);
break;
case 'Q':
setQuirks(atoi(optarg));
break;
case 'R':
setRole(optarg);
break;
case '?':
break;
}
}
if (optind < argc) {
fprintf(stderr,
"unrecognized option: %s\n\n"
"usage: %s <gtest options> <test options>\n\n"
"test options are:\n\n"
"-I, --instance: HAL instance to test\n"
"-C, --component: OMX component to test\n"
"-R, --Role: OMX component Role\n"
"-Q, --quirks: Component quirks\n",
argv[optind ?: 1], argv[0]);
return 2;
}
return 0;
}
private:
hidl_string instance;
hidl_string component;
hidl_string role;
// to be removed when IOmxNode::setQuirks is removed
int quirks;
};
static ComponentTestEnvironment* gEnv = nullptr;
class VideoEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
public:
virtual void SetUp() override {
android::hardware::media::omx::V1_0::Status status;
omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>(
gEnv->getInstance());
ASSERT_NE(omx, nullptr);
observer = new CodecObserver();
ASSERT_NE(observer, nullptr);
ASSERT_EQ(strncmp(gEnv->getComponent().c_str(), "OMX.", 4), 0)
<< "Invalid Component Name";
EXPECT_TRUE(omx->allocateNode(
gEnv->getComponent(), observer,
[&](android::hardware::media::omx::V1_0::Status _s,
sp<IOmxNode> const& _nl) {
status = _s;
this->omxNode = _nl;
})
.isOk());
ASSERT_NE(omxNode, nullptr);
ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
struct StringToName {
const char* Name;
standardComp CompName;
};
const StringToName kStringToName[] = {
{"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
{"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
};
const size_t kNumStringToName =
sizeof(kStringToName) / sizeof(kStringToName[0]);
const char* pch;
char substring[OMX_MAX_STRINGNAME_SIZE];
strcpy(substring, gEnv->getRole().c_str());
pch = strchr(substring, '.');
ASSERT_NE(pch, nullptr);
compName = unknown_comp;
for (size_t i = 0; i < kNumStringToName; ++i) {
if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
compName = kStringToName[i].CompName;
break;
}
}
ASSERT_NE(compName, unknown_comp);
struct CompToCompression {
standardComp CompName;
OMX_VIDEO_CODINGTYPE eCompressionFormat;
};
static const CompToCompression kCompToCompression[] = {
{h263, OMX_VIDEO_CodingH263}, {avc, OMX_VIDEO_CodingAVC},
{mpeg2, OMX_VIDEO_CodingMPEG2}, {mpeg4, OMX_VIDEO_CodingMPEG4},
{hevc, OMX_VIDEO_CodingHEVC}, {vp8, OMX_VIDEO_CodingVP8},
{vp9, OMX_VIDEO_CodingVP9},
};
static const size_t kNumCompToCompression =
sizeof(kCompToCompression) / sizeof(kCompToCompression[0]);
size_t i;
for (i = 0; i < kNumCompToCompression; ++i) {
if (kCompToCompression[i].CompName == compName) {
eCompressionFormat = kCompToCompression[i].eCompressionFormat;
break;
}
}
ASSERT_NE(i, kNumCompToCompression);
}
virtual void TearDown() override {
if (omxNode != nullptr) {
EXPECT_TRUE((omxNode->freeNode()).isOk());
omxNode = nullptr;
}
}
enum standardComp {
h263,
avc,
mpeg2,
mpeg4,
hevc,
vp8,
vp9,
unknown_comp,
};
sp<IOmx> omx;
sp<CodecObserver> observer;
sp<IOmxNode> omxNode;
standardComp compName;
OMX_VIDEO_CODINGTYPE eCompressionFormat;
protected:
static void description(const std::string& description) {
RecordProperty("description", description);
}
};
// Set Default port param.
void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE eCompressionFormat,
OMX_U32 nBitrate, OMX_U32 xFramerate) {
android::hardware::media::omx::V1_0::Status status;
OMX_PARAM_PORTDEFINITIONTYPE portDef;
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
&portDef);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
portDef.format.video.nBitrate = nBitrate;
portDef.format.video.xFramerate = xFramerate;
portDef.format.video.bFlagErrorConcealment = OMX_TRUE;
portDef.format.video.eCompressionFormat = eCompressionFormat;
portDef.format.video.eColorFormat = OMX_COLOR_FormatUnused;
status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
&portDef);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
switch ((int)eCompressionFormat) {
case OMX_VIDEO_CodingAVC:
setupAVCPort(omxNode, portIndex, OMX_VIDEO_AVCProfileBaseline,
OMX_VIDEO_AVCLevel31, xFramerate);
break;
default:
break;
}
}
// LookUpTable of clips and metadata for component testing
void GetURLForComponent(VideoEncHidlTest::standardComp comp,
const char** mURL) {
struct CompToURL {
VideoEncHidlTest::standardComp comp;
const char* mURL;
};
static const CompToURL kCompToURL[] = {
{VideoEncHidlTest::standardComp::avc,
"/sdcard/media/bbb_480x360_420p_30fps_32frames.yuv"},
};
*mURL = nullptr;
for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
if (kCompToURL[i].comp == comp) {
*mURL = kCompToURL[i].mURL;
return;
}
}
}
// Encode N Frames
void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
android::Vector<BufferInfo>* iBuffer,
android::Vector<BufferInfo>* oBuffer, uint32_t nFrames,
uint32_t xFramerate, int bytesCount,
std::ifstream& eleStream) {
android::hardware::media::omx::V1_0::Status status;
Message msg;
// dispatch output buffers
for (size_t i = 0; i < oBuffer->size(); i++) {
dispatchOutputBuffer(omxNode, oBuffer, i);
}
// dispatch input buffers
int32_t timestampIncr = (int)((float)1000000 / (xFramerate >> 16));
uint64_t timestamp = 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--;
}
while (1) {
status =
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
if (status == android::hardware::media::omx::V1_0::Status::OK)
ASSERT_TRUE(false);
if (nFrames == 0) break;
// 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--;
}
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
dispatchOutputBuffer(omxNode, oBuffer, index);
}
}
}
TEST_F(VideoEncHidlTest, SetRole) {
description("Test Set Component Role");
android::hardware::media::omx::V1_0::Status status;
status = setRole(omxNode, gEnv->getRole().c_str());
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
TEST_F(VideoEncHidlTest, EnumeratePortFormat) {
description("Test Component on Mandatory Port Parameters (Port Format)");
android::hardware::media::omx::V1_0::Status status;
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
OMX_U32 xFramerate = (30U << 16);
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, &params);
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
ASSERT_EQ(params.nPorts, 2U);
kPortIndexInput = params.nStartPortNumber;
kPortIndexOutput = kPortIndexInput + 1;
}
status =
setVideoPortFormat(omxNode, kPortIndexInput, OMX_VIDEO_CodingUnused,
eColorFormat, xFramerate);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
status = setVideoPortFormat(omxNode, kPortIndexOutput, eCompressionFormat,
OMX_COLOR_FormatUnused, 0U);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
TEST_F(VideoEncHidlTest, EncodeTest) {
description("Test Encode");
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, &params);
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
ASSERT_EQ(params.nPorts, 2U);
kPortIndexInput = params.nStartPortNumber;
kPortIndexOutput = kPortIndexInput + 1;
}
const char* mURL = nullptr;
GetURLForComponent(compName, &mURL);
EXPECT_NE(mURL, nullptr);
std::ifstream eleStream;
eleStream.open(mURL, std::ifstream::binary);
ASSERT_EQ(eleStream.is_open(), true);
// Configure input port
uint32_t nFrameWidth = 480;
uint32_t nFrameHeight = 360;
uint32_t xFramerate = (30U << 16);
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
xFramerate, eColorFormat);
// Configure output port
uint32_t nBitRate = 768000;
setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat, nBitRate,
xFramerate);
android::Vector<BufferInfo> iBuffer, oBuffer;
// set state to idle
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
kPortIndexInput, kPortIndexOutput);
// set state to executing
changeStateIdletoExecute(omxNode, observer);
encodeNFrames(omxNode, observer, &iBuffer, &oBuffer, 1024, xFramerate,
(nFrameWidth * nFrameHeight * 3) >> 1, eleStream);
// 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) {
gEnv = new ComponentTestEnvironment();
::testing::AddGlobalTestEnvironment(gEnv);
::testing::InitGoogleTest(&argc, argv);
int status = gEnv->initFromOptions(argc, argv);
if (status == 0) {
status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
}
return status;
}

View File

@@ -0,0 +1,451 @@
/*
* 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"
#include <android-base/logging.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <android/hardware/media/omx/1.0/IOmxObserver.h>
#include <android/hardware/media/omx/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::media::omx::V1_0::IOmxObserver;
using ::android::hardware::media::omx::V1_0::IOmxNode;
using ::android::hardware::media::omx::V1_0::Message;
using ::android::hardware::media::omx::V1_0::CodecBuffer;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::hidl::memory::V1_0::IMapper;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;
#include <VtsHalHidlTargetTestBase.h>
#include <hidlmemory/mapping.h>
#include <media_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) {
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);
}
}
Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE eCompressionFormat, OMX_COLOR_FORMATTYPE eColorFormat,
OMX_U32 xFramerate) {
OMX_U32 index = 0;
OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
std::vector<OMX_COLOR_FORMATTYPE> arrColorFormat;
std::vector<OMX_VIDEO_CODINGTYPE> arrCompressionFormat;
android::hardware::media::omx::V1_0::Status status;
while (1) {
portFormat.nIndex = index;
status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat, portIndex,
&portFormat);
if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
if (eCompressionFormat == OMX_VIDEO_CodingUnused)
arrColorFormat.push_back(portFormat.eColorFormat);
else
arrCompressionFormat.push_back(portFormat.eCompressionFormat);
index++;
if (index == 512) {
// enumerated way too many formats, highly unusual for this to
// happen.
EXPECT_LE(index, 512U)
<< "Expecting OMX_ErrorNoMore but not received";
break;
}
}
if (!index) return status;
if (eCompressionFormat == OMX_VIDEO_CodingUnused) {
for (index = 0; index < arrColorFormat.size(); index++) {
if (arrColorFormat[index] == eColorFormat) {
portFormat.eColorFormat = arrColorFormat[index];
break;
}
}
if (index == arrColorFormat.size()) {
ALOGI("setting default color format");
portFormat.eColorFormat = arrColorFormat[0];
}
portFormat.eCompressionFormat = OMX_VIDEO_CodingUnused;
} else {
for (index = 0; index < arrCompressionFormat.size(); index++) {
if (arrCompressionFormat[index] == eCompressionFormat) {
portFormat.eCompressionFormat = arrCompressionFormat[index];
break;
}
}
if (index == arrCompressionFormat.size()) {
ALOGI("setting default compression format");
portFormat.eCompressionFormat = arrCompressionFormat[0];
}
portFormat.eColorFormat = OMX_COLOR_FormatUnused;
}
portFormat.nIndex = 0;
portFormat.xFramerate = xFramerate;
status = setPortParam(omxNode, OMX_IndexParamVideoPortFormat, portIndex,
&portFormat);
return status;
}
Return<android::hardware::media::omx::V1_0::Status> setRole(
sp<IOmxNode> omxNode, const char* role) {
OMX_PARAM_COMPONENTROLETYPE params;
strcpy((char*)params.cRole, role);
return setParam(omxNode, OMX_IndexParamStandardComponentRole, &params);
}
void setupRAWPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_U32 nFrameWidth,
OMX_U32 nFrameHeight, OMX_U32 nBitrate, OMX_U32 xFramerate,
OMX_COLOR_FORMATTYPE eColorFormat) {
android::hardware::media::omx::V1_0::Status status;
OMX_PARAM_PORTDEFINITIONTYPE portDef;
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
&portDef);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
portDef.format.video.nFrameWidth = nFrameWidth;
portDef.format.video.nFrameHeight = nFrameHeight;
portDef.format.video.nStride = (((nFrameWidth + 15) >> 4) << 4);
portDef.format.video.nSliceHeight = (((nFrameHeight + 15) >> 4) << 4);
portDef.format.video.nBitrate = nBitrate;
portDef.format.video.xFramerate = xFramerate;
portDef.format.video.bFlagErrorConcealment = OMX_TRUE;
portDef.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
portDef.format.video.eColorFormat = eColorFormat;
status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
&portDef);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupAVCPort(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_VIDEO_AVCPROFILETYPE eProfile,
OMX_VIDEO_AVCLEVELTYPE eLevel, OMX_U32 xFramerate) {
android::hardware::media::omx::V1_0::Status status;
OMX_VIDEO_PARAM_AVCTYPE param;
(void)xFramerate; // necessary for intra frame spacing
status = getPortParam(omxNode, OMX_IndexParamVideoAvc, portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
param.nSliceHeaderSpacing = 0;
param.nPFrames = 0xFFFFFFFE;
param.nBFrames = 0;
param.bUseHadamard = OMX_TRUE;
param.nRefFrames = 1;
param.eProfile = eProfile;
param.eLevel = eLevel;
param.nAllowedPictureTypes =
OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
param.bFrameMBsOnly = OMX_TRUE;
param.bEntropyCodingCABAC = OMX_FALSE;
param.bWeightedPPrediction = OMX_FALSE;
param.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
status = setPortParam(omxNode, OMX_IndexParamVideoAvc, portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}
void setupHEVCPort(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_VIDEO_HEVCPROFILETYPE eProfile,
OMX_VIDEO_HEVCLEVELTYPE eLevel) {
android::hardware::media::omx::V1_0::Status status;
OMX_VIDEO_PARAM_HEVCTYPE param;
status = getPortParam(omxNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc,
portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
param.eProfile = eProfile;
param.eLevel = eLevel;
param.nKeyFrameInterval = 0xFFFFFFFE;
status = setPortParam(omxNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc,
portIndex, &param);
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2016, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MEDIA_VIDEO_HIDL_TEST_COMMON_H
#define MEDIA_VIDEO_HIDL_TEST_COMMON_H
/*
* Random Index used for monkey testing while get/set parameters
*/
#define RANDOM_INDEX 1729
/*
* 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);
Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE eCompressionFormat, OMX_COLOR_FORMATTYPE eColorFormat,
OMX_U32 xFramerate);
Return<android::hardware::media::omx::V1_0::Status> setRole(
sp<IOmxNode> omxNode, const char* role);
void setupRAWPort(sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_U32 nFrameWidth,
OMX_U32 nFrameHeight, OMX_U32 nBitrate, OMX_U32 xFramerate,
OMX_COLOR_FORMATTYPE eColorFormat);
void setupAVCPort(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_VIDEO_AVCPROFILETYPE eProfile,
OMX_VIDEO_AVCLEVELTYPE eLevel, OMX_U32 xFramerate);
void setupHEVCPort(sp<IOmxNode> omxNode, OMX_U32 portIndex,
OMX_VIDEO_HEVCPROFILETYPE eProfile,
OMX_VIDEO_HEVCLEVELTYPE eLevel);
#endif // MEDIA_VIDEO_HIDL_TEST_COMMON_H

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1,242 @@
31 0 0
8 0 0
481702 1 0
137895 0 33333
81863 0 100000
98914 0 133333
6855 0 166666
2738 0 200000
1340 0 266666
1680 0 300000
2217 0 333333
3275 0 366666
3509 0 433333
4688 0 466666
4996 0 500000
6057 0 533333
7061 0 600000
7427 0 633333
7484 0 666666
8361 0 700000
7803 0 766666
8506 0 800000
8132 0 833333
8651 0 866666
8424 0 933333
8861 0 966666
9004 0 1000000
9431 0 1033333
8854 0 1100000
9681 0 1133333
9498 0 1166666
9694 0 1200000
17571 0 1266666
10029 0 1300000
10022 0 1333333
9939 0 1366666
8427 0 1433333
9522 0 1466666
7192 0 1500000
9844 0 1533333
5693 0 1600000
8057 0 1633333
5997 0 1666666
4028 0 1700000
2303 0 1766666
845 0 1800000
191414 1 1833333
13266 0 1866666
16120 0 1933333
19751 0 1966666
6559 0 2000000
8098 0 2033333
8596 0 2100000
9331 0 2133333
9908 0 2166666
13843 0 2200000
13776 0 2266666
14556 0 2300000
14524 0 2333333
15089 0 2366666
14666 0 2433333
15552 0 2466666
15020 0 2500000
16506 0 2533333
15664 0 2600000
16499 0 2633333
16113 0 2666666
16924 0 2700000
15948 0 2766666
17219 0 2800000
16448 0 2833333
17729 0 2866666
16884 0 2933333
17941 0 2966666
17215 0 3000000
18159 0 3033333
17424 0 3100000
18479 0 3133333
17255 0 3166666
18463 0 3200000
18723 0 3266666
19291 0 3300000
18297 0 3333333
19633 0 3366666
18719 0 3433333
20323 0 3466666
17035 0 3500000
19071 0 3533333
17921 0 3600000
19198 0 3633333
18723 0 3666666
19036 0 3700000
18735 0 3766666
19613 0 3800000
18537 0 3833333
20868 0 3866666
16731 0 3933333
19380 0 3966666
18409 0 4000000
19580 0 4033333
18465 0 4100000
20104 0 4133333
16783 0 4166666
19341 0 4200000
18674 0 4266666
19983 0 4300000
19154 0 4333333
19750 0 4366666
19483 0 4433333
21206 0 4466666
17608 0 4500000
20220 0 4533333
18918 0 4600000
19494 0 4633333
19072 0 4666666
19786 0 4700000
18540 0 4766666
19638 0 4800000
18656 0 4833333
19453 0 4866666
19673 0 4933333
17616 0 4966666
18317 0 5000000
18749 0 5033333
18193 0 5100000
18732 0 5133333
18186 0 5166666
18271 0 5200000
18256 0 5266666
16806 0 5300000
17119 0 5333333
16466 0 5366666
15315 0 5433333
14877 0 5466666
13235 0 5500000
13025 0 5533333
10305 0 5600000
10120 0 5633333
7706 0 5666666
112698 1 5700000
1544 0 5766666
1285 0 5800000
1576 0 5833333
1714 0 5866666
1384 0 5933333
1551 0 5966666
3916 0 6000000
8019 0 6033333
8304 0 6100000
8416 0 6133333
8086 0 6166666
8452 0 6200000
9205 0 6266666
11098 0 6300000
19805 0 6333333
18292 0 6366666
14974 0 6433333
10425 0 6466666
9997 0 6500000
8832 0 6533333
7909 0 6600000
6400 0 6633333
5939 0 6666666
5965 0 6700000
6221 0 6766666
6522 0 6800000
7062 0 6833333
6877 0 6866666
6859 0 6933333
6550 0 6966666
6127 0 7000000
5386 0 7033333
5092 0 7100000
4370 0 7133333
4048 0 7166666
3922 0 7200000
11453 0 7266666
16041 0 7300000
16756 0 7333333
8616 0 7366666
9856 0 7433333
14997 0 7466666
18365 0 7500000
21295 0 7533333
19335 0 7600000
13689 0 7633333
14147 0 7666666
13198 0 7700000
10999 0 7766666
7726 0 7800000
8744 0 7833333
11321 0 7866666
14840 0 7933333
21702 0 7966666
27091 0 8000000
28992 0 8033333
26391 0 8100000
13809 0 8133333
11196 0 8166666
10494 0 8200000
9921 0 8266666
7637 0 8300000
7301 0 8333333
6890 0 8366666
9059 0 8433333
9324 0 8466666
10277 0 8500000
10436 0 8533333
10635 0 8600000
9554 0 8633333
8268 0 8666666
8450 0 8700000
8430 0 8766666
8258 0 8800000
8879 0 8833333
8050 0 8866666
7963 0 8933333
8974 0 8966666
10037 0 9000000
8547 0 9033333
6424 0 9100000
5672 0 9133333
6159 0 9166666
6498 0 9200000
7064 0 9266666
6673 0 9300000
6959 0 9333333
6226 0 9366666
6312 0 9433333
8893 0 9466666
8253 0 9500000
5876 0 9533333
5867 0 9600000
6212 0 9633333
6984 0 9666666
6220 0 9700000
6993 0 9766666
15014 0 9800000
22390 0 9833333
29552 0 9866666
24024 0 9933333
15820 0 9966666

View File

@@ -0,0 +1,414 @@
576 1 0
576 1 24000
576 1 48000
576 1 72000
576 1 96000
576 1 120000
576 1 144000
576 1 168000
576 1 192000
576 1 216000
576 1 240000
576 1 264000
576 1 288000
576 1 312000
576 1 336000
576 1 360000
576 1 384000
576 1 408000
576 1 432000
576 1 456000
576 1 480000
576 1 504000
576 1 528000
576 1 552000
576 1 576000
576 1 600000
576 1 624000
576 1 648000
576 1 672000
576 1 696000
576 1 720000
576 1 744000
576 1 768000
576 1 792000
576 1 816000
576 1 840000
576 1 864000
576 1 888000
576 1 912000
576 1 936000
576 1 960000
576 1 984000
576 1 1008000
576 1 1032000
576 1 1056000
576 1 1080000
576 1 1104000
576 1 1128000
576 1 1152000
576 1 1176000
576 1 1200000
576 1 1224000
576 1 1248000
576 1 1272000
576 1 1296000
576 1 1320000
576 1 1344000
576 1 1368000
576 1 1392000
576 1 1416000
576 1 1440000
576 1 1464000
576 1 1488000
576 1 1512000
576 1 1536000
576 1 1560000
576 1 1584000
576 1 1608000
576 1 1632000
576 1 1656000
576 1 1680000
576 1 1704000
576 1 1728000
576 1 1752000
576 1 1776000
576 1 1800000
576 1 1824000
576 1 1848000
576 1 1872000
576 1 1896000
576 1 1920000
576 1 1944000
576 1 1968000
576 1 1992000
576 1 2016000
576 1 2040000
576 1 2064000
576 1 2088000
576 1 2112000
576 1 2136000
576 1 2160000
576 1 2184000
576 1 2208000
576 1 2232000
576 1 2256000
576 1 2280000
576 1 2304000
576 1 2328000
576 1 2352000
576 1 2376000
576 1 2400000
576 1 2424000
576 1 2448000
576 1 2472000
576 1 2496000
576 1 2520000
576 1 2544000
576 1 2568000
576 1 2592000
576 1 2616000
576 1 2640000
576 1 2664000
576 1 2688000
576 1 2712000
576 1 2736000
576 1 2760000
576 1 2784000
576 1 2808000
576 1 2832000
576 1 2856000
576 1 2880000
576 1 2904000
576 1 2928000
576 1 2952000
576 1 2976000
576 1 3000000
576 1 3024000
576 1 3048000
576 1 3072000
576 1 3096000
576 1 3120000
576 1 3144000
576 1 3168000
576 1 3192000
576 1 3216000
576 1 3240000
576 1 3264000
576 1 3288000
576 1 3312000
576 1 3336000
576 1 3360000
576 1 3384000
576 1 3408000
576 1 3432000
576 1 3456000
576 1 3480000
576 1 3504000
576 1 3528000
576 1 3552000
576 1 3576000
576 1 3600000
576 1 3624000
576 1 3648000
576 1 3672000
576 1 3696000
576 1 3720000
576 1 3744000
576 1 3768000
576 1 3792000
576 1 3816000
576 1 3840000
576 1 3864000
576 1 3888000
576 1 3912000
576 1 3936000
576 1 3960000
576 1 3984000
576 1 4008000
576 1 4032000
576 1 4056000
576 1 4080000
576 1 4104000
576 1 4128000
576 1 4152000
576 1 4176000
576 1 4200000
576 1 4224000
576 1 4248000
576 1 4272000
576 1 4296000
576 1 4320000
576 1 4344000
576 1 4368000
576 1 4392000
576 1 4416000
576 1 4440000
576 1 4464000
576 1 4488000
576 1 4512000
576 1 4536000
576 1 4560000
576 1 4584000
576 1 4608000
576 1 4632000
576 1 4656000
576 1 4680000
576 1 4704000
576 1 4728000
576 1 4752000
576 1 4776000
576 1 4800000
576 1 4824000
576 1 4848000
576 1 4872000
576 1 4896000
576 1 4920000
576 1 4944000
576 1 4968000
576 1 4992000
576 1 5016000
576 1 5040000
576 1 5064000
576 1 5088000
576 1 5112000
576 1 5136000
576 1 5160000
576 1 5184000
576 1 5208000
576 1 5232000
576 1 5256000
576 1 5280000
576 1 5304000
576 1 5328000
576 1 5352000
576 1 5376000
576 1 5400000
576 1 5424000
576 1 5448000
576 1 5472000
576 1 5496000
576 1 5520000
576 1 5544000
576 1 5568000
576 1 5592000
576 1 5616000
576 1 5640000
576 1 5664000
576 1 5688000
576 1 5712000
576 1 5736000
576 1 5760000
576 1 5784000
576 1 5808000
576 1 5832000
576 1 5856000
576 1 5880000
576 1 5904000
576 1 5928000
576 1 5952000
576 1 5976000
576 1 6000000
576 1 6024000
576 1 6048000
576 1 6072000
576 1 6096000
576 1 6120000
576 1 6144000
576 1 6168000
576 1 6192000
576 1 6216000
576 1 6240000
576 1 6264000
576 1 6288000
576 1 6312000
576 1 6336000
576 1 6360000
576 1 6384000
576 1 6408000
576 1 6432000
576 1 6456000
576 1 6480000
576 1 6504000
576 1 6528000
576 1 6552000
576 1 6576000
576 1 6600000
576 1 6624000
576 1 6648000
576 1 6672000
576 1 6696000
576 1 6720000
576 1 6744000
576 1 6768000
576 1 6792000
576 1 6816000
576 1 6840000
576 1 6864000
576 1 6888000
576 1 6912000
576 1 6936000
576 1 6960000
576 1 6984000
576 1 7008000
576 1 7032000
576 1 7056000
576 1 7080000
576 1 7104000
576 1 7128000
576 1 7152000
576 1 7176000
576 1 7200000
576 1 7224000
576 1 7248000
576 1 7272000
576 1 7296000
576 1 7320000
576 1 7344000
576 1 7368000
576 1 7392000
576 1 7416000
576 1 7440000
576 1 7464000
576 1 7488000
576 1 7512000
576 1 7536000
576 1 7560000
576 1 7584000
576 1 7608000
576 1 7632000
576 1 7656000
576 1 7680000
576 1 7704000
576 1 7728000
576 1 7752000
576 1 7776000
576 1 7800000
576 1 7824000
576 1 7848000
576 1 7872000
576 1 7896000
576 1 7920000
576 1 7944000
576 1 7968000
576 1 7992000
576 1 8016000
576 1 8040000
576 1 8064000
576 1 8088000
576 1 8112000
576 1 8136000
576 1 8160000
576 1 8184000
576 1 8208000
576 1 8232000
576 1 8256000
576 1 8280000
576 1 8304000
576 1 8328000
576 1 8352000
576 1 8376000
576 1 8400000
576 1 8424000
576 1 8448000
576 1 8472000
576 1 8496000
576 1 8520000
576 1 8544000
576 1 8568000
576 1 8592000
576 1 8616000
576 1 8640000
576 1 8664000
576 1 8688000
576 1 8712000
576 1 8736000
576 1 8760000
576 1 8784000
576 1 8808000
576 1 8832000
576 1 8856000
576 1 8880000
576 1 8904000
576 1 8928000
576 1 8952000
576 1 8976000
576 1 9000000
576 1 9024000
576 1 9048000
576 1 9072000
576 1 9096000
576 1 9120000
576 1 9144000
576 1 9168000
576 1 9192000
576 1 9216000
576 1 9240000
576 1 9264000
576 1 9288000
576 1 9312000
576 1 9336000
576 1 9360000
576 1 9384000
576 1 9408000
576 1 9432000
576 1 9456000
576 1 9480000
576 1 9504000
576 1 9528000
576 1 9552000
576 1 9576000
576 1 9600000
576 1 9624000
576 1 9648000
576 1 9672000
576 1 9696000
576 1 9720000
576 1 9744000
576 1 9768000
576 1 9792000
576 1 9816000
576 1 9840000
576 1 9864000
576 1 9888000
576 1 9912000

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,833 @@
32 1 0
32 1 20000
32 1 40000
32 1 60000
32 1 80000
32 1 100000
32 1 120000
32 1 140000
32 1 160000
32 1 180000
32 1 200000
32 1 220000
32 1 240000
32 1 260000
32 1 280000
32 1 300000
32 1 320000
32 1 340000
32 1 360000
32 1 380000
32 1 400000
32 1 420000
32 1 440000
32 1 460000
32 1 480000
32 1 500000
32 1 520000
32 1 540000
32 1 560000
32 1 580000
32 1 600000
32 1 620000
32 1 640000
32 1 660000
32 1 680000
32 1 700000
32 1 720000
32 1 740000
32 1 760000
32 1 780000
32 1 800000
32 1 820000
32 1 840000
32 1 860000
32 1 880000
32 1 900000
32 1 920000
32 1 940000
32 1 960000
32 1 980000
32 1 1000000
32 1 1020000
32 1 1040000
32 1 1060000
32 1 1080000
32 1 1100000
32 1 1120000
32 1 1140000
32 1 1160000
32 1 1180000
32 1 1200000
32 1 1220000
32 1 1240000
32 1 1260000
32 1 1280000
32 1 1300000
32 1 1320000
32 1 1340000
32 1 1360000
32 1 1380000
32 1 1400000
32 1 1420000
32 1 1440000
32 1 1460000
32 1 1480000
32 1 1500000
32 1 1520000
32 1 1540000
32 1 1560000
32 1 1580000
32 1 1600000
32 1 1620000
32 1 1640000
32 1 1660000
32 1 1680000
32 1 1700000
32 1 1720000
32 1 1740000
32 1 1760000
32 1 1780000
32 1 1800000
32 1 1820000
32 1 1840000
32 1 1860000
32 1 1880000
32 1 1900000
32 1 1920000
32 1 1940000
32 1 1960000
32 1 1980000
32 1 2000000
32 1 2020000
32 1 2040000
32 1 2060000
32 1 2080000
32 1 2100000
32 1 2120000
32 1 2140000
32 1 2160000
32 1 2180000
32 1 2200000
32 1 2220000
32 1 2240000
32 1 2260000
32 1 2280000
32 1 2300000
32 1 2320000
32 1 2340000
32 1 2360000
32 1 2380000
32 1 2400000
32 1 2420000
32 1 2440000
32 1 2460000
32 1 2480000
32 1 2500000
32 1 2520000
32 1 2540000
32 1 2560000
32 1 2580000
32 1 2600000
32 1 2620000
32 1 2640000
32 1 2660000
32 1 2680000
32 1 2700000
32 1 2720000
32 1 2740000
32 1 2760000
32 1 2780000
32 1 2800000
32 1 2820000
32 1 2840000
32 1 2860000
32 1 2880000
32 1 2900000
32 1 2920000
32 1 2940000
32 1 2960000
32 1 2980000
32 1 3000000
32 1 3020000
32 1 3040000
32 1 3060000
32 1 3080000
32 1 3100000
32 1 3120000
32 1 3140000
32 1 3160000
32 1 3180000
32 1 3200000
32 1 3220000
32 1 3240000
32 1 3260000
32 1 3280000
32 1 3300000
32 1 3320000
32 1 3340000
32 1 3360000
32 1 3380000
32 1 3400000
32 1 3420000
32 1 3440000
32 1 3460000
32 1 3480000
32 1 3500000
32 1 3520000
32 1 3540000
32 1 3560000
32 1 3580000
32 1 3600000
32 1 3620000
32 1 3640000
32 1 3660000
32 1 3680000
32 1 3700000
32 1 3720000
32 1 3740000
32 1 3760000
32 1 3780000
32 1 3800000
32 1 3820000
32 1 3840000
32 1 3860000
32 1 3880000
32 1 3900000
32 1 3920000
32 1 3940000
32 1 3960000
32 1 3980000
32 1 4000000
32 1 4020000
32 1 4040000
32 1 4060000
32 1 4080000
32 1 4100000
32 1 4120000
32 1 4140000
32 1 4160000
32 1 4180000
32 1 4200000
32 1 4220000
32 1 4240000
32 1 4260000
32 1 4280000
32 1 4300000
32 1 4320000
32 1 4340000
32 1 4360000
32 1 4380000
32 1 4400000
32 1 4420000
32 1 4440000
32 1 4460000
32 1 4480000
32 1 4500000
32 1 4520000
32 1 4540000
32 1 4560000
32 1 4580000
32 1 4600000
32 1 4620000
32 1 4640000
32 1 4660000
32 1 4680000
32 1 4700000
32 1 4720000
32 1 4740000
32 1 4760000
32 1 4780000
32 1 4800000
32 1 4820000
32 1 4840000
32 1 4860000
32 1 4880000
32 1 4900000
32 1 4920000
32 1 4940000
32 1 4960000
32 1 4980000
32 1 5000000
32 1 5020000
32 1 5040000
32 1 5060000
32 1 5080000
32 1 5100000
32 1 5120000
32 1 5140000
32 1 5160000
32 1 5180000
32 1 5200000
32 1 5220000
32 1 5240000
32 1 5260000
32 1 5280000
32 1 5300000
32 1 5320000
32 1 5340000
32 1 5360000
32 1 5380000
32 1 5400000
32 1 5420000
32 1 5440000
32 1 5460000
32 1 5480000
32 1 5500000
32 1 5520000
32 1 5540000
32 1 5560000
32 1 5580000
32 1 5600000
32 1 5620000
32 1 5640000
32 1 5660000
32 1 5680000
32 1 5700000
32 1 5720000
32 1 5740000
32 1 5760000
32 1 5780000
32 1 5800000
32 1 5820000
32 1 5840000
32 1 5860000
32 1 5880000
32 1 5900000
32 1 5920000
32 1 5940000
32 1 5960000
32 1 5980000
32 1 6000000
32 1 6020000
32 1 6040000
32 1 6060000
32 1 6080000
32 1 6100000
32 1 6120000
32 1 6140000
32 1 6160000
32 1 6180000
32 1 6200000
32 1 6220000
32 1 6240000
32 1 6260000
32 1 6280000
32 1 6300000
32 1 6320000
32 1 6340000
32 1 6360000
32 1 6380000
32 1 6400000
32 1 6420000
32 1 6440000
32 1 6460000
32 1 6480000
32 1 6500000
32 1 6520000
32 1 6540000
32 1 6560000
32 1 6580000
32 1 6600000
32 1 6620000
32 1 6640000
32 1 6660000
32 1 6680000
32 1 6700000
32 1 6720000
32 1 6740000
32 1 6760000
32 1 6780000
32 1 6800000
32 1 6820000
32 1 6840000
32 1 6860000
32 1 6880000
32 1 6900000
32 1 6920000
32 1 6940000
32 1 6960000
32 1 6980000
32 1 7000000
32 1 7020000
32 1 7040000
32 1 7060000
32 1 7080000
32 1 7100000
32 1 7120000
32 1 7140000
32 1 7160000
32 1 7180000
32 1 7200000
32 1 7220000
32 1 7240000
32 1 7260000
32 1 7280000
32 1 7300000
32 1 7320000
32 1 7340000
32 1 7360000
32 1 7380000
32 1 7400000
32 1 7420000
32 1 7440000
32 1 7460000
32 1 7480000
32 1 7500000
32 1 7520000
32 1 7540000
32 1 7560000
32 1 7580000
32 1 7600000
32 1 7620000
32 1 7640000
32 1 7660000
32 1 7680000
32 1 7700000
32 1 7720000
32 1 7740000
32 1 7760000
32 1 7780000
32 1 7800000
32 1 7820000
32 1 7840000
32 1 7860000
32 1 7880000
32 1 7900000
32 1 7920000
32 1 7940000
32 1 7960000
32 1 7980000
32 1 8000000
32 1 8020000
32 1 8040000
32 1 8060000
32 1 8080000
32 1 8100000
32 1 8120000
32 1 8140000
32 1 8160000
32 1 8180000
32 1 8200000
32 1 8220000
32 1 8240000
32 1 8260000
32 1 8280000
32 1 8300000
32 1 8320000
32 1 8340000
32 1 8360000
32 1 8380000
32 1 8400000
32 1 8420000
32 1 8440000
32 1 8460000
32 1 8480000
32 1 8500000
32 1 8520000
32 1 8540000
32 1 8560000
32 1 8580000
32 1 8600000
32 1 8620000
32 1 8640000
32 1 8660000
32 1 8680000
32 1 8700000
32 1 8720000
32 1 8740000
32 1 8760000
32 1 8780000
32 1 8800000
32 1 8820000
32 1 8840000
32 1 8860000
32 1 8880000
32 1 8900000
32 1 8920000
32 1 8940000
32 1 8960000
32 1 8980000
32 1 9000000
32 1 9020000
32 1 9040000
32 1 9060000
32 1 9080000
32 1 9100000
32 1 9120000
32 1 9140000
32 1 9160000
32 1 9180000
32 1 9200000
32 1 9220000
32 1 9240000
32 1 9260000
32 1 9280000
32 1 9300000
32 1 9320000
32 1 9340000
32 1 9360000
32 1 9380000
32 1 9400000
32 1 9420000
32 1 9440000
32 1 9460000
32 1 9480000
32 1 9500000
32 1 9520000
32 1 9540000
32 1 9560000
32 1 9580000
32 1 9600000
32 1 9620000
32 1 9640000
32 1 9660000
32 1 9680000
32 1 9700000
32 1 9720000
32 1 9740000
32 1 9760000
32 1 9780000
32 1 9800000
32 1 9820000
32 1 9840000
32 1 9860000
32 1 9880000
32 1 9900000
32 1 9920000
32 1 9940000
32 1 9960000
32 1 9980000
32 1 10000000
32 1 10020000
32 1 10040000
32 1 10060000
32 1 10080000
32 1 10100000
32 1 10120000
32 1 10140000
32 1 10160000
32 1 10180000
32 1 10200000
32 1 10220000
32 1 10240000
32 1 10260000
32 1 10280000
32 1 10300000
32 1 10320000
32 1 10340000
32 1 10360000
32 1 10380000
32 1 10400000
32 1 10420000
32 1 10440000
32 1 10460000
32 1 10480000
32 1 10500000
32 1 10520000
32 1 10540000
32 1 10560000
32 1 10580000
32 1 10600000
32 1 10620000
32 1 10640000
32 1 10660000
32 1 10680000
32 1 10700000
32 1 10720000
32 1 10740000
32 1 10760000
32 1 10780000
32 1 10800000
32 1 10820000
32 1 10840000
32 1 10860000
32 1 10880000
32 1 10900000
32 1 10920000
32 1 10940000
32 1 10960000
32 1 10980000
32 1 11000000
32 1 11020000
32 1 11040000
32 1 11060000
32 1 11080000
32 1 11100000
32 1 11120000
32 1 11140000
32 1 11160000
32 1 11180000
32 1 11200000
32 1 11220000
32 1 11240000
32 1 11260000
32 1 11280000
32 1 11300000
32 1 11320000
32 1 11340000
32 1 11360000
32 1 11380000
32 1 11400000
32 1 11420000
32 1 11440000
32 1 11460000
32 1 11480000
32 1 11500000
32 1 11520000
32 1 11540000
32 1 11560000
32 1 11580000
32 1 11600000
32 1 11620000
32 1 11640000
32 1 11660000
32 1 11680000
32 1 11700000
32 1 11720000
32 1 11740000
32 1 11760000
32 1 11780000
32 1 11800000
32 1 11820000
32 1 11840000
32 1 11860000
32 1 11880000
32 1 11900000
32 1 11920000
32 1 11940000
32 1 11960000
32 1 11980000
32 1 12000000
32 1 12020000
32 1 12040000
32 1 12060000
32 1 12080000
32 1 12100000
32 1 12120000
32 1 12140000
32 1 12160000
32 1 12180000
32 1 12200000
32 1 12220000
32 1 12240000
32 1 12260000
32 1 12280000
32 1 12300000
32 1 12320000
32 1 12340000
32 1 12360000
32 1 12380000
32 1 12400000
32 1 12420000
32 1 12440000
32 1 12460000
32 1 12480000
32 1 12500000
32 1 12520000
32 1 12540000
32 1 12560000
32 1 12580000
32 1 12600000
32 1 12620000
32 1 12640000
32 1 12660000
32 1 12680000
32 1 12700000
32 1 12720000
32 1 12740000
32 1 12760000
32 1 12780000
32 1 12800000
32 1 12820000
32 1 12840000
32 1 12860000
32 1 12880000
32 1 12900000
32 1 12920000
32 1 12940000
32 1 12960000
32 1 12980000
32 1 13000000
32 1 13020000
32 1 13040000
32 1 13060000
32 1 13080000
32 1 13100000
32 1 13120000
32 1 13140000
32 1 13160000
32 1 13180000
32 1 13200000
32 1 13220000
32 1 13240000
32 1 13260000
32 1 13280000
32 1 13300000
32 1 13320000
32 1 13340000
32 1 13360000
32 1 13380000
32 1 13400000
32 1 13420000
32 1 13440000
32 1 13460000
32 1 13480000
32 1 13500000
32 1 13520000
32 1 13540000
32 1 13560000
32 1 13580000
32 1 13600000
32 1 13620000
32 1 13640000
32 1 13660000
32 1 13680000
32 1 13700000
32 1 13720000
32 1 13740000
32 1 13760000
32 1 13780000
32 1 13800000
32 1 13820000
32 1 13840000
32 1 13860000
32 1 13880000
32 1 13900000
32 1 13920000
32 1 13940000
32 1 13960000
32 1 13980000
32 1 14000000
32 1 14020000
32 1 14040000
32 1 14060000
32 1 14080000
32 1 14100000
32 1 14120000
32 1 14140000
32 1 14160000
32 1 14180000
32 1 14200000
32 1 14220000
32 1 14240000
32 1 14260000
32 1 14280000
32 1 14300000
32 1 14320000
32 1 14340000
32 1 14360000
32 1 14380000
32 1 14400000
32 1 14420000
32 1 14440000
32 1 14460000
32 1 14480000
32 1 14500000
32 1 14520000
32 1 14540000
32 1 14560000
32 1 14580000
32 1 14600000
32 1 14620000
32 1 14640000
32 1 14660000
32 1 14680000
32 1 14700000
32 1 14720000
32 1 14740000
32 1 14760000
32 1 14780000
32 1 14800000
32 1 14820000
32 1 14840000
32 1 14860000
32 1 14880000
32 1 14900000
32 1 14920000
32 1 14940000
32 1 14960000
32 1 14980000
32 1 15000000
32 1 15020000
32 1 15040000
32 1 15060000
32 1 15080000
32 1 15100000
32 1 15120000
32 1 15140000
32 1 15160000
32 1 15180000
32 1 15200000
32 1 15220000
32 1 15240000
32 1 15260000
32 1 15280000
32 1 15300000
32 1 15320000
32 1 15340000
32 1 15360000
32 1 15380000
32 1 15400000
32 1 15420000
32 1 15440000
32 1 15460000
32 1 15480000
32 1 15500000
32 1 15520000
32 1 15540000
32 1 15560000
32 1 15580000
32 1 15600000
32 1 15620000
32 1 15640000
32 1 15660000
32 1 15680000
32 1 15700000
32 1 15720000
32 1 15740000
32 1 15760000
32 1 15780000
32 1 15800000
32 1 15820000
32 1 15840000
32 1 15860000
32 1 15880000
32 1 15900000
32 1 15920000
32 1 15940000
32 1 15960000
32 1 15980000
32 1 16000000
32 1 16020000
32 1 16040000
32 1 16060000
32 1 16080000
32 1 16100000
32 1 16120000
32 1 16140000
32 1 16160000
32 1 16180000
32 1 16200000
32 1 16220000
32 1 16240000
32 1 16260000
32 1 16280000
32 1 16300000
32 1 16320000
32 1 16340000
32 1 16360000
32 1 16380000
32 1 16400000
32 1 16420000
32 1 16440000
32 1 16460000
32 1 16480000
32 1 16500000
32 1 16520000
32 1 16540000
32 1 16560000
32 1 16580000
32 1 16600000
32 1 16620000
32 1 16640000