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 #define boolean jpegboolean
19 #include "jpeglib.h"
20 #undef boolean
21
22 #include "CommandLineInterface.h"
23 #include "CommandParser.h"
24 #include "PreviewerEngineLog.h"
25 #include "TraceTool.h"
26
27 using namespace std;
28
GetInstance()29 VirtualScreenImpl& VirtualScreenImpl::GetInstance()
30 {
31 static VirtualScreenImpl virtualScreen;
32 return virtualScreen;
33 }
34
StartTimer()35 void VirtualScreenImpl::StartTimer()
36 {
37 while (true) {
38 auto endTime = std::chrono::system_clock::now();
39 int64_t timePassed = chrono::duration_cast<chrono::milliseconds>(endTime -
40 VirtualScreenImpl::GetInstance().startTime).count();
41 if (timePassed >= SEND_IMG_DURATION_MS) {
42 GetInstance().SetLoadDocFlag(VirtualScreen::LoadDocType::NORMAL);
43 VirtualScreen::isStartCount = true;
44 {
45 std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex);
46 if (GetInstance().loadDocCopyBuffer != nullptr) {
47 delete [] GetInstance().loadDocCopyBuffer;
48 GetInstance().loadDocCopyBuffer = nullptr;
49 }
50 GetInstance().loadDocCopyBuffer = new uint8_t[GetInstance().lengthTemp];
51 std::copy(GetInstance().loadDocTempBuffer,
52 GetInstance().loadDocTempBuffer + GetInstance().lengthTemp,
53 GetInstance().loadDocCopyBuffer);
54 }
55 VirtualScreenImpl::GetInstance().protocolVersion =
56 static_cast<uint16_t>(VirtualScreen::ProtocolVersion::LOADDOC);
57 GetInstance().bufferSize = GetInstance().lengthTemp + GetInstance().headSize;
58 GetInstance().wholeBuffer = new uint8_t[LWS_PRE + GetInstance().bufferSize];
59 GetInstance().screenBuffer = GetInstance().wholeBuffer + LWS_PRE;
60 GetInstance().SendPixmap(GetInstance().loadDocCopyBuffer,
61 GetInstance().lengthTemp,
62 GetInstance().widthTemp,
63 GetInstance().heightTemp);
64 ILOG("LoadDocFlag2:finished");
65 return;
66 }
67 }
68 }
69
LoadDocCallback(const void * data,const size_t length,const int32_t width,const int32_t height)70 bool VirtualScreenImpl::LoadDocCallback(const void* data,
71 const size_t length,
72 const int32_t width,
73 const int32_t height)
74 {
75 if (GetInstance().GetLoadDocFlag() == VirtualScreen::LoadDocType::FINISHED) {
76 {
77 std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex);
78 if (GetInstance().loadDocTempBuffer != nullptr) {
79 delete [] GetInstance().loadDocTempBuffer;
80 GetInstance().loadDocTempBuffer = nullptr;
81 }
82 GetInstance().lengthTemp = length;
83 GetInstance().widthTemp = width;
84 GetInstance().heightTemp = height;
85 if (length <= 0) {
86 return false;
87 }
88 GetInstance().loadDocTempBuffer = new uint8_t[length];
89 uint8_t* dataPtr = reinterpret_cast<uint8_t*>(const_cast<void*>(data));
90 std::copy(dataPtr, dataPtr + length, GetInstance().loadDocTempBuffer);
91 }
92 if (VirtualScreen::isStartCount) {
93 VirtualScreen::isStartCount = false;
94 VirtualScreen::startTime = std::chrono::system_clock::now();
95 thread timerThread(std::ref(VirtualScreenImpl::StartTimer));
96 timerThread.detach();
97 }
98 return false;
99 }
100 return true;
101 }
102
CallBack(const void * data,const size_t length,const int32_t width,const int32_t height)103 bool VirtualScreenImpl::CallBack(const void* data, const size_t length,
104 const int32_t width, const int32_t height)
105 {
106 if (VirtualScreenImpl::GetInstance().StopSendStaticCardImage(STOP_SEND_CARD_DURATION_MS)) {
107 return false;
108 }
109 if (VirtualScreenImpl::GetInstance().GetLoadDocFlag() < VirtualScreen::LoadDocType::FINISHED) {
110 return false;
111 }
112 if (VirtualScreenImpl::GetInstance().JudgeAndDropFrame()) {
113 return false;
114 }
115 VirtualScreenImpl::GetInstance().SetOrignalWidth(width);
116 VirtualScreenImpl::GetInstance().SetOrignalHeight(height);
117 VirtualScreenImpl::GetInstance().SetCompressionWidth(width);
118 VirtualScreenImpl::GetInstance().SetCompressionHeight(height);
119
120 bool staticRet = VirtualScreen::JudgeStaticImage(SEND_IMG_DURATION_MS);
121 if (!staticRet) {
122 return false;
123 }
124
125 if (!LoadDocCallback(data, length, width, height)) {
126 return false;
127 }
128
129 GetInstance().bufferSize = length + GetInstance().headSize;
130 GetInstance().wholeBuffer = new uint8_t[LWS_PRE + GetInstance().bufferSize];
131 GetInstance().screenBuffer = GetInstance().wholeBuffer + LWS_PRE;
132
133 return GetInstance().SendPixmap(data, length, width, height);
134 }
135
PageCallBack(const std::string currentRouterPath)136 bool VirtualScreenImpl::PageCallBack(const std::string currentRouterPath)
137 {
138 std::string currentRouter = currentRouterPath.substr(0, currentRouterPath.size() - 3);
139 ILOG("PageCallback currentPage is : %s", currentRouter.c_str());
140 GetInstance().SetCurrentRouter(currentRouter);
141 Json::Value val;
142 CommandLineInterface::GetInstance().CreatCommandToSendData("CurrentRouter", val, "get");
143 return true;
144 }
145
LoadContentCallBack(const std::string currentRouterPath)146 bool VirtualScreenImpl::LoadContentCallBack(const std::string currentRouterPath)
147 {
148 ILOG("LoadContentCallback currentPage is : %s", currentRouterPath.c_str());
149 GetInstance().SetAbilityCurrentRouter(currentRouterPath);
150 Json::Value val;
151 CommandLineInterface::GetInstance().CreatCommandToSendData("LoadContent", val, "get");
152 return true;
153 }
154
FastPreviewCallBack(const std::string & jsonStr)155 void VirtualScreenImpl::FastPreviewCallBack(const std::string& jsonStr)
156 {
157 GetInstance().SetFastPreviewMsg(jsonStr);
158 Json::Value val;
159 CommandLineInterface::GetInstance().CreatCommandToSendData("FastPreviewMsg", val, "get");
160 }
161
InitAll(string pipeName,string pipePort)162 void VirtualScreenImpl::InitAll(string pipeName, string pipePort)
163 {
164 VirtualScreen::InitPipe(pipeName, pipePort);
165 }
166
VirtualScreenImpl()167 VirtualScreenImpl::VirtualScreenImpl()
168 : isFirstSend(true),
169 isFirstRender(true),
170 writed(0),
171 wholeBuffer(nullptr),
172 screenBuffer(nullptr),
173 bufferSize(0),
174 currentPos(0)
175 {
176 }
177
~VirtualScreenImpl()178 VirtualScreenImpl::~VirtualScreenImpl()
179 {
180 FreeJpgMemory();
181 if (WebSocketServer::GetInstance().firstImageBuffer) {
182 delete [] WebSocketServer::GetInstance().firstImageBuffer;
183 WebSocketServer::GetInstance().firstImageBuffer = nullptr;
184 }
185 if (VirtualScreenImpl::GetInstance().loadDocTempBuffer != nullptr) {
186 delete [] VirtualScreenImpl::GetInstance().loadDocTempBuffer;
187 VirtualScreenImpl::GetInstance().loadDocTempBuffer = nullptr;
188 }
189 if (VirtualScreenImpl::GetInstance().loadDocCopyBuffer != nullptr) {
190 delete [] VirtualScreenImpl::GetInstance().loadDocCopyBuffer;
191 VirtualScreenImpl::GetInstance().loadDocCopyBuffer = nullptr;
192 }
193 }
194
Send(const void * data,int32_t retWidth,int32_t retHeight)195 void VirtualScreenImpl::Send(const void* data, int32_t retWidth, int32_t retHeight)
196 {
197 if (CommandParser::GetInstance().GetScreenMode() == CommandParser::ScreenMode::STATIC
198 && VirtualScreen::isOutOfSeconds) {
199 return;
200 }
201
202 if (retWidth < 1 || retHeight < 1) {
203 FLOG("VirtualScreenImpl::RgbToJpg the retWidth or height is invalid value");
204 }
205 unsigned char* dataTemp = new unsigned char[retWidth * retHeight * jpgPix];
206 for (int i = 0; i < retHeight; i++) {
207 for (int j = 0; j < retWidth; j++) {
208 int input_base_pos = i * retWidth * pixelSize + j * pixelSize;
209 int now_base_pos = i * retWidth * jpgPix + j * jpgPix;
210 dataTemp[now_base_pos + redPos] = *((char*)data + input_base_pos + redPos);
211 dataTemp[now_base_pos + greenPos] = *((char*)data + input_base_pos + greenPos);
212 dataTemp[now_base_pos + bluePos] = *((char*)data + input_base_pos + bluePos);
213 }
214 }
215 VirtualScreen::RgbToJpg(dataTemp, retWidth, retHeight);
216 delete [] dataTemp;
217 if (jpgBufferSize > bufferSize - headSize) {
218 FLOG("VirtualScreenImpl::Send length must < %d", bufferSize - headSize);
219 }
220
221 std::copy(jpgScreenBuffer, jpgScreenBuffer + jpgBufferSize, screenBuffer + headSize);
222 writed = WebSocketServer::GetInstance().WriteData(screenBuffer, headSize + jpgBufferSize);
223 std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex);
224 if (WebSocketServer::GetInstance().firstImageBuffer) {
225 delete [] WebSocketServer::GetInstance().firstImageBuffer;
226 WebSocketServer::GetInstance().firstImageBuffer = nullptr;
227 }
228 WebSocketServer::GetInstance().firstImageBuffer = new uint8_t[LWS_PRE + bufferSize];
229 WebSocketServer::GetInstance().firstImagebufferSize = headSize + jpgBufferSize;
230 std::copy(screenBuffer,
231 screenBuffer + headSize + jpgBufferSize,
232 WebSocketServer::GetInstance().firstImageBuffer + LWS_PRE);
233
234 FreeJpgMemory();
235 }
236
SendPixmap(const void * data,size_t length,int32_t retWidth,int32_t retHeight)237 bool VirtualScreenImpl::SendPixmap(const void* data, size_t length, int32_t retWidth, int32_t retHeight)
238 {
239 if (data == nullptr) {
240 ELOG("render callback data is null.");
241 invalidFrameCountPerMinute++;
242 return false;
243 }
244
245 if (!isWebSocketConfiged) {
246 ELOG("image socket is not ready");
247 return false;
248 }
249
250 if (isFirstRender) {
251 ILOG("Get first render buffer");
252 TraceTool::GetInstance().HandleTrace("Get first render buffer");
253 isFirstRender = false;
254 }
255
256 isFrameUpdated = true;
257 currentPos = 0;
258
259 WriteBuffer(headStart);
260 WriteBuffer(retWidth);
261 WriteBuffer(retHeight);
262 WriteBuffer(retWidth);
263 WriteBuffer(retHeight);
264 if (!CommandParser::GetInstance().IsRegionRefresh()) {
265 for (size_t i = 0; i < headReservedSize / sizeof(int32_t); i++) {
266 WriteBuffer(static_cast<uint32_t>(0));
267 }
268 } else {
269 uint16_t x1 = 0;
270 uint16_t y1 = 0;
271 uint16_t width = static_cast<uint16_t>(retWidth);
272 uint16_t height = static_cast<uint16_t>(retHeight);
273 WriteBuffer(protocolVersion);
274 WriteBuffer(x1);
275 WriteBuffer(y1);
276 WriteBuffer(width);
277 WriteBuffer(height);
278 for (size_t i = 0; i < 10 / sizeof(uint16_t); i++) { // fill 10bytes for header
279 WriteBuffer(static_cast<uint16_t>(0));
280 }
281 }
282 Send(data, retWidth, retHeight);
283 if (isFirstSend) {
284 ILOG("Send first buffer finish");
285 TraceTool::GetInstance().HandleTrace("Send first buffer finish");
286 isFirstSend = false;
287 }
288
289 validFrameCountPerMinute++;
290 sendFrameCountPerMinute++;
291 return writed == length;
292 }
293
FreeJpgMemory()294 void VirtualScreenImpl::FreeJpgMemory()
295 {
296 if (wholeBuffer != nullptr) {
297 delete [] wholeBuffer;
298 wholeBuffer = nullptr;
299 screenBuffer = nullptr;
300 }
301 if (jpgScreenBuffer != nullptr) {
302 free(jpgScreenBuffer);
303 jpgScreenBuffer = NULL;
304 jpgBufferSize = 0;
305 }
306 if (VirtualScreenImpl::GetInstance().loadDocCopyBuffer != nullptr) {
307 delete [] VirtualScreenImpl::GetInstance().loadDocCopyBuffer;
308 VirtualScreenImpl::GetInstance().loadDocCopyBuffer = nullptr;
309 }
310 }
311