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 "VirtualScreen.h"
17 #include "CommandParser.h"
18 #include "CppTimerManager.h"
19 #include "PreviewerEngineLog.h"
20 #include "VirtualScreen.h"
21 
22 #define boolean jpegboolean
23 #include "jpeglib.h"
24 #undef boolean
25 
26 uint32_t VirtualScreen::validFrameCountPerMinute = 0;
27 uint32_t VirtualScreen::invalidFrameCountPerMinute = 0;
28 uint32_t VirtualScreen::sendFrameCountPerMinute = 0;
29 uint32_t VirtualScreen::inputKeyCountPerMinute = 0;
30 uint32_t VirtualScreen::inputMethodCountPerMinute = 0;
31 bool VirtualScreen::isWebSocketListening = false;
32 std::string VirtualScreen::webSocketPort = "";
33 
34 std::chrono::system_clock::time_point VirtualScreen::startTime = std::chrono::system_clock::now();
35 std::chrono::system_clock::time_point VirtualScreen::staticCardStartTime = std::chrono::system_clock::now();
36 bool VirtualScreen::isStartCount = true;
37 bool VirtualScreen::isOutOfSeconds = false;
38 
VirtualScreen()39 VirtualScreen::VirtualScreen()
40     : isFrameUpdated(false),
41       orignalResolutionWidth(0),
42       orignalResolutionHeight(0),
43       compressionResolutionWidth(0),
44       compressionResolutionHeight(0),
45       screenSocket(nullptr),
46       frameCountTimer(nullptr),
47       isWebSocketConfiged(false),
48       currentRouter(""),
49       jpgScreenBuffer(nullptr),
50       jpgBufferSize(0)
51 {
52 }
53 
~VirtualScreen()54 VirtualScreen::~VirtualScreen()
55 {
56     if (screenSocket != nullptr) {
57         screenSocket->DisconnectFromServer();
58         delete screenSocket;
59         screenSocket = nullptr;
60     }
61 }
62 
GetCurrentRouter() const63 std::string VirtualScreen::GetCurrentRouter() const
64 {
65     return currentRouter;
66 }
67 
SetCurrentRouter(const std::string currentRouterValue)68 void VirtualScreen::SetCurrentRouter(const std::string currentRouterValue)
69 {
70     currentRouter = currentRouterValue;
71 }
72 
GetAbilityCurrentRouter() const73 std::string VirtualScreen::GetAbilityCurrentRouter() const
74 {
75     return abilityCurrentRouter;
76 }
77 
SetAbilityCurrentRouter(const std::string currentRouterValue)78 void VirtualScreen::SetAbilityCurrentRouter(const std::string currentRouterValue)
79 {
80     abilityCurrentRouter = currentRouterValue;
81 }
82 
GetOrignalWidth() const83 int32_t VirtualScreen::GetOrignalWidth() const
84 {
85     return orignalResolutionWidth;
86 }
87 
SetOrignalWidth(const int32_t& value)88 void VirtualScreen::SetOrignalWidth(const int32_t& value)
89 {
90     orignalResolutionWidth = value;
91 }
92 
GetOrignalHeight() const93 int32_t VirtualScreen::GetOrignalHeight() const
94 {
95     return orignalResolutionHeight;
96 }
97 
SetOrignalHeight(const int32_t& value)98 void VirtualScreen::SetOrignalHeight(const int32_t& value)
99 {
100     orignalResolutionHeight = value;
101 }
102 
GetCompressionWidth() const103 int32_t VirtualScreen::GetCompressionWidth() const
104 {
105     return compressionResolutionWidth;
106 }
107 
SetCompressionWidth(const int32_t& value)108 void VirtualScreen::SetCompressionWidth(const int32_t& value)
109 {
110     compressionResolutionWidth = value;
111 }
112 
GetCompressionHeight() const113 int32_t VirtualScreen::GetCompressionHeight() const
114 {
115     return compressionResolutionHeight;
116 }
117 
SetCompressionHeight(const int32_t& value)118 void VirtualScreen::SetCompressionHeight(const int32_t& value)
119 {
120     compressionResolutionHeight = value;
121 }
122 
InitPipe(std::string pipeName, std::string pipePort)123 void VirtualScreen::InitPipe(std::string pipeName, std::string pipePort)
124 {
125     webSocketPort = pipePort;
126     isWebSocketConfiged = true;
127     WebSocketServer::GetInstance().SetServerPort(atoi(pipePort.c_str()));
128     WebSocketServer::GetInstance().Run();
129     isWebSocketListening = true;
130 }
131 
InitVirtualScreen()132 void VirtualScreen::InitVirtualScreen()
133 {
134     int32_t orignalWidth = CommandParser::GetInstance().GetOrignalResolutionWidth();
135     int32_t orignalHeight = CommandParser::GetInstance().GetOrignalResolutionHeight();
136     int32_t compressionWidth = CommandParser::GetInstance().GetCompressionResolutionWidth();
137     int32_t compressionHeight = CommandParser::GetInstance().GetCompressionResolutionHeight();
138     SetVirtualScreenWidthAndHeight(orignalWidth, orignalHeight, compressionWidth, compressionHeight);
139 }
140 
SetVirtualScreenWidthAndHeight(const int32_t& orignalWidth, const int32_t& orignalHeight, const int32_t& compressionWidth, const int32_t& compressionHeight)141 void VirtualScreen::SetVirtualScreenWidthAndHeight(const int32_t& orignalWidth,
142                                                    const int32_t& orignalHeight,
143                                                    const int32_t& compressionWidth,
144                                                    const int32_t& compressionHeight)
145 {
146     VirtualScreen::SetOrignalWidth(orignalWidth);
147     VirtualScreen::SetOrignalHeight(orignalHeight);
148     VirtualScreen::SetCompressionWidth(compressionWidth);
149     VirtualScreen::SetCompressionHeight(compressionHeight);
150 }
151 
WidthAndHeightReverse()152 void VirtualScreen::WidthAndHeightReverse()
153 {
154     int32_t temp = 0;
155     temp = orignalResolutionHeight;
156     orignalResolutionHeight = orignalResolutionWidth;
157     orignalResolutionWidth = temp;
158     temp = compressionResolutionHeight;
159     compressionResolutionHeight = compressionResolutionWidth;
160     compressionResolutionWidth = temp;
161 }
162 
InitFrameCountTimer()163 void VirtualScreen::InitFrameCountTimer()
164 {
165     if (frameCountTimer.get() != nullptr) {
166         ILOG("VirtualScreen::InitFrameCountTimer timer is already started.");
167         return;
168     }
169 
170     frameCountTimer = std::make_unique<CppTimer>(VirtualScreen::PrintFrameCount);
171     if (frameCountTimer == nullptr) {
172         ELOG("JsApp::InitTimer taskHandleTimer memory allocation failed.");
173         return;
174     }
175     CppTimerManager::GetTimerManager().AddCppTimer(*frameCountTimer);
176     frameCountTimer->Start(frameCountPeriod);
177 }
178 
PrintFrameCount()179 void VirtualScreen::PrintFrameCount()
180 {
181     if ((validFrameCountPerMinute | invalidFrameCountPerMinute | sendFrameCountPerMinute |
182         inputKeyCountPerMinute | inputMethodCountPerMinute) == 0) {
183         return;
184     }
185 
186     ELOG("ValidFrameCount: %d InvalidFrameCount: %d SendFrameCount: %d inputKeyCount: %d\
187          inputMethodCount: %d", validFrameCountPerMinute, invalidFrameCountPerMinute,
188          sendFrameCountPerMinute, inputKeyCountPerMinute, inputMethodCountPerMinute);
189     validFrameCountPerMinute = 0;
190     invalidFrameCountPerMinute = 0;
191     sendFrameCountPerMinute = 0;
192     inputKeyCountPerMinute = 0;
193     inputMethodCountPerMinute = 0;
194 }
195 
196 
SetLoadDocFlag(VirtualScreen::LoadDocType flag)197 void VirtualScreen::SetLoadDocFlag(VirtualScreen::LoadDocType flag)
198 {
199     startLoadDoc = flag;
200 }
201 
GetLoadDocFlag() const202 VirtualScreen::LoadDocType VirtualScreen::GetLoadDocFlag() const
203 {
204     return startLoadDoc;
205 }
206 
GetJpgQualityValue(int32_t width, int32_t height) const207 int VirtualScreen::GetJpgQualityValue(int32_t width, int32_t height) const
208 {
209     long long pixCount = static_cast<long long>(width) * static_cast<long long>(height);
210     if (pixCount <= static_cast<int>(JpgPixCountLevel::LOWCOUNT)) {
211         return static_cast<int>(JpgQualityLevel::HIGHLEVEL);
212     } else if (pixCount > static_cast<int>(JpgPixCountLevel::LOWCOUNT) &&
213         pixCount <= static_cast<int>(JpgPixCountLevel::MIDDLECOUNT)) {
214         return static_cast<int>(JpgQualityLevel::MIDDLELEVEL);
215     } else if (pixCount > static_cast<int>(JpgPixCountLevel::MIDDLECOUNT) &&
216         pixCount <= static_cast<int>(JpgPixCountLevel::HIGHCOUNT)) {
217         return static_cast<int>(JpgQualityLevel::LOWLEVEL);
218     } else {
219         return static_cast<int>(JpgQualityLevel::DEFAULTLEVEL);
220     }
221 }
222 
GetFastPreviewMsg() const223 std::string VirtualScreen::GetFastPreviewMsg() const
224 {
225     return fastPreviewMsg;
226 }
227 
SetFastPreviewMsg(const std::string msg)228 void VirtualScreen::SetFastPreviewMsg(const std::string msg)
229 {
230     fastPreviewMsg = msg;
231 }
232 
SetDropFrameFrequency(const int32_t& value)233 void VirtualScreen::SetDropFrameFrequency(const int32_t& value)
234 {
235     dropFrameFrequency = value;
236     startDropFrameTime = std::chrono::system_clock::now();
237 }
238 
JudgeAndDropFrame()239 bool VirtualScreen::JudgeAndDropFrame()
240 {
241     if (dropFrameFrequency <= 0) {
242         return false;
243     }
244     auto endTime = std::chrono::system_clock::now();
245     int64_t timePassed = std::chrono::duration_cast<std::chrono::milliseconds>(endTime -
246                         startDropFrameTime).count();
247     if (timePassed >= dropFrameFrequency) {
248         startDropFrameTime = std::chrono::system_clock::now();
249     }
250     return timePassed < dropFrameFrequency;
251 }
252 
JudgeStaticImage(const int duration)253 bool VirtualScreen::JudgeStaticImage(const int duration)
254 {
255     if (CommandParser::GetInstance().GetScreenMode() == CommandParser::ScreenMode::STATIC) {
256         if (VirtualScreen::isOutOfSeconds) {
257             return false;
258         }
259         if (VirtualScreen::isStartCount) {
260             VirtualScreen::isStartCount = false;
261             VirtualScreen::startTime = std::chrono::system_clock::now();
262         }
263         auto endTime = std::chrono::system_clock::now();
264         int64_t timePassed = std::chrono::duration_cast<std::chrono::milliseconds>(endTime -
265                              VirtualScreen::startTime).count();
266         if (timePassed > duration) {
267             VirtualScreen::isOutOfSeconds = true;
268             return false;
269         }
270     }
271     return true;
272 }
273 
StopSendStaticCardImage(const int duration)274 bool VirtualScreen::StopSendStaticCardImage(const int duration)
275 {
276     if (CommandParser::GetInstance().IsStaticCard()) {
277         static bool first = true;
278         if (first) {
279             first = false;
280             VirtualScreen::staticCardStartTime = std::chrono::system_clock::now();
281         }
282         auto endTime = std::chrono::system_clock::now();
283         int64_t timePassed = std::chrono::duration_cast<std::chrono::milliseconds>(endTime -
284             VirtualScreen::staticCardStartTime).count();
285         if (timePassed > duration) {
286             return true;
287         }
288     }
289     return false;
290 }
291 
RgbToJpg(unsigned char* data, const int32_t width, const int32_t height)292 void VirtualScreen::RgbToJpg(unsigned char* data, const int32_t width, const int32_t height)
293 {
294     if (width < 1 || height < 1) {
295         FLOG("VirtualScreenImpl::RgbToJpg the width or height is invalid value");
296     }
297     jpeg_compress_struct jpeg = {0};
298     jpeg_error_mgr jerr;
299     jpeg.err = jpeg_std_error(&jerr);
300     jpeg_create_compress(&jpeg);
301     jpeg_mem_dest(&jpeg, &jpgScreenBuffer, &jpgBufferSize);
302     jpeg.image_width = width;
303     jpeg.image_height = height;
304     jpeg.input_components = jpgPix;
305     jpeg.in_color_space = JCS_RGB;
306     jpeg_set_defaults(&jpeg);
307     jpeg_set_quality(&jpeg, GetJpgQualityValue(width, height), TRUE);
308     jpeg_start_compress(&jpeg, TRUE);
309     JSAMPROW rowPointer[1];
310     int rowStride = width * jpgPix;
311     while (jpeg.next_scanline < jpeg.image_height) {
312         rowPointer[0] = &data[jpeg.next_scanline * rowStride];
313         jpeg_write_scanlines(&jpeg, rowPointer, 1);
314     }
315     jpeg_finish_compress(&jpeg);
316     jpeg_destroy_compress(&jpeg);
317 }
318 
SetFoldable(const bool value)319 void VirtualScreen::SetFoldable(const bool value)
320 {
321     foldable = value;
322 }
323 
GetFoldable() const324 bool VirtualScreen::GetFoldable() const
325 {
326     return foldable;
327 }
328 
SetFoldStatus(const std::string& value)329 void VirtualScreen::SetFoldStatus(const std::string& value)
330 {
331     foldStatus = value;
332 }
333 
GetFoldStatus() const334 std::string VirtualScreen::GetFoldStatus() const
335 {
336     return foldStatus;
337 }
338 
SetFoldResolution(int32_t changedFoldWidth, int32_t changedFoldHeight)339 void VirtualScreen::SetFoldResolution(int32_t changedFoldWidth, int32_t changedFoldHeight)
340 {
341     foldWidth = changedFoldWidth;
342     foldHeight = changedFoldHeight;
343 }
344 
GetFoldWidth() const345 int32_t VirtualScreen::GetFoldWidth() const
346 {
347     return foldWidth;
348 }
349 
GetFoldHeight() const350 int32_t VirtualScreen::GetFoldHeight() const
351 {
352     return foldHeight;
353 }
354 
SetCurrentResolution(int32_t width, int32_t height)355 void VirtualScreen::SetCurrentResolution(int32_t width, int32_t height)
356 {
357     currentWidth = width;
358     currentHeight = height;
359 }
360 
GetCurrentWidth() const361 int32_t VirtualScreen::GetCurrentWidth() const
362 {
363     return currentWidth;
364 }
365 
GetCurrentHeight() const366 int32_t VirtualScreen::GetCurrentHeight() const
367 {
368     return currentHeight;
369 }
370 
InitFlushEmptyTime()371 void VirtualScreen::InitFlushEmptyTime() {}
372 
InitResolution()373 void VirtualScreen::InitResolution()
374 {
375     CommandInfo commandInfo;
376     CommandParser::GetInstance().GetCommandInfo(commandInfo);
377     SetOrignalWidth(commandInfo.orignalResolutionWidth);
378     SetOrignalHeight(commandInfo.orignalResolutionHeight);
379     SetCompressionWidth(commandInfo.compressionResolutionWidth);
380     SetCompressionHeight(commandInfo.compressionResolutionHeight);
381     SetCurrentResolution(commandInfo.orignalResolutionWidth, commandInfo.orignalResolutionHeight);
382 }