17c804472Sopenharmony_ci/* 27c804472Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 37c804472Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 47c804472Sopenharmony_ci * you may not use this file except in compliance with the License. 57c804472Sopenharmony_ci * You may obtain a copy of the License at 67c804472Sopenharmony_ci * 77c804472Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 87c804472Sopenharmony_ci * 97c804472Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 107c804472Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 117c804472Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 127c804472Sopenharmony_ci * See the License for the specific language governing permissions and 137c804472Sopenharmony_ci * limitations under the License. 147c804472Sopenharmony_ci */ 157c804472Sopenharmony_ci 167c804472Sopenharmony_ci#include "VirtualScreenImpl.h" 177c804472Sopenharmony_ci 187c804472Sopenharmony_ci#include "draw/draw_utils.h" 197c804472Sopenharmony_ci#include "hal_tick.h" 207c804472Sopenharmony_ci#include "image_decode_ability.h" 217c804472Sopenharmony_ci 227c804472Sopenharmony_ci#define boolean jpegboolean 237c804472Sopenharmony_ci#include "jpeglib.h" 247c804472Sopenharmony_ci#undef boolean 257c804472Sopenharmony_ci#include "task_manager.h" 267c804472Sopenharmony_ci#include "CommandParser.h" 277c804472Sopenharmony_ci#include "ModelManager.h" 287c804472Sopenharmony_ci#include "PreviewerEngineLog.h" 297c804472Sopenharmony_ci#include "TraceTool.h" 307c804472Sopenharmony_ci 317c804472Sopenharmony_civoid VirtualScreenImpl::InitAll(std::string pipeName, std::string pipePort) 327c804472Sopenharmony_ci{ 337c804472Sopenharmony_ci OHOS::ImageDecodeAbility& ability = OHOS::ImageDecodeAbility::GetInstance(); 347c804472Sopenharmony_ci ability.SetImageDecodeAbility(OHOS::IMG_SUPPORT_BITMAP | OHOS::IMG_SUPPORT_JPEG | OHOS::IMG_SUPPORT_PNG); 357c804472Sopenharmony_ci if (CommandParser::GetInstance().GetDeviceType() == "liteWearable") { 367c804472Sopenharmony_ci ability.SetImageDecodeAbility(OHOS::IMG_SUPPORT_BITMAP); 377c804472Sopenharmony_ci } 387c804472Sopenharmony_ci 397c804472Sopenharmony_ci InitPipe(pipeName, pipePort); 407c804472Sopenharmony_ci if ((!CommandParser::GetInstance().IsResolutionValid(orignalResolutionWidth)) || 417c804472Sopenharmony_ci (!CommandParser::GetInstance().IsResolutionValid(orignalResolutionHeight))) { 427c804472Sopenharmony_ci ELOG("VirtualScreen::InitAll invalid resolution, width : %d height : %d", orignalResolutionWidth, 437c804472Sopenharmony_ci orignalResolutionHeight); 447c804472Sopenharmony_ci return; 457c804472Sopenharmony_ci } 467c804472Sopenharmony_ci 477c804472Sopenharmony_ci bufferSize = orignalResolutionWidth * orignalResolutionHeight * pixelSize + headSize; 487c804472Sopenharmony_ci wholeBuffer = new(std::nothrow) uint8_t[LWS_PRE + bufferSize]; 497c804472Sopenharmony_ci if (!wholeBuffer) { 507c804472Sopenharmony_ci ELOG("Memory allocation failed : wholeBuffer."); 517c804472Sopenharmony_ci return; 527c804472Sopenharmony_ci } 537c804472Sopenharmony_ci regionWholeBuffer = new(std::nothrow) uint8_t[LWS_PRE + bufferSize]; 547c804472Sopenharmony_ci if (!regionWholeBuffer) { 557c804472Sopenharmony_ci ELOG("Memory allocation failed: regionWholeBuffer."); 567c804472Sopenharmony_ci return; 577c804472Sopenharmony_ci } 587c804472Sopenharmony_ci screenBuffer = wholeBuffer + LWS_PRE; 597c804472Sopenharmony_ci regionBuffer = regionWholeBuffer + LWS_PRE; 607c804472Sopenharmony_ci osBuffer = new(std::nothrow) uint8_t[bufferSize]; 617c804472Sopenharmony_ci if (!osBuffer) { 627c804472Sopenharmony_ci ELOG("Memory allocation failed: osBuffer."); 637c804472Sopenharmony_ci return; 647c804472Sopenharmony_ci } 657c804472Sopenharmony_ci if (screenBuffer == nullptr) { 667c804472Sopenharmony_ci ELOG("VirtualScreen::InitAll wholeBuffer memory allocation failed"); 677c804472Sopenharmony_ci return; 687c804472Sopenharmony_ci } 697c804472Sopenharmony_ci InitBuffer(); 707c804472Sopenharmony_ci} 717c804472Sopenharmony_ci 727c804472Sopenharmony_cibool VirtualScreenImpl::IsRectValid(int32_t x1, int32_t y1, int32_t x2, int32_t y2) const 737c804472Sopenharmony_ci{ 747c804472Sopenharmony_ci if (x1 < 0 || y1 < 0) { 757c804472Sopenharmony_ci return false; 767c804472Sopenharmony_ci } 777c804472Sopenharmony_ci 787c804472Sopenharmony_ci if (x2 >= orignalResolutionWidth || y2 >= orignalResolutionHeight) { 797c804472Sopenharmony_ci return false; 807c804472Sopenharmony_ci } 817c804472Sopenharmony_ci return true; 827c804472Sopenharmony_ci} 837c804472Sopenharmony_ci 847c804472Sopenharmony_civoid VirtualScreenImpl::WriteRefreshRegion() 857c804472Sopenharmony_ci{ 867c804472Sopenharmony_ci currentPos = VERSION_POS; 877c804472Sopenharmony_ci WriteBuffer(protocolVersion); 887c804472Sopenharmony_ci WriteBuffer(regionX1); 897c804472Sopenharmony_ci WriteBuffer(regionY1); 907c804472Sopenharmony_ci regionWidth = static_cast<uint16_t>(orignalResolutionWidth); 917c804472Sopenharmony_ci WriteBuffer(regionWidth); 927c804472Sopenharmony_ci regionHeight = static_cast<uint16_t>(orignalResolutionHeight); 937c804472Sopenharmony_ci WriteBuffer(regionHeight); 947c804472Sopenharmony_ci} 957c804472Sopenharmony_ci 967c804472Sopenharmony_civoid VirtualScreenImpl::UpdateRegion(int32_t x1, int32_t y1, int32_t x2, int32_t y2) 977c804472Sopenharmony_ci{ 987c804472Sopenharmony_ci regionX1 = x1; 997c804472Sopenharmony_ci regionY1 = y1; 1007c804472Sopenharmony_ci regionX2 = (x2 < compressionResolutionWidth - extendPix) 1017c804472Sopenharmony_ci ? (x2 + extendPix) : (compressionResolutionWidth - 1); 1027c804472Sopenharmony_ci regionY2 = (y2 < compressionResolutionHeight - extendPix) 1037c804472Sopenharmony_ci ? (y2 + extendPix) : (compressionResolutionHeight - 1); 1047c804472Sopenharmony_ci regionWidth = regionX2 - regionX1 + 1; 1057c804472Sopenharmony_ci regionHeight = regionY2 - regionY1 + 1; 1067c804472Sopenharmony_ci} 1077c804472Sopenharmony_ci 1087c804472Sopenharmony_civoid VirtualScreenImpl::InitBuffer() 1097c804472Sopenharmony_ci{ 1107c804472Sopenharmony_ci currentPos = 0; 1117c804472Sopenharmony_ci WriteBuffer(headStart); 1127c804472Sopenharmony_ci WriteBuffer(orignalResolutionWidth); 1137c804472Sopenharmony_ci WriteBuffer(orignalResolutionHeight); 1147c804472Sopenharmony_ci WriteBuffer(compressionResolutionWidth); 1157c804472Sopenharmony_ci WriteBuffer(compressionResolutionHeight); 1167c804472Sopenharmony_ci} 1177c804472Sopenharmony_ci 1187c804472Sopenharmony_civoid VirtualScreenImpl::ScheduleBufferSend() 1197c804472Sopenharmony_ci{ 1207c804472Sopenharmony_ci if (!isChanged) { 1217c804472Sopenharmony_ci return; 1227c804472Sopenharmony_ci } 1237c804472Sopenharmony_ci 1247c804472Sopenharmony_ci if (!isWebSocketConfiged) { 1257c804472Sopenharmony_ci ELOG("image socket is not ready"); 1267c804472Sopenharmony_ci return; 1277c804472Sopenharmony_ci } 1287c804472Sopenharmony_ci isFrameUpdated = true; 1297c804472Sopenharmony_ci if (CommandParser::GetInstance().IsRegionRefresh()) { 1307c804472Sopenharmony_ci SendFullBuffer(); 1317c804472Sopenharmony_ci } else { 1327c804472Sopenharmony_ci SendFullBuffer(); 1337c804472Sopenharmony_ci } 1347c804472Sopenharmony_ci if (isFirstSend) { 1357c804472Sopenharmony_ci ILOG("Send first buffer finish"); 1367c804472Sopenharmony_ci TraceTool::GetInstance().HandleTrace("Send first buffer finish"); 1377c804472Sopenharmony_ci isFirstSend = false; 1387c804472Sopenharmony_ci } 1397c804472Sopenharmony_ci 1407c804472Sopenharmony_ci { 1417c804472Sopenharmony_ci std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex); 1427c804472Sopenharmony_ci if (!WebSocketServer::GetInstance().firstImageBuffer) { 1437c804472Sopenharmony_ci WebSocketServer::GetInstance().firstImageBuffer = new(std::nothrow) uint8_t[LWS_PRE + bufferSize]; 1447c804472Sopenharmony_ci if (!WebSocketServer::GetInstance().firstImageBuffer) { 1457c804472Sopenharmony_ci ELOG("Memory allocation failed: firstImageBuffer."); 1467c804472Sopenharmony_ci return; 1477c804472Sopenharmony_ci } 1487c804472Sopenharmony_ci WebSocketServer::GetInstance().firstImagebufferSize = headSize + jpgBufferSize; 1497c804472Sopenharmony_ci } 1507c804472Sopenharmony_ci std::copy(regionBuffer, 1517c804472Sopenharmony_ci regionBuffer + headSize + jpgBufferSize, 1527c804472Sopenharmony_ci WebSocketServer::GetInstance().firstImageBuffer + LWS_PRE); 1537c804472Sopenharmony_ci } 1547c804472Sopenharmony_ci 1557c804472Sopenharmony_ci sendFrameCountPerMinute++; 1567c804472Sopenharmony_ci isChanged = false; 1577c804472Sopenharmony_ci} 1587c804472Sopenharmony_ci 1597c804472Sopenharmony_civoid VirtualScreenImpl::Send(unsigned char* data, int32_t width, int32_t height) 1607c804472Sopenharmony_ci{ 1617c804472Sopenharmony_ci if (CommandParser::GetInstance().GetScreenMode() == CommandParser::ScreenMode::STATIC 1627c804472Sopenharmony_ci && VirtualScreen::isOutOfSeconds) { 1637c804472Sopenharmony_ci return; 1647c804472Sopenharmony_ci } 1657c804472Sopenharmony_ci // if websocket is config, use websocet, else use localsocket 1667c804472Sopenharmony_ci VirtualScreen::RgbToJpg(data + headSize, width, height); 1677c804472Sopenharmony_ci std::copy(jpgScreenBuffer, jpgScreenBuffer + jpgBufferSize, regionBuffer + headSize); 1687c804472Sopenharmony_ci WebSocketServer::GetInstance().WriteData(regionBuffer, headSize + jpgBufferSize); 1697c804472Sopenharmony_ci FreeJpgMemory(); 1707c804472Sopenharmony_ci} 1717c804472Sopenharmony_ci 1727c804472Sopenharmony_civoid VirtualScreenImpl::SendFullBuffer() 1737c804472Sopenharmony_ci{ 1747c804472Sopenharmony_ci WriteRefreshRegion(); 1757c804472Sopenharmony_ci std::copy(screenBuffer, screenBuffer + headSize, regionBuffer); 1767c804472Sopenharmony_ci Send(reinterpret_cast<unsigned char*>(screenBuffer), 1777c804472Sopenharmony_ci compressionResolutionWidth, 1787c804472Sopenharmony_ci compressionResolutionHeight); 1797c804472Sopenharmony_ci} 1807c804472Sopenharmony_ci 1817c804472Sopenharmony_civoid VirtualScreenImpl::SendRegionBuffer() 1827c804472Sopenharmony_ci{ 1837c804472Sopenharmony_ci WriteRefreshRegion(); 1847c804472Sopenharmony_ci std::copy(screenBuffer, screenBuffer + headSize, regionBuffer); 1857c804472Sopenharmony_ci for (int i = regionY1; i <= regionY2; ++i) { 1867c804472Sopenharmony_ci uint8_t* startPos = screenBuffer + (i * compressionResolutionWidth + regionX1) * jpgPix + headSize; 1877c804472Sopenharmony_ci std::copy(startPos, 1887c804472Sopenharmony_ci startPos + regionWidth * jpgPix, 1897c804472Sopenharmony_ci regionBuffer + ((i - regionY1) * regionWidth) * jpgPix + headSize); 1907c804472Sopenharmony_ci } 1917c804472Sopenharmony_ci Send(reinterpret_cast<unsigned char*>(regionBuffer), regionWidth, regionHeight); 1927c804472Sopenharmony_ci} 1937c804472Sopenharmony_ci 1947c804472Sopenharmony_civoid VirtualScreenImpl::FreeJpgMemory() 1957c804472Sopenharmony_ci{ 1967c804472Sopenharmony_ci if (jpgScreenBuffer != nullptr) { 1977c804472Sopenharmony_ci free(jpgScreenBuffer); 1987c804472Sopenharmony_ci jpgScreenBuffer = NULL; 1997c804472Sopenharmony_ci } 2007c804472Sopenharmony_ci} 2017c804472Sopenharmony_ci 2027c804472Sopenharmony_ciVirtualScreenImpl& VirtualScreenImpl::GetInstance() 2037c804472Sopenharmony_ci{ 2047c804472Sopenharmony_ci static VirtualScreenImpl virtualScreen; 2057c804472Sopenharmony_ci BaseGfxEngine::InitGfxEngine(&virtualScreen); 2067c804472Sopenharmony_ci return virtualScreen; 2077c804472Sopenharmony_ci} 2087c804472Sopenharmony_ci 2097c804472Sopenharmony_civoid VirtualScreenImpl::CheckBufferSend() 2107c804472Sopenharmony_ci{ 2117c804472Sopenharmony_ci VirtualScreenImpl::GetInstance().ScheduleBufferSend(); 2127c804472Sopenharmony_ci} 2137c804472Sopenharmony_ci 2147c804472Sopenharmony_ciVirtualScreenImpl::VirtualScreenImpl() 2157c804472Sopenharmony_ci : wholeBuffer(nullptr), 2167c804472Sopenharmony_ci regionWholeBuffer(nullptr), 2177c804472Sopenharmony_ci screenBuffer(nullptr), 2187c804472Sopenharmony_ci regionBuffer(nullptr), 2197c804472Sopenharmony_ci osBuffer(nullptr), 2207c804472Sopenharmony_ci isChanged(false), 2217c804472Sopenharmony_ci currentPos(0), 2227c804472Sopenharmony_ci bufferSize(0), 2237c804472Sopenharmony_ci isFirstRender(true), 2247c804472Sopenharmony_ci isFirstSend(true), 2257c804472Sopenharmony_ci regionX1(0), 2267c804472Sopenharmony_ci regionY1(0), 2277c804472Sopenharmony_ci regionX2(0), 2287c804472Sopenharmony_ci regionY2(0), 2297c804472Sopenharmony_ci regionWidth(0), 2307c804472Sopenharmony_ci regionHeight(0), 2317c804472Sopenharmony_ci bufferInfo(nullptr) 2327c804472Sopenharmony_ci{ 2337c804472Sopenharmony_ci} 2347c804472Sopenharmony_ci 2357c804472Sopenharmony_ciVirtualScreenImpl::~VirtualScreenImpl() 2367c804472Sopenharmony_ci{ 2377c804472Sopenharmony_ci if (wholeBuffer != nullptr) { 2387c804472Sopenharmony_ci delete [] wholeBuffer; 2397c804472Sopenharmony_ci wholeBuffer = nullptr; 2407c804472Sopenharmony_ci screenBuffer = nullptr; 2417c804472Sopenharmony_ci } 2427c804472Sopenharmony_ci FreeJpgMemory(); 2437c804472Sopenharmony_ci if (WebSocketServer::GetInstance().firstImageBuffer) { 2447c804472Sopenharmony_ci delete [] WebSocketServer::GetInstance().firstImageBuffer; 2457c804472Sopenharmony_ci WebSocketServer::GetInstance().firstImageBuffer = nullptr; 2467c804472Sopenharmony_ci } 2477c804472Sopenharmony_ci} 2487c804472Sopenharmony_ci 2497c804472Sopenharmony_civoid VirtualScreenImpl::Flush(const OHOS::Rect& flushRect) 2507c804472Sopenharmony_ci{ 2517c804472Sopenharmony_ci if (isFirstRender) { 2527c804472Sopenharmony_ci ILOG("Get first render buffer"); 2537c804472Sopenharmony_ci TraceTool::GetInstance().HandleTrace("Get first render buffer"); 2547c804472Sopenharmony_ci isFirstRender = false; 2557c804472Sopenharmony_ci } 2567c804472Sopenharmony_ci 2577c804472Sopenharmony_ci bool staticRet = VirtualScreen::JudgeStaticImage(SEND_IMG_DURATION_MS); 2587c804472Sopenharmony_ci if (!staticRet) { 2597c804472Sopenharmony_ci return; 2607c804472Sopenharmony_ci } 2617c804472Sopenharmony_ci 2627c804472Sopenharmony_ci for (int i = 0; i <= compressionResolutionHeight - 1; ++i) { 2637c804472Sopenharmony_ci for (int j = 0; j <= compressionResolutionWidth - 1; ++j) { 2647c804472Sopenharmony_ci uint8_t* curPixel = screenBuffer + (i * compressionResolutionWidth + j) * jpgPix + headSize; 2657c804472Sopenharmony_ci uint8_t* osPixel = osBuffer + (i * compressionResolutionWidth + j) * pixelSize + headSize; 2667c804472Sopenharmony_ci *(curPixel + redPos) = *(osPixel + bluePos); 2677c804472Sopenharmony_ci *(curPixel + greenPos) = *(osPixel + greenPos); 2687c804472Sopenharmony_ci *(curPixel + bluePos) = *(osPixel + redPos); 2697c804472Sopenharmony_ci } 2707c804472Sopenharmony_ci } 2717c804472Sopenharmony_ci 2727c804472Sopenharmony_ci validFrameCountPerMinute++; 2737c804472Sopenharmony_ci isChanged = true; 2747c804472Sopenharmony_ci ScheduleBufferSend(); 2757c804472Sopenharmony_ci} 2767c804472Sopenharmony_ci 2777c804472Sopenharmony_ciOHOS::BufferInfo* VirtualScreenImpl::GetFBBufferInfo() 2787c804472Sopenharmony_ci{ 2797c804472Sopenharmony_ci if (bufferInfo == nullptr) { 2807c804472Sopenharmony_ci bufferInfo = new(std::nothrow) OHOS::BufferInfo; 2817c804472Sopenharmony_ci if (!bufferInfo) { 2827c804472Sopenharmony_ci ELOG("Memory allocation failed: osBuffer."); 2837c804472Sopenharmony_ci return bufferInfo; 2847c804472Sopenharmony_ci } 2857c804472Sopenharmony_ci bufferInfo->rect = {0, 0, compressionResolutionWidth - 1, compressionResolutionHeight - 1}; 2867c804472Sopenharmony_ci bufferInfo->mode = OHOS::ARGB8888; 2877c804472Sopenharmony_ci 2887c804472Sopenharmony_ci bufferInfo->color = 0x44; 2897c804472Sopenharmony_ci bufferInfo->phyAddr = bufferInfo->virAddr = osBuffer + headSize; 2907c804472Sopenharmony_ci // 3: Shift right 3 bits 2917c804472Sopenharmony_ci bufferInfo->stride = orignalResolutionWidth * (OHOS::DrawUtils::GetPxSizeByColorMode(bufferInfo->mode) >> 3); 2927c804472Sopenharmony_ci bufferInfo->width = orignalResolutionWidth; 2937c804472Sopenharmony_ci bufferInfo->height = orignalResolutionHeight; 2947c804472Sopenharmony_ci } 2957c804472Sopenharmony_ci 2967c804472Sopenharmony_ci return bufferInfo; 2977c804472Sopenharmony_ci} 2987c804472Sopenharmony_ci 2997c804472Sopenharmony_ciuint16_t VirtualScreenImpl::GetScreenWidth() 3007c804472Sopenharmony_ci{ 3017c804472Sopenharmony_ci return orignalResolutionWidth; 3027c804472Sopenharmony_ci} 3037c804472Sopenharmony_ci 3047c804472Sopenharmony_ciuint16_t VirtualScreenImpl::GetScreenHeight() 3057c804472Sopenharmony_ci{ 3067c804472Sopenharmony_ci return orignalResolutionHeight; 3077c804472Sopenharmony_ci} 308