blob: 6845dbbd356de21878f55217e8a790e5e0b5563e [file] [log] [blame]
fei.dengf7a0cd32023-08-29 09:36:37 +00001/*
2 * Copyright (C) 2021 Amlogic Corporation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <linux/videodev2.h>
17#include "wstclient_wayland.h"
18#include "wstclient_plugin.h"
19#include "Logger.h"
fei.dengb9a1a572023-09-13 01:33:57 +000020#include "ErrorCode.h"
fei.dengf7a0cd32023-08-29 09:36:37 +000021
22#define TAG "rlib:wstClient_plugin"
23#define DEFAULT_VIDEO_SERVER "video"
24
fei.dengb9a1a572023-09-13 01:33:57 +000025WstClientPlugin::WstClientPlugin(int logCategory)
26 : mFullscreen(true),
27 mLogCategory(logCategory)
fei.dengf7a0cd32023-08-29 09:36:37 +000028{
29 mIsVideoPip = false;
30 mBufferFormat = VIDEO_FORMAT_UNKNOWN;
31 mNumDroppedFrames = 0;
32 mCommitFrameCnt = 0;
33 mReadyDisplayFrameCnt = 0;
fei.dengb9a1a572023-09-13 01:33:57 +000034 mWayland = new WstClientWayland(this, logCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +000035 mWstClientSocket = NULL;
36 mKeepLastFrame.isSet = false;
37 mKeepLastFrame.value = 0;
38 mHideVideo.isSet = false;
39 mHideVideo.value = 0;
40 mFirstFramePts = -1;
41 mImmediatelyOutput = false;
42 mSetCropFrameRect = false;
fei.dengb9a1a572023-09-13 01:33:57 +000043 mWstEssRMgrOps = new WstEssRMgrOps(this,logCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +000044}
45
46WstClientPlugin::~WstClientPlugin()
47{
48 if (mWayland) {
49 delete mWayland;
50 mWayland = NULL;
51 }
52 if (mWstEssRMgrOps) {
53 delete mWstEssRMgrOps;
54 mWstEssRMgrOps = NULL;
55 }
56
fei.dengb9a1a572023-09-13 01:33:57 +000057 TRACE(mLogCategory,"deconstruct");
fei.dengf7a0cd32023-08-29 09:36:37 +000058}
59
60void WstClientPlugin::init()
61{
fei.dengb9a1a572023-09-13 01:33:57 +000062 INFO(mLogCategory,"\n--------------------------------\n"
fei.dengf7a0cd32023-08-29 09:36:37 +000063 "plugin : westeros\n"
64 "ARCH : %s\n"
65 "branch name : %s\n"
66 "git version : %s\n"
67 "change id : %s \n"
68 "ID : %s \n"
69 "last changed: %s\n"
70 "build-time : %s\n"
71 "build-name : %s\n"
72 "--------------------------------\n",
73#if defined(__aarch64__)
74 "arm64",
75#else
76 "arm",
77#endif
78 BRANCH_NAME,
79 GIT_VERSION,
80 COMMIT_CHANGEID,
81 COMMIT_PD,
82 LAST_CHANGED,
83 BUILD_TIME,
84 BUILD_NAME
85 );
86}
87
88void WstClientPlugin::release()
89{
fei.dengb9a1a572023-09-13 01:33:57 +000090 DEBUG(mLogCategory,"release");
fei.dengf7a0cd32023-08-29 09:36:37 +000091}
92
93void WstClientPlugin::setCallback(void *userData, PluginCallback *callback)
94{
95 mUserData = userData;
96 mCallback = callback;
97}
98
99int WstClientPlugin::openDisplay()
100{
101 int ret = 0;
102
fei.dengb9a1a572023-09-13 01:33:57 +0000103 DEBUG(mLogCategory,"openDisplay");
fei.dengf7a0cd32023-08-29 09:36:37 +0000104
105 mWstEssRMgrOps->resMgrInit();
106 mWstEssRMgrOps->resMgrRequestDecoder(mIsVideoPip);
107
108 //connect video server first
109 if (!mWstClientSocket) {
110 bool rc;
fei.dengb9a1a572023-09-13 01:33:57 +0000111 mWstClientSocket = new WstClientSocket(this, mLogCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +0000112 rc = mWstClientSocket->connectToSocket(DEFAULT_VIDEO_SERVER);
113 if (!rc) {
fei.dengb9a1a572023-09-13 01:33:57 +0000114 ERROR(mLogCategory,"Error connect to video server fail");
fei.dengf7a0cd32023-08-29 09:36:37 +0000115 delete mWstClientSocket;
116 mWstClientSocket = NULL;
fei.dengb9a1a572023-09-13 01:33:57 +0000117 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000118 }
119 }
120
121 if (mWstClientSocket) {
122 mWstClientSocket->sendLayerVideoClientConnection(mIsVideoPip);
123 mWstClientSocket->sendResourceVideoClientConnection(mIsVideoPip);
124 }
125
126 ret = mWayland->connectToWayland();
fei.dengb9a1a572023-09-13 01:33:57 +0000127 if (ret != NO_ERROR) {
128 ERROR(mLogCategory,"Error open display");
fei.dengf7a0cd32023-08-29 09:36:37 +0000129 } else {
130 //run wl display queue dispatch
fei.dengb9a1a572023-09-13 01:33:57 +0000131 DEBUG(mLogCategory,"To run wl display dispatch queue");
fei.dengf7a0cd32023-08-29 09:36:37 +0000132 mWayland->run("display queue");
133 }
134
fei.dengb9a1a572023-09-13 01:33:57 +0000135 DEBUG(mLogCategory,"openDisplay end");
136 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000137}
138
139int WstClientPlugin::openWindow()
140{
141 int ret;
142
fei.dengb9a1a572023-09-13 01:33:57 +0000143 DEBUG(mLogCategory,"openWindow");
fei.dengf7a0cd32023-08-29 09:36:37 +0000144 mCommitFrameCnt = 0;
145 mNumDroppedFrames = 0;
146 mReadyDisplayFrameCnt = 0;
147 /*send session info to server
148 we use mediasync to sync a/v,so select AV_SYNC_MODE_VIDEO_MONO as av clock*/
149 if (mWstClientSocket) {
150 if (mImmediatelyOutput) {
151 mWstClientSocket->sendSessionInfoVideoClientConnection(INVALID_SESSION_ID, SYNC_IMMEDIATE);
152 } else {
153 mWstClientSocket->sendSessionInfoVideoClientConnection(AV_SYNC_SESSION_V_MONO, AV_SYNC_MODE_VIDEO_MONO);
154 }
155 }
156
157 //send hide video
158 if (mWstClientSocket && mHideVideo.isSet) {
159 mWstClientSocket->sendHideVideoClientConnection(mHideVideo.value);
160 }
161
162 //send keep last video frame
163 if (mWstClientSocket && mKeepLastFrame.isSet) {
164 mWstClientSocket->sendKeepLastFrameVideoClientConnection(mKeepLastFrame.value);
165 }
166
167 //send crop frame size if set before window opened
168 if (mSetCropFrameRect) {
169 setCropFrameRect();
170 }
171
fei.dengb9a1a572023-09-13 01:33:57 +0000172 DEBUG(mLogCategory,"openWindow,end");
fei.dengf7a0cd32023-08-29 09:36:37 +0000173 return ret;
174}
175
176int WstClientPlugin::prepareFrame(RenderBuffer *buffer)
177{
fei.dengb9a1a572023-09-13 01:33:57 +0000178 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000179}
180
181int WstClientPlugin::displayFrame(RenderBuffer *buffer, int64_t displayTime)
182{
183 bool ret;
184 WstBufferInfo wstBufferInfo;
185 WstRect wstRect;
186 int x,y,w,h;
187
188 mWayland->getVideoBounds(&x, &y, &w, &h);
189
190 //init wstBufferInfo,must set fd to -1 value
191 memset(&wstBufferInfo, 0, sizeof(WstBufferInfo));
192 for (int i = 0; i < WST_MAX_PLANES; i++) {
193 wstBufferInfo.planeInfo[0].fd = -1;
194 wstBufferInfo.planeInfo[1].fd = -1;
195 wstBufferInfo.planeInfo[2].fd = -1;
196 }
197
198 wstBufferInfo.bufferId = buffer->id;
199 wstBufferInfo.planeCount = buffer->dma.planeCnt;
fei.dengb9a1a572023-09-13 01:33:57 +0000200 TRACE(mLogCategory,"buffer width:%d,height:%d",buffer->dma.width,buffer->dma.height);
fei.dengf7a0cd32023-08-29 09:36:37 +0000201 for (int i = 0; i < buffer->dma.planeCnt; i++) {
202 wstBufferInfo.planeInfo[i].fd = buffer->dma.fd[i];
203 wstBufferInfo.planeInfo[i].stride = buffer->dma.stride[i];
204 wstBufferInfo.planeInfo[i].offset = buffer->dma.offset[i];
fei.dengb9a1a572023-09-13 01:33:57 +0000205 DEBUG(mLogCategory,"buffer id:%d,plane[%d],fd:%d,stride:%d,offset:%d",buffer->id,i,buffer->dma.fd[i],buffer->dma.stride[i],buffer->dma.offset[i]);
fei.dengf7a0cd32023-08-29 09:36:37 +0000206 }
207
208 wstBufferInfo.frameWidth = buffer->dma.width;
209 wstBufferInfo.frameHeight = buffer->dma.height;
210 wstBufferInfo.frameTime = displayTime;
211
212 //change render lib video format to v4l2 support format
213 if (mBufferFormat == VIDEO_FORMAT_NV12) {
214 wstBufferInfo.pixelFormat = V4L2_PIX_FMT_NV12;
215 } else if (mBufferFormat == VIDEO_FORMAT_NV21) {
216 wstBufferInfo.pixelFormat = V4L2_PIX_FMT_NV21;
217 } else {
fei.dengb9a1a572023-09-13 01:33:57 +0000218 ERROR(mLogCategory,"unknown video buffer format:%d",mBufferFormat);
fei.dengf7a0cd32023-08-29 09:36:37 +0000219 }
220
221 wstRect.x = x;
222 wstRect.y = y;
223 wstRect.w = w;
224 wstRect.h = h;
225
226 if (mWstClientSocket) {
227 ret = mWstClientSocket->sendFrameVideoClientConnection(&wstBufferInfo, &wstRect);
228 if (!ret) {
fei.dengb9a1a572023-09-13 01:33:57 +0000229 ERROR(mLogCategory,"send video frame to server fail");
fei.dengf7a0cd32023-08-29 09:36:37 +0000230 handleFrameDropped(buffer);
231 handleBufferRelease(buffer);
fei.dengb9a1a572023-09-13 01:33:57 +0000232 return ERROR_FAILED_TRANSACTION;
fei.dengf7a0cd32023-08-29 09:36:37 +0000233 }
234 }
235
236 //storage render buffer to manager
237 std::lock_guard<std::mutex> lck(mRenderLock);
238 std::pair<int, RenderBuffer *> item(buffer->id, buffer);
239 mRenderBuffersMap.insert(item);
240 ++mCommitFrameCnt;
241 ++mReadyDisplayFrameCnt;
fei.dengb9a1a572023-09-13 01:33:57 +0000242 TRACE(mLogCategory,"committed to westeros cnt:%d,readyDisplayFramesCnt:%d",mCommitFrameCnt,mReadyDisplayFrameCnt);
fei.dengf7a0cd32023-08-29 09:36:37 +0000243
244 //storage displayed render buffer
245 std::pair<int, int64_t> displayitem(buffer->id, displayTime);
246 mDisplayedFrameMap.insert(displayitem);
247 if (mFirstFramePts == -1) {
248 mFirstFramePts = buffer->pts;
249 }
250
fei.dengb9a1a572023-09-13 01:33:57 +0000251 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000252}
253
254int WstClientPlugin::flush()
255{
256 int ret;
fei.dengb9a1a572023-09-13 01:33:57 +0000257 INFO(mLogCategory,"flush");
fei.dengf7a0cd32023-08-29 09:36:37 +0000258 if (mWstClientSocket) {
259 mWstClientSocket->sendFlushVideoClientConnection();
260 }
261 //drop frames those had committed to westeros
262 std::lock_guard<std::mutex> lck(mRenderLock);
263 for (auto item = mDisplayedFrameMap.begin(); item != mDisplayedFrameMap.end(); ) {
264 int bufferid = (int)item->first;
265 auto bufItem = mRenderBuffersMap.find(bufferid);
266 if (bufItem == mRenderBuffersMap.end()) {
267 continue;
268 }
269 mDisplayedFrameMap.erase(item++);
270 RenderBuffer *renderbuffer = (RenderBuffer*) bufItem->second;
271 if (renderbuffer) {
272 handleFrameDropped(renderbuffer);
273 }
274 }
275
fei.dengb9a1a572023-09-13 01:33:57 +0000276 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000277}
278
279int WstClientPlugin::pause()
280{
281 int ret;
fei.dengb9a1a572023-09-13 01:33:57 +0000282 INFO(mLogCategory,"pause");
fei.dengf7a0cd32023-08-29 09:36:37 +0000283 if (mWstClientSocket) {
284 int waitCnt = 20; //we wait about 10 vsync duration
285 while (mReadyDisplayFrameCnt != 0 && waitCnt > 0) {
286 usleep(8000);
287 --waitCnt;
288 }
289 std::lock_guard<std::mutex> lck(mRenderLock);
290 if (mReadyDisplayFrameCnt == 0) { //send pause cmd immediatialy if no frame displays
291 mWstClientSocket->sendPauseVideoClientConnection(true);
292 }
293 }
294 mWstEssRMgrOps->resMgrUpdateState(EssRMgrRes_paused);
fei.dengb9a1a572023-09-13 01:33:57 +0000295 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000296}
297
298int WstClientPlugin::resume()
299{
300 int ret;
fei.dengb9a1a572023-09-13 01:33:57 +0000301 INFO(mLogCategory,"resume");
fei.dengf7a0cd32023-08-29 09:36:37 +0000302 std::lock_guard<std::mutex> lck(mRenderLock);
303 if (mWstClientSocket) {
304 mWstClientSocket->sendPauseVideoClientConnection(false);
305 }
306 mWstEssRMgrOps->resMgrUpdateState(EssRMgrRes_active);
fei.dengb9a1a572023-09-13 01:33:57 +0000307 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000308}
309
310int WstClientPlugin::closeDisplay()
311{
fei.dengb9a1a572023-09-13 01:33:57 +0000312 INFO(mLogCategory,"closeDisplay, in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000313 mWayland->disconnectFromWayland();
314 mWstEssRMgrOps->resMgrReleaseDecoder();
315 mWstEssRMgrOps->resMgrTerm();
fei.dengb9a1a572023-09-13 01:33:57 +0000316 INFO(mLogCategory,"closeDisplay, out");
317 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000318}
319
320int WstClientPlugin::closeWindow()
321{
fei.dengb9a1a572023-09-13 01:33:57 +0000322 DEBUG(mLogCategory,"closeWindow, in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000323 if (mWstClientSocket) {
324 mWstClientSocket->disconnectFromSocket();
325 delete mWstClientSocket;
326 mWstClientSocket = NULL;
327 }
328
329 std::lock_guard<std::mutex> lck(mRenderLock);
330 //drop all frames those don't displayed
331 for (auto item = mDisplayedFrameMap.begin(); item != mDisplayedFrameMap.end(); ) {
332 int bufferid = (int)item->first;
333 auto bufItem = mRenderBuffersMap.find(bufferid);
334 if (bufItem == mRenderBuffersMap.end()) {
335 continue;
336 }
337 mDisplayedFrameMap.erase(item++);
338 RenderBuffer *renderbuffer = (RenderBuffer*) bufItem->second;
339 if (renderbuffer) {
340 handleFrameDropped(renderbuffer);
341 }
342 }
343 //release all frames those had committed to westeros server
344 for (auto item = mRenderBuffersMap.begin(); item != mRenderBuffersMap.end();) {
345 RenderBuffer *renderbuffer = (RenderBuffer*) item->second;
346 mRenderBuffersMap.erase(item++);
347 if (renderbuffer) {
348 handleBufferRelease(renderbuffer);
349 }
350 }
351 mWstEssRMgrOps->resMgrUpdateState(EssRMgrRes_idle);
352 mRenderBuffersMap.clear();
353 mDisplayedFrameMap.clear();
354 mCommitFrameCnt = 0;
355 mNumDroppedFrames = 0;
356 mReadyDisplayFrameCnt = 0;
357 mImmediatelyOutput = false;
fei.dengb9a1a572023-09-13 01:33:57 +0000358 DEBUG(mLogCategory,"out");
359 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000360}
361
362int WstClientPlugin::getValue(PluginKey key, void *value)
363{
364 switch (key) {
365 case PLUGIN_KEY_KEEP_LAST_FRAME: {
366 *(int *)value = mKeepLastFrame.value;
fei.dengb9a1a572023-09-13 01:33:57 +0000367 TRACE(mLogCategory,"get keep last frame:%d",*(int *)value);
fei.dengf7a0cd32023-08-29 09:36:37 +0000368 } break;
369 case PLUGIN_KEY_HIDE_VIDEO: {
370 *(int *)value = mHideVideo.value;
fei.dengb9a1a572023-09-13 01:33:57 +0000371 TRACE(mLogCategory,"get hide video:%d",*(int *)value);
fei.dengf7a0cd32023-08-29 09:36:37 +0000372 } break;
373 case PLUGIN_KEY_CROP_FRAME_SIZE: {
374 RenderRect* rect = static_cast<RenderRect*>(value);
375 rect->x = mCropFrameRect.x;
376 rect->y = mCropFrameRect.y;
377 rect->w = mCropFrameRect.w;
378 rect->h = mCropFrameRect.h;
379 } break;
380 }
fei.dengb9a1a572023-09-13 01:33:57 +0000381 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000382}
383
384int WstClientPlugin::setValue(PluginKey key, void *value)
385{
386 switch (key) {
387 case PLUGIN_KEY_WINDOW_SIZE: {
388 RenderRect* rect = static_cast<RenderRect*>(value);
389 if (mWayland) {
390 mWayland->setWindowSize(rect->x, rect->y, rect->w, rect->h);
391 }
392 } break;
393 case PLUGIN_KEY_FRAME_SIZE: {
394 RenderFrameSize * frameSize = static_cast<RenderFrameSize * >(value);
395 if (mWayland) {
396 mWayland->setFrameSize(frameSize->width, frameSize->height);
397 }
398 //if set crop property before set frame size,we set crop params now, because
399 //crop property dependent frame size
400 if (mSetCropFrameRect) {
401 setCropFrameRect();
402 }
403 } break;
404 case PLUGIN_KEY_VIDEO_FORMAT: {
405 int format = *(int *)(value);
406 mBufferFormat = (RenderVideoFormat) format;
fei.dengb9a1a572023-09-13 01:33:57 +0000407 DEBUG(mLogCategory,"Set video format :%d",mBufferFormat);
fei.dengf7a0cd32023-08-29 09:36:37 +0000408 } break;
409 case PLUGIN_KEY_VIDEO_PIP: {
410 int pip = *(int *) (value);
411 mIsVideoPip = pip > 0? true:false;
412 };
413 case PLUGIN_KEY_KEEP_LAST_FRAME: {
414 int keep = *(int *) (value);
415 mKeepLastFrame.value = keep > 0? true:false;
416 mKeepLastFrame.isSet = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000417 DEBUG(mLogCategory, "Set keep last frame :%d",mKeepLastFrame.value);
fei.dengf7a0cd32023-08-29 09:36:37 +0000418 if (mWstClientSocket) {
419 mWstClientSocket->sendKeepLastFrameVideoClientConnection(mKeepLastFrame.value);
420 }
421 } break;
422 case PLUGIN_KEY_HIDE_VIDEO: {
423 int hide = *(int *)(value);
424 mHideVideo.value = hide > 0? true:false;
425 mHideVideo.isSet = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000426 DEBUG(mLogCategory, "Set hide video:%d",mHideVideo.value);
fei.dengf7a0cd32023-08-29 09:36:37 +0000427 if (mWstClientSocket) {
428 mWstClientSocket->sendHideVideoClientConnection(mHideVideo.value);
429 }
430 } break;
431 case PLUGIN_KEY_FORCE_ASPECT_RATIO: {
432 int forceAspectRatio = *(int *)(value);
433 if (mWayland) {
434 mWayland->setForceAspectRatio(forceAspectRatio > 0? true:false);
435 }
436 } break;
437 case PLUGIN_KEY_IMMEDIATELY_OUTPUT: {
438 int immediately = *(int *)(value);
439 mImmediatelyOutput = immediately > 0? true: false;
fei.dengb9a1a572023-09-13 01:33:57 +0000440 DEBUG(mLogCategory,"Set immediately output:%d",mImmediatelyOutput);
fei.dengf7a0cd32023-08-29 09:36:37 +0000441 if (mImmediatelyOutput && mWstClientSocket) {
442 mWstClientSocket->sendSessionInfoVideoClientConnection(INVALID_SESSION_ID, SYNC_IMMEDIATE);
443 }
444 } break;
445 case PLUGIN_KEY_CROP_FRAME_SIZE: {
446 RenderRect* rect = static_cast<RenderRect*>(value);
447 mCropFrameRect.x = rect->x;
448 mCropFrameRect.y = rect->y;
449 mCropFrameRect.w = rect->w;
450 mCropFrameRect.h = rect->h;
451 mSetCropFrameRect = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000452 INFO(mLogCategory,"crop params (%d,%d,%d,%d)",rect->x,rect->y,rect->w,rect->h);
fei.dengf7a0cd32023-08-29 09:36:37 +0000453 setCropFrameRect();
454 } break;
455 case PLUGIN_KEY_PIXEL_ASPECT_RATIO: {
456 double ratio = *(double *)(value);
fei.dengb9a1a572023-09-13 01:33:57 +0000457 INFO(mLogCategory,"pixel aspect ratio :%f",ratio);
fei.dengf7a0cd32023-08-29 09:36:37 +0000458 if (mWayland) {
459 mWayland->setPixelAspectRatio((double)ratio);
460 }
461 } break;
462 }
fei.dengb9a1a572023-09-13 01:33:57 +0000463 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000464}
465
466void WstClientPlugin::handleBufferRelease(RenderBuffer *buffer)
467{
468 if (mCallback) {
469 mCallback->doBufferReleaseCallback(mUserData, (void *)buffer);
470 }
471}
472
473void WstClientPlugin::handleFrameDisplayed(RenderBuffer *buffer)
474{
475 if (mCallback) {
476 mCallback->doBufferDisplayedCallback(mUserData, (void *)buffer);
477 }
478}
479
480void WstClientPlugin::handleFrameDropped(RenderBuffer *buffer)
481{
482 if (mCallback) {
483 mCallback->doBufferDropedCallback(mUserData, (void *)buffer);
484 }
485}
486
487void WstClientPlugin::handleMsgNotify(int type, void *detail)
488{
489 if (mCallback) {
490 mCallback->doMsgCallback(mUserData, type, detail);
491 }
492}
493
494void WstClientPlugin::setVideoRect(int videoX, int videoY, int videoWidth, int videoHeight)
495{
496 if (mWstClientSocket) {
497 mWstClientSocket->sendRectVideoClientConnection(videoX, videoY, videoWidth, videoHeight);
498 }
499}
500
501void WstClientPlugin::onWstSocketEvent(WstEvent *event)
502{
fei.dengb9a1a572023-09-13 01:33:57 +0000503 Tls::Mutex::Autolock _l(mMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000504 switch (event->event)
505 {
506 case WST_REFRESH_RATE: {
507 int rate = event->param;
fei.dengb9a1a572023-09-13 01:33:57 +0000508 INFO(mLogCategory,"refresh rate:%d",rate);
fei.dengf7a0cd32023-08-29 09:36:37 +0000509 } break;
510 case WST_BUFFER_RELEASE: {
511 int bufferid = event->param;
fei.dengb9a1a572023-09-13 01:33:57 +0000512 TRACE(mLogCategory,"Buffer release id:%d",bufferid);
fei.dengf7a0cd32023-08-29 09:36:37 +0000513 RenderBuffer *renderbuffer = NULL;
514 bool isDropped = false;
515 int64_t displaytime = 0;
516 {
517 std::lock_guard<std::mutex> lck(mRenderLock);
518 auto renderBufferItem = mRenderBuffersMap.find(bufferid);
519 if (renderBufferItem == mRenderBuffersMap.end()) {
fei.dengb9a1a572023-09-13 01:33:57 +0000520 WARNING(mLogCategory,"can't find map Renderbuffer");
fei.dengf7a0cd32023-08-29 09:36:37 +0000521 return ;
522 }
523 --mCommitFrameCnt;
524 renderbuffer = (RenderBuffer*) renderBufferItem->second;
525 //remove had release render buffer
526 mRenderBuffersMap.erase(bufferid);
527 auto displayFrameItem = mDisplayedFrameMap.find(bufferid);
528 if (displayFrameItem != mDisplayedFrameMap.end()) {
529 mDisplayedFrameMap.erase(bufferid);
530 --mReadyDisplayFrameCnt;
531 isDropped = true;
532 displaytime = (int64_t)displayFrameItem->second;
533 }
534 }
535
536 if (renderbuffer) {
537 /*if we can find item in mDisplayedFrameMap,
538 this buffer is dropped by westeros server,so we
539 must call displayed callback*/
540 if (isDropped) {
fei.dengb9a1a572023-09-13 01:33:57 +0000541 WARNING(mLogCategory,"Frame droped,pts:%lld us,displaytime:%lld,readyDisplayFramesCnt:%d",\
fei.dengf7a0cd32023-08-29 09:36:37 +0000542 renderbuffer->pts/1000,displaytime,mReadyDisplayFrameCnt);
543 handleFrameDropped(renderbuffer);
544 }
545 handleBufferRelease(renderbuffer);
546 }
fei.dengb9a1a572023-09-13 01:33:57 +0000547 TRACE(mLogCategory,"remain on westeros cnt:%d",mCommitFrameCnt);
fei.dengf7a0cd32023-08-29 09:36:37 +0000548 } break;
549 case WST_STATUS: {
550 int dropframes = event->param;
551 int64_t frameTime = event->lparam;
fei.dengb9a1a572023-09-13 01:33:57 +0000552 TRACE(mLogCategory,"WST_STATUS,dropframes:%d,frameTime:%lld",dropframes,frameTime);
fei.dengf7a0cd32023-08-29 09:36:37 +0000553 RenderBuffer *renderbuffer = NULL;
554 if (mNumDroppedFrames != event->param) {
555 mNumDroppedFrames = event->param;
fei.dengb9a1a572023-09-13 01:33:57 +0000556 WARNING(mLogCategory,"frame dropped cnt:%d",mNumDroppedFrames);
fei.dengf7a0cd32023-08-29 09:36:37 +0000557 }
558 //update status,if frameTime isn't equal -1LL
559 //this buffer had displayed
560 if (frameTime != -1LL) {
561 std::lock_guard<std::mutex> lck(mRenderLock);
562 --mReadyDisplayFrameCnt;
fei.dengb9a1a572023-09-13 01:33:57 +0000563 TRACE(mLogCategory,"displayed frame time:%lld,readyDisplayFramesCnt:%d",frameTime,mReadyDisplayFrameCnt);
fei.dengf7a0cd32023-08-29 09:36:37 +0000564 int bufferId = getDisplayFrameBufferId(frameTime);
565 if (bufferId < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000566 WARNING(mLogCategory,"can't find map displayed frame:%lld",frameTime);
fei.dengf7a0cd32023-08-29 09:36:37 +0000567 return ;
568 }
569 auto displayItem = mDisplayedFrameMap.find(bufferId);
570 if (displayItem != mDisplayedFrameMap.end()) {
571 mDisplayedFrameMap.erase(bufferId);
572 }
573 auto item = mRenderBuffersMap.find(bufferId);
574 if (item != mRenderBuffersMap.end()) {
575 renderbuffer = (RenderBuffer*) item->second;
576 }
577 }
578 if (renderbuffer) {
579 //first frame signal
580 if (renderbuffer->pts == mFirstFramePts) {
581 handleMsgNotify(MSG_FIRST_FRAME,(void*)&renderbuffer->pts);
582 }
583 handleFrameDisplayed(renderbuffer);
584 }
585 } break;
586 case WST_UNDERFLOW: {
587 uint64_t frameTime = event->lparam;
fei.dengb9a1a572023-09-13 01:33:57 +0000588 TRACE(mLogCategory,"under flow frametime:%lld",frameTime);
fei.dengf7a0cd32023-08-29 09:36:37 +0000589 //under flow event sended must be after sending first frame to westeros
590 if (mFirstFramePts != -1) {
591 handleMsgNotify(MSG_UNDER_FLOW, NULL);
592 }
593 } break;
594 case WST_ZOOM_MODE: {
595 int mode = event->param;
596 bool globalZoomActive = event->param1 > 0? true:false;
597 bool allow4kZoom = event->param2 > 0? true:false;;
598 mWayland->setZoomMode(mode, globalZoomActive, allow4kZoom);
599 } break;
600 case WST_DEBUG_LEVEL: {
601 /* code */
602 } break;
603 default:
604 break;
605 }
606}
607
608int WstClientPlugin::getDisplayFrameBufferId(int64_t displayTime)
609{
610 int bufId = -1;
611 for (auto item = mDisplayedFrameMap.begin(); item != mDisplayedFrameMap.end(); item++) {
612 int64_t time = (int64_t)item->second;
613 if (time == displayTime) {
614 bufId = (int)item->first;
615 break;
616 }
617 }
618 return bufId;
619}
620
621bool WstClientPlugin::setCropFrameRect()
622{
623 if (mWayland) {
624 int frameWidth,frameHeight;
625 mWayland->getFrameSize(&frameWidth, &frameHeight);
626 if (frameWidth <= 0 || frameHeight <= 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000627 WARNING(mLogCategory, "no set video frame size,set crop params later");
fei.dengf7a0cd32023-08-29 09:36:37 +0000628 goto bad_param;
629 }
630
631 //correct crop rect if needed
632 if (frameWidth > 0 && (mCropFrameRect.x + mCropFrameRect.w) > frameWidth) {
633 if (mCropFrameRect.x < frameWidth) {
634 int oriX = mCropFrameRect.x;
635 int oriW = mCropFrameRect.w;
636 mCropFrameRect.w = frameWidth - mCropFrameRect.x;
fei.dengb9a1a572023-09-13 01:33:57 +0000637 WARNING(mLogCategory, "correct crop x:%d, w:%d to x:%d, w:%d", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000638 oriX,oriW,mCropFrameRect.x,mCropFrameRect.w);
639 } else {
fei.dengb9a1a572023-09-13 01:33:57 +0000640 ERROR(mLogCategory, "Error crop params (%d,%d,%d,%d) frame(%d,%d)", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000641 mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h,frameWidth,frameHeight);
642 goto bad_param;
643 }
644 }
645 if (frameHeight > 0 && (mCropFrameRect.y + mCropFrameRect.h) > frameHeight) {
646 if (mCropFrameRect.y < frameHeight) {
647 int oriY = mCropFrameRect.x;
648 int oriH = mCropFrameRect.w;
649 mCropFrameRect.h = frameHeight - mCropFrameRect.y;
fei.dengb9a1a572023-09-13 01:33:57 +0000650 WARNING(mLogCategory, "correct crop y:%d, h:%d to y:%d, h:%d", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000651 oriY,oriH,mCropFrameRect.y,mCropFrameRect.h);
652 } else {
fei.dengb9a1a572023-09-13 01:33:57 +0000653 ERROR(mLogCategory, "Error crop params (%d,%d,%d,%d) frame(%d,%d)", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000654 mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h,frameWidth,frameHeight);
655 goto bad_param;
656 }
657 }
fei.dengb9a1a572023-09-13 01:33:57 +0000658 INFO(mLogCategory, "crop (%d,%d,%d,%d)", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000659 mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h);
660 }
661 if (mWstClientSocket && mSetCropFrameRect) {
662 mWstClientSocket->sendCropFrameSizeClientConnection(mCropFrameRect.x, mCropFrameRect.y, mCropFrameRect.w, mCropFrameRect.h);
663 mSetCropFrameRect = false;
664 }
665 return true;
666bad_param:
667 return false;
668}
669
670void *makePluginInstance(int id)
671{
fei.dengb9a1a572023-09-13 01:33:57 +0000672 int category =Logger_init(id);
fei.dengf7a0cd32023-08-29 09:36:37 +0000673 char *env = getenv("VIDEO_RENDER_LOG_LEVEL");
674 if (env) {
675 int level = atoi(env);
676 Logger_set_level(level);
fei.dengb9a1a572023-09-13 01:33:57 +0000677 INFO(category,"VIDEO_RENDER_LOG_LEVEL=%d",level);
fei.dengf7a0cd32023-08-29 09:36:37 +0000678 }
fei.dengb9a1a572023-09-13 01:33:57 +0000679 WstClientPlugin *pluginInstance = new WstClientPlugin(category);
fei.dengf7a0cd32023-08-29 09:36:37 +0000680 return static_cast<void *>(pluginInstance);
681}
682
683void destroyPluginInstance(void * plugin)
684{
fei.dengb9a1a572023-09-13 01:33:57 +0000685 int category;
686
fei.dengf7a0cd32023-08-29 09:36:37 +0000687 WstClientPlugin *pluginInstance = static_cast<WstClientPlugin *>(plugin);
fei.dengb9a1a572023-09-13 01:33:57 +0000688 category = pluginInstance->getLogCategory();
fei.dengf7a0cd32023-08-29 09:36:37 +0000689 delete pluginInstance;
fei.dengb9a1a572023-09-13 01:33:57 +0000690 Logger_exit(category);
fei.dengf7a0cd32023-08-29 09:36:37 +0000691}