blob: 1fa50774422c9bfee3403c9a7c38ba59729af84d [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.deng7ac1aeb2023-12-05 01:38:57 +000043 mFrameRateFractionNum = 0;
44 mFrameRateFractionDenom = 0;
45 mFrameRateChanged = false;
fei.dengb9a1a572023-09-13 01:33:57 +000046 mWstEssRMgrOps = new WstEssRMgrOps(this,logCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +000047}
48
49WstClientPlugin::~WstClientPlugin()
50{
51 if (mWayland) {
52 delete mWayland;
53 mWayland = NULL;
54 }
55 if (mWstEssRMgrOps) {
56 delete mWstEssRMgrOps;
57 mWstEssRMgrOps = NULL;
58 }
59
fei.dengb9a1a572023-09-13 01:33:57 +000060 TRACE(mLogCategory,"deconstruct");
fei.dengf7a0cd32023-08-29 09:36:37 +000061}
62
63void WstClientPlugin::init()
64{
fei.dengb9a1a572023-09-13 01:33:57 +000065 INFO(mLogCategory,"\n--------------------------------\n"
fei.dengf7a0cd32023-08-29 09:36:37 +000066 "plugin : westeros\n"
67 "ARCH : %s\n"
68 "branch name : %s\n"
69 "git version : %s\n"
70 "change id : %s \n"
71 "ID : %s \n"
72 "last changed: %s\n"
73 "build-time : %s\n"
74 "build-name : %s\n"
75 "--------------------------------\n",
76#if defined(__aarch64__)
77 "arm64",
78#else
79 "arm",
80#endif
81 BRANCH_NAME,
82 GIT_VERSION,
83 COMMIT_CHANGEID,
84 COMMIT_PD,
85 LAST_CHANGED,
86 BUILD_TIME,
87 BUILD_NAME
88 );
89}
90
91void WstClientPlugin::release()
92{
fei.dengb9a1a572023-09-13 01:33:57 +000093 DEBUG(mLogCategory,"release");
fei.dengf7a0cd32023-08-29 09:36:37 +000094}
95
96void WstClientPlugin::setCallback(void *userData, PluginCallback *callback)
97{
98 mUserData = userData;
99 mCallback = callback;
100}
101
102int WstClientPlugin::openDisplay()
103{
104 int ret = 0;
105
fei.dengb9a1a572023-09-13 01:33:57 +0000106 DEBUG(mLogCategory,"openDisplay");
fei.dengf7a0cd32023-08-29 09:36:37 +0000107
108 mWstEssRMgrOps->resMgrInit();
109 mWstEssRMgrOps->resMgrRequestDecoder(mIsVideoPip);
110
111 //connect video server first
112 if (!mWstClientSocket) {
113 bool rc;
fei.dengb9a1a572023-09-13 01:33:57 +0000114 mWstClientSocket = new WstClientSocket(this, mLogCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +0000115 rc = mWstClientSocket->connectToSocket(DEFAULT_VIDEO_SERVER);
116 if (!rc) {
fei.dengb9a1a572023-09-13 01:33:57 +0000117 ERROR(mLogCategory,"Error connect to video server fail");
fei.dengf7a0cd32023-08-29 09:36:37 +0000118 delete mWstClientSocket;
119 mWstClientSocket = NULL;
fei.dengb9a1a572023-09-13 01:33:57 +0000120 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000121 }
122 }
123
124 if (mWstClientSocket) {
125 mWstClientSocket->sendLayerVideoClientConnection(mIsVideoPip);
126 mWstClientSocket->sendResourceVideoClientConnection(mIsVideoPip);
127 }
128
129 ret = mWayland->connectToWayland();
fei.dengb9a1a572023-09-13 01:33:57 +0000130 if (ret != NO_ERROR) {
131 ERROR(mLogCategory,"Error open display");
fei.dengf7a0cd32023-08-29 09:36:37 +0000132 } else {
133 //run wl display queue dispatch
fei.dengb9a1a572023-09-13 01:33:57 +0000134 DEBUG(mLogCategory,"To run wl display dispatch queue");
fei.dengf7a0cd32023-08-29 09:36:37 +0000135 mWayland->run("display queue");
136 }
137
fei.dengb9a1a572023-09-13 01:33:57 +0000138 DEBUG(mLogCategory,"openDisplay end");
139 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000140}
141
142int WstClientPlugin::openWindow()
143{
144 int ret;
145
fei.dengb9a1a572023-09-13 01:33:57 +0000146 DEBUG(mLogCategory,"openWindow");
fei.dengf7a0cd32023-08-29 09:36:37 +0000147 mCommitFrameCnt = 0;
148 mNumDroppedFrames = 0;
149 mReadyDisplayFrameCnt = 0;
150 /*send session info to server
151 we use mediasync to sync a/v,so select AV_SYNC_MODE_VIDEO_MONO as av clock*/
152 if (mWstClientSocket) {
153 if (mImmediatelyOutput) {
154 mWstClientSocket->sendSessionInfoVideoClientConnection(INVALID_SESSION_ID, SYNC_IMMEDIATE);
155 } else {
156 mWstClientSocket->sendSessionInfoVideoClientConnection(AV_SYNC_SESSION_V_MONO, AV_SYNC_MODE_VIDEO_MONO);
157 }
158 }
159
160 //send hide video
161 if (mWstClientSocket && mHideVideo.isSet) {
162 mWstClientSocket->sendHideVideoClientConnection(mHideVideo.value);
163 }
164
165 //send keep last video frame
166 if (mWstClientSocket && mKeepLastFrame.isSet) {
167 mWstClientSocket->sendKeepLastFrameVideoClientConnection(mKeepLastFrame.value);
168 }
169
170 //send crop frame size if set before window opened
171 if (mSetCropFrameRect) {
172 setCropFrameRect();
173 }
174
fei.dengb9a1a572023-09-13 01:33:57 +0000175 DEBUG(mLogCategory,"openWindow,end");
fei.dengf7a0cd32023-08-29 09:36:37 +0000176 return ret;
177}
178
179int WstClientPlugin::prepareFrame(RenderBuffer *buffer)
180{
fei.dengb9a1a572023-09-13 01:33:57 +0000181 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000182}
183
184int WstClientPlugin::displayFrame(RenderBuffer *buffer, int64_t displayTime)
185{
186 bool ret;
187 WstBufferInfo wstBufferInfo;
188 WstRect wstRect;
189 int x,y,w,h;
190
fei.deng7ac1aeb2023-12-05 01:38:57 +0000191 if (mWstClientSocket && mFrameRateChanged) {
192 mFrameRateChanged = false;
193 mWstClientSocket->sendRateVideoClientConnection(mFrameRateFractionNum, mFrameRateFractionDenom);
194 }
195
fei.dengf7a0cd32023-08-29 09:36:37 +0000196 mWayland->getVideoBounds(&x, &y, &w, &h);
197
198 //init wstBufferInfo,must set fd to -1 value
199 memset(&wstBufferInfo, 0, sizeof(WstBufferInfo));
200 for (int i = 0; i < WST_MAX_PLANES; i++) {
201 wstBufferInfo.planeInfo[0].fd = -1;
202 wstBufferInfo.planeInfo[1].fd = -1;
203 wstBufferInfo.planeInfo[2].fd = -1;
204 }
205
206 wstBufferInfo.bufferId = buffer->id;
207 wstBufferInfo.planeCount = buffer->dma.planeCnt;
fei.dengb9a1a572023-09-13 01:33:57 +0000208 TRACE(mLogCategory,"buffer width:%d,height:%d",buffer->dma.width,buffer->dma.height);
fei.dengf7a0cd32023-08-29 09:36:37 +0000209 for (int i = 0; i < buffer->dma.planeCnt; i++) {
210 wstBufferInfo.planeInfo[i].fd = buffer->dma.fd[i];
211 wstBufferInfo.planeInfo[i].stride = buffer->dma.stride[i];
212 wstBufferInfo.planeInfo[i].offset = buffer->dma.offset[i];
fei.dengb9a1a572023-09-13 01:33:57 +0000213 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 +0000214 }
215
216 wstBufferInfo.frameWidth = buffer->dma.width;
217 wstBufferInfo.frameHeight = buffer->dma.height;
218 wstBufferInfo.frameTime = displayTime;
219
220 //change render lib video format to v4l2 support format
221 if (mBufferFormat == VIDEO_FORMAT_NV12) {
222 wstBufferInfo.pixelFormat = V4L2_PIX_FMT_NV12;
223 } else if (mBufferFormat == VIDEO_FORMAT_NV21) {
224 wstBufferInfo.pixelFormat = V4L2_PIX_FMT_NV21;
225 } else {
fei.dengb9a1a572023-09-13 01:33:57 +0000226 ERROR(mLogCategory,"unknown video buffer format:%d",mBufferFormat);
fei.dengf7a0cd32023-08-29 09:36:37 +0000227 }
228
229 wstRect.x = x;
230 wstRect.y = y;
231 wstRect.w = w;
232 wstRect.h = h;
233
234 if (mWstClientSocket) {
235 ret = mWstClientSocket->sendFrameVideoClientConnection(&wstBufferInfo, &wstRect);
236 if (!ret) {
fei.dengb9a1a572023-09-13 01:33:57 +0000237 ERROR(mLogCategory,"send video frame to server fail");
fei.dengf7a0cd32023-08-29 09:36:37 +0000238 handleFrameDropped(buffer);
239 handleBufferRelease(buffer);
fei.dengb9a1a572023-09-13 01:33:57 +0000240 return ERROR_FAILED_TRANSACTION;
fei.dengf7a0cd32023-08-29 09:36:37 +0000241 }
242 }
243
244 //storage render buffer to manager
245 std::lock_guard<std::mutex> lck(mRenderLock);
246 std::pair<int, RenderBuffer *> item(buffer->id, buffer);
247 mRenderBuffersMap.insert(item);
248 ++mCommitFrameCnt;
249 ++mReadyDisplayFrameCnt;
fei.dengb9a1a572023-09-13 01:33:57 +0000250 TRACE(mLogCategory,"committed to westeros cnt:%d,readyDisplayFramesCnt:%d",mCommitFrameCnt,mReadyDisplayFrameCnt);
fei.dengf7a0cd32023-08-29 09:36:37 +0000251
252 //storage displayed render buffer
253 std::pair<int, int64_t> displayitem(buffer->id, displayTime);
254 mDisplayedFrameMap.insert(displayitem);
255 if (mFirstFramePts == -1) {
256 mFirstFramePts = buffer->pts;
257 }
258
fei.dengb9a1a572023-09-13 01:33:57 +0000259 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000260}
261
262int WstClientPlugin::flush()
263{
264 int ret;
fei.dengb9a1a572023-09-13 01:33:57 +0000265 INFO(mLogCategory,"flush");
fei.dengf7a0cd32023-08-29 09:36:37 +0000266 if (mWstClientSocket) {
267 mWstClientSocket->sendFlushVideoClientConnection();
268 }
269 //drop frames those had committed to westeros
270 std::lock_guard<std::mutex> lck(mRenderLock);
271 for (auto item = mDisplayedFrameMap.begin(); item != mDisplayedFrameMap.end(); ) {
272 int bufferid = (int)item->first;
273 auto bufItem = mRenderBuffersMap.find(bufferid);
274 if (bufItem == mRenderBuffersMap.end()) {
275 continue;
276 }
277 mDisplayedFrameMap.erase(item++);
278 RenderBuffer *renderbuffer = (RenderBuffer*) bufItem->second;
279 if (renderbuffer) {
280 handleFrameDropped(renderbuffer);
281 }
282 }
283
fei.dengb9a1a572023-09-13 01:33:57 +0000284 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000285}
286
287int WstClientPlugin::pause()
288{
289 int ret;
fei.dengb9a1a572023-09-13 01:33:57 +0000290 INFO(mLogCategory,"pause");
fei.dengf7a0cd32023-08-29 09:36:37 +0000291 if (mWstClientSocket) {
292 int waitCnt = 20; //we wait about 10 vsync duration
293 while (mReadyDisplayFrameCnt != 0 && waitCnt > 0) {
294 usleep(8000);
295 --waitCnt;
296 }
297 std::lock_guard<std::mutex> lck(mRenderLock);
298 if (mReadyDisplayFrameCnt == 0) { //send pause cmd immediatialy if no frame displays
299 mWstClientSocket->sendPauseVideoClientConnection(true);
300 }
301 }
sheng.liua7baed72024-01-24 07:31:24 +0000302 mWayland->setPause(true);
fei.dengf7a0cd32023-08-29 09:36:37 +0000303 mWstEssRMgrOps->resMgrUpdateState(EssRMgrRes_paused);
fei.dengb9a1a572023-09-13 01:33:57 +0000304 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000305}
306
307int WstClientPlugin::resume()
308{
309 int ret;
fei.dengb9a1a572023-09-13 01:33:57 +0000310 INFO(mLogCategory,"resume");
fei.dengf7a0cd32023-08-29 09:36:37 +0000311 std::lock_guard<std::mutex> lck(mRenderLock);
312 if (mWstClientSocket) {
313 mWstClientSocket->sendPauseVideoClientConnection(false);
314 }
sheng.liua7baed72024-01-24 07:31:24 +0000315 mWayland->setPause(false);
fei.dengf7a0cd32023-08-29 09:36:37 +0000316 mWstEssRMgrOps->resMgrUpdateState(EssRMgrRes_active);
fei.dengb9a1a572023-09-13 01:33:57 +0000317 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000318}
319
320int WstClientPlugin::closeDisplay()
321{
fei.dengb9a1a572023-09-13 01:33:57 +0000322 INFO(mLogCategory,"closeDisplay, in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000323 mWayland->disconnectFromWayland();
324 mWstEssRMgrOps->resMgrReleaseDecoder();
325 mWstEssRMgrOps->resMgrTerm();
fei.dengb9a1a572023-09-13 01:33:57 +0000326 INFO(mLogCategory,"closeDisplay, out");
327 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000328}
329
330int WstClientPlugin::closeWindow()
331{
fei.dengb9a1a572023-09-13 01:33:57 +0000332 DEBUG(mLogCategory,"closeWindow, in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000333 if (mWstClientSocket) {
334 mWstClientSocket->disconnectFromSocket();
335 delete mWstClientSocket;
336 mWstClientSocket = NULL;
337 }
338
339 std::lock_guard<std::mutex> lck(mRenderLock);
340 //drop all frames those don't displayed
341 for (auto item = mDisplayedFrameMap.begin(); item != mDisplayedFrameMap.end(); ) {
342 int bufferid = (int)item->first;
343 auto bufItem = mRenderBuffersMap.find(bufferid);
344 if (bufItem == mRenderBuffersMap.end()) {
345 continue;
346 }
347 mDisplayedFrameMap.erase(item++);
348 RenderBuffer *renderbuffer = (RenderBuffer*) bufItem->second;
349 if (renderbuffer) {
350 handleFrameDropped(renderbuffer);
351 }
352 }
353 //release all frames those had committed to westeros server
354 for (auto item = mRenderBuffersMap.begin(); item != mRenderBuffersMap.end();) {
355 RenderBuffer *renderbuffer = (RenderBuffer*) item->second;
356 mRenderBuffersMap.erase(item++);
357 if (renderbuffer) {
358 handleBufferRelease(renderbuffer);
359 }
360 }
361 mWstEssRMgrOps->resMgrUpdateState(EssRMgrRes_idle);
362 mRenderBuffersMap.clear();
363 mDisplayedFrameMap.clear();
364 mCommitFrameCnt = 0;
365 mNumDroppedFrames = 0;
366 mReadyDisplayFrameCnt = 0;
367 mImmediatelyOutput = false;
fei.dengb9a1a572023-09-13 01:33:57 +0000368 DEBUG(mLogCategory,"out");
369 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000370}
371
372int WstClientPlugin::getValue(PluginKey key, void *value)
373{
374 switch (key) {
375 case PLUGIN_KEY_KEEP_LAST_FRAME: {
376 *(int *)value = mKeepLastFrame.value;
fei.dengb9a1a572023-09-13 01:33:57 +0000377 TRACE(mLogCategory,"get keep last frame:%d",*(int *)value);
fei.dengf7a0cd32023-08-29 09:36:37 +0000378 } break;
379 case PLUGIN_KEY_HIDE_VIDEO: {
380 *(int *)value = mHideVideo.value;
fei.dengb9a1a572023-09-13 01:33:57 +0000381 TRACE(mLogCategory,"get hide video:%d",*(int *)value);
fei.dengf7a0cd32023-08-29 09:36:37 +0000382 } break;
383 case PLUGIN_KEY_CROP_FRAME_SIZE: {
384 RenderRect* rect = static_cast<RenderRect*>(value);
385 rect->x = mCropFrameRect.x;
386 rect->y = mCropFrameRect.y;
387 rect->w = mCropFrameRect.w;
388 rect->h = mCropFrameRect.h;
389 } break;
390 }
fei.dengb9a1a572023-09-13 01:33:57 +0000391 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000392}
393
394int WstClientPlugin::setValue(PluginKey key, void *value)
395{
396 switch (key) {
397 case PLUGIN_KEY_WINDOW_SIZE: {
398 RenderRect* rect = static_cast<RenderRect*>(value);
399 if (mWayland) {
400 mWayland->setWindowSize(rect->x, rect->y, rect->w, rect->h);
401 }
402 } break;
403 case PLUGIN_KEY_FRAME_SIZE: {
404 RenderFrameSize * frameSize = static_cast<RenderFrameSize * >(value);
405 if (mWayland) {
406 mWayland->setFrameSize(frameSize->width, frameSize->height);
407 }
408 //if set crop property before set frame size,we set crop params now, because
409 //crop property dependent frame size
410 if (mSetCropFrameRect) {
411 setCropFrameRect();
412 }
413 } break;
414 case PLUGIN_KEY_VIDEO_FORMAT: {
415 int format = *(int *)(value);
416 mBufferFormat = (RenderVideoFormat) format;
fei.dengb9a1a572023-09-13 01:33:57 +0000417 DEBUG(mLogCategory,"Set video format :%d",mBufferFormat);
fei.dengf7a0cd32023-08-29 09:36:37 +0000418 } break;
419 case PLUGIN_KEY_VIDEO_PIP: {
420 int pip = *(int *) (value);
421 mIsVideoPip = pip > 0? true:false;
fei.deng76493fa2023-11-09 11:13:34 +0000422 } break;
fei.dengf7a0cd32023-08-29 09:36:37 +0000423 case PLUGIN_KEY_KEEP_LAST_FRAME: {
424 int keep = *(int *) (value);
425 mKeepLastFrame.value = keep > 0? true:false;
426 mKeepLastFrame.isSet = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000427 DEBUG(mLogCategory, "Set keep last frame :%d",mKeepLastFrame.value);
fei.dengf7a0cd32023-08-29 09:36:37 +0000428 if (mWstClientSocket) {
429 mWstClientSocket->sendKeepLastFrameVideoClientConnection(mKeepLastFrame.value);
430 }
431 } break;
432 case PLUGIN_KEY_HIDE_VIDEO: {
433 int hide = *(int *)(value);
434 mHideVideo.value = hide > 0? true:false;
435 mHideVideo.isSet = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000436 DEBUG(mLogCategory, "Set hide video:%d",mHideVideo.value);
fei.dengf7a0cd32023-08-29 09:36:37 +0000437 if (mWstClientSocket) {
438 mWstClientSocket->sendHideVideoClientConnection(mHideVideo.value);
439 }
440 } break;
441 case PLUGIN_KEY_FORCE_ASPECT_RATIO: {
442 int forceAspectRatio = *(int *)(value);
443 if (mWayland) {
444 mWayland->setForceAspectRatio(forceAspectRatio > 0? true:false);
445 }
446 } break;
447 case PLUGIN_KEY_IMMEDIATELY_OUTPUT: {
448 int immediately = *(int *)(value);
449 mImmediatelyOutput = immediately > 0? true: false;
fei.dengb9a1a572023-09-13 01:33:57 +0000450 DEBUG(mLogCategory,"Set immediately output:%d",mImmediatelyOutput);
fei.dengf7a0cd32023-08-29 09:36:37 +0000451 if (mImmediatelyOutput && mWstClientSocket) {
452 mWstClientSocket->sendSessionInfoVideoClientConnection(INVALID_SESSION_ID, SYNC_IMMEDIATE);
453 }
454 } break;
455 case PLUGIN_KEY_CROP_FRAME_SIZE: {
456 RenderRect* rect = static_cast<RenderRect*>(value);
457 mCropFrameRect.x = rect->x;
458 mCropFrameRect.y = rect->y;
459 mCropFrameRect.w = rect->w;
460 mCropFrameRect.h = rect->h;
461 mSetCropFrameRect = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000462 INFO(mLogCategory,"crop params (%d,%d,%d,%d)",rect->x,rect->y,rect->w,rect->h);
fei.dengf7a0cd32023-08-29 09:36:37 +0000463 setCropFrameRect();
464 } break;
465 case PLUGIN_KEY_PIXEL_ASPECT_RATIO: {
466 double ratio = *(double *)(value);
fei.dengb9a1a572023-09-13 01:33:57 +0000467 INFO(mLogCategory,"pixel aspect ratio :%f",ratio);
fei.dengf7a0cd32023-08-29 09:36:37 +0000468 if (mWayland) {
469 mWayland->setPixelAspectRatio((double)ratio);
470 }
471 } break;
fei.deng7ac1aeb2023-12-05 01:38:57 +0000472 case PLUGIN_KEY_VIDEO_FRAME_RATE: {
473 RenderFraction * fraction = static_cast<RenderFraction*>(value);
474 INFO(mLogCategory,"frame rate,num:%d,denom:%d",fraction->num,fraction->denom);
475 if (fraction->num != mFrameRateFractionNum ||
476 fraction->denom != mFrameRateFractionDenom) {
477 mFrameRateFractionNum = fraction->num;
478 mFrameRateFractionDenom = fraction->denom;
479 if (mFrameRateFractionDenom == 0) {
480 mFrameRateFractionDenom = 1;
481 }
482 mFrameRateChanged = true;
483 }
484 if (mWstClientSocket && mFrameRateChanged) {
485 mFrameRateChanged = false;
486 mWstClientSocket->sendRateVideoClientConnection(mFrameRateFractionNum, mFrameRateFractionDenom);
487 }
488 } break;
fei.dengf7a0cd32023-08-29 09:36:37 +0000489 }
fei.dengb9a1a572023-09-13 01:33:57 +0000490 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000491}
492
493void WstClientPlugin::handleBufferRelease(RenderBuffer *buffer)
494{
495 if (mCallback) {
496 mCallback->doBufferReleaseCallback(mUserData, (void *)buffer);
497 }
498}
499
500void WstClientPlugin::handleFrameDisplayed(RenderBuffer *buffer)
501{
502 if (mCallback) {
503 mCallback->doBufferDisplayedCallback(mUserData, (void *)buffer);
504 }
505}
506
507void WstClientPlugin::handleFrameDropped(RenderBuffer *buffer)
508{
509 if (mCallback) {
510 mCallback->doBufferDropedCallback(mUserData, (void *)buffer);
511 }
512}
513
514void WstClientPlugin::handleMsgNotify(int type, void *detail)
515{
516 if (mCallback) {
517 mCallback->doMsgCallback(mUserData, type, detail);
518 }
519}
520
521void WstClientPlugin::setVideoRect(int videoX, int videoY, int videoWidth, int videoHeight)
522{
523 if (mWstClientSocket) {
524 mWstClientSocket->sendRectVideoClientConnection(videoX, videoY, videoWidth, videoHeight);
525 }
526}
527
528void WstClientPlugin::onWstSocketEvent(WstEvent *event)
529{
fei.dengb9a1a572023-09-13 01:33:57 +0000530 Tls::Mutex::Autolock _l(mMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000531 switch (event->event)
532 {
533 case WST_REFRESH_RATE: {
534 int rate = event->param;
fei.dengb9a1a572023-09-13 01:33:57 +0000535 INFO(mLogCategory,"refresh rate:%d",rate);
fei.dengf7a0cd32023-08-29 09:36:37 +0000536 } break;
537 case WST_BUFFER_RELEASE: {
538 int bufferid = event->param;
fei.dengb9a1a572023-09-13 01:33:57 +0000539 TRACE(mLogCategory,"Buffer release id:%d",bufferid);
fei.dengf7a0cd32023-08-29 09:36:37 +0000540 RenderBuffer *renderbuffer = NULL;
541 bool isDropped = false;
542 int64_t displaytime = 0;
543 {
544 std::lock_guard<std::mutex> lck(mRenderLock);
545 auto renderBufferItem = mRenderBuffersMap.find(bufferid);
546 if (renderBufferItem == mRenderBuffersMap.end()) {
fei.dengb9a1a572023-09-13 01:33:57 +0000547 WARNING(mLogCategory,"can't find map Renderbuffer");
fei.dengf7a0cd32023-08-29 09:36:37 +0000548 return ;
549 }
550 --mCommitFrameCnt;
551 renderbuffer = (RenderBuffer*) renderBufferItem->second;
552 //remove had release render buffer
553 mRenderBuffersMap.erase(bufferid);
554 auto displayFrameItem = mDisplayedFrameMap.find(bufferid);
555 if (displayFrameItem != mDisplayedFrameMap.end()) {
556 mDisplayedFrameMap.erase(bufferid);
557 --mReadyDisplayFrameCnt;
558 isDropped = true;
559 displaytime = (int64_t)displayFrameItem->second;
560 }
561 }
562
563 if (renderbuffer) {
564 /*if we can find item in mDisplayedFrameMap,
565 this buffer is dropped by westeros server,so we
566 must call displayed callback*/
567 if (isDropped) {
fei.dengb9a1a572023-09-13 01:33:57 +0000568 WARNING(mLogCategory,"Frame droped,pts:%lld us,displaytime:%lld,readyDisplayFramesCnt:%d",\
fei.dengf7a0cd32023-08-29 09:36:37 +0000569 renderbuffer->pts/1000,displaytime,mReadyDisplayFrameCnt);
570 handleFrameDropped(renderbuffer);
571 }
572 handleBufferRelease(renderbuffer);
573 }
fei.dengb9a1a572023-09-13 01:33:57 +0000574 TRACE(mLogCategory,"remain on westeros cnt:%d",mCommitFrameCnt);
fei.dengf7a0cd32023-08-29 09:36:37 +0000575 } break;
576 case WST_STATUS: {
577 int dropframes = event->param;
578 int64_t frameTime = event->lparam;
fei.dengb9a1a572023-09-13 01:33:57 +0000579 TRACE(mLogCategory,"WST_STATUS,dropframes:%d,frameTime:%lld",dropframes,frameTime);
fei.dengf7a0cd32023-08-29 09:36:37 +0000580 RenderBuffer *renderbuffer = NULL;
581 if (mNumDroppedFrames != event->param) {
582 mNumDroppedFrames = event->param;
fei.dengb9a1a572023-09-13 01:33:57 +0000583 WARNING(mLogCategory,"frame dropped cnt:%d",mNumDroppedFrames);
fei.dengf7a0cd32023-08-29 09:36:37 +0000584 }
585 //update status,if frameTime isn't equal -1LL
586 //this buffer had displayed
587 if (frameTime != -1LL) {
588 std::lock_guard<std::mutex> lck(mRenderLock);
589 --mReadyDisplayFrameCnt;
fei.dengb9a1a572023-09-13 01:33:57 +0000590 TRACE(mLogCategory,"displayed frame time:%lld,readyDisplayFramesCnt:%d",frameTime,mReadyDisplayFrameCnt);
fei.dengf7a0cd32023-08-29 09:36:37 +0000591 int bufferId = getDisplayFrameBufferId(frameTime);
592 if (bufferId < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000593 WARNING(mLogCategory,"can't find map displayed frame:%lld",frameTime);
fei.dengf7a0cd32023-08-29 09:36:37 +0000594 return ;
595 }
596 auto displayItem = mDisplayedFrameMap.find(bufferId);
597 if (displayItem != mDisplayedFrameMap.end()) {
598 mDisplayedFrameMap.erase(bufferId);
599 }
600 auto item = mRenderBuffersMap.find(bufferId);
601 if (item != mRenderBuffersMap.end()) {
602 renderbuffer = (RenderBuffer*) item->second;
603 }
604 }
605 if (renderbuffer) {
606 //first frame signal
607 if (renderbuffer->pts == mFirstFramePts) {
608 handleMsgNotify(MSG_FIRST_FRAME,(void*)&renderbuffer->pts);
609 }
610 handleFrameDisplayed(renderbuffer);
611 }
612 } break;
613 case WST_UNDERFLOW: {
614 uint64_t frameTime = event->lparam;
fei.dengb9a1a572023-09-13 01:33:57 +0000615 TRACE(mLogCategory,"under flow frametime:%lld",frameTime);
fei.dengf7a0cd32023-08-29 09:36:37 +0000616 //under flow event sended must be after sending first frame to westeros
617 if (mFirstFramePts != -1) {
618 handleMsgNotify(MSG_UNDER_FLOW, NULL);
619 }
620 } break;
621 case WST_ZOOM_MODE: {
622 int mode = event->param;
623 bool globalZoomActive = event->param1 > 0? true:false;
624 bool allow4kZoom = event->param2 > 0? true:false;;
625 mWayland->setZoomMode(mode, globalZoomActive, allow4kZoom);
626 } break;
627 case WST_DEBUG_LEVEL: {
628 /* code */
629 } break;
630 default:
631 break;
632 }
633}
634
635int WstClientPlugin::getDisplayFrameBufferId(int64_t displayTime)
636{
637 int bufId = -1;
638 for (auto item = mDisplayedFrameMap.begin(); item != mDisplayedFrameMap.end(); item++) {
639 int64_t time = (int64_t)item->second;
640 if (time == displayTime) {
641 bufId = (int)item->first;
642 break;
643 }
644 }
645 return bufId;
646}
647
648bool WstClientPlugin::setCropFrameRect()
649{
650 if (mWayland) {
651 int frameWidth,frameHeight;
652 mWayland->getFrameSize(&frameWidth, &frameHeight);
653 if (frameWidth <= 0 || frameHeight <= 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000654 WARNING(mLogCategory, "no set video frame size,set crop params later");
fei.dengf7a0cd32023-08-29 09:36:37 +0000655 goto bad_param;
656 }
657
658 //correct crop rect if needed
659 if (frameWidth > 0 && (mCropFrameRect.x + mCropFrameRect.w) > frameWidth) {
660 if (mCropFrameRect.x < frameWidth) {
661 int oriX = mCropFrameRect.x;
662 int oriW = mCropFrameRect.w;
663 mCropFrameRect.w = frameWidth - mCropFrameRect.x;
fei.dengb9a1a572023-09-13 01:33:57 +0000664 WARNING(mLogCategory, "correct crop x:%d, w:%d to x:%d, w:%d", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000665 oriX,oriW,mCropFrameRect.x,mCropFrameRect.w);
666 } else {
fei.dengb9a1a572023-09-13 01:33:57 +0000667 ERROR(mLogCategory, "Error crop params (%d,%d,%d,%d) frame(%d,%d)", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000668 mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h,frameWidth,frameHeight);
669 goto bad_param;
670 }
671 }
672 if (frameHeight > 0 && (mCropFrameRect.y + mCropFrameRect.h) > frameHeight) {
673 if (mCropFrameRect.y < frameHeight) {
674 int oriY = mCropFrameRect.x;
675 int oriH = mCropFrameRect.w;
676 mCropFrameRect.h = frameHeight - mCropFrameRect.y;
fei.dengb9a1a572023-09-13 01:33:57 +0000677 WARNING(mLogCategory, "correct crop y:%d, h:%d to y:%d, h:%d", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000678 oriY,oriH,mCropFrameRect.y,mCropFrameRect.h);
679 } else {
fei.dengb9a1a572023-09-13 01:33:57 +0000680 ERROR(mLogCategory, "Error crop params (%d,%d,%d,%d) frame(%d,%d)", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000681 mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h,frameWidth,frameHeight);
682 goto bad_param;
683 }
684 }
fei.dengb9a1a572023-09-13 01:33:57 +0000685 INFO(mLogCategory, "crop (%d,%d,%d,%d)", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000686 mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h);
687 }
688 if (mWstClientSocket && mSetCropFrameRect) {
689 mWstClientSocket->sendCropFrameSizeClientConnection(mCropFrameRect.x, mCropFrameRect.y, mCropFrameRect.w, mCropFrameRect.h);
690 mSetCropFrameRect = false;
691 }
692 return true;
693bad_param:
694 return false;
695}
696
697void *makePluginInstance(int id)
698{
fei.dengb9a1a572023-09-13 01:33:57 +0000699 int category =Logger_init(id);
fei.dengc4677852023-10-09 07:21:04 +0000700 char *env = getenv("VIDEO_RENDER_PLUGIN_LOG_LEVEL");
fei.dengf7a0cd32023-08-29 09:36:37 +0000701 if (env) {
702 int level = atoi(env);
703 Logger_set_level(level);
fei.dengc4677852023-10-09 07:21:04 +0000704 INFO(category,"VIDEO_RENDER_PLUGIN_LOG_LEVEL=%d",level);
fei.dengf7a0cd32023-08-29 09:36:37 +0000705 }
fei.dengb9a1a572023-09-13 01:33:57 +0000706 WstClientPlugin *pluginInstance = new WstClientPlugin(category);
fei.dengf7a0cd32023-08-29 09:36:37 +0000707 return static_cast<void *>(pluginInstance);
708}
709
710void destroyPluginInstance(void * plugin)
711{
fei.dengb9a1a572023-09-13 01:33:57 +0000712 int category;
713
fei.dengf7a0cd32023-08-29 09:36:37 +0000714 WstClientPlugin *pluginInstance = static_cast<WstClientPlugin *>(plugin);
fei.dengb9a1a572023-09-13 01:33:57 +0000715 category = pluginInstance->getLogCategory();
fei.dengf7a0cd32023-08-29 09:36:37 +0000716 delete pluginInstance;
fei.dengb9a1a572023-09-13 01:33:57 +0000717 Logger_exit(category);
fei.dengf7a0cd32023-08-29 09:36:37 +0000718}