• 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 #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