/* * 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 #include #include "TestUtils.h" #include #include #include #include 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 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(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 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 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) { mCommandVisitor = visitor; return 0; } int CommandProcessor::setInterrupter(const std::function& 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 args = split(buf); mCommandVisitor(args); } } return 0; } std::vector CommandProcessor::split(const std::string& str) { std::vector 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; } }