• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "VirtualScreenImpl.h"
17 
18 #include "draw/draw_utils.h"
19 #include "hal_tick.h"
20 #include "image_decode_ability.h"
21 
22 #define boolean jpegboolean
23 #include "jpeglib.h"
24 #undef boolean
25 #include "task_manager.h"
26 #include "CommandParser.h"
27 #include "ModelManager.h"
28 #include "PreviewerEngineLog.h"
29 #include "TraceTool.h"
30 
31 using namespace std;
32 using namespace std::chrono;
33 
InitAll(std::string pipeName,std::string pipePort)34 void VirtualScreenImpl::InitAll(std::string pipeName, std::string pipePort)
35 {
36     OHOS::ImageDecodeAbility& ability = OHOS::ImageDecodeAbility::GetInstance();
37     ability.SetImageDecodeAbility(OHOS::IMG_SUPPORT_BITMAP | OHOS::IMG_SUPPORT_JPEG | OHOS::IMG_SUPPORT_PNG);
38     if (CommandParser::GetInstance().GetDeviceType() == "liteWearable") {
39         ability.SetImageDecodeAbility(OHOS::IMG_SUPPORT_BITMAP);
40     }
41 
42     InitPipe(pipeName, pipePort);
43     if ((!CommandParser::GetInstance().IsResolutionValid(orignalResolutionWidth)) ||
44         (!CommandParser::GetInstance().IsResolutionValid(orignalResolutionHeight))) {
45         ELOG("VirtualScreen::InitAll invalid resolution, width : %d height : %d", orignalResolutionWidth,
46              orignalResolutionHeight);
47         return;
48     }
49 
50     bufferSize = orignalResolutionWidth * orignalResolutionHeight * pixelSize + headSize;
51     wholeBuffer = new uint8_t[LWS_PRE + bufferSize];
52     regionWholeBuffer = new uint8_t[LWS_PRE + bufferSize];
53     screenBuffer = wholeBuffer + LWS_PRE;
54     regionBuffer = regionWholeBuffer + LWS_PRE;
55     osBuffer = new uint8_t[bufferSize];
56     if (screenBuffer == nullptr) {
57         ELOG("VirtualScreen::InitAll wholeBuffer memory allocation failed");
58         return;
59     }
60     InitBuffer();
61 }
62 
IsRectValid(int32_t x1,int32_t y1,int32_t x2,int32_t y2) const63 bool VirtualScreenImpl::IsRectValid(int32_t x1, int32_t y1, int32_t x2, int32_t y2) const
64 {
65     if (x1 < 0 || y1 < 0) {
66         return false;
67     }
68 
69     if (x2 >= orignalResolutionWidth || y2 >= orignalResolutionHeight) {
70         return false;
71     }
72     return true;
73 }
74 
WriteRefreshRegion()75 void VirtualScreenImpl::WriteRefreshRegion()
76 {
77     currentPos = VERSION_POS;
78     WriteBuffer(protocolVersion);
79     WriteBuffer(regionX1);
80     WriteBuffer(regionY1);
81     regionWidth = static_cast<uint16_t>(orignalResolutionWidth);
82     WriteBuffer(regionWidth);
83     regionHeight = static_cast<uint16_t>(orignalResolutionHeight);
84     WriteBuffer(regionHeight);
85 }
86 
UpdateRegion(int32_t x1,int32_t y1,int32_t x2,int32_t y2)87 void VirtualScreenImpl::UpdateRegion(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
88 {
89     regionX1 = x1;
90     regionY1 = y1;
91     regionX2 = (x2 < compressionResolutionWidth - extendPix)
92                    ? (x2 + extendPix) : (compressionResolutionWidth - 1);
93     regionY2 = (y2 < compressionResolutionHeight - extendPix)
94                    ? (y2 + extendPix) : (compressionResolutionHeight - 1);
95     regionWidth = regionX2 - regionX1 + 1;
96     regionHeight = regionY2 - regionY1 + 1;
97 }
98 
InitBuffer()99 void VirtualScreenImpl::InitBuffer()
100 {
101     currentPos = 0;
102     WriteBuffer(headStart);
103     WriteBuffer(orignalResolutionWidth);
104     WriteBuffer(orignalResolutionHeight);
105     WriteBuffer(compressionResolutionWidth);
106     WriteBuffer(compressionResolutionHeight);
107 }
108 
ScheduleBufferSend()109 void VirtualScreenImpl::ScheduleBufferSend()
110 {
111     if (!isChanged) {
112         return;
113     }
114 
115     if (!isWebSocketConfiged) {
116         ELOG("image socket is not ready");
117         return;
118     }
119     isFrameUpdated = true;
120     if (CommandParser::GetInstance().IsRegionRefresh()) {
121         SendFullBuffer();
122     } else {
123         SendFullBuffer();
124     }
125     if (isFirstSend) {
126         ILOG("Send first buffer finish");
127         TraceTool::GetInstance().HandleTrace("Send first buffer finish");
128         isFirstSend = false;
129     }
130 
131     {
132         std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex);
133         if (!WebSocketServer::GetInstance().firstImageBuffer) {
134             WebSocketServer::GetInstance().firstImageBuffer = new uint8_t[LWS_PRE + bufferSize];
135             WebSocketServer::GetInstance().firstImagebufferSize = headSize + jpgBufferSize;
136         }
137         std::copy(regionBuffer,
138                   regionBuffer + headSize + jpgBufferSize,
139                   WebSocketServer::GetInstance().firstImageBuffer + LWS_PRE);
140     }
141 
142     sendFrameCountPerMinute++;
143     isChanged = false;
144 }
145 
Send(unsigned char * data,int32_t width,int32_t height)146 void VirtualScreenImpl::Send(unsigned char* data, int32_t width, int32_t height)
147 {
148     if (CommandParser::GetInstance().GetScreenMode() == CommandParser::ScreenMode::STATIC
149         && VirtualScreen::isOutOfSeconds) {
150         return;
151     }
152     // if websocket is config, use websocet, else use localsocket
153     VirtualScreen::RgbToJpg(data + headSize, width, height);
154     std::copy(jpgScreenBuffer, jpgScreenBuffer + jpgBufferSize, regionBuffer + headSize);
155     WebSocketServer::GetInstance().WriteData(regionBuffer, headSize + jpgBufferSize);
156     FreeJpgMemory();
157 }
158 
SendFullBuffer()159 void VirtualScreenImpl::SendFullBuffer()
160 {
161     WriteRefreshRegion();
162     std::copy(screenBuffer, screenBuffer + headSize, regionBuffer);
163     Send(reinterpret_cast<unsigned char*>(screenBuffer),
164          compressionResolutionWidth,
165          compressionResolutionHeight);
166 }
167 
SendRegionBuffer()168 void VirtualScreenImpl::SendRegionBuffer()
169 {
170     WriteRefreshRegion();
171     std::copy(screenBuffer, screenBuffer + headSize, regionBuffer);
172     for (int i = regionY1; i <= regionY2; ++i) {
173         uint8_t* startPos = screenBuffer + (i * compressionResolutionWidth + regionX1) * jpgPix + headSize;
174         std::copy(startPos,
175                   startPos + regionWidth * jpgPix,
176                   regionBuffer + ((i - regionY1) * regionWidth) * jpgPix + headSize);
177     }
178     Send(reinterpret_cast<unsigned char*>(regionBuffer), regionWidth, regionHeight);
179 }
180 
FreeJpgMemory()181 void VirtualScreenImpl::FreeJpgMemory()
182 {
183     if (jpgScreenBuffer != nullptr) {
184         free(jpgScreenBuffer);
185         jpgScreenBuffer = NULL;
186     }
187 }
188 
GetInstance()189 VirtualScreenImpl& VirtualScreenImpl::GetInstance()
190 {
191     static VirtualScreenImpl virtualScreen;
192     BaseGfxEngine::InitGfxEngine(&virtualScreen);
193     return virtualScreen;
194 }
195 
CheckBufferSend()196 void VirtualScreenImpl::CheckBufferSend()
197 {
198     VirtualScreenImpl::GetInstance().ScheduleBufferSend();
199 }
200 
VirtualScreenImpl()201 VirtualScreenImpl::VirtualScreenImpl()
202     : wholeBuffer(nullptr),
203       regionWholeBuffer(nullptr),
204       screenBuffer(nullptr),
205       regionBuffer(nullptr),
206       osBuffer(nullptr),
207       isChanged(false),
208       currentPos(0),
209       bufferSize(0),
210       isFirstRender(true),
211       isFirstSend(true),
212       regionX1(0),
213       regionY1(0),
214       regionX2(0),
215       regionY2(0),
216       regionWidth(0),
217       regionHeight(0),
218       bufferInfo(nullptr)
219 {
220 }
221 
~VirtualScreenImpl()222 VirtualScreenImpl::~VirtualScreenImpl()
223 {
224     if (wholeBuffer != nullptr) {
225         delete [] wholeBuffer;
226         wholeBuffer = nullptr;
227         screenBuffer = nullptr;
228     }
229     FreeJpgMemory();
230     if (WebSocketServer::GetInstance().firstImageBuffer) {
231         delete [] WebSocketServer::GetInstance().firstImageBuffer;
232         WebSocketServer::GetInstance().firstImageBuffer = nullptr;
233     }
234 }
235 
Flush(const OHOS::Rect & flushRect)236 void VirtualScreenImpl::Flush(const OHOS::Rect& flushRect)
237 {
238     if (isFirstRender) {
239         ILOG("Get first render buffer");
240         TraceTool::GetInstance().HandleTrace("Get first render buffer");
241         isFirstRender = false;
242     }
243 
244     bool staticRet = VirtualScreen::JudgeStaticImage(SEND_IMG_DURATION_MS);
245     if (!staticRet) {
246         return;
247     }
248 
249     for (int i = 0; i <= compressionResolutionHeight - 1; ++i) {
250         for (int j = 0; j <= compressionResolutionWidth - 1; ++j) {
251             uint8_t* curPixel = screenBuffer + (i * compressionResolutionWidth + j) * jpgPix + headSize;
252             uint8_t* osPixel = osBuffer + (i * compressionResolutionWidth + j) * pixelSize + headSize;
253             *(curPixel + redPos) = *(osPixel + bluePos);
254             *(curPixel + greenPos) = *(osPixel + greenPos);
255             *(curPixel + bluePos) = *(osPixel + redPos);
256         }
257     }
258 
259     validFrameCountPerMinute++;
260     isChanged = true;
261     ScheduleBufferSend();
262 }
263 
GetFBBufferInfo()264 OHOS::BufferInfo* VirtualScreenImpl::GetFBBufferInfo()
265 {
266     if (bufferInfo == nullptr) {
267         bufferInfo = new OHOS::BufferInfo;
268         bufferInfo->rect = {0, 0, compressionResolutionWidth - 1, compressionResolutionHeight - 1};
269         bufferInfo->mode = OHOS::ARGB8888;
270         bufferInfo->color = 0x44;
271         bufferInfo->phyAddr = bufferInfo->virAddr = osBuffer + headSize;
272         // 3: Shift right 3 bits
273         bufferInfo->stride = orignalResolutionWidth * (OHOS::DrawUtils::GetPxSizeByColorMode(bufferInfo->mode) >> 3);
274         bufferInfo->width = orignalResolutionWidth;
275         bufferInfo->height = orignalResolutionHeight;
276     }
277 
278     return bufferInfo;
279 }
280 
GetScreenWidth()281 uint16_t VirtualScreenImpl::GetScreenWidth()
282 {
283     return orignalResolutionWidth;
284 }
285 
GetScreenHeight()286 uint16_t VirtualScreenImpl::GetScreenHeight()
287 {
288     return orignalResolutionHeight;
289 }
290