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 <cinttypes>
197c804472Sopenharmony_ci#define boolean jpegboolean
207c804472Sopenharmony_ci#include "jpeglib.h"
217c804472Sopenharmony_ci#undef boolean
227c804472Sopenharmony_ci
237c804472Sopenharmony_ci#include "CommandLineInterface.h"
247c804472Sopenharmony_ci#include "CommandParser.h"
257c804472Sopenharmony_ci#include "PreviewerEngineLog.h"
267c804472Sopenharmony_ci#include "TraceTool.h"
277c804472Sopenharmony_ci#include <sstream>
287c804472Sopenharmony_ci
297c804472Sopenharmony_ciVirtualScreenImpl& VirtualScreenImpl::GetInstance()
307c804472Sopenharmony_ci{
317c804472Sopenharmony_ci    static VirtualScreenImpl virtualScreen;
327c804472Sopenharmony_ci    return virtualScreen;
337c804472Sopenharmony_ci}
347c804472Sopenharmony_ci
357c804472Sopenharmony_civoid VirtualScreenImpl::SendBufferOnTimer()
367c804472Sopenharmony_ci{
377c804472Sopenharmony_ci    GetInstance().SetLoadDocFlag(VirtualScreen::LoadDocType::NORMAL);
387c804472Sopenharmony_ci    if (GetInstance().loadDocTempBuffer == nullptr) {
397c804472Sopenharmony_ci        PrintLoadDocFinishedLog("onRender timeout,no buffer to send");
407c804472Sopenharmony_ci        return;
417c804472Sopenharmony_ci    }
427c804472Sopenharmony_ci    VirtualScreen::isStartCount = true;
437c804472Sopenharmony_ci    {
447c804472Sopenharmony_ci        std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex);
457c804472Sopenharmony_ci        if (GetInstance().loadDocCopyBuffer != nullptr) {
467c804472Sopenharmony_ci            delete [] GetInstance().loadDocCopyBuffer;
477c804472Sopenharmony_ci            GetInstance().loadDocCopyBuffer = nullptr;
487c804472Sopenharmony_ci        }
497c804472Sopenharmony_ci        GetInstance().loadDocCopyBuffer = new(std::nothrow) uint8_t[GetInstance().lengthTemp];
507c804472Sopenharmony_ci        if (!GetInstance().loadDocCopyBuffer) {
517c804472Sopenharmony_ci            ELOG("Memory allocation failed : loadDocCopyBuffer.");
527c804472Sopenharmony_ci            return;
537c804472Sopenharmony_ci        }
547c804472Sopenharmony_ci        std::copy(GetInstance().loadDocTempBuffer,
557c804472Sopenharmony_ci            GetInstance().loadDocTempBuffer + GetInstance().lengthTemp,
567c804472Sopenharmony_ci            GetInstance().loadDocCopyBuffer);
577c804472Sopenharmony_ci    }
587c804472Sopenharmony_ci    VirtualScreenImpl::GetInstance().protocolVersion =
597c804472Sopenharmony_ci        static_cast<uint16_t>(VirtualScreen::ProtocolVersion::LOADDOC);
607c804472Sopenharmony_ci    GetInstance().bufferSize = GetInstance().lengthTemp + GetInstance().headSize;
617c804472Sopenharmony_ci    GetInstance().wholeBuffer = new(std::nothrow) uint8_t[LWS_PRE + GetInstance().bufferSize];
627c804472Sopenharmony_ci    if (!GetInstance().wholeBuffer) {
637c804472Sopenharmony_ci        ELOG("Memory allocation failed : wholeBuffer.");
647c804472Sopenharmony_ci        return;
657c804472Sopenharmony_ci    }
667c804472Sopenharmony_ci    GetInstance().screenBuffer = GetInstance().wholeBuffer + LWS_PRE;
677c804472Sopenharmony_ci    GetInstance().SendPixmap(GetInstance().loadDocCopyBuffer, GetInstance().lengthTemp,
687c804472Sopenharmony_ci        GetInstance().widthTemp, GetInstance().heightTemp);
697c804472Sopenharmony_ci}
707c804472Sopenharmony_ci
717c804472Sopenharmony_civoid VirtualScreenImpl::PrintLoadDocFinishedLog(const std::string& logStr)
727c804472Sopenharmony_ci{
737c804472Sopenharmony_ci    ILOG("loadDoc: LoadDocFlag2:finished %s, onRenderTime:%" PRIu64 ", flushEmptyTime:%" PRIu64 ", \
747c804472Sopenharmony_ci        onRenderTimeStamp:%" PRIu64 " flushEmptyTimeStamp:%" PRIu64 "", logStr.c_str(),
757c804472Sopenharmony_ci        GetInstance().onRenderTime, GetInstance().flushEmptyTime,
767c804472Sopenharmony_ci        GetInstance().timeStampTemp, GetInstance().flushEmptyTimeStamp);
777c804472Sopenharmony_ci}
787c804472Sopenharmony_ci
797c804472Sopenharmony_cibool VirtualScreenImpl::FlushEmptyFunc(std::chrono::system_clock::time_point endTime, int64_t timePassed)
807c804472Sopenharmony_ci{
817c804472Sopenharmony_ci    if (GetInstance().onRenderTime > GetInstance().flushEmptyTime) {
827c804472Sopenharmony_ci        if (GetInstance().timeStampTemp < GetInstance().flushEmptyTimeStamp) {
837c804472Sopenharmony_ci            SendBufferOnTimer(); // 有收到结束标记,且flushEmpty后有继续出图
847c804472Sopenharmony_ci            PrintLoadDocFinishedLog("flushEmpty normal, onRender normal");
857c804472Sopenharmony_ci            return true;
867c804472Sopenharmony_ci        }
877c804472Sopenharmony_ci    } else {
887c804472Sopenharmony_ci        // flushEmpty后没有继续出图,计时100ms,如果仍没有onRender,发送上一次的的onRender buffer
897c804472Sopenharmony_ci        int64_t timePassed2 = std::chrono::duration_cast<std::chrono::milliseconds>(endTime -
907c804472Sopenharmony_ci            GetInstance().flushEmptyTime).count();
917c804472Sopenharmony_ci        if (timePassed2 > TIMEOUT_ONRENDER_DURATION_MS) {
927c804472Sopenharmony_ci            if (GetInstance().timeStampTemp < GetInstance().flushEmptyTimeStamp) {
937c804472Sopenharmony_ci                SendBufferOnTimer();
947c804472Sopenharmony_ci                PrintLoadDocFinishedLog("flushEmpty normal, onRender timeout");
957c804472Sopenharmony_ci                return true;
967c804472Sopenharmony_ci            }
977c804472Sopenharmony_ci        }
987c804472Sopenharmony_ci    }
997c804472Sopenharmony_ci    if (timePassed >= TIMEOUT_NINE_S) { // 有结束点,无出图
1007c804472Sopenharmony_ci        PrintLoadDocFinishedLog("flushEmpty normal, onRender timeout");
1017c804472Sopenharmony_ci        return true; // 有收到结束标记,且超过最大时限还没有出图则结束
1027c804472Sopenharmony_ci    }
1037c804472Sopenharmony_ci    return false;
1047c804472Sopenharmony_ci}
1057c804472Sopenharmony_ci
1067c804472Sopenharmony_cibool VirtualScreenImpl::NoFlushEmptyFunc(int64_t timePassed)
1077c804472Sopenharmony_ci{
1087c804472Sopenharmony_ci    if (timePassed >= SEND_IMG_DURATION_MS &&
1097c804472Sopenharmony_ci        GetInstance().onRenderTime != std::chrono::system_clock::time_point::min()) {
1107c804472Sopenharmony_ci        SendBufferOnTimer(); // 没有收到结束标记,300ms内有出图选取最后一张图
1117c804472Sopenharmony_ci        PrintLoadDocFinishedLog("async load, flushEmpty timeout, onRender normal");
1127c804472Sopenharmony_ci        return true;
1137c804472Sopenharmony_ci    }
1147c804472Sopenharmony_ci    if (timePassed >= TIMEOUT_NINE_S) {
1157c804472Sopenharmony_ci        SendBufferOnTimer();
1167c804472Sopenharmony_ci        PrintLoadDocFinishedLog("flushEmpty timeout, onRender unknown");
1177c804472Sopenharmony_ci        return true; // 没有收到结束标记,且超过最大时限还没有出图则结束
1187c804472Sopenharmony_ci    }
1197c804472Sopenharmony_ci    return false;
1207c804472Sopenharmony_ci}
1217c804472Sopenharmony_ci
1227c804472Sopenharmony_ci
1237c804472Sopenharmony_civoid VirtualScreenImpl::StartTimer()
1247c804472Sopenharmony_ci{
1257c804472Sopenharmony_ci    while (true) {
1267c804472Sopenharmony_ci        auto endTime = std::chrono::system_clock::now();
1277c804472Sopenharmony_ci        int64_t timePassed = std::chrono::duration_cast<std::chrono::milliseconds>(endTime -
1287c804472Sopenharmony_ci                                VirtualScreenImpl::GetInstance().startTime).count();
1297c804472Sopenharmony_ci        bool ret = false;
1307c804472Sopenharmony_ci        if (GetInstance().isFlushEmpty) {
1317c804472Sopenharmony_ci            ret = FlushEmptyFunc(endTime, timePassed);
1327c804472Sopenharmony_ci        } else {
1337c804472Sopenharmony_ci            ret = NoFlushEmptyFunc(timePassed);
1347c804472Sopenharmony_ci        }
1357c804472Sopenharmony_ci        if (ret) {
1367c804472Sopenharmony_ci            return;
1377c804472Sopenharmony_ci        }
1387c804472Sopenharmony_ci    }
1397c804472Sopenharmony_ci}
1407c804472Sopenharmony_ci
1417c804472Sopenharmony_cibool VirtualScreenImpl::LoadDocCallback(const void* data, const size_t length, const int32_t width,
1427c804472Sopenharmony_ci                                        const int32_t height, const uint64_t timeStamp)
1437c804472Sopenharmony_ci{
1447c804472Sopenharmony_ci    if (timeStamp < GetInstance().loadDocTimeStamp) {
1457c804472Sopenharmony_ci        return false;
1467c804472Sopenharmony_ci    }
1477c804472Sopenharmony_ci    if (GetInstance().GetLoadDocFlag() == VirtualScreen::LoadDocType::FINISHED) {
1487c804472Sopenharmony_ci        {
1497c804472Sopenharmony_ci            std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex);
1507c804472Sopenharmony_ci            if (GetInstance().loadDocTempBuffer != nullptr) {
1517c804472Sopenharmony_ci                delete [] GetInstance().loadDocTempBuffer;
1527c804472Sopenharmony_ci                GetInstance().loadDocTempBuffer = nullptr;
1537c804472Sopenharmony_ci            }
1547c804472Sopenharmony_ci            GetInstance().lengthTemp = length;
1557c804472Sopenharmony_ci            GetInstance().widthTemp = width;
1567c804472Sopenharmony_ci            GetInstance().heightTemp = height;
1577c804472Sopenharmony_ci            GetInstance().timeStampTemp = timeStamp;
1587c804472Sopenharmony_ci            if (length <= 0) {
1597c804472Sopenharmony_ci                return false;
1607c804472Sopenharmony_ci            }
1617c804472Sopenharmony_ci            GetInstance().loadDocTempBuffer = new(std::nothrow) uint8_t[length];
1627c804472Sopenharmony_ci            if (!GetInstance().loadDocTempBuffer) {
1637c804472Sopenharmony_ci                ELOG("Memory allocation failed : loadDocTempBuffer.");
1647c804472Sopenharmony_ci                return false;
1657c804472Sopenharmony_ci            }
1667c804472Sopenharmony_ci            uint8_t*  dataPtr = reinterpret_cast<uint8_t*>(const_cast<void*>(data));
1677c804472Sopenharmony_ci            std::copy(dataPtr, dataPtr + length, GetInstance().loadDocTempBuffer);
1687c804472Sopenharmony_ci            GetInstance().onRenderTime = std::chrono::system_clock::now();
1697c804472Sopenharmony_ci        }
1707c804472Sopenharmony_ci        if (VirtualScreen::isStartCount) {
1717c804472Sopenharmony_ci            VirtualScreen::isStartCount = false;
1727c804472Sopenharmony_ci            VirtualScreen::startTime = std::chrono::system_clock::now();
1737c804472Sopenharmony_ci            std::thread timerThread(std::ref(VirtualScreenImpl::StartTimer));
1747c804472Sopenharmony_ci            timerThread.detach();
1757c804472Sopenharmony_ci        }
1767c804472Sopenharmony_ci        return false;
1777c804472Sopenharmony_ci    }
1787c804472Sopenharmony_ci    return true;
1797c804472Sopenharmony_ci}
1807c804472Sopenharmony_ci
1817c804472Sopenharmony_cibool VirtualScreenImpl::Callback(const void* data, const size_t length,
1827c804472Sopenharmony_ci                                 const int32_t width, const int32_t height, const uint64_t timeStamp)
1837c804472Sopenharmony_ci{
1847c804472Sopenharmony_ci    if (VirtualScreenImpl::GetInstance().StopSendStaticCardImage(STOP_SEND_CARD_DURATION_MS)) {
1857c804472Sopenharmony_ci        return false; // 静态卡片
1867c804472Sopenharmony_ci    }
1877c804472Sopenharmony_ci    if (VirtualScreenImpl::GetInstance().GetLoadDocFlag() < VirtualScreen::LoadDocType::FINISHED) {
1887c804472Sopenharmony_ci        return false;
1897c804472Sopenharmony_ci    }
1907c804472Sopenharmony_ci    if (VirtualScreenImpl::GetInstance().JudgeAndDropFrame()) {
1917c804472Sopenharmony_ci        return false; // 丢帧*
1927c804472Sopenharmony_ci    }
1937c804472Sopenharmony_ci    bool staticRet = VirtualScreen::JudgeStaticImage(SEND_IMG_DURATION_MS);
1947c804472Sopenharmony_ci    if (!staticRet) {
1957c804472Sopenharmony_ci        return false; // 平行世界
1967c804472Sopenharmony_ci    }
1977c804472Sopenharmony_ci    if (!LoadDocCallback(data, length, width, height, timeStamp)) {
1987c804472Sopenharmony_ci        return false; // 组件预览
1997c804472Sopenharmony_ci    }
2007c804472Sopenharmony_ci
2017c804472Sopenharmony_ci    GetInstance().bufferSize = length + GetInstance().headSize;
2027c804472Sopenharmony_ci    GetInstance().wholeBuffer = new(std::nothrow) uint8_t[LWS_PRE + GetInstance().bufferSize];
2037c804472Sopenharmony_ci    if (!GetInstance().wholeBuffer) {
2047c804472Sopenharmony_ci        ELOG("Memory allocation failed : wholeBuffer.");
2057c804472Sopenharmony_ci        return false;
2067c804472Sopenharmony_ci    }
2077c804472Sopenharmony_ci    GetInstance().screenBuffer = GetInstance().wholeBuffer + LWS_PRE;
2087c804472Sopenharmony_ci
2097c804472Sopenharmony_ci    return GetInstance().SendPixmap(data, length, width, height);
2107c804472Sopenharmony_ci}
2117c804472Sopenharmony_ci
2127c804472Sopenharmony_cibool VirtualScreenImpl::FlushEmptyCallback(const uint64_t timeStamp)
2137c804472Sopenharmony_ci{
2147c804472Sopenharmony_ci    if (timeStamp < GetInstance().loadDocTimeStamp) {
2157c804472Sopenharmony_ci        return false;
2167c804472Sopenharmony_ci    }
2177c804472Sopenharmony_ci    ILOG("loadDoc: flushEmptyTimeStamp:%" PRIu64 ", loadDocTimeStamp:%" PRIu64 "",
2187c804472Sopenharmony_ci        timeStamp, GetInstance().loadDocTimeStamp);
2197c804472Sopenharmony_ci    GetInstance().isFlushEmpty = true;
2207c804472Sopenharmony_ci    GetInstance().flushEmptyTime = std::chrono::system_clock::now();
2217c804472Sopenharmony_ci    GetInstance().flushEmptyTimeStamp = timeStamp;
2227c804472Sopenharmony_ci    return true;
2237c804472Sopenharmony_ci}
2247c804472Sopenharmony_ci
2257c804472Sopenharmony_civoid VirtualScreenImpl::InitFlushEmptyTime()
2267c804472Sopenharmony_ci{
2277c804472Sopenharmony_ci    GetInstance().isFlushEmpty = false;
2287c804472Sopenharmony_ci    GetInstance().flushEmptyTime = std::chrono::system_clock::time_point::min();
2297c804472Sopenharmony_ci    GetInstance().onRenderTime = std::chrono::system_clock::time_point::min();
2307c804472Sopenharmony_ci    GetInstance().flushEmptyTimeStamp = 0;
2317c804472Sopenharmony_ci    struct timespec ts;
2327c804472Sopenharmony_ci    clock_gettime(CLOCK_MONOTONIC, &ts);
2337c804472Sopenharmony_ci    loadDocTimeStamp = ts.tv_sec * SEC_TO_NANOSEC + ts.tv_nsec;
2347c804472Sopenharmony_ci    ILOG("loadDoc: loadDocTimeStamp:%" PRIu64 "", loadDocTimeStamp);
2357c804472Sopenharmony_ci}
2367c804472Sopenharmony_ci
2377c804472Sopenharmony_cibool VirtualScreenImpl::PageCallback(const std::string currentRouterPath)
2387c804472Sopenharmony_ci{
2397c804472Sopenharmony_ci    std::string currentRouter = currentRouterPath.substr(0, currentRouterPath.size() - 3);
2407c804472Sopenharmony_ci    ILOG("PageCallback currentPage is : %s", currentRouter.c_str());
2417c804472Sopenharmony_ci    GetInstance().SetCurrentRouter(currentRouter);
2427c804472Sopenharmony_ci    Json2::Value val;
2437c804472Sopenharmony_ci    CommandLineInterface::GetInstance().CreatCommandToSendData("CurrentRouter", val, "get");
2447c804472Sopenharmony_ci    return true;
2457c804472Sopenharmony_ci}
2467c804472Sopenharmony_ci
2477c804472Sopenharmony_cibool VirtualScreenImpl::LoadContentCallback(const std::string currentRouterPath)
2487c804472Sopenharmony_ci{
2497c804472Sopenharmony_ci    ILOG("LoadContentCallback currentPage is : %s", currentRouterPath.c_str());
2507c804472Sopenharmony_ci    GetInstance().SetAbilityCurrentRouter(currentRouterPath);
2517c804472Sopenharmony_ci    Json2::Value val;
2527c804472Sopenharmony_ci    CommandLineInterface::GetInstance().CreatCommandToSendData("LoadContent", val, "get");
2537c804472Sopenharmony_ci    return true;
2547c804472Sopenharmony_ci}
2557c804472Sopenharmony_ci
2567c804472Sopenharmony_civoid VirtualScreenImpl::FastPreviewCallback(const std::string& jsonStr)
2577c804472Sopenharmony_ci{
2587c804472Sopenharmony_ci    GetInstance().SetFastPreviewMsg(jsonStr);
2597c804472Sopenharmony_ci    Json2::Value val;
2607c804472Sopenharmony_ci    CommandLineInterface::GetInstance().CreatCommandToSendData("FastPreviewMsg", val, "get");
2617c804472Sopenharmony_ci}
2627c804472Sopenharmony_ci
2637c804472Sopenharmony_civoid VirtualScreenImpl::InitAll(std::string pipeName, std::string pipePort)
2647c804472Sopenharmony_ci{
2657c804472Sopenharmony_ci    VirtualScreen::InitPipe(pipeName, pipePort);
2667c804472Sopenharmony_ci}
2677c804472Sopenharmony_ci
2687c804472Sopenharmony_ciVirtualScreenImpl::VirtualScreenImpl()
2697c804472Sopenharmony_ci    : isFirstSend(true),
2707c804472Sopenharmony_ci      isFirstRender(true),
2717c804472Sopenharmony_ci      writed(0),
2727c804472Sopenharmony_ci      wholeBuffer(nullptr),
2737c804472Sopenharmony_ci      screenBuffer(nullptr),
2747c804472Sopenharmony_ci      bufferSize(0),
2757c804472Sopenharmony_ci      currentPos(0)
2767c804472Sopenharmony_ci{
2777c804472Sopenharmony_ci}
2787c804472Sopenharmony_ci
2797c804472Sopenharmony_ciVirtualScreenImpl::~VirtualScreenImpl()
2807c804472Sopenharmony_ci{
2817c804472Sopenharmony_ci    FreeJpgMemory();
2827c804472Sopenharmony_ci    if (WebSocketServer::GetInstance().firstImageBuffer) {
2837c804472Sopenharmony_ci        delete [] WebSocketServer::GetInstance().firstImageBuffer;
2847c804472Sopenharmony_ci        WebSocketServer::GetInstance().firstImageBuffer = nullptr;
2857c804472Sopenharmony_ci    }
2867c804472Sopenharmony_ci    if (VirtualScreenImpl::GetInstance().loadDocTempBuffer != nullptr) {
2877c804472Sopenharmony_ci        delete [] VirtualScreenImpl::GetInstance().loadDocTempBuffer;
2887c804472Sopenharmony_ci        VirtualScreenImpl::GetInstance().loadDocTempBuffer = nullptr;
2897c804472Sopenharmony_ci    }
2907c804472Sopenharmony_ci    if (VirtualScreenImpl::GetInstance().loadDocCopyBuffer != nullptr) {
2917c804472Sopenharmony_ci        delete [] VirtualScreenImpl::GetInstance().loadDocCopyBuffer;
2927c804472Sopenharmony_ci        VirtualScreenImpl::GetInstance().loadDocCopyBuffer = nullptr;
2937c804472Sopenharmony_ci    }
2947c804472Sopenharmony_ci}
2957c804472Sopenharmony_ci
2967c804472Sopenharmony_civoid VirtualScreenImpl::Send(const void* data, int32_t retWidth, int32_t retHeight)
2977c804472Sopenharmony_ci{
2987c804472Sopenharmony_ci    if (CommandParser::GetInstance().GetScreenMode() == CommandParser::ScreenMode::STATIC
2997c804472Sopenharmony_ci        && VirtualScreen::isOutOfSeconds) {
3007c804472Sopenharmony_ci        return;
3017c804472Sopenharmony_ci    }
3027c804472Sopenharmony_ci
3037c804472Sopenharmony_ci    if (retWidth < 1 || retHeight < 1) {
3047c804472Sopenharmony_ci        FLOG("VirtualScreenImpl::RgbToJpg the retWidth or height is invalid value");
3057c804472Sopenharmony_ci        return;
3067c804472Sopenharmony_ci    }
3077c804472Sopenharmony_ci    unsigned char* dataTemp = new(std::nothrow) unsigned char[retWidth * retHeight * jpgPix];
3087c804472Sopenharmony_ci    if (!dataTemp) {
3097c804472Sopenharmony_ci        ELOG("Memory allocation failed : dataTemp.");
3107c804472Sopenharmony_ci        return;
3117c804472Sopenharmony_ci    }
3127c804472Sopenharmony_ci    for (int i = 0; i < retHeight; i++) {
3137c804472Sopenharmony_ci        for (int j = 0; j < retWidth; j++) {
3147c804472Sopenharmony_ci            int inputBasePos = i * retWidth * pixelSize + j * pixelSize;
3157c804472Sopenharmony_ci            int nowBasePos = i * retWidth * jpgPix + j * jpgPix;
3167c804472Sopenharmony_ci            dataTemp[nowBasePos + redPos] = *((char*)data + inputBasePos + redPos);
3177c804472Sopenharmony_ci            dataTemp[nowBasePos + greenPos] = *((char*)data + inputBasePos + greenPos);
3187c804472Sopenharmony_ci            dataTemp[nowBasePos + bluePos] = *((char*)data + inputBasePos + bluePos);
3197c804472Sopenharmony_ci        }
3207c804472Sopenharmony_ci    }
3217c804472Sopenharmony_ci    VirtualScreen::RgbToJpg(dataTemp, retWidth, retHeight);
3227c804472Sopenharmony_ci    delete [] dataTemp;
3237c804472Sopenharmony_ci    if (jpgBufferSize > bufferSize - headSize) {
3247c804472Sopenharmony_ci        FLOG("VirtualScreenImpl::Send length must < %d", bufferSize - headSize);
3257c804472Sopenharmony_ci        return;
3267c804472Sopenharmony_ci    }
3277c804472Sopenharmony_ci
3287c804472Sopenharmony_ci    std::copy(jpgScreenBuffer, jpgScreenBuffer + jpgBufferSize, screenBuffer + headSize);
3297c804472Sopenharmony_ci    writed = WebSocketServer::GetInstance().WriteData(screenBuffer, headSize + jpgBufferSize);
3307c804472Sopenharmony_ci    std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex);
3317c804472Sopenharmony_ci    if (WebSocketServer::GetInstance().firstImageBuffer) {
3327c804472Sopenharmony_ci        delete [] WebSocketServer::GetInstance().firstImageBuffer;
3337c804472Sopenharmony_ci        WebSocketServer::GetInstance().firstImageBuffer = nullptr;
3347c804472Sopenharmony_ci    }
3357c804472Sopenharmony_ci    WebSocketServer::GetInstance().firstImageBuffer = new(std::nothrow) uint8_t[LWS_PRE + bufferSize];
3367c804472Sopenharmony_ci    if (!WebSocketServer::GetInstance().firstImageBuffer) {
3377c804472Sopenharmony_ci        ELOG("Memory allocation failed : firstImageBuffer.");
3387c804472Sopenharmony_ci        return;
3397c804472Sopenharmony_ci    }
3407c804472Sopenharmony_ci    WebSocketServer::GetInstance().firstImagebufferSize = headSize + jpgBufferSize;
3417c804472Sopenharmony_ci    std::copy(screenBuffer,
3427c804472Sopenharmony_ci              screenBuffer + headSize + jpgBufferSize,
3437c804472Sopenharmony_ci              WebSocketServer::GetInstance().firstImageBuffer + LWS_PRE);
3447c804472Sopenharmony_ci
3457c804472Sopenharmony_ci    FreeJpgMemory();
3467c804472Sopenharmony_ci}
3477c804472Sopenharmony_ci
3487c804472Sopenharmony_cibool VirtualScreenImpl::SendPixmap(const void* data, size_t length, int32_t retWidth, int32_t retHeight)
3497c804472Sopenharmony_ci{
3507c804472Sopenharmony_ci    if (data == nullptr) {
3517c804472Sopenharmony_ci        ELOG("render callback data is null.");
3527c804472Sopenharmony_ci        invalidFrameCountPerMinute++;
3537c804472Sopenharmony_ci        return false;
3547c804472Sopenharmony_ci    }
3557c804472Sopenharmony_ci
3567c804472Sopenharmony_ci    if (!isWebSocketConfiged) {
3577c804472Sopenharmony_ci        ELOG("image socket is not ready");
3587c804472Sopenharmony_ci        return false;
3597c804472Sopenharmony_ci    }
3607c804472Sopenharmony_ci
3617c804472Sopenharmony_ci    if (isFirstRender) {
3627c804472Sopenharmony_ci        ILOG("Get first render buffer");
3637c804472Sopenharmony_ci        TraceTool::GetInstance().HandleTrace("Get first render buffer");
3647c804472Sopenharmony_ci        isFirstRender = false;
3657c804472Sopenharmony_ci    }
3667c804472Sopenharmony_ci
3677c804472Sopenharmony_ci    isFrameUpdated = true;
3687c804472Sopenharmony_ci    currentPos = 0;
3697c804472Sopenharmony_ci
3707c804472Sopenharmony_ci    WriteBuffer(headStart);
3717c804472Sopenharmony_ci    WriteBuffer(retWidth);
3727c804472Sopenharmony_ci    WriteBuffer(retHeight);
3737c804472Sopenharmony_ci    WriteBuffer(retWidth);
3747c804472Sopenharmony_ci    WriteBuffer(retHeight);
3757c804472Sopenharmony_ci    if (!CommandParser::GetInstance().IsRegionRefresh()) {
3767c804472Sopenharmony_ci        for (size_t i = 0; i < headReservedSize / sizeof(int32_t); i++) {
3777c804472Sopenharmony_ci            WriteBuffer(static_cast<uint32_t>(0));
3787c804472Sopenharmony_ci        }
3797c804472Sopenharmony_ci    } else {
3807c804472Sopenharmony_ci        uint16_t x1 = 0;
3817c804472Sopenharmony_ci        uint16_t y1 = 0;
3827c804472Sopenharmony_ci        uint16_t width = static_cast<uint16_t>(retWidth);
3837c804472Sopenharmony_ci        uint16_t height = static_cast<uint16_t>(retHeight);
3847c804472Sopenharmony_ci        WriteBuffer(protocolVersion);
3857c804472Sopenharmony_ci        WriteBuffer(x1);
3867c804472Sopenharmony_ci        WriteBuffer(y1);
3877c804472Sopenharmony_ci        WriteBuffer(width);
3887c804472Sopenharmony_ci        WriteBuffer(height);
3897c804472Sopenharmony_ci        for (size_t i = 0; i < 10 / sizeof(uint16_t); i++) { // fill 10bytes for header
3907c804472Sopenharmony_ci            WriteBuffer(static_cast<uint16_t>(0));
3917c804472Sopenharmony_ci        }
3927c804472Sopenharmony_ci    }
3937c804472Sopenharmony_ci    Send(data, retWidth, retHeight);
3947c804472Sopenharmony_ci    if (isFirstSend) {
3957c804472Sopenharmony_ci        ILOG("Send first buffer finish");
3967c804472Sopenharmony_ci        TraceTool::GetInstance().HandleTrace("Send first buffer finish");
3977c804472Sopenharmony_ci        isFirstSend = false;
3987c804472Sopenharmony_ci    }
3997c804472Sopenharmony_ci
4007c804472Sopenharmony_ci    validFrameCountPerMinute++;
4017c804472Sopenharmony_ci    sendFrameCountPerMinute++;
4027c804472Sopenharmony_ci    return writed == length;
4037c804472Sopenharmony_ci}
4047c804472Sopenharmony_ci
4057c804472Sopenharmony_civoid VirtualScreenImpl::FreeJpgMemory()
4067c804472Sopenharmony_ci{
4077c804472Sopenharmony_ci    if (wholeBuffer != nullptr) {
4087c804472Sopenharmony_ci        delete [] wholeBuffer;
4097c804472Sopenharmony_ci        wholeBuffer = nullptr;
4107c804472Sopenharmony_ci        screenBuffer = nullptr;
4117c804472Sopenharmony_ci    }
4127c804472Sopenharmony_ci    if (jpgScreenBuffer != nullptr) {
4137c804472Sopenharmony_ci        free(jpgScreenBuffer);
4147c804472Sopenharmony_ci        jpgScreenBuffer = NULL;
4157c804472Sopenharmony_ci        jpgBufferSize = 0;
4167c804472Sopenharmony_ci    }
4177c804472Sopenharmony_ci    if (loadDocCopyBuffer != nullptr) {
4187c804472Sopenharmony_ci        delete [] loadDocCopyBuffer;
4197c804472Sopenharmony_ci        loadDocCopyBuffer = nullptr;
4207c804472Sopenharmony_ci    }
4217c804472Sopenharmony_ci    if (loadDocTempBuffer != nullptr) {
4227c804472Sopenharmony_ci        delete [] loadDocTempBuffer;
4237c804472Sopenharmony_ci        loadDocTempBuffer = nullptr;
4247c804472Sopenharmony_ci    }
4257c804472Sopenharmony_ci}
4267c804472Sopenharmony_ci
4277c804472Sopenharmony_ciScreenInfo VirtualScreenImpl::GetScreenInfo()
4287c804472Sopenharmony_ci{
4297c804472Sopenharmony_ci    ScreenInfo info;
4307c804472Sopenharmony_ci    info.orignalResolutionWidth = GetOrignalWidth();
4317c804472Sopenharmony_ci    info.orignalResolutionHeight = GetOrignalHeight();
4327c804472Sopenharmony_ci    info.compressionResolutionWidth = GetCompressionWidth();
4337c804472Sopenharmony_ci    info.compressionResolutionHeight = GetCompressionHeight();
4347c804472Sopenharmony_ci    info.foldStatus = GetFoldStatus();
4357c804472Sopenharmony_ci    info.foldable = GetFoldable();
4367c804472Sopenharmony_ci    info.foldWidth = GetFoldWidth();
4377c804472Sopenharmony_ci    info.foldHeight = GetFoldHeight();
4387c804472Sopenharmony_ci    return info;
4397c804472Sopenharmony_ci}
4407c804472Sopenharmony_ci
4417c804472Sopenharmony_civoid VirtualScreenImpl::InitFoldParams()
4427c804472Sopenharmony_ci{
4437c804472Sopenharmony_ci    CommandParser& parser = CommandParser::GetInstance();
4447c804472Sopenharmony_ci    FoldInfo info;
4457c804472Sopenharmony_ci    parser.GetFoldInfo(info);
4467c804472Sopenharmony_ci    if (parser.IsSet("foldable")) {
4477c804472Sopenharmony_ci        SetFoldable(info.foldable);
4487c804472Sopenharmony_ci    }
4497c804472Sopenharmony_ci    if (parser.IsSet("foldStatus")) {
4507c804472Sopenharmony_ci        SetFoldStatus(info.foldStatus);
4517c804472Sopenharmony_ci    }
4527c804472Sopenharmony_ci    if (parser.IsSet("fr")) {
4537c804472Sopenharmony_ci        SetFoldResolution(info.foldResolutionWidth, info.foldResolutionHeight);
4547c804472Sopenharmony_ci    }
4557c804472Sopenharmony_ci}