mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 05:49:27 +00:00
lock() will be removing these params in the future and they are unused anyway, so remove them Test: make Change-Id: I339c3b9ffa8e7a9cef50d1d80c8cd1a7d0950d82
1476 lines
59 KiB
C++
1476 lines
59 KiB
C++
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "media_omx_hidl_video_enc_test"
|
|
#ifdef __LP64__
|
|
#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
|
|
#endif
|
|
|
|
#include <android-base/logging.h>
|
|
|
|
#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
|
|
#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
|
|
#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
|
|
#include <android/hardware/media/omx/1.0/IOmx.h>
|
|
#include <android/hardware/media/omx/1.0/IOmxBufferSource.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>
|
|
#include <gtest/gtest.h>
|
|
#include <hidl/GtestPrinter.h>
|
|
|
|
using ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer;
|
|
using ::android::hardware::graphics::bufferqueue::V1_0::IProducerListener;
|
|
using ::android::hardware::graphics::common::V1_0::BufferUsage;
|
|
using ::android::hardware::graphics::common::V1_0::PixelFormat;
|
|
using ::android::hardware::media::omx::V1_0::IGraphicBufferSource;
|
|
using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
|
|
using ::android::hardware::media::omx::V1_0::IOmx;
|
|
using ::android::hardware::media::omx::V1_0::IOmxObserver;
|
|
using ::android::hardware::media::omx::V1_0::IOmxNode;
|
|
using ::android::hardware::media::omx::V1_0::Message;
|
|
using ::android::hardware::media::omx::V1_0::CodecBuffer;
|
|
using ::android::hardware::media::omx::V1_0::PortMode;
|
|
using ::android::hidl::allocator::V1_0::IAllocator;
|
|
using ::android::hidl::memory::V1_0::IMemory;
|
|
using ::android::hidl::memory::V1_0::IMapper;
|
|
using ::android::hardware::Return;
|
|
using ::android::hardware::Void;
|
|
using ::android::hardware::hidl_vec;
|
|
using ::android::hardware::hidl_string;
|
|
using ::android::sp;
|
|
|
|
#include <getopt.h>
|
|
#include <media/hardware/HardwareAPI.h>
|
|
#include <media_video_hidl_test_common.h>
|
|
#include <system/window.h>
|
|
#include <fstream>
|
|
#include <variant>
|
|
|
|
// Resource directory
|
|
std::string sResourceDir = "";
|
|
|
|
// video encoder test fixture class
|
|
class VideoEncHidlTest
|
|
: public ::testing::TestWithParam<std::tuple<std::string, std::string, std::string>> {
|
|
public:
|
|
::std::string getTestCaseInfo() const {
|
|
return ::std::string() + "Component: " + component_ + " | " + "Role: " + role_ + " | " +
|
|
"Instance: " + instance_ + " | " + "Res: " + sResourceDir;
|
|
}
|
|
|
|
virtual void SetUp() override {
|
|
instance_ = std::get<0>(GetParam());
|
|
component_ = std::get<1>(GetParam());
|
|
role_ = std::get<2>(GetParam());
|
|
ASSERT_NE(sResourceDir.empty(), true);
|
|
|
|
disableTest = false;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
omx = IOmx::getService(instance_);
|
|
ASSERT_NE(omx, nullptr);
|
|
observer =
|
|
new CodecObserver([this](Message msg, const BufferInfo* buffer) {
|
|
handleMessage(msg, buffer);
|
|
});
|
|
ASSERT_NE(observer, nullptr);
|
|
if (component_.find("OMX.") != 0) disableTest = true;
|
|
EXPECT_TRUE(omx->allocateNode(component_, observer,
|
|
[&](android::hardware::media::omx::V1_0::Status _s,
|
|
sp<IOmxNode> const& _nl) {
|
|
status = _s;
|
|
this->omxNode = _nl;
|
|
})
|
|
.isOk());
|
|
if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
|
|
disableTest = true;
|
|
std::cout << "[ WARN ] Test Disabled, component not present\n";
|
|
return;
|
|
}
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
ASSERT_NE(omxNode, nullptr);
|
|
ASSERT_NE(role_.empty(), true) << "Invalid Component Role";
|
|
struct StringToName {
|
|
const char* Name;
|
|
standardComp CompName;
|
|
};
|
|
const StringToName kStringToName[] = {
|
|
{"h263", h263}, {"avc", avc}, {"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, role_.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;
|
|
}
|
|
}
|
|
if (compName == unknown_comp) disableTest = true;
|
|
struct CompToCompression {
|
|
standardComp CompName;
|
|
OMX_VIDEO_CODINGTYPE eCompressionFormat;
|
|
};
|
|
static const CompToCompression kCompToCompression[] = {
|
|
{h263, OMX_VIDEO_CodingH263}, {avc, OMX_VIDEO_CodingAVC},
|
|
{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;
|
|
}
|
|
}
|
|
if (i == kNumCompToCompression) disableTest = true;
|
|
eosFlag = false;
|
|
prependSPSPPS = false;
|
|
timestampDevTest = false;
|
|
producer = nullptr;
|
|
source = nullptr;
|
|
isSecure = false;
|
|
size_t suffixLen = strlen(".secure");
|
|
if (component_.rfind(".secure") == component_.length() - suffixLen) {
|
|
isSecure = true;
|
|
}
|
|
if (isSecure) disableTest = true;
|
|
if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
|
|
}
|
|
|
|
virtual void TearDown() override {
|
|
if (omxNode != nullptr) {
|
|
// If you have encountered a fatal failure, it is possible that
|
|
// freeNode() will not go through. Instead of hanging the app.
|
|
// let it pass through and report errors
|
|
if (::testing::Test::HasFatalFailure()) return;
|
|
EXPECT_TRUE((omxNode->freeNode()).isOk());
|
|
omxNode = nullptr;
|
|
}
|
|
}
|
|
|
|
// callback function to process messages received by onMessages() from IL
|
|
// client.
|
|
void handleMessage(Message msg, const BufferInfo* buffer) {
|
|
(void)buffer;
|
|
|
|
if (msg.type == Message::Type::FILL_BUFFER_DONE) {
|
|
if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
|
|
eosFlag = true;
|
|
}
|
|
if (msg.data.extendedBufferData.rangeLength != 0) {
|
|
// Test if current timestamp is among the list of queued
|
|
// timestamps
|
|
if (timestampDevTest && ((msg.data.extendedBufferData.flags &
|
|
OMX_BUFFERFLAG_CODECCONFIG) == 0)) {
|
|
bool tsHit = false;
|
|
android::List<uint64_t>::iterator it =
|
|
timestampUslist.begin();
|
|
while (it != timestampUslist.end()) {
|
|
if (*it == msg.data.extendedBufferData.timestampUs) {
|
|
timestampUslist.erase(it);
|
|
tsHit = true;
|
|
break;
|
|
}
|
|
it++;
|
|
}
|
|
if (tsHit == false) {
|
|
if (timestampUslist.empty() == false) {
|
|
EXPECT_EQ(tsHit, true)
|
|
<< "TimeStamp not recognized";
|
|
} else {
|
|
std::cout << "[ INFO ] Received non-zero "
|
|
"output / TimeStamp not recognized \n";
|
|
}
|
|
}
|
|
}
|
|
#define WRITE_OUTPUT 0
|
|
#if WRITE_OUTPUT
|
|
static int count = 0;
|
|
FILE* ofp = nullptr;
|
|
if (count)
|
|
ofp = fopen("out.bin", "ab");
|
|
else
|
|
ofp = fopen("out.bin", "wb");
|
|
if (ofp != nullptr) {
|
|
fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
|
|
sizeof(char),
|
|
msg.data.extendedBufferData.rangeLength, ofp);
|
|
fclose(ofp);
|
|
count++;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
enum standardComp {
|
|
h263,
|
|
avc,
|
|
mpeg4,
|
|
hevc,
|
|
vp8,
|
|
vp9,
|
|
unknown_comp,
|
|
};
|
|
|
|
std::string component_;
|
|
std::string role_;
|
|
std::string instance_;
|
|
|
|
sp<IOmx> omx;
|
|
sp<CodecObserver> observer;
|
|
sp<IOmxNode> omxNode;
|
|
standardComp compName;
|
|
OMX_VIDEO_CODINGTYPE eCompressionFormat;
|
|
bool disableTest;
|
|
bool eosFlag;
|
|
bool prependSPSPPS;
|
|
::android::List<uint64_t> timestampUslist;
|
|
bool timestampDevTest;
|
|
bool isSecure;
|
|
sp<IGraphicBufferProducer> producer;
|
|
sp<IGraphicBufferSource> source;
|
|
|
|
protected:
|
|
static void description(const std::string& description) {
|
|
RecordProperty("description", description);
|
|
}
|
|
};
|
|
|
|
// CodecProducerListener class
|
|
struct CodecProducerListener : public IProducerListener {
|
|
public:
|
|
CodecProducerListener(int a, int b)
|
|
: freeBuffers(a), minUnDequeuedCount(b) {}
|
|
virtual ::android::hardware::Return<void> onBufferReleased() override {
|
|
android::Mutex::Autolock autoLock(bufferLock);
|
|
freeBuffers += 1;
|
|
return Void();
|
|
}
|
|
virtual ::android::hardware::Return<bool> needsReleaseNotify() override {
|
|
return true;
|
|
}
|
|
void reduceCount() {
|
|
android::Mutex::Autolock autoLock(bufferLock);
|
|
freeBuffers -= 1;
|
|
EXPECT_GE(freeBuffers, minUnDequeuedCount);
|
|
}
|
|
|
|
size_t freeBuffers;
|
|
size_t minUnDequeuedCount;
|
|
android::Mutex bufferLock;
|
|
};
|
|
|
|
// Mock IOmxBufferSource class. GraphicBufferSource.cpp in libstagefright/omx/
|
|
// implements this class. Below class is introduced to test if callback
|
|
// functions are actually being called or not
|
|
struct MockBufferSource : public IOmxBufferSource {
|
|
public:
|
|
MockBufferSource(sp<IOmxNode> node) {
|
|
callback = 0;
|
|
executing = false;
|
|
omxNode = node;
|
|
}
|
|
virtual Return<void> onOmxExecuting();
|
|
virtual Return<void> onOmxIdle();
|
|
virtual Return<void> onOmxLoaded();
|
|
virtual Return<void> onInputBufferAdded(uint32_t buffer);
|
|
virtual Return<void> onInputBufferEmptied(
|
|
uint32_t buffer, const ::android::hardware::hidl_handle& fence);
|
|
|
|
int callback;
|
|
bool executing;
|
|
sp<IOmxNode> omxNode;
|
|
android::Vector<BufferInfo> iBuffer, oBuffer;
|
|
};
|
|
|
|
Return<void> MockBufferSource::onOmxExecuting() {
|
|
executing = true;
|
|
callback |= 0x1;
|
|
size_t index;
|
|
// Fetch a client owned input buffer and send an EOS
|
|
if ((index = getEmptyBufferID(&iBuffer)) < iBuffer.size()) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
CodecBuffer t = iBuffer[index].omxBuffer;
|
|
t.type = CodecBuffer::Type::ANW_BUFFER;
|
|
native_handle_t* fenceNh = native_handle_create(0, 0);
|
|
EXPECT_NE(fenceNh, nullptr);
|
|
status = omxNode->emptyBuffer(iBuffer[index].id, t, OMX_BUFFERFLAG_EOS,
|
|
0, fenceNh);
|
|
native_handle_close(fenceNh);
|
|
native_handle_delete(fenceNh);
|
|
EXPECT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
|
|
iBuffer.editItemAt(index).owner = component;
|
|
}
|
|
return Void();
|
|
};
|
|
|
|
Return<void> MockBufferSource::onOmxIdle() {
|
|
callback |= 0x2;
|
|
executing = false;
|
|
return Void();
|
|
};
|
|
|
|
Return<void> MockBufferSource::onOmxLoaded() {
|
|
callback |= 0x4;
|
|
return Void();
|
|
};
|
|
|
|
Return<void> MockBufferSource::onInputBufferAdded(uint32_t buffer) {
|
|
(void)buffer;
|
|
EXPECT_EQ(executing, false);
|
|
callback |= 0x8;
|
|
return Void();
|
|
};
|
|
|
|
Return<void> MockBufferSource::onInputBufferEmptied(
|
|
uint32_t buffer, const ::android::hardware::hidl_handle& fence) {
|
|
(void)fence;
|
|
callback |= 0x10;
|
|
size_t i;
|
|
for (i = 0; i < iBuffer.size(); i++) {
|
|
if (iBuffer[i].id == buffer) {
|
|
iBuffer.editItemAt(i).owner = client;
|
|
break;
|
|
}
|
|
}
|
|
return Void();
|
|
};
|
|
|
|
// request VOP refresh
|
|
void requestIDR(sp<IOmxNode> omxNode, OMX_U32 portIndex) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_CONFIG_INTRAREFRESHVOPTYPE param;
|
|
param.IntraRefreshVOP = OMX_TRUE;
|
|
status = setPortConfig(omxNode, OMX_IndexConfigVideoIntraVOPRefresh,
|
|
portIndex, ¶m);
|
|
if (status != ::android::hardware::media::omx::V1_0::Status::OK)
|
|
std::cout << "[ INFO ] unable to request IDR \n";
|
|
}
|
|
|
|
// modify bitrate
|
|
void changeBitrate(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t nBitrate) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_VIDEO_CONFIG_BITRATETYPE param;
|
|
param.nEncodeBitrate = nBitrate;
|
|
status =
|
|
setPortConfig(omxNode, OMX_IndexConfigVideoBitrate, portIndex, ¶m);
|
|
if (status != ::android::hardware::media::omx::V1_0::Status::OK)
|
|
std::cout << "[ INFO ] unable to change Bitrate \n";
|
|
}
|
|
|
|
// modify framerate
|
|
Return<android::hardware::media::omx::V1_0::Status> changeFrameRate(
|
|
sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t xFramerate) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_CONFIG_FRAMERATETYPE param;
|
|
param.xEncodeFramerate = xFramerate;
|
|
status = setPortConfig(omxNode, OMX_IndexConfigVideoFramerate, portIndex,
|
|
¶m);
|
|
if (status != ::android::hardware::media::omx::V1_0::Status::OK)
|
|
std::cout << "[ INFO ] unable to change Framerate \n";
|
|
return status;
|
|
}
|
|
|
|
// modify intra refresh interval
|
|
void changeRefreshPeriod(sp<IOmxNode> omxNode, OMX_U32 portIndex,
|
|
uint32_t nRefreshPeriod) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE param;
|
|
param.nRefreshPeriod = nRefreshPeriod;
|
|
status = setPortConfig(omxNode,
|
|
(OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
|
|
portIndex, ¶m);
|
|
if (status != ::android::hardware::media::omx::V1_0::Status::OK)
|
|
std::cout << "[ INFO ] unable to change Refresh Period\n";
|
|
}
|
|
|
|
// set intra refresh interval
|
|
void setRefreshPeriod(sp<IOmxNode> omxNode, OMX_U32 portIndex,
|
|
uint32_t nRefreshPeriod) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_VIDEO_PARAM_INTRAREFRESHTYPE param;
|
|
param.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
|
|
param.nCirMBs = 0;
|
|
if (nRefreshPeriod == 0)
|
|
param.nCirMBs = 0;
|
|
else {
|
|
OMX_PARAM_PORTDEFINITIONTYPE portDef;
|
|
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
|
|
&portDef);
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
param.nCirMBs =
|
|
((portDef.format.video.nFrameWidth + 15) >>
|
|
4 * (portDef.format.video.nFrameHeight + 15) >> 4) /
|
|
nRefreshPeriod;
|
|
}
|
|
}
|
|
status = setPortParam(omxNode, OMX_IndexParamVideoIntraRefresh, portIndex,
|
|
¶m);
|
|
if (status != ::android::hardware::media::omx::V1_0::Status::OK)
|
|
std::cout << "[ INFO ] unable to set Refresh Period \n";
|
|
}
|
|
|
|
void setLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t latency) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_PARAM_U32TYPE param;
|
|
param.nU32 = (OMX_U32)latency;
|
|
status = setPortConfig(omxNode, (OMX_INDEXTYPE)OMX_IndexConfigLatency,
|
|
portIndex, ¶m);
|
|
if (status != ::android::hardware::media::omx::V1_0::Status::OK)
|
|
std::cout << "[ INFO ] unable to set latency\n";
|
|
}
|
|
|
|
void getLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t* latency) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_PARAM_U32TYPE param;
|
|
status = getPortConfig(omxNode, (OMX_INDEXTYPE)OMX_IndexConfigLatency,
|
|
portIndex, ¶m);
|
|
if (status != ::android::hardware::media::omx::V1_0::Status::OK)
|
|
std::cout << "[ INFO ] unable to get latency\n";
|
|
else
|
|
*latency = param.nU32;
|
|
}
|
|
|
|
// Set Default port param.
|
|
void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
|
|
OMX_VIDEO_CODINGTYPE eCompressionFormat,
|
|
OMX_U32 nFrameWidth, OMX_U32 nFrameHeight,
|
|
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.nFrameWidth = nFrameWidth;
|
|
portDef.format.video.nFrameHeight = nFrameHeight;
|
|
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);
|
|
|
|
std::vector<int32_t> arrProfile;
|
|
std::vector<int32_t> arrLevel;
|
|
enumerateProfileAndLevel(omxNode, portIndex, &arrProfile, &arrLevel);
|
|
if (arrProfile.empty() == true || arrLevel.empty() == true)
|
|
ASSERT_TRUE(false);
|
|
int32_t profile = arrProfile[0];
|
|
int32_t level = arrLevel[0];
|
|
|
|
switch ((int)eCompressionFormat) {
|
|
case OMX_VIDEO_CodingAVC:
|
|
setupAVCPort(omxNode, portIndex,
|
|
static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile),
|
|
static_cast<OMX_VIDEO_AVCLEVELTYPE>(level),
|
|
xFramerate);
|
|
break;
|
|
case OMX_VIDEO_CodingHEVC:
|
|
setupHEVCPort(omxNode, portIndex,
|
|
static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile),
|
|
static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level));
|
|
break;
|
|
case OMX_VIDEO_CodingH263:
|
|
setupH263Port(omxNode, portIndex,
|
|
static_cast<OMX_VIDEO_H263PROFILETYPE>(profile),
|
|
static_cast<OMX_VIDEO_H263LEVELTYPE>(level),
|
|
xFramerate);
|
|
break;
|
|
case OMX_VIDEO_CodingMPEG4:
|
|
setupMPEG4Port(omxNode, portIndex,
|
|
static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile),
|
|
static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level),
|
|
xFramerate);
|
|
break;
|
|
case OMX_VIDEO_CodingVP8:
|
|
setupVPXPort(omxNode, portIndex, xFramerate);
|
|
setupVP8Port(omxNode, portIndex,
|
|
static_cast<OMX_VIDEO_VP8PROFILETYPE>(profile),
|
|
static_cast<OMX_VIDEO_VP8LEVELTYPE>(level));
|
|
break;
|
|
case OMX_VIDEO_CodingVP9:
|
|
setupVPXPort(omxNode, portIndex, xFramerate);
|
|
setupVP9Port(omxNode, portIndex,
|
|
static_cast<OMX_VIDEO_VP9PROFILETYPE>(profile),
|
|
static_cast<OMX_VIDEO_VP9LEVELTYPE>(level));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// LookUpTable of clips and metadata for component testing
|
|
void GetURLForComponent(char* URL) {
|
|
strcat(URL, "bbb_352x288_420p_30fps_32frames.yuv");
|
|
}
|
|
|
|
// blocking call to ensures application to Wait till all the inputs are consumed
|
|
void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|
android::Vector<BufferInfo>* iBuffer,
|
|
android::Vector<BufferInfo>* oBuffer,
|
|
bool inputDataIsMeta = false,
|
|
sp<CodecProducerListener> listener = nullptr) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
Message msg;
|
|
int timeOut = TIMEOUT_COUNTER_Q;
|
|
|
|
while (timeOut--) {
|
|
size_t i = 0;
|
|
status =
|
|
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
|
|
ASSERT_EQ(status,
|
|
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
|
|
// status == TIMED_OUT, it could be due to process time being large
|
|
// than DEFAULT_TIMEOUT or component needs output buffers to start
|
|
// processing.
|
|
if (inputDataIsMeta) {
|
|
if (listener->freeBuffers == iBuffer->size()) break;
|
|
} else {
|
|
for (; i < iBuffer->size(); i++) {
|
|
if ((*iBuffer)[i].owner != client) break;
|
|
}
|
|
if (i == iBuffer->size()) break;
|
|
}
|
|
|
|
// Dispatch an output buffer assuming outQueue.empty() is true
|
|
size_t index;
|
|
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
dispatchOutputBuffer(omxNode, oBuffer, index));
|
|
timeOut = TIMEOUT_COUNTER_Q;
|
|
}
|
|
}
|
|
}
|
|
|
|
int colorFormatConversion(BufferInfo* buffer, buffer_handle_t buff, PixelFormat format,
|
|
std::ifstream& eleStream) {
|
|
android::GraphicBufferMapper& gbmapper = android::GraphicBufferMapper::get();
|
|
|
|
android::Rect rect(0, 0, buffer->omxBuffer.attr.anwBuffer.width,
|
|
buffer->omxBuffer.attr.anwBuffer.height);
|
|
android_ycbcr ycbcrLayout;
|
|
android::status_t error = android::NO_ERROR;
|
|
|
|
if (format == PixelFormat::YV12 || format == PixelFormat::YCRCB_420_SP ||
|
|
format == PixelFormat::YCBCR_420_888) {
|
|
error = gbmapper.lockYCbCr(buff, buffer->omxBuffer.attr.anwBuffer.usage, rect,
|
|
&ycbcrLayout);
|
|
EXPECT_EQ(error, android::NO_ERROR);
|
|
if (error != android::NO_ERROR) return 1;
|
|
|
|
int size = ((rect.getWidth() * rect.getHeight() * 3) >> 1);
|
|
char* img = new char[size];
|
|
if (img == nullptr) return 1;
|
|
eleStream.read(img, size);
|
|
if (eleStream.gcount() != size) {
|
|
delete[] img;
|
|
return 1;
|
|
}
|
|
|
|
char* imgTmp = img;
|
|
char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
|
|
for (size_t y = rect.getHeight(); y > 0; --y) {
|
|
memcpy(ipBuffer, imgTmp, rect.getWidth());
|
|
ipBuffer += ycbcrLayout.ystride;
|
|
imgTmp += rect.getWidth();
|
|
}
|
|
|
|
if (format == PixelFormat::YV12)
|
|
EXPECT_EQ(ycbcrLayout.chroma_step, 1U);
|
|
else if (format == PixelFormat::YCRCB_420_SP)
|
|
EXPECT_EQ(ycbcrLayout.chroma_step, 2U);
|
|
|
|
ipBuffer = static_cast<char*>(ycbcrLayout.cb);
|
|
for (size_t y = rect.getHeight() >> 1; y > 0; --y) {
|
|
for (int32_t x = 0; x < (rect.getWidth() >> 1); ++x) {
|
|
ipBuffer[ycbcrLayout.chroma_step * x] = *imgTmp++;
|
|
}
|
|
ipBuffer += ycbcrLayout.cstride;
|
|
}
|
|
ipBuffer = static_cast<char*>(ycbcrLayout.cr);
|
|
for (size_t y = rect.getHeight() >> 1; y > 0; --y) {
|
|
for (int32_t x = 0; x < (rect.getWidth() >> 1); ++x) {
|
|
ipBuffer[ycbcrLayout.chroma_step * x] = *imgTmp++;
|
|
}
|
|
ipBuffer += ycbcrLayout.cstride;
|
|
}
|
|
|
|
delete[] img;
|
|
|
|
error = gbmapper.unlock(buff);
|
|
EXPECT_EQ(error, android::NO_ERROR);
|
|
if (error != android::NO_ERROR) return 1;
|
|
} else {
|
|
void* data;
|
|
error = gbmapper.lock(buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, &data);
|
|
EXPECT_EQ(error, android::NO_ERROR);
|
|
if (error != android::NO_ERROR) return 1;
|
|
|
|
if (format == PixelFormat::BGRA_8888) {
|
|
char* ipBuffer = static_cast<char*>(data);
|
|
for (size_t y = rect.getHeight(); y > 0; --y) {
|
|
eleStream.read(ipBuffer, rect.getWidth() * 4);
|
|
if (eleStream.gcount() != rect.getWidth() * 4) return 1;
|
|
ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
|
|
}
|
|
} else {
|
|
EXPECT_TRUE(false) << "un expected pixel format";
|
|
return 1;
|
|
}
|
|
|
|
error = gbmapper.unlock(buff);
|
|
EXPECT_EQ(error, android::NO_ERROR);
|
|
if (error != android::NO_ERROR) return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int fillGraphicBuffer(BufferInfo* buffer, PixelFormat format,
|
|
std::ifstream& eleStream) {
|
|
android::GraphicBufferMapper& gbmapper = android::GraphicBufferMapper::get();
|
|
buffer_handle_t buff;
|
|
android::status_t error = android::NO_ERROR;
|
|
gbmapper.importBuffer(
|
|
buffer->omxBuffer.nativeHandle, buffer->omxBuffer.attr.anwBuffer.width,
|
|
buffer->omxBuffer.attr.anwBuffer.height, buffer->omxBuffer.attr.anwBuffer.layerCount,
|
|
static_cast<android::PixelFormat>(format), buffer->omxBuffer.attr.anwBuffer.usage,
|
|
buffer->omxBuffer.attr.anwBuffer.stride, &buff);
|
|
EXPECT_EQ(error, android::NO_ERROR);
|
|
if (error != android::NO_ERROR) return 1;
|
|
|
|
if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
|
|
|
|
error = gbmapper.freeBuffer(buff);
|
|
EXPECT_EQ(error, android::NO_ERROR);
|
|
if (error != android::NO_ERROR) return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dispatchGraphicBuffer(sp<IOmxNode> omxNode,
|
|
sp<IGraphicBufferProducer> producer,
|
|
sp<CodecProducerListener> listener,
|
|
android::Vector<BufferInfo>* buffArray,
|
|
OMX_U32 portIndex, std::ifstream& eleStream,
|
|
uint64_t timestamp) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_PARAM_PORTDEFINITIONTYPE portDef;
|
|
|
|
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
|
|
&portDef);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
if (status != ::android::hardware::media::omx::V1_0::Status::OK) return 1;
|
|
|
|
enum {
|
|
// A flag returned by dequeueBuffer when the client needs to call
|
|
// requestBuffer immediately thereafter.
|
|
BUFFER_NEEDS_REALLOCATION = 0x1,
|
|
// A flag returned by dequeueBuffer when all mirrored slots should be
|
|
// released by the client. This flag should always be processed first.
|
|
RELEASE_ALL_BUFFERS = 0x2,
|
|
};
|
|
|
|
int32_t slot;
|
|
int32_t result;
|
|
::android::hardware::hidl_handle fence;
|
|
IGraphicBufferProducer::FrameEventHistoryDelta outTimestamps;
|
|
::android::hardware::media::V1_0::AnwBuffer AnwBuffer;
|
|
PixelFormat format = PixelFormat::YCBCR_420_888;
|
|
producer->dequeueBuffer(
|
|
portDef.format.video.nFrameWidth, portDef.format.video.nFrameHeight,
|
|
format, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
|
|
true, [&](int32_t _s, int32_t const& _n1,
|
|
::android::hardware::hidl_handle const& _n2,
|
|
IGraphicBufferProducer::FrameEventHistoryDelta const& _n3) {
|
|
result = _s;
|
|
slot = _n1;
|
|
fence = _n2;
|
|
outTimestamps = _n3;
|
|
});
|
|
if (result & BUFFER_NEEDS_REALLOCATION) {
|
|
producer->requestBuffer(
|
|
slot, [&](int32_t _s,
|
|
::android::hardware::media::V1_0::AnwBuffer const& _n1) {
|
|
result = _s;
|
|
AnwBuffer = _n1;
|
|
});
|
|
EXPECT_EQ(result, 0);
|
|
if (result != 0) return 1;
|
|
size_t i;
|
|
for (i = 0; i < buffArray->size(); i++) {
|
|
if ((*buffArray)[i].slot == -1) {
|
|
buffArray->editItemAt(i).slot = slot;
|
|
buffArray->editItemAt(i).omxBuffer.nativeHandle =
|
|
AnwBuffer.nativeHandle;
|
|
buffArray->editItemAt(i).omxBuffer.attr.anwBuffer =
|
|
AnwBuffer.attr;
|
|
break;
|
|
}
|
|
}
|
|
EXPECT_NE(i, buffArray->size());
|
|
if (i == buffArray->size()) return 1;
|
|
}
|
|
EXPECT_EQ(result, 0);
|
|
if (result != 0) return 1;
|
|
|
|
// fill Buffer
|
|
BufferInfo buffer;
|
|
size_t i;
|
|
for (i = 0; i < buffArray->size(); i++) {
|
|
if ((*buffArray)[i].slot == slot) {
|
|
buffer = (*buffArray)[i];
|
|
break;
|
|
}
|
|
}
|
|
EXPECT_NE(i, buffArray->size());
|
|
if (i == buffArray->size()) return 1;
|
|
if (fillGraphicBuffer(&buffer, format, eleStream)) return 1;
|
|
|
|
// queue Buffer
|
|
IGraphicBufferProducer::QueueBufferOutput output;
|
|
IGraphicBufferProducer::QueueBufferInput input;
|
|
android::hardware::media::V1_0::Rect rect;
|
|
rect.left = 0;
|
|
rect.top = 0;
|
|
rect.right = buffer.omxBuffer.attr.anwBuffer.width;
|
|
rect.bottom = buffer.omxBuffer.attr.anwBuffer.height;
|
|
input.timestamp = timestamp;
|
|
input.isAutoTimestamp = false;
|
|
input.dataSpace =
|
|
android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN;
|
|
input.crop = rect;
|
|
input.scalingMode = 0;
|
|
input.transform = 0;
|
|
input.stickyTransform = 0;
|
|
input.fence = android::hardware::hidl_handle();
|
|
input.surfaceDamage =
|
|
android::hardware::hidl_vec<android::hardware::media::V1_0::Rect>{rect};
|
|
input.getFrameTimestamps = false;
|
|
producer->queueBuffer(
|
|
buffer.slot, input,
|
|
[&](int32_t _s, const IGraphicBufferProducer::QueueBufferOutput& _n1) {
|
|
result = _s;
|
|
output = _n1;
|
|
});
|
|
EXPECT_EQ(result, 0);
|
|
if (result != 0) return 1;
|
|
|
|
listener->reduceCount();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int fillByteBuffer(sp<IOmxNode> omxNode, char* ipBuffer, OMX_U32 portIndexInput,
|
|
std::ifstream& eleStream) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
OMX_PARAM_PORTDEFINITIONTYPE portDef;
|
|
uint32_t i, j;
|
|
|
|
status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndexInput,
|
|
&portDef);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
int size = ((portDef.format.video.nFrameWidth *
|
|
portDef.format.video.nFrameHeight * 3) >>
|
|
1);
|
|
char* img = new char[size];
|
|
if (img == nullptr) return 1;
|
|
eleStream.read(img, size);
|
|
if (eleStream.gcount() != size) {
|
|
delete[] img;
|
|
return 1;
|
|
}
|
|
|
|
char* Y = ipBuffer;
|
|
char* imgTmp = img;
|
|
for (j = 0; j < portDef.format.video.nFrameHeight; ++j) {
|
|
memcpy(Y, imgTmp, portDef.format.video.nFrameWidth);
|
|
Y += portDef.format.video.nStride;
|
|
imgTmp += portDef.format.video.nFrameWidth;
|
|
}
|
|
|
|
if (portDef.format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
|
|
char* Cb = ipBuffer + (portDef.format.video.nFrameHeight *
|
|
portDef.format.video.nStride);
|
|
char* Cr = Cb + 1;
|
|
for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
|
|
for (i = 0; i < (portDef.format.video.nFrameWidth >> 1); ++i) {
|
|
Cb[2 * i] = *imgTmp++;
|
|
}
|
|
Cb += portDef.format.video.nStride;
|
|
}
|
|
for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
|
|
for (i = 0; i < (portDef.format.video.nFrameWidth >> 1); ++i) {
|
|
Cr[2 * i] = *imgTmp++;
|
|
}
|
|
Cr += portDef.format.video.nStride;
|
|
}
|
|
} else if (portDef.format.video.eColorFormat ==
|
|
OMX_COLOR_FormatYUV420Planar) {
|
|
char* Cb = ipBuffer + (portDef.format.video.nFrameHeight *
|
|
portDef.format.video.nStride);
|
|
char* Cr = Cb + ((portDef.format.video.nFrameHeight *
|
|
portDef.format.video.nStride) >>
|
|
2);
|
|
for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
|
|
memcpy(Cb, imgTmp, (portDef.format.video.nFrameWidth >> 1));
|
|
Cb += (portDef.format.video.nStride >> 1);
|
|
imgTmp += (portDef.format.video.nFrameWidth >> 1);
|
|
}
|
|
for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
|
|
memcpy(Cr, imgTmp, (portDef.format.video.nFrameWidth >> 1));
|
|
Cr += (portDef.format.video.nStride >> 1);
|
|
imgTmp += (portDef.format.video.nFrameWidth >> 1);
|
|
}
|
|
}
|
|
|
|
delete[] img;
|
|
return 0;
|
|
}
|
|
|
|
// Encode N Frames
|
|
void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
|
|
OMX_U32 portIndexInput, OMX_U32 portIndexOutput,
|
|
android::Vector<BufferInfo>* iBuffer,
|
|
android::Vector<BufferInfo>* oBuffer, uint32_t nFrames,
|
|
uint32_t xFramerate, int bytesCount,
|
|
std::ifstream& eleStream,
|
|
::android::List<uint64_t>* timestampUslist = nullptr,
|
|
bool signalEOS = true, bool inputDataIsMeta = false,
|
|
sp<IGraphicBufferProducer> producer = nullptr,
|
|
sp<CodecProducerListener> listener = nullptr) {
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
Message msg;
|
|
uint64_t timestamp = 0;
|
|
uint32_t flags = 0;
|
|
int timeOut = TIMEOUT_COUNTER_Q;
|
|
bool iQueued, oQueued;
|
|
|
|
uint32_t ipCount = 0;
|
|
if (ipCount == 0) {
|
|
status = changeFrameRate(omxNode, portIndexOutput, (24U << 16));
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK)
|
|
xFramerate = (24U << 16);
|
|
}
|
|
int32_t timestampIncr = (int)((float)1000000 / (xFramerate >> 16));
|
|
if (inputDataIsMeta) timestampIncr *= 1000; // timestamp scale: Nano sec
|
|
|
|
while (1) {
|
|
iQueued = oQueued = false;
|
|
status =
|
|
observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
|
|
// Port Reconfiguration
|
|
if (status == android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(msg.type, Message::Type::EVENT);
|
|
if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
|
|
ASSERT_EQ(msg.data.eventData.data1, portIndexOutput);
|
|
ASSERT_EQ(msg.data.eventData.data2,
|
|
OMX_IndexConfigAndroidIntraRefresh);
|
|
} else if (msg.data.eventData.event == OMX_EventError) {
|
|
ASSERT_TRUE(false) << "Received OMX_EventError, not sure why";
|
|
} else if (msg.data.eventData.event == OMX_EventDataSpaceChanged) {
|
|
// TODO: how am i supposed to respond now?
|
|
std::cout << "[ INFO ] OMX_EventDataSpaceChanged \n";
|
|
} else {
|
|
ASSERT_TRUE(false);
|
|
}
|
|
}
|
|
|
|
if (nFrames == 0) break;
|
|
|
|
// Dispatch input buffer
|
|
size_t index = 0;
|
|
if (inputDataIsMeta) {
|
|
if (listener->freeBuffers > listener->minUnDequeuedCount) {
|
|
if (dispatchGraphicBuffer(omxNode, producer, listener, iBuffer,
|
|
portIndexInput, eleStream,
|
|
timestamp)) {
|
|
if (::testing::Test::HasFailure())
|
|
ASSERT_TRUE(false);
|
|
else
|
|
break;
|
|
}
|
|
timestamp += timestampIncr;
|
|
nFrames--;
|
|
ipCount++;
|
|
iQueued = true;
|
|
}
|
|
} else {
|
|
if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
|
|
char* ipBuffer = static_cast<char*>(static_cast<void*>(
|
|
(*iBuffer)[index].mMemory->getPointer()));
|
|
ASSERT_LE(
|
|
bytesCount,
|
|
static_cast<int>((*iBuffer)[index].mMemory->getSize()));
|
|
if (fillByteBuffer(omxNode, ipBuffer, portIndexInput,
|
|
eleStream))
|
|
break;
|
|
flags = OMX_BUFFERFLAG_ENDOFFRAME;
|
|
if (signalEOS && (nFrames == 1)) flags |= OMX_BUFFERFLAG_EOS;
|
|
ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
|
|
omxNode, iBuffer, index, bytesCount, flags, timestamp));
|
|
if (timestampUslist) timestampUslist->push_back(timestamp);
|
|
timestamp += timestampIncr;
|
|
nFrames--;
|
|
ipCount++;
|
|
iQueued = true;
|
|
}
|
|
}
|
|
// Dispatch output buffer
|
|
if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
dispatchOutputBuffer(omxNode, oBuffer, index));
|
|
oQueued = true;
|
|
}
|
|
// Reset Counters when either input or output buffer is dispatched
|
|
if (iQueued || oQueued)
|
|
timeOut = TIMEOUT_COUNTER_Q;
|
|
else
|
|
timeOut--;
|
|
if (timeOut == 0) {
|
|
ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
|
|
}
|
|
// Runtime Param Configuration
|
|
if (ipCount == 15) {
|
|
changeBitrate(omxNode, portIndexOutput, 768000);
|
|
requestIDR(omxNode, portIndexOutput);
|
|
changeRefreshPeriod(omxNode, portIndexOutput, 15);
|
|
}
|
|
}
|
|
}
|
|
|
|
// set component role
|
|
TEST_P(VideoEncHidlTest, SetRole) {
|
|
description("Test Set Component Role");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
status = setRole(omxNode, role_);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
}
|
|
|
|
// port format enumeration
|
|
TEST_P(VideoEncHidlTest, EnumeratePortFormat) {
|
|
description("Test Component on Mandatory Port Parameters (Port Format)");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
|
|
OMX_U32 xFramerate = (30U << 16);
|
|
status = setRole(omxNode, role_);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
kPortIndexInput = params.nStartPortNumber;
|
|
kPortIndexOutput = kPortIndexInput + 1;
|
|
}
|
|
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 IOmxBufferSource CallBacks
|
|
TEST_P(VideoEncHidlTest, BufferSourceCallBacks) {
|
|
description("Test IOmxBufferSource CallBacks");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
status = setRole(omxNode, role_);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
kPortIndexInput = params.nStartPortNumber;
|
|
kPortIndexOutput = kPortIndexInput + 1;
|
|
}
|
|
|
|
// Configure input port
|
|
uint32_t nFrameWidth = 352;
|
|
uint32_t nFrameHeight = 288;
|
|
uint32_t xFramerate = (30U << 16);
|
|
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatAndroidOpaque;
|
|
setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
|
|
xFramerate, eColorFormat);
|
|
|
|
sp<MockBufferSource> buffersource = new MockBufferSource(omxNode);
|
|
ASSERT_NE(buffersource, nullptr);
|
|
status = omxNode->setInputSurface(buffersource);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set port mode
|
|
PortMode portMode[2];
|
|
portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
|
|
portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
|
|
omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer,
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
|
|
ASSERT_NO_FATAL_FAILURE(testEOS(omxNode, observer, &buffersource->iBuffer,
|
|
&buffersource->oBuffer, false, eosFlag));
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(changeStateExecutetoIdle(
|
|
omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer));
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &buffersource->iBuffer,
|
|
&buffersource->oBuffer, kPortIndexInput,
|
|
kPortIndexOutput, portMode));
|
|
// test for callbacks
|
|
EXPECT_EQ(buffersource->callback, 31);
|
|
}
|
|
|
|
// test raw stream encode (input is byte buffers)
|
|
TEST_P(VideoEncHidlTest, EncodeTest) {
|
|
description("Test Encode");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
status = setRole(omxNode, role_);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
kPortIndexInput = params.nStartPortNumber;
|
|
kPortIndexOutput = kPortIndexInput + 1;
|
|
}
|
|
char mURL[512];
|
|
strcpy(mURL, sResourceDir.c_str());
|
|
GetURLForComponent(mURL);
|
|
|
|
std::ifstream eleStream;
|
|
|
|
timestampDevTest = true;
|
|
|
|
// Configure input port
|
|
uint32_t nFrameWidth = 352;
|
|
uint32_t nFrameHeight = 288;
|
|
uint32_t xFramerate = (30U << 16);
|
|
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
|
|
OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
|
|
portFormat.nIndex = 0;
|
|
while (1) {
|
|
status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat,
|
|
kPortIndexInput, &portFormat);
|
|
if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
|
|
EXPECT_EQ(portFormat.eCompressionFormat, OMX_VIDEO_CodingUnused);
|
|
if (OMX_COLOR_FormatYUV420SemiPlanar == portFormat.eColorFormat ||
|
|
OMX_COLOR_FormatYUV420Planar == portFormat.eColorFormat) {
|
|
eColorFormat = portFormat.eColorFormat;
|
|
break;
|
|
}
|
|
portFormat.nIndex++;
|
|
if (portFormat.nIndex == 512) break;
|
|
}
|
|
ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
|
|
setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
|
|
xFramerate, eColorFormat);
|
|
|
|
// Configure output port
|
|
uint32_t nBitRate = 512000;
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat,
|
|
nFrameWidth, nFrameHeight, nBitRate, xFramerate));
|
|
setRefreshPeriod(omxNode, kPortIndexOutput, 0);
|
|
|
|
unsigned int index;
|
|
omxNode->getExtensionIndex(
|
|
"OMX.google.android.index.prependSPSPPSToIDRFrames",
|
|
[&status, &index](android::hardware::media::omx::V1_0::Status _s,
|
|
unsigned int _nl) {
|
|
status = _s;
|
|
index = _nl;
|
|
});
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
android::PrependSPSPPSToIDRFramesParams param;
|
|
param.bEnable = OMX_TRUE;
|
|
status = setParam(omxNode, static_cast<OMX_INDEXTYPE>(index), ¶m);
|
|
}
|
|
if (status != ::android::hardware::media::omx::V1_0::Status::OK)
|
|
std::cout << "[ INFO ] unable to prependSPSPPSToIDRFrames\n";
|
|
else
|
|
prependSPSPPS = true;
|
|
|
|
// set port mode
|
|
PortMode portMode[2];
|
|
portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
uint32_t latency = 0;
|
|
setLatency(omxNode, kPortIndexInput, latency);
|
|
getLatency(omxNode, kPortIndexInput, &latency);
|
|
|
|
android::Vector<BufferInfo> iBuffer, oBuffer;
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
|
|
|
|
eleStream.open(mURL, std::ifstream::binary);
|
|
ASSERT_EQ(eleStream.is_open(), true);
|
|
ASSERT_NO_FATAL_FAILURE(encodeNFrames(
|
|
omxNode, observer, kPortIndexInput, kPortIndexOutput, &iBuffer,
|
|
&oBuffer, 32, xFramerate, (nFrameWidth * nFrameHeight * 3) >> 1,
|
|
eleStream, ×tampUslist));
|
|
eleStream.close();
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer));
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
|
|
if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
}
|
|
|
|
// test raw stream encode (input is ANW buffers)
|
|
TEST_P(VideoEncHidlTest, EncodeTestBufferMetaModes) {
|
|
description("Test Encode Input buffer metamodes");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
status = setRole(omxNode, role_);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
kPortIndexInput = params.nStartPortNumber;
|
|
kPortIndexOutput = kPortIndexInput + 1;
|
|
}
|
|
|
|
// Configure input port
|
|
uint32_t nFrameWidth = 352;
|
|
uint32_t nFrameHeight = 288;
|
|
uint32_t xFramerate = (30U << 16);
|
|
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatAndroidOpaque;
|
|
setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
|
|
xFramerate, eColorFormat);
|
|
|
|
// Configure output port
|
|
uint32_t nBitRate = 512000;
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat,
|
|
nFrameWidth, nFrameHeight, nBitRate, xFramerate));
|
|
// CreateInputSurface
|
|
EXPECT_TRUE(omx->createInputSurface(
|
|
[&](android::hardware::media::omx::V1_0::Status _s,
|
|
sp<IGraphicBufferProducer> const& _nl,
|
|
sp<IGraphicBufferSource> const& _n2) {
|
|
status = _s;
|
|
producer = _nl;
|
|
source = _n2;
|
|
})
|
|
.isOk());
|
|
ASSERT_NE(producer, nullptr);
|
|
ASSERT_NE(source, nullptr);
|
|
|
|
// setMaxDequeuedBufferCount
|
|
int32_t returnval;
|
|
int32_t value;
|
|
producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
|
|
[&returnval, &value](int32_t _s, int32_t _n1) {
|
|
returnval = _s;
|
|
value = _n1;
|
|
});
|
|
ASSERT_EQ(returnval, 0);
|
|
OMX_PARAM_PORTDEFINITIONTYPE portDef;
|
|
status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
|
|
kPortIndexInput, &portDef);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
ASSERT_EQ(::android::OK,
|
|
producer->setMaxDequeuedBufferCount(portDef.nBufferCountActual));
|
|
|
|
// Connect :: Mock Producer Listener
|
|
IGraphicBufferProducer::QueueBufferOutput qbo;
|
|
sp<CodecProducerListener> listener =
|
|
new CodecProducerListener(portDef.nBufferCountActual + value, value);
|
|
producer->connect(
|
|
listener, NATIVE_WINDOW_API_CPU, false,
|
|
[&](int32_t _s, IGraphicBufferProducer::QueueBufferOutput const& _n1) {
|
|
returnval = _s;
|
|
qbo = _n1;
|
|
});
|
|
ASSERT_EQ(returnval, 0);
|
|
|
|
portDef.nBufferCountActual = portDef.nBufferCountActual + value;
|
|
status = setPortParam(omxNode, OMX_IndexParamPortDefinition,
|
|
kPortIndexInput, &portDef);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// Do setInputSurface()
|
|
// enable MetaMode on input port
|
|
status = source->configure(
|
|
omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set port mode
|
|
PortMode portMode[2];
|
|
portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
|
|
portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
char mURL[512];
|
|
strcpy(mURL, sResourceDir.c_str());
|
|
GetURLForComponent(mURL);
|
|
|
|
uint32_t latency = 0;
|
|
setLatency(omxNode, kPortIndexInput, latency);
|
|
getLatency(omxNode, kPortIndexInput, &latency);
|
|
|
|
std::ifstream eleStream;
|
|
|
|
status = source->setSuspend(false, 0);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = source->setRepeatPreviousFrameDelayUs(100000);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = source->setMaxFps(24.0f);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = source->setTimeLapseConfig(24.0, 24.0);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = source->setTimeOffsetUs(-100);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = source->setStartTimeUs(10);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = source->setStopTimeUs(1000000);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
::android::hardware::media::omx::V1_0::ColorAspects aspects;
|
|
aspects.range =
|
|
::android::hardware::media::omx::V1_0::ColorAspects::Range::UNSPECIFIED;
|
|
aspects.primaries = ::android::hardware::media::omx::V1_0::ColorAspects::
|
|
Primaries::UNSPECIFIED;
|
|
aspects.transfer = ::android::hardware::media::omx::V1_0::ColorAspects::
|
|
Transfer::UNSPECIFIED;
|
|
aspects.matrixCoeffs = ::android::hardware::media::omx::V1_0::ColorAspects::
|
|
MatrixCoeffs::UNSPECIFIED;
|
|
status = source->setColorAspects(aspects);
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
int64_t stopTimeOffsetUs;
|
|
source->getStopTimeOffsetUs(
|
|
[&](android::hardware::media::omx::V1_0::Status _s, int64_t _n1) {
|
|
status = _s;
|
|
stopTimeOffsetUs = _n1;
|
|
});
|
|
EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
android::Vector<BufferInfo> iBuffer, oBuffer;
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
|
|
|
|
eleStream.open(mURL, std::ifstream::binary);
|
|
ASSERT_EQ(eleStream.is_open(), true);
|
|
ASSERT_NO_FATAL_FAILURE(encodeNFrames(
|
|
omxNode, observer, kPortIndexInput, kPortIndexOutput, &iBuffer,
|
|
&oBuffer, 1024, xFramerate, (nFrameWidth * nFrameHeight * 3) >> 1,
|
|
eleStream, nullptr, false, true, producer, listener));
|
|
eleStream.close();
|
|
ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(omxNode, observer, &iBuffer,
|
|
&oBuffer, true, listener));
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
|
|
EXPECT_EQ(portDef.nBufferCountActual, listener->freeBuffers);
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
|
|
returnval = producer->disconnect(
|
|
NATIVE_WINDOW_API_CPU, IGraphicBufferProducer::DisconnectMode::API);
|
|
ASSERT_EQ(returnval, 0);
|
|
}
|
|
|
|
// Test end of stream
|
|
TEST_P(VideoEncHidlTest, EncodeTestEOS) {
|
|
description("Test EOS");
|
|
if (disableTest) return;
|
|
android::hardware::media::omx::V1_0::Status status;
|
|
uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
|
|
status = setRole(omxNode, role_);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
OMX_PORT_PARAM_TYPE params;
|
|
status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
|
|
if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
|
|
ASSERT_EQ(params.nPorts, 2U);
|
|
kPortIndexInput = params.nStartPortNumber;
|
|
kPortIndexOutput = kPortIndexInput + 1;
|
|
}
|
|
|
|
// Configure input port
|
|
uint32_t nFrameWidth = 352;
|
|
uint32_t nFrameHeight = 288;
|
|
uint32_t xFramerate = (30U << 16);
|
|
OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatAndroidOpaque;
|
|
setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
|
|
xFramerate, eColorFormat);
|
|
|
|
// CreateInputSurface
|
|
EXPECT_TRUE(omx->createInputSurface(
|
|
[&](android::hardware::media::omx::V1_0::Status _s,
|
|
sp<IGraphicBufferProducer> const& _nl,
|
|
sp<IGraphicBufferSource> const& _n2) {
|
|
status = _s;
|
|
producer = _nl;
|
|
source = _n2;
|
|
})
|
|
.isOk());
|
|
ASSERT_NE(producer, nullptr);
|
|
ASSERT_NE(source, nullptr);
|
|
|
|
// setMaxDequeuedBufferCount
|
|
int32_t returnval;
|
|
int32_t value;
|
|
producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
|
|
[&returnval, &value](int32_t _s, int32_t _n1) {
|
|
returnval = _s;
|
|
value = _n1;
|
|
});
|
|
ASSERT_EQ(returnval, 0);
|
|
OMX_PARAM_PORTDEFINITIONTYPE portDef;
|
|
status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
|
|
kPortIndexInput, &portDef);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
ASSERT_EQ(::android::OK,
|
|
producer->setMaxDequeuedBufferCount(portDef.nBufferCountActual));
|
|
|
|
// Connect :: Mock Producer Listener
|
|
IGraphicBufferProducer::QueueBufferOutput qbo;
|
|
sp<CodecProducerListener> listener =
|
|
new CodecProducerListener(portDef.nBufferCountActual + value, value);
|
|
producer->connect(
|
|
listener, NATIVE_WINDOW_API_CPU, false,
|
|
[&](int32_t _s, IGraphicBufferProducer::QueueBufferOutput const& _n1) {
|
|
returnval = _s;
|
|
qbo = _n1;
|
|
});
|
|
ASSERT_EQ(returnval, 0);
|
|
|
|
portDef.nBufferCountActual = portDef.nBufferCountActual + value;
|
|
status = setPortParam(omxNode, OMX_IndexParamPortDefinition,
|
|
kPortIndexInput, &portDef);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// Do setInputSurface()
|
|
// enable MetaMode on input port
|
|
status = source->configure(
|
|
omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
// set port mode
|
|
PortMode portMode[2];
|
|
portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
|
|
portMode[1] = PortMode::PRESET_BYTE_BUFFER;
|
|
status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
|
|
android::Vector<BufferInfo> iBuffer, oBuffer;
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
|
|
|
|
// send EOS
|
|
status = source->signalEndOfInputStream();
|
|
ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
|
|
ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(omxNode, observer, &iBuffer,
|
|
&oBuffer, true, listener));
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
|
|
|
|
// set state to idle
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
|
|
EXPECT_EQ(portDef.nBufferCountActual, listener->freeBuffers);
|
|
// set state to executing
|
|
ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
|
|
kPortIndexInput, kPortIndexOutput, portMode));
|
|
|
|
returnval = producer->disconnect(
|
|
NATIVE_WINDOW_API_CPU, IGraphicBufferProducer::DisconnectMode::API);
|
|
ASSERT_EQ(returnval, 0);
|
|
}
|
|
|
|
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VideoEncHidlTest);
|
|
INSTANTIATE_TEST_SUITE_P(PerInstance, VideoEncHidlTest, testing::ValuesIn(kTestParameters),
|
|
android::hardware::PrintInstanceTupleNameToString<>);
|
|
|
|
int main(int argc, char** argv) {
|
|
kTestParameters = getTestParameters("video_encoder");
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
|
|
// Set the resource directory based on command line args.
|
|
// Test will fail to set up if the argument is not set.
|
|
for (int i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
|
|
sResourceDir = argv[i + 1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return RUN_ALL_TESTS();
|
|
} |