mirror of
https://github.com/openharmony/tools_previewer.git
synced 2026-08-27 08:41:15 -04:00
9a476a6440
Signed-off-by: libenyao <libenyao@h-partners.com>
290 lines
9.0 KiB
C++
290 lines
9.0 KiB
C++
/*
|
|
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
|
* 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.
|
|
*/
|
|
|
|
#include "VirtualScreenImpl.h"
|
|
|
|
#include "draw/draw_utils.h"
|
|
#include "hal_tick.h"
|
|
#include "image_decode_ability.h"
|
|
|
|
#define boolean jpegboolean
|
|
#include "jpeglib.h"
|
|
#undef boolean
|
|
#include "task_manager.h"
|
|
#include "CommandParser.h"
|
|
#include "ModelManager.h"
|
|
#include "PreviewerEngineLog.h"
|
|
#include "TraceTool.h"
|
|
|
|
using namespace std;
|
|
using namespace std::chrono;
|
|
|
|
void VirtualScreenImpl::InitAll(std::string pipeName, std::string pipePort)
|
|
{
|
|
OHOS::ImageDecodeAbility& ability = OHOS::ImageDecodeAbility::GetInstance();
|
|
ability.SetImageDecodeAbility(OHOS::IMG_SUPPORT_BITMAP | OHOS::IMG_SUPPORT_JPEG | OHOS::IMG_SUPPORT_PNG);
|
|
if (CommandParser::GetInstance().GetDeviceType() == "liteWearable") {
|
|
ability.SetImageDecodeAbility(OHOS::IMG_SUPPORT_BITMAP);
|
|
}
|
|
|
|
InitPipe(pipeName, pipePort);
|
|
if ((!CommandParser::GetInstance().IsResolutionValid(orignalResolutionWidth)) ||
|
|
(!CommandParser::GetInstance().IsResolutionValid(orignalResolutionHeight))) {
|
|
ELOG("VirtualScreen::InitAll invalid resolution, width : %d height : %d", orignalResolutionWidth,
|
|
orignalResolutionHeight);
|
|
return;
|
|
}
|
|
|
|
bufferSize = orignalResolutionWidth * orignalResolutionHeight * pixelSize + headSize;
|
|
wholeBuffer = new uint8_t[LWS_PRE + bufferSize];
|
|
regionWholeBuffer = new uint8_t[LWS_PRE + bufferSize];
|
|
screenBuffer = wholeBuffer + LWS_PRE;
|
|
regionBuffer = regionWholeBuffer + LWS_PRE;
|
|
osBuffer = new uint8_t[bufferSize];
|
|
if (screenBuffer == nullptr) {
|
|
ELOG("VirtualScreen::InitAll wholeBuffer memory allocation failed");
|
|
return;
|
|
}
|
|
InitBuffer();
|
|
}
|
|
|
|
bool VirtualScreenImpl::IsRectValid(int32_t x1, int32_t y1, int32_t x2, int32_t y2) const
|
|
{
|
|
if (x1 < 0 || y1 < 0) {
|
|
return false;
|
|
}
|
|
|
|
if (x2 >= orignalResolutionWidth || y2 >= orignalResolutionHeight) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void VirtualScreenImpl::WriteRefreshRegion()
|
|
{
|
|
currentPos = VERSION_POS;
|
|
WriteBuffer(protocolVersion);
|
|
WriteBuffer(regionX1);
|
|
WriteBuffer(regionY1);
|
|
regionWidth = static_cast<uint16_t>(orignalResolutionWidth);
|
|
WriteBuffer(regionWidth);
|
|
regionHeight = static_cast<uint16_t>(orignalResolutionHeight);
|
|
WriteBuffer(regionHeight);
|
|
}
|
|
|
|
void VirtualScreenImpl::UpdateRegion(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
|
|
{
|
|
regionX1 = x1;
|
|
regionY1 = y1;
|
|
regionX2 = (x2 < compressionResolutionWidth - extendPix)
|
|
? (x2 + extendPix) : (compressionResolutionWidth - 1);
|
|
regionY2 = (y2 < compressionResolutionHeight - extendPix)
|
|
? (y2 + extendPix) : (compressionResolutionHeight - 1);
|
|
regionWidth = regionX2 - regionX1 + 1;
|
|
regionHeight = regionY2 - regionY1 + 1;
|
|
}
|
|
|
|
void VirtualScreenImpl::InitBuffer()
|
|
{
|
|
currentPos = 0;
|
|
WriteBuffer(headStart);
|
|
WriteBuffer(orignalResolutionWidth);
|
|
WriteBuffer(orignalResolutionHeight);
|
|
WriteBuffer(compressionResolutionWidth);
|
|
WriteBuffer(compressionResolutionHeight);
|
|
}
|
|
|
|
void VirtualScreenImpl::ScheduleBufferSend()
|
|
{
|
|
if (!isChanged) {
|
|
return;
|
|
}
|
|
|
|
if (!isWebSocketConfiged) {
|
|
ELOG("image socket is not ready");
|
|
return;
|
|
}
|
|
isFrameUpdated = true;
|
|
if (CommandParser::GetInstance().IsRegionRefresh()) {
|
|
SendFullBuffer();
|
|
} else {
|
|
SendFullBuffer();
|
|
}
|
|
if (isFirstSend) {
|
|
ILOG("Send first buffer finish");
|
|
TraceTool::GetInstance().HandleTrace("Send first buffer finish");
|
|
isFirstSend = false;
|
|
}
|
|
|
|
{
|
|
std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex);
|
|
if (!WebSocketServer::GetInstance().firstImageBuffer) {
|
|
WebSocketServer::GetInstance().firstImageBuffer = new uint8_t[LWS_PRE + bufferSize];
|
|
WebSocketServer::GetInstance().firstImagebufferSize = headSize + jpgBufferSize;
|
|
}
|
|
std::copy(regionBuffer,
|
|
regionBuffer + headSize + jpgBufferSize,
|
|
WebSocketServer::GetInstance().firstImageBuffer + LWS_PRE);
|
|
}
|
|
|
|
sendFrameCountPerMinute++;
|
|
isChanged = false;
|
|
}
|
|
|
|
void VirtualScreenImpl::Send(unsigned char* data, int32_t width, int32_t height)
|
|
{
|
|
if (CommandParser::GetInstance().GetScreenMode() == CommandParser::ScreenMode::STATIC
|
|
&& VirtualScreen::isOutOfSeconds) {
|
|
return;
|
|
}
|
|
// if websocket is config, use websocet, else use localsocket
|
|
VirtualScreen::RgbToJpg(data + headSize, width, height);
|
|
std::copy(jpgScreenBuffer, jpgScreenBuffer + jpgBufferSize, regionBuffer + headSize);
|
|
WebSocketServer::GetInstance().WriteData(regionBuffer, headSize + jpgBufferSize);
|
|
FreeJpgMemory();
|
|
}
|
|
|
|
void VirtualScreenImpl::SendFullBuffer()
|
|
{
|
|
WriteRefreshRegion();
|
|
std::copy(screenBuffer, screenBuffer + headSize, regionBuffer);
|
|
Send(reinterpret_cast<unsigned char*>(screenBuffer),
|
|
compressionResolutionWidth,
|
|
compressionResolutionHeight);
|
|
}
|
|
|
|
void VirtualScreenImpl::SendRegionBuffer()
|
|
{
|
|
WriteRefreshRegion();
|
|
std::copy(screenBuffer, screenBuffer + headSize, regionBuffer);
|
|
for (int i = regionY1; i <= regionY2; ++i) {
|
|
uint8_t* startPos = screenBuffer + (i * compressionResolutionWidth + regionX1) * jpgPix + headSize;
|
|
std::copy(startPos,
|
|
startPos + regionWidth * jpgPix,
|
|
regionBuffer + ((i - regionY1) * regionWidth) * jpgPix + headSize);
|
|
}
|
|
Send(reinterpret_cast<unsigned char*>(regionBuffer), regionWidth, regionHeight);
|
|
}
|
|
|
|
void VirtualScreenImpl::FreeJpgMemory()
|
|
{
|
|
if (jpgScreenBuffer != nullptr) {
|
|
free(jpgScreenBuffer);
|
|
jpgScreenBuffer = NULL;
|
|
}
|
|
}
|
|
|
|
VirtualScreenImpl& VirtualScreenImpl::GetInstance()
|
|
{
|
|
static VirtualScreenImpl virtualScreen;
|
|
BaseGfxEngine::InitGfxEngine(&virtualScreen);
|
|
return virtualScreen;
|
|
}
|
|
|
|
void VirtualScreenImpl::CheckBufferSend()
|
|
{
|
|
VirtualScreenImpl::GetInstance().ScheduleBufferSend();
|
|
}
|
|
|
|
VirtualScreenImpl::VirtualScreenImpl()
|
|
: wholeBuffer(nullptr),
|
|
regionWholeBuffer(nullptr),
|
|
screenBuffer(nullptr),
|
|
regionBuffer(nullptr),
|
|
osBuffer(nullptr),
|
|
isChanged(false),
|
|
currentPos(0),
|
|
bufferSize(0),
|
|
isFirstRender(true),
|
|
isFirstSend(true),
|
|
regionX1(0),
|
|
regionY1(0),
|
|
regionX2(0),
|
|
regionY2(0),
|
|
regionWidth(0),
|
|
regionHeight(0),
|
|
bufferInfo(nullptr)
|
|
{
|
|
}
|
|
|
|
VirtualScreenImpl::~VirtualScreenImpl()
|
|
{
|
|
if (wholeBuffer != nullptr) {
|
|
delete [] wholeBuffer;
|
|
wholeBuffer = nullptr;
|
|
screenBuffer = nullptr;
|
|
}
|
|
FreeJpgMemory();
|
|
if (WebSocketServer::GetInstance().firstImageBuffer) {
|
|
delete [] WebSocketServer::GetInstance().firstImageBuffer;
|
|
WebSocketServer::GetInstance().firstImageBuffer = nullptr;
|
|
}
|
|
}
|
|
|
|
void VirtualScreenImpl::Flush(const OHOS::Rect& flushRect)
|
|
{
|
|
if (isFirstRender) {
|
|
ILOG("Get first render buffer");
|
|
TraceTool::GetInstance().HandleTrace("Get first render buffer");
|
|
isFirstRender = false;
|
|
}
|
|
|
|
bool staticRet = VirtualScreen::JudgeStaticImage(SEND_IMG_DURATION_MS);
|
|
if (!staticRet) {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i <= compressionResolutionHeight - 1; ++i) {
|
|
for (int j = 0; j <= compressionResolutionWidth - 1; ++j) {
|
|
uint8_t* curPixel = screenBuffer + (i * compressionResolutionWidth + j) * jpgPix + headSize;
|
|
uint8_t* osPixel = osBuffer + (i * compressionResolutionWidth + j) * pixelSize + headSize;
|
|
*(curPixel + redPos) = *(osPixel + bluePos);
|
|
*(curPixel + greenPos) = *(osPixel + greenPos);
|
|
*(curPixel + bluePos) = *(osPixel + redPos);
|
|
}
|
|
}
|
|
|
|
validFrameCountPerMinute++;
|
|
isChanged = true;
|
|
ScheduleBufferSend();
|
|
}
|
|
|
|
OHOS::BufferInfo* VirtualScreenImpl::GetFBBufferInfo()
|
|
{
|
|
if (bufferInfo == nullptr) {
|
|
bufferInfo = new OHOS::BufferInfo;
|
|
bufferInfo->rect = {0, 0, compressionResolutionWidth - 1, compressionResolutionHeight - 1};
|
|
bufferInfo->mode = OHOS::ARGB8888;
|
|
bufferInfo->color = 0x44;
|
|
bufferInfo->phyAddr = bufferInfo->virAddr = osBuffer + headSize;
|
|
// 3: Shift right 3 bits
|
|
bufferInfo->stride = orignalResolutionWidth * (OHOS::DrawUtils::GetPxSizeByColorMode(bufferInfo->mode) >> 3);
|
|
bufferInfo->width = orignalResolutionWidth;
|
|
bufferInfo->height = orignalResolutionHeight;
|
|
}
|
|
|
|
return bufferInfo;
|
|
}
|
|
|
|
uint16_t VirtualScreenImpl::GetScreenWidth()
|
|
{
|
|
return orignalResolutionWidth;
|
|
}
|
|
|
|
uint16_t VirtualScreenImpl::GetScreenHeight()
|
|
{
|
|
return orignalResolutionHeight;
|
|
}
|