• 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 
InitAll(std::string pipeName,std::string pipePort)31 void VirtualScreenImpl::InitAll(std::string pipeName, std::string pipePort)
32 {
33     OHOS::ImageDecodeAbility& ability = OHOS::ImageDecodeAbility::GetInstance();
34     ability.SetImageDecodeAbility(OHOS::IMG_SUPPORT_BITMAP | OHOS::IMG_SUPPORT_JPEG | OHOS::IMG_SUPPORT_PNG);
35     if (CommandParser::GetInstance().GetDeviceType() == "liteWearable") {
36         ability.SetImageDecodeAbility(OHOS::IMG_SUPPORT_BITMAP);
37     }
38 
39     InitPipe(pipeName, pipePort);
40     if ((!CommandParser::GetInstance().IsResolutionValid(orignalResolutionWidth)) ||
41         (!CommandParser::GetInstance().IsResolutionValid(orignalResolutionHeight))) {
42         ELOG("VirtualScreen::InitAll invalid resolution, width : %d height : %d", orignalResolutionWidth,
43              orignalResolutionHeight);
44         return;
45     }
46 
47     bufferSize = orignalResolutionWidth * orignalResolutionHeight * pixelSize + headSize;
48     wholeBuffer = new(std::nothrow) uint8_t[LWS_PRE + bufferSize];
49     if (!wholeBuffer) {
50         ELOG("Memory allocation failed : wholeBuffer.");
51         return;
52     }
53     regionWholeBuffer = new(std::nothrow) uint8_t[LWS_PRE + bufferSize];
54     if (!regionWholeBuffer) {
55         ELOG("Memory allocation failed: regionWholeBuffer.");
56         return;
57     }
58     screenBuffer = wholeBuffer + LWS_PRE;
59     regionBuffer = regionWholeBuffer + LWS_PRE;
60     osBuffer = new(std::nothrow) uint8_t[bufferSize];
61     if (!osBuffer) {
62         ELOG("Memory allocation failed: osBuffer.");
63         return;
64     }
65     if (screenBuffer == nullptr) {
66         ELOG("VirtualScreen::InitAll wholeBuffer memory allocation failed");
67         return;
68     }
69     InitBuffer();
70 }
71 
IsRectValid(int32_t x1,int32_t y1,int32_t x2,int32_t y2) const72 bool VirtualScreenImpl::IsRectValid(int32_t x1, int32_t y1, int32_t x2, int32_t y2) const
73 {
74     if (x1 < 0 || y1 < 0) {
75         return false;
76     }
77 
78     if (x2 >= orignalResolutionWidth || y2 >= orignalResolutionHeight) {
79         return false;
80     }
81     return true;
82 }
83 
WriteRefreshRegion()84 void VirtualScreenImpl::WriteRefreshRegion()
85 {
86     currentPos = VERSION_POS;
87     WriteBuffer(protocolVersion);
88     WriteBuffer(regionX1);
89     WriteBuffer(regionY1);
90     regionWidth = static_cast<uint16_t>(orignalResolutionWidth);
91     WriteBuffer(regionWidth);
92     regionHeight = static_cast<uint16_t>(orignalResolutionHeight);
93     WriteBuffer(regionHeight);
94 }
95 
UpdateRegion(int32_t x1,int32_t y1,int32_t x2,int32_t y2)96 void VirtualScreenImpl::UpdateRegion(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
97 {
98     regionX1 = x1;
99     regionY1 = y1;
100     regionX2 = (x2 < compressionResolutionWidth - extendPix)
101                    ? (x2 + extendPix) : (compressionResolutionWidth - 1);
102     regionY2 = (y2 < compressionResolutionHeight - extendPix)
103                    ? (y2 + extendPix) : (compressionResolutionHeight - 1);
104     regionWidth = regionX2 - regionX1 + 1;
105     regionHeight = regionY2 - regionY1 + 1;
106 }
107 
InitBuffer()108 void VirtualScreenImpl::InitBuffer()
109 {
110     currentPos = 0;
111     WriteBuffer(headStart);
112     WriteBuffer(orignalResolutionWidth);
113     WriteBuffer(orignalResolutionHeight);
114     WriteBuffer(compressionResolutionWidth);
115     WriteBuffer(compressionResolutionHeight);
116 }
117 
ScheduleBufferSend()118 void VirtualScreenImpl::ScheduleBufferSend()
119 {
120     if (!isChanged) {
121         return;
122     }
123 
124     if (!isWebSocketConfiged) {
125         ELOG("image socket is not ready");
126         return;
127     }
128     isFrameUpdated = true;
129     if (CommandParser::GetInstance().IsRegionRefresh()) {
130         SendFullBuffer();
131     } else {
132         SendFullBuffer();
133     }
134     if (isFirstSend) {
135         ILOG("Send first buffer finish");
136         TraceTool::GetInstance().HandleTrace("Send first buffer finish");
137         isFirstSend = false;
138     }
139 
140     {
141         std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex);
142         if (!WebSocketServer::GetInstance().firstImageBuffer) {
143             WebSocketServer::GetInstance().firstImageBuffer = new(std::nothrow) uint8_t[LWS_PRE + bufferSize];
144             if (!WebSocketServer::GetInstance().firstImageBuffer) {
145                 ELOG("Memory allocation failed: firstImageBuffer.");
146                 return;
147             }
148             WebSocketServer::GetInstance().firstImagebufferSize = headSize + jpgBufferSize;
149         }
150         std::copy(regionBuffer,
151                   regionBuffer + headSize + jpgBufferSize,
152                   WebSocketServer::GetInstance().firstImageBuffer + LWS_PRE);
153     }
154 
155     sendFrameCountPerMinute++;
156     isChanged = false;
157 }
158 
Send(unsigned char * data,int32_t width,int32_t height)159 void VirtualScreenImpl::Send(unsigned char* data, int32_t width, int32_t height)
160 {
161     if (CommandParser::GetInstance().GetScreenMode() == CommandParser::ScreenMode::STATIC
162         && VirtualScreen::isOutOfSeconds) {
163         return;
164     }
165     // if websocket is config, use websocet, else use localsocket
166     VirtualScreen::RgbToJpg(data + headSize, width, height);
167     std::copy(jpgScreenBuffer, jpgScreenBuffer + jpgBufferSize, regionBuffer + headSize);
168     WebSocketServer::GetInstance().WriteData(regionBuffer, headSize + jpgBufferSize);
169     FreeJpgMemory();
170 }
171 
SendFullBuffer()172 void VirtualScreenImpl::SendFullBuffer()
173 {
174     WriteRefreshRegion();
175     std::copy(screenBuffer, screenBuffer + headSize, regionBuffer);
176     Send(reinterpret_cast<unsigned char*>(screenBuffer),
177          compressionResolutionWidth,
178          compressionResolutionHeight);
179 }
180 
SendRegionBuffer()181 void VirtualScreenImpl::SendRegionBuffer()
182 {
183     WriteRefreshRegion();
184     std::copy(screenBuffer, screenBuffer + headSize, regionBuffer);
185     for (int i = regionY1; i <= regionY2; ++i) {
186         uint8_t* startPos = screenBuffer + (i * compressionResolutionWidth + regionX1) * jpgPix + headSize;
187         std::copy(startPos,
188                   startPos + regionWidth * jpgPix,
189                   regionBuffer + ((i - regionY1) * regionWidth) * jpgPix + headSize);
190     }
191     Send(reinterpret_cast<unsigned char*>(regionBuffer), regionWidth, regionHeight);
192 }
193 
FreeJpgMemory()194 void VirtualScreenImpl::FreeJpgMemory()
195 {
196     if (jpgScreenBuffer != nullptr) {
197         free(jpgScreenBuffer);
198         jpgScreenBuffer = NULL;
199     }
200 }
201 
GetInstance()202 VirtualScreenImpl& VirtualScreenImpl::GetInstance()
203 {
204     static VirtualScreenImpl virtualScreen;
205     BaseGfxEngine::InitGfxEngine(&virtualScreen);
206     return virtualScreen;
207 }
208 
CheckBufferSend()209 void VirtualScreenImpl::CheckBufferSend()
210 {
211     VirtualScreenImpl::GetInstance().ScheduleBufferSend();
212 }
213 
VirtualScreenImpl()214 VirtualScreenImpl::VirtualScreenImpl()
215     : wholeBuffer(nullptr),
216       regionWholeBuffer(nullptr),
217       screenBuffer(nullptr),
218       regionBuffer(nullptr),
219       osBuffer(nullptr),
220       isChanged(false),
221       currentPos(0),
222       bufferSize(0),
223       isFirstRender(true),
224       isFirstSend(true),
225       regionX1(0),
226       regionY1(0),
227       regionX2(0),
228       regionY2(0),
229       regionWidth(0),
230       regionHeight(0),
231       bufferInfo(nullptr)
232 {
233 }
234 
~VirtualScreenImpl()235 VirtualScreenImpl::~VirtualScreenImpl()
236 {
237     if (wholeBuffer != nullptr) {
238         delete [] wholeBuffer;
239         wholeBuffer = nullptr;
240         screenBuffer = nullptr;
241     }
242     FreeJpgMemory();
243     if (WebSocketServer::GetInstance().firstImageBuffer) {
244         delete [] WebSocketServer::GetInstance().firstImageBuffer;
245         WebSocketServer::GetInstance().firstImageBuffer = nullptr;
246     }
247 }
248 
Flush(const OHOS::Rect & flushRect)249 void VirtualScreenImpl::Flush(const OHOS::Rect& flushRect)
250 {
251     if (isFirstRender) {
252         ILOG("Get first render buffer");
253         TraceTool::GetInstance().HandleTrace("Get first render buffer");
254         isFirstRender = false;
255     }
256 
257     bool staticRet = VirtualScreen::JudgeStaticImage(SEND_IMG_DURATION_MS);
258     if (!staticRet) {
259         return;
260     }
261 
262     for (int i = 0; i <= compressionResolutionHeight - 1; ++i) {
263         for (int j = 0; j <= compressionResolutionWidth - 1; ++j) {
264             uint8_t* curPixel = screenBuffer + (i * compressionResolutionWidth + j) * jpgPix + headSize;
265             uint8_t* osPixel = osBuffer + (i * compressionResolutionWidth + j) * pixelSize + headSize;
266             *(curPixel + redPos) = *(osPixel + bluePos);
267             *(curPixel + greenPos) = *(osPixel + greenPos);
268             *(curPixel + bluePos) = *(osPixel + redPos);
269         }
270     }
271 
272     validFrameCountPerMinute++;
273     isChanged = true;
274     ScheduleBufferSend();
275 }
276 
GetFBBufferInfo()277 OHOS::BufferInfo* VirtualScreenImpl::GetFBBufferInfo()
278 {
279     if (bufferInfo == nullptr) {
280         bufferInfo = new(std::nothrow) OHOS::BufferInfo;
281         if (!bufferInfo) {
282             ELOG("Memory allocation failed: osBuffer.");
283             return bufferInfo;
284         }
285         bufferInfo->rect = {0, 0, compressionResolutionWidth - 1, compressionResolutionHeight - 1};
286         bufferInfo->mode = OHOS::ARGB8888;
287 
288         bufferInfo->color = 0x44;
289         bufferInfo->phyAddr = bufferInfo->virAddr = osBuffer + headSize;
290         // 3: Shift right 3 bits
291         bufferInfo->stride = orignalResolutionWidth * (OHOS::DrawUtils::GetPxSizeByColorMode(bufferInfo->mode) >> 3);
292         bufferInfo->width = orignalResolutionWidth;
293         bufferInfo->height = orignalResolutionHeight;
294     }
295 
296     return bufferInfo;
297 }
298 
GetScreenWidth()299 uint16_t VirtualScreenImpl::GetScreenWidth()
300 {
301     return orignalResolutionWidth;
302 }
303 
GetScreenHeight()304 uint16_t VirtualScreenImpl::GetScreenHeight()
305 {
306     return orignalResolutionHeight;
307 }
308