Files
BPI-CM9-Linux/aml-comp/multimedia/aml_mp_sdk/tests/amlMpTestSupporter/TestUtils.cpp
T
2026-08-24 10:03:24 +08:00

349 lines
9.3 KiB
C++

/*
* Copyright (c) 2020 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in the
* file 'LICENSE' which is part of this source code package.
*
* Description:
*/
#define LOG_TAG "AmlMpPlayerDemo_TestUtils"
#include <utils/AmlMpLog.h>
#include <utils/AmlMpUtils.h>
#include "TestUtils.h"
#include <signal.h>
#include <thread>
#include <poll.h>
#include <unistd.h>
static const char* mName = LOG_TAG;
namespace aml_mp {
NativeUI::NativeUI()
{
#ifdef ANDROID
#ifndef __ANDROID_VNDK__
mComposerClient = new android::SurfaceComposerClient;
AML_MP_CHECK_EQ(mComposerClient->initCheck(), android::OK);
//sp<android::IBinder> displayToken = nullptr;
//displayToken = mComposerClient->getInternalDisplayToken();
//android::DisplayInfo displayInfo;
//CHECK_EQ(OK, mComposerClient->getDisplayInfo(displayToken, &displayInfo));
//mDisplayWidth = displayInfo.w;
//mDisplayHeight = displayInfo.h;
mDisplayWidth = mSurfaceWidth;
mDisplayHeight = mSurfaceHeight;
MLOGI("mDisplayWidth: %d, mDisplayHeight: %d", mDisplayWidth, mDisplayHeight);
//mSurfaceWidth = mDisplayWidth >> 1;
//mSurfaceHeight = mDisplayHeight >> 1;
//MLOGI("mSurfaceWidth: %d, mSurfaceHeight: %d", mSurfaceWidth, mSurfaceHeight);
mSurfaceControl = mComposerClient->createSurface(android::String8("AmlMpPlayer"), mSurfaceWidth, mSurfaceHeight, android::PIXEL_FORMAT_RGB_565, 0);
AML_MP_CHECK(mSurfaceControl->isValid());
mSurface = mSurfaceControl->getSurface();
//coverity[uninit_use_in_call]
android::SurfaceComposerClient::Transaction()
.setFlags(mSurfaceControl, android::layer_state_t::eLayerOpaque, android::layer_state_t::eLayerOpaque)
#if ANDROID_PLATFORM_SDK_VERSION >= 31
.setCrop(mSurfaceControl, android::Rect(mSurfaceWidth, mSurfaceHeight))
#elif ANDROID_PLATFORM_SDK_VERSION >= 29
.setCrop_legacy(mSurfaceControl, android::Rect(mSurfaceWidth, mSurfaceHeight))
#endif
.show(mSurfaceControl)
.apply();
mSurfaceControlUi = mComposerClient->createSurface(android::String8("AmlMpPlayer-ui"), mDisplayWidth, mDisplayHeight, android::PIXEL_FORMAT_RGBA_8888, 0);
AML_MP_CHECK(mSurfaceControlUi->isValid());
mSurfaceUi = mSurfaceControlUi->getSurface();
int ret = native_window_api_connect(mSurfaceUi.get(), NATIVE_WINDOW_API_CPU);
if (ret < 0) {
MLOGE("mSurfaceUi connect failed with %d!", ret);
return;
}
mSurfaceUi->allocateBuffers();
//coverity[uninit_use_in_call]
android::SurfaceComposerClient::Transaction()
#if ANDROID_PLATFORM_SDK_VERSION >= 31
.setCrop(mSurfaceControlUi, android::Rect(mDisplayWidth, mDisplayHeight))
#elif ANDROID_PLATFORM_SDK_VERSION >= 29
.setCrop_legacy(mSurfaceControlUi, android::Rect(mDisplayWidth, mDisplayHeight))
#endif
.setLayer(mSurfaceControlUi, UI_LAYER)
.show(mSurfaceControlUi)
.apply();
ANativeWindow* nativeWindow = static_cast<ANativeWindow*>(mSurfaceUi.get());
int err = 0;
ANativeWindowBuffer* buf = nullptr;
err = nativeWindow->dequeueBuffer_DEPRECATED(nativeWindow, &buf);
if (err != 0) {
MLOGE("dequeueBuffer failed:%d\n", err);
return;
}
nativeWindow->lockBuffer_DEPRECATED(nativeWindow, buf);
sp<android::GraphicBuffer> graphicBuffer = android::GraphicBuffer::from(buf);
char* vaddr = nullptr;
graphicBuffer->lock(1, (void **)&vaddr);
if (vaddr != nullptr) {
memset(vaddr, 0x0, graphicBuffer->getWidth() * graphicBuffer->getHeight() * 4); /*to show video in osd hole...*/
}
graphicBuffer->unlock();
graphicBuffer.clear();
nativeWindow->queueBuffer_DEPRECATED(nativeWindow, buf);
#endif
#else
mSurfaceWidth = 0;
mSurfaceHeight = 0;
#endif
}
NativeUI::~NativeUI()
{
}
#ifdef ANDROID
sp<ANativeWindow> NativeUI::getNativeWindow() const
{
#ifndef __ANDROID_VNDK__
return mSurface;
#else
return nullptr;
#endif
}
#endif
void NativeUI::controlSurface(int zorder)
{
#ifdef ANDROID
#ifndef __ANDROID_VNDK__
auto transcation = android::SurfaceComposerClient::Transaction();
transcation.setLayer(mSurfaceControl, zorder);
transcation.setLayer(mSurfaceControlUi, zorder);
transcation.apply();
#else
AML_MP_UNUSED(zorder);
#endif
#endif
//coverity[uninit_use_in_call]
}
void NativeUI::controlSurface(int left, int top, int right, int bottom)
{
#ifdef ANDROID
#ifndef __ANDROID_VNDK__
auto transcation = android::SurfaceComposerClient::Transaction();
if (left >= 0 && top >= 0) {
transcation.setPosition(mSurfaceControl, left, top);
}
if (right > left && bottom > top) {
int width = right - left;
int height = bottom - top;
transcation.setSize(mSurfaceControl, width, height);
#if ANDROID_PLATFORM_SDK_VERSION >= 31
transcation.setCrop(mSurfaceControl, android::Rect(width, height));
#elif ANDROID_PLATFORM_SDK_VERSION >= 29
transcation.setCrop_legacy(mSurfaceControl, android::Rect(width, height));
#endif
}
transcation.apply();
#else
AML_MP_UNUSED(left);
AML_MP_UNUSED(top);
AML_MP_UNUSED(right);
AML_MP_UNUSED(bottom);
#endif
#endif
//coverity[uninit_use_in_call]
}
int NativeUI::getDefaultSurfaceWidth() const
{
return mSurfaceWidth;
}
int NativeUI::getDefaultSurfaceHeight() const
{
return mSurfaceHeight;
}
CommandProcessor::CommandProcessor(const std::string& prompt)
: mPrompt(prompt)
{
}
CommandProcessor::~CommandProcessor()
{
}
int CommandProcessor::setCommandVisitor(const std::function<Visitor>& visitor)
{
mCommandVisitor = visitor;
return 0;
}
int CommandProcessor::setInterrupter(const std::function<Interrupter>& interrupter)
{
mInterrupter = interrupter;
return 0;
}
int CommandProcessor::fetchAndProcessCommands()
{
bool prompt = false;
std::string lastCommand;
for (;;) {
if (mInterrupter()) {
break;
}
if (tcgetpgrp(0) != getpid()) {
usleep(10 * 1000);
continue;
}
if (prompt) {
prompt = false;
fprintf(stderr, "%s", mPrompt.c_str());
}
struct pollfd fds;
fds.fd = STDIN_FILENO;
fds.events = POLL_IN;
fds.revents = 0;
// change the wait time from 1s to 100ms to avoid
// the situation that the signal change is not detected in time
int ret = ::poll(&fds, 1, 100);
if (ret < 0) {
//printf("poll STDIN_FILENO failed! %d\n", -errno);
} else if (ret > 0) {
if (fds.revents & POLL_ERR) {
MLOGE("poll error!");
continue;
} else if (!(fds.revents & POLL_IN)) {
continue;
}
prompt = true;
char buffer[100]{0};
int len = ::read(STDIN_FILENO, buffer, sizeof(buffer));
if (len <= 0) {
MLOGE("read failed! %d", -errno);
continue;
}
buffer[len-1] = '\0';
//printf("read buf:%s, size:%d\n", buffer, len);
std::string buf(buffer);
size_t b = 0;
size_t e = buf.size();
while (b < e) {
if (isspace(buf[b])) ++b;
else if (isspace(buf[e])) --e;
else break;
}
if (b < e) {
buf = buf.substr(b, e - b);
lastCommand = buf;
} else if (b == e && !lastCommand.empty()) {
buf = lastCommand;
} else {
continue;
}
std::vector<std::string> args = split(buf);
mCommandVisitor(args);
}
}
return 0;
}
std::vector<std::string> CommandProcessor::split(const std::string& str)
{
std::vector<std::string> result;
std::string::size_type pos, prev = 0;
std::string s;
std::string cmdDelimiter = " ";
std::string argDelimiter = ", ";
// Handle empty string case
if (str.empty()) {
return result;
}
pos = str.find_first_of(cmdDelimiter);
if (pos == std::string::npos) {
// Safe emplace_back for entire string
if (!str.empty()) {
result.push_back(str);
}
return result;
}
// Safe emplace_back for first token
if (pos > 0 && pos <= str.size()) {
result.push_back(str.substr(0, pos));
}
prev = pos + 1;
while (prev < str.size() && (pos = str.find_first_of(argDelimiter, prev)) != std::string::npos) {
if (pos > prev) {
size_t b = prev;
size_t e = pos;
while (b < e) {
if (isspace(str[b]) || isDelimiter(argDelimiter, str[b])) ++b;
else if (isspace(str[e]) || isDelimiter(argDelimiter, str[e])) --e;
else break;
}
if (b <= e && b < str.size() && e < str.size()) {
// Safe emplace_back with bounds checking
result.push_back(str.substr(b, e - b + 1));
}
}
prev = pos + 1;
}
while (prev < str.size()) {
if (isspace(str[prev]) || isDelimiter(argDelimiter, str[prev]))
++prev;
else
break;
}
// Safe emplace_back for last token
if (prev < str.size()) {
result.push_back(str.substr(prev));
}
return result;
}
}