blob: 370dd8d18db0b10a1d86af60934e8b0b44e04504 [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"
20
21#define TAG "rlib:wstClient_plugin"
22#define DEFAULT_VIDEO_SERVER "video"
23
24WstClientPlugin::WstClientPlugin()
25 : mFullscreen(true)
26{
27 mIsVideoPip = false;
28 mBufferFormat = VIDEO_FORMAT_UNKNOWN;
29 mNumDroppedFrames = 0;
30 mCommitFrameCnt = 0;
31 mReadyDisplayFrameCnt = 0;
32 mWayland = new WstClientWayland(this);
33 mWstClientSocket = NULL;
34 mKeepLastFrame.isSet = false;
35 mKeepLastFrame.value = 0;
36 mHideVideo.isSet = false;
37 mHideVideo.value = 0;
38 mFirstFramePts = -1;
39 mImmediatelyOutput = false;
40 mSetCropFrameRect = false;
41 mWstEssRMgrOps = new WstEssRMgrOps(this);
42}
43
44WstClientPlugin::~WstClientPlugin()
45{
46 if (mWayland) {
47 delete mWayland;
48 mWayland = NULL;
49 }
50 if (mWstEssRMgrOps) {
51 delete mWstEssRMgrOps;
52 mWstEssRMgrOps = NULL;
53 }
54
55 TRACE("deconstruct");
56}
57
58void WstClientPlugin::init()
59{
60 INFO("\n--------------------------------\n"
61 "plugin : westeros\n"
62 "ARCH : %s\n"
63 "branch name : %s\n"
64 "git version : %s\n"
65 "change id : %s \n"
66 "ID : %s \n"
67 "last changed: %s\n"
68 "build-time : %s\n"
69 "build-name : %s\n"
70 "--------------------------------\n",
71#if defined(__aarch64__)
72 "arm64",
73#else
74 "arm",
75#endif
76 BRANCH_NAME,
77 GIT_VERSION,
78 COMMIT_CHANGEID,
79 COMMIT_PD,
80 LAST_CHANGED,
81 BUILD_TIME,
82 BUILD_NAME
83 );
84}
85
86void WstClientPlugin::release()
87{
88}
89
90void WstClientPlugin::setCallback(void *userData, PluginCallback *callback)
91{
92 mUserData = userData;
93 mCallback = callback;
94}
95
96int WstClientPlugin::openDisplay()
97{
98 int ret = 0;
99
100 DEBUG("openDisplay");
101
102 mWstEssRMgrOps->resMgrInit();
103 mWstEssRMgrOps->resMgrRequestDecoder(mIsVideoPip);
104
105 //connect video server first
106 if (!mWstClientSocket) {
107 bool rc;
108 mWstClientSocket = new WstClientSocket(this);
109 rc = mWstClientSocket->connectToSocket(DEFAULT_VIDEO_SERVER);
110 if (!rc) {
111 ERROR("Error connect to video server fail");
112 delete mWstClientSocket;
113 mWstClientSocket = NULL;
114 return -1;
115 }
116 }
117
118 if (mWstClientSocket) {
119 mWstClientSocket->sendLayerVideoClientConnection(mIsVideoPip);
120 mWstClientSocket->sendResourceVideoClientConnection(mIsVideoPip);
121 }
122
123 ret = mWayland->connectToWayland();
124 if (ret != 0) {
125 ERROR("Error open display");
126 } else {
127 //run wl display queue dispatch
128 DEBUG("To run wl display dispatch queue");
129 mWayland->run("display queue");
130 }
131
132 DEBUG("openDisplay end");
133 return 0;
134}
135
136int WstClientPlugin::openWindow()
137{
138 int ret;
139
140 DEBUG("openWindow");
141 mCommitFrameCnt = 0;
142 mNumDroppedFrames = 0;
143 mReadyDisplayFrameCnt = 0;
144 /*send session info to server
145 we use mediasync to sync a/v,so select AV_SYNC_MODE_VIDEO_MONO as av clock*/
146 if (mWstClientSocket) {
147 if (mImmediatelyOutput) {
148 mWstClientSocket->sendSessionInfoVideoClientConnection(INVALID_SESSION_ID, SYNC_IMMEDIATE);
149 } else {
150 mWstClientSocket->sendSessionInfoVideoClientConnection(AV_SYNC_SESSION_V_MONO, AV_SYNC_MODE_VIDEO_MONO);
151 }
152 }
153
154 //send hide video
155 if (mWstClientSocket && mHideVideo.isSet) {
156 mWstClientSocket->sendHideVideoClientConnection(mHideVideo.value);
157 }
158
159 //send keep last video frame
160 if (mWstClientSocket && mKeepLastFrame.isSet) {
161 mWstClientSocket->sendKeepLastFrameVideoClientConnection(mKeepLastFrame.value);
162 }
163
164 //send crop frame size if set before window opened
165 if (mSetCropFrameRect) {
166 setCropFrameRect();
167 }
168
169 DEBUG("openWindow,end");
170 return ret;
171}
172
173int WstClientPlugin::prepareFrame(RenderBuffer *buffer)
174{
175 return 0;
176}
177
178int WstClientPlugin::displayFrame(RenderBuffer *buffer, int64_t displayTime)
179{
180 bool ret;
181 WstBufferInfo wstBufferInfo;
182 WstRect wstRect;
183 int x,y,w,h;
184
185 mWayland->getVideoBounds(&x, &y, &w, &h);
186
187 //init wstBufferInfo,must set fd to -1 value
188 memset(&wstBufferInfo, 0, sizeof(WstBufferInfo));
189 for (int i = 0; i < WST_MAX_PLANES; i++) {
190 wstBufferInfo.planeInfo[0].fd = -1;
191 wstBufferInfo.planeInfo[1].fd = -1;
192 wstBufferInfo.planeInfo[2].fd = -1;
193 }
194
195 wstBufferInfo.bufferId = buffer->id;
196 wstBufferInfo.planeCount = buffer->dma.planeCnt;
197 TRACE("buffer width:%d,height:%d",buffer->dma.width,buffer->dma.height);
198 for (int i = 0; i < buffer->dma.planeCnt; i++) {
199 wstBufferInfo.planeInfo[i].fd = buffer->dma.fd[i];
200 wstBufferInfo.planeInfo[i].stride = buffer->dma.stride[i];
201 wstBufferInfo.planeInfo[i].offset = buffer->dma.offset[i];
202 DEBUG("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]);
203 }
204
205 wstBufferInfo.frameWidth = buffer->dma.width;
206 wstBufferInfo.frameHeight = buffer->dma.height;
207 wstBufferInfo.frameTime = displayTime;
208
209 //change render lib video format to v4l2 support format
210 if (mBufferFormat == VIDEO_FORMAT_NV12) {
211 wstBufferInfo.pixelFormat = V4L2_PIX_FMT_NV12;
212 } else if (mBufferFormat == VIDEO_FORMAT_NV21) {
213 wstBufferInfo.pixelFormat = V4L2_PIX_FMT_NV21;
214 } else {
215 ERROR("unknown video buffer format:%d",mBufferFormat);
216 }
217
218 wstRect.x = x;
219 wstRect.y = y;
220 wstRect.w = w;
221 wstRect.h = h;
222
223 if (mWstClientSocket) {
224 ret = mWstClientSocket->sendFrameVideoClientConnection(&wstBufferInfo, &wstRect);
225 if (!ret) {
226 ERROR("send video frame to server fail");
227 handleFrameDropped(buffer);
228 handleBufferRelease(buffer);
229 return -1;
230 }
231 }
232
233 //storage render buffer to manager
234 std::lock_guard<std::mutex> lck(mRenderLock);
235 std::pair<int, RenderBuffer *> item(buffer->id, buffer);
236 mRenderBuffersMap.insert(item);
237 ++mCommitFrameCnt;
238 ++mReadyDisplayFrameCnt;
239 TRACE("committed to westeros cnt:%d,readyDisplayFramesCnt:%d",mCommitFrameCnt,mReadyDisplayFrameCnt);
240
241 //storage displayed render buffer
242 std::pair<int, int64_t> displayitem(buffer->id, displayTime);
243 mDisplayedFrameMap.insert(displayitem);
244 if (mFirstFramePts == -1) {
245 mFirstFramePts = buffer->pts;
246 }
247
248 return 0;
249}
250
251int WstClientPlugin::flush()
252{
253 int ret;
254 INFO("flush");
255 if (mWstClientSocket) {
256 mWstClientSocket->sendFlushVideoClientConnection();
257 }
258 //drop frames those had committed to westeros
259 std::lock_guard<std::mutex> lck(mRenderLock);
260 for (auto item = mDisplayedFrameMap.begin(); item != mDisplayedFrameMap.end(); ) {
261 int bufferid = (int)item->first;
262 auto bufItem = mRenderBuffersMap.find(bufferid);
263 if (bufItem == mRenderBuffersMap.end()) {
264 continue;
265 }
266 mDisplayedFrameMap.erase(item++);
267 RenderBuffer *renderbuffer = (RenderBuffer*) bufItem->second;
268 if (renderbuffer) {
269 handleFrameDropped(renderbuffer);
270 }
271 }
272
273 return 0;
274}
275
276int WstClientPlugin::pause()
277{
278 int ret;
279 INFO("pause");
280 if (mWstClientSocket) {
281 int waitCnt = 20; //we wait about 10 vsync duration
282 while (mReadyDisplayFrameCnt != 0 && waitCnt > 0) {
283 usleep(8000);
284 --waitCnt;
285 }
286 std::lock_guard<std::mutex> lck(mRenderLock);
287 if (mReadyDisplayFrameCnt == 0) { //send pause cmd immediatialy if no frame displays
288 mWstClientSocket->sendPauseVideoClientConnection(true);
289 }
290 }
291 mWstEssRMgrOps->resMgrUpdateState(EssRMgrRes_paused);
292 return 0;
293}
294
295int WstClientPlugin::resume()
296{
297 int ret;
298 INFO("resume");
299 std::lock_guard<std::mutex> lck(mRenderLock);
300 if (mWstClientSocket) {
301 mWstClientSocket->sendPauseVideoClientConnection(false);
302 }
303 mWstEssRMgrOps->resMgrUpdateState(EssRMgrRes_active);
304 return 0;
305}
306
307int WstClientPlugin::closeDisplay()
308{
309 INFO("closeDisplay, in");
310 mWayland->disconnectFromWayland();
311 mWstEssRMgrOps->resMgrReleaseDecoder();
312 mWstEssRMgrOps->resMgrTerm();
313 INFO("closeDisplay, out");
314 return 0;
315}
316
317int WstClientPlugin::closeWindow()
318{
319 DEBUG("closeWindow, in");
320 if (mWstClientSocket) {
321 mWstClientSocket->disconnectFromSocket();
322 delete mWstClientSocket;
323 mWstClientSocket = NULL;
324 }
325
326 std::lock_guard<std::mutex> lck(mRenderLock);
327 //drop all frames those don't displayed
328 for (auto item = mDisplayedFrameMap.begin(); item != mDisplayedFrameMap.end(); ) {
329 int bufferid = (int)item->first;
330 auto bufItem = mRenderBuffersMap.find(bufferid);
331 if (bufItem == mRenderBuffersMap.end()) {
332 continue;
333 }
334 mDisplayedFrameMap.erase(item++);
335 RenderBuffer *renderbuffer = (RenderBuffer*) bufItem->second;
336 if (renderbuffer) {
337 handleFrameDropped(renderbuffer);
338 }
339 }
340 //release all frames those had committed to westeros server
341 for (auto item = mRenderBuffersMap.begin(); item != mRenderBuffersMap.end();) {
342 RenderBuffer *renderbuffer = (RenderBuffer*) item->second;
343 mRenderBuffersMap.erase(item++);
344 if (renderbuffer) {
345 handleBufferRelease(renderbuffer);
346 }
347 }
348 mWstEssRMgrOps->resMgrUpdateState(EssRMgrRes_idle);
349 mRenderBuffersMap.clear();
350 mDisplayedFrameMap.clear();
351 mCommitFrameCnt = 0;
352 mNumDroppedFrames = 0;
353 mReadyDisplayFrameCnt = 0;
354 mImmediatelyOutput = false;
355 DEBUG("out");
356 return 0;
357}
358
359int WstClientPlugin::getValue(PluginKey key, void *value)
360{
361 switch (key) {
362 case PLUGIN_KEY_KEEP_LAST_FRAME: {
363 *(int *)value = mKeepLastFrame.value;
364 TRACE("get keep last frame:%d",*(int *)value);
365 } break;
366 case PLUGIN_KEY_HIDE_VIDEO: {
367 *(int *)value = mHideVideo.value;
368 TRACE("get hide video:%d",*(int *)value);
369 } break;
370 case PLUGIN_KEY_CROP_FRAME_SIZE: {
371 RenderRect* rect = static_cast<RenderRect*>(value);
372 rect->x = mCropFrameRect.x;
373 rect->y = mCropFrameRect.y;
374 rect->w = mCropFrameRect.w;
375 rect->h = mCropFrameRect.h;
376 } break;
377 }
378 return 0;
379}
380
381int WstClientPlugin::setValue(PluginKey key, void *value)
382{
383 switch (key) {
384 case PLUGIN_KEY_WINDOW_SIZE: {
385 RenderRect* rect = static_cast<RenderRect*>(value);
386 if (mWayland) {
387 mWayland->setWindowSize(rect->x, rect->y, rect->w, rect->h);
388 }
389 } break;
390 case PLUGIN_KEY_FRAME_SIZE: {
391 RenderFrameSize * frameSize = static_cast<RenderFrameSize * >(value);
392 if (mWayland) {
393 mWayland->setFrameSize(frameSize->width, frameSize->height);
394 }
395 //if set crop property before set frame size,we set crop params now, because
396 //crop property dependent frame size
397 if (mSetCropFrameRect) {
398 setCropFrameRect();
399 }
400 } break;
401 case PLUGIN_KEY_VIDEO_FORMAT: {
402 int format = *(int *)(value);
403 mBufferFormat = (RenderVideoFormat) format;
404 DEBUG("Set video format :%d",mBufferFormat);
405 } break;
406 case PLUGIN_KEY_VIDEO_PIP: {
407 int pip = *(int *) (value);
408 mIsVideoPip = pip > 0? true:false;
409 };
410 case PLUGIN_KEY_KEEP_LAST_FRAME: {
411 int keep = *(int *) (value);
412 mKeepLastFrame.value = keep > 0? true:false;
413 mKeepLastFrame.isSet = true;
414 DEBUG( "Set keep last frame :%d",mKeepLastFrame.value);
415 if (mWstClientSocket) {
416 mWstClientSocket->sendKeepLastFrameVideoClientConnection(mKeepLastFrame.value);
417 }
418 } break;
419 case PLUGIN_KEY_HIDE_VIDEO: {
420 int hide = *(int *)(value);
421 mHideVideo.value = hide > 0? true:false;
422 mHideVideo.isSet = true;
423 DEBUG( "Set hide video:%d",mHideVideo.value);
424 if (mWstClientSocket) {
425 mWstClientSocket->sendHideVideoClientConnection(mHideVideo.value);
426 }
427 } break;
428 case PLUGIN_KEY_FORCE_ASPECT_RATIO: {
429 int forceAspectRatio = *(int *)(value);
430 if (mWayland) {
431 mWayland->setForceAspectRatio(forceAspectRatio > 0? true:false);
432 }
433 } break;
434 case PLUGIN_KEY_IMMEDIATELY_OUTPUT: {
435 int immediately = *(int *)(value);
436 mImmediatelyOutput = immediately > 0? true: false;
437 DEBUG("Set immediately output:%d",mImmediatelyOutput);
438 if (mImmediatelyOutput && mWstClientSocket) {
439 mWstClientSocket->sendSessionInfoVideoClientConnection(INVALID_SESSION_ID, SYNC_IMMEDIATE);
440 }
441 } break;
442 case PLUGIN_KEY_CROP_FRAME_SIZE: {
443 RenderRect* rect = static_cast<RenderRect*>(value);
444 mCropFrameRect.x = rect->x;
445 mCropFrameRect.y = rect->y;
446 mCropFrameRect.w = rect->w;
447 mCropFrameRect.h = rect->h;
448 mSetCropFrameRect = true;
449 INFO("crop params (%d,%d,%d,%d)",rect->x,rect->y,rect->w,rect->h);
450 setCropFrameRect();
451 } break;
452 case PLUGIN_KEY_PIXEL_ASPECT_RATIO: {
453 double ratio = *(double *)(value);
454 INFO("pixel aspect ratio :%f",ratio);
455 if (mWayland) {
456 mWayland->setPixelAspectRatio((double)ratio);
457 }
458 } break;
459 }
460 return 0;
461}
462
463void WstClientPlugin::handleBufferRelease(RenderBuffer *buffer)
464{
465 if (mCallback) {
466 mCallback->doBufferReleaseCallback(mUserData, (void *)buffer);
467 }
468}
469
470void WstClientPlugin::handleFrameDisplayed(RenderBuffer *buffer)
471{
472 if (mCallback) {
473 mCallback->doBufferDisplayedCallback(mUserData, (void *)buffer);
474 }
475}
476
477void WstClientPlugin::handleFrameDropped(RenderBuffer *buffer)
478{
479 if (mCallback) {
480 mCallback->doBufferDropedCallback(mUserData, (void *)buffer);
481 }
482}
483
484void WstClientPlugin::handleMsgNotify(int type, void *detail)
485{
486 if (mCallback) {
487 mCallback->doMsgCallback(mUserData, type, detail);
488 }
489}
490
491void WstClientPlugin::setVideoRect(int videoX, int videoY, int videoWidth, int videoHeight)
492{
493 if (mWstClientSocket) {
494 mWstClientSocket->sendRectVideoClientConnection(videoX, videoY, videoWidth, videoHeight);
495 }
496}
497
498void WstClientPlugin::onWstSocketEvent(WstEvent *event)
499{
500 std::lock_guard<std::mutex> lck(mMutex);
501 switch (event->event)
502 {
503 case WST_REFRESH_RATE: {
504 int rate = event->param;
505 INFO("refresh rate:%d",rate);
506 } break;
507 case WST_BUFFER_RELEASE: {
508 int bufferid = event->param;
509 TRACE("Buffer release id:%d",bufferid);
510 RenderBuffer *renderbuffer = NULL;
511 bool isDropped = false;
512 int64_t displaytime = 0;
513 {
514 std::lock_guard<std::mutex> lck(mRenderLock);
515 auto renderBufferItem = mRenderBuffersMap.find(bufferid);
516 if (renderBufferItem == mRenderBuffersMap.end()) {
517 WARNING("can't find map Renderbuffer");
518 return ;
519 }
520 --mCommitFrameCnt;
521 renderbuffer = (RenderBuffer*) renderBufferItem->second;
522 //remove had release render buffer
523 mRenderBuffersMap.erase(bufferid);
524 auto displayFrameItem = mDisplayedFrameMap.find(bufferid);
525 if (displayFrameItem != mDisplayedFrameMap.end()) {
526 mDisplayedFrameMap.erase(bufferid);
527 --mReadyDisplayFrameCnt;
528 isDropped = true;
529 displaytime = (int64_t)displayFrameItem->second;
530 }
531 }
532
533 if (renderbuffer) {
534 /*if we can find item in mDisplayedFrameMap,
535 this buffer is dropped by westeros server,so we
536 must call displayed callback*/
537 if (isDropped) {
538 WARNING("Frame droped,pts:%lld us,displaytime:%lld,readyDisplayFramesCnt:%d",\
539 renderbuffer->pts/1000,displaytime,mReadyDisplayFrameCnt);
540 handleFrameDropped(renderbuffer);
541 }
542 handleBufferRelease(renderbuffer);
543 }
544 TRACE("remain commit to westeros cnt:%d",mCommitFrameCnt);
545 } break;
546 case WST_STATUS: {
547 int dropframes = event->param;
548 int64_t frameTime = event->lparam;
549 TRACE("WST_STATUS,dropframes:%d,frameTime:%lld",dropframes,frameTime);
550 RenderBuffer *renderbuffer = NULL;
551 if (mNumDroppedFrames != event->param) {
552 mNumDroppedFrames = event->param;
553 WARNING("frame dropped cnt:%d",mNumDroppedFrames);
554 }
555 //update status,if frameTime isn't equal -1LL
556 //this buffer had displayed
557 if (frameTime != -1LL) {
558 std::lock_guard<std::mutex> lck(mRenderLock);
559 --mReadyDisplayFrameCnt;
560 TRACE("displayed frame time:%lld,readyDisplayFramesCnt:%d",frameTime,mReadyDisplayFrameCnt);
561 int bufferId = getDisplayFrameBufferId(frameTime);
562 if (bufferId < 0) {
563 WARNING("can't find map displayed frame:%lld",frameTime);
564 return ;
565 }
566 auto displayItem = mDisplayedFrameMap.find(bufferId);
567 if (displayItem != mDisplayedFrameMap.end()) {
568 mDisplayedFrameMap.erase(bufferId);
569 }
570 auto item = mRenderBuffersMap.find(bufferId);
571 if (item != mRenderBuffersMap.end()) {
572 renderbuffer = (RenderBuffer*) item->second;
573 }
574 }
575 if (renderbuffer) {
576 //first frame signal
577 if (renderbuffer->pts == mFirstFramePts) {
578 handleMsgNotify(MSG_FIRST_FRAME,(void*)&renderbuffer->pts);
579 }
580 handleFrameDisplayed(renderbuffer);
581 }
582 } break;
583 case WST_UNDERFLOW: {
584 uint64_t frameTime = event->lparam;
585 TRACE("under flow frametime:%lld",frameTime);
586 //under flow event sended must be after sending first frame to westeros
587 if (mFirstFramePts != -1) {
588 handleMsgNotify(MSG_UNDER_FLOW, NULL);
589 }
590 } break;
591 case WST_ZOOM_MODE: {
592 int mode = event->param;
593 bool globalZoomActive = event->param1 > 0? true:false;
594 bool allow4kZoom = event->param2 > 0? true:false;;
595 mWayland->setZoomMode(mode, globalZoomActive, allow4kZoom);
596 } break;
597 case WST_DEBUG_LEVEL: {
598 /* code */
599 } break;
600 default:
601 break;
602 }
603}
604
605int WstClientPlugin::getDisplayFrameBufferId(int64_t displayTime)
606{
607 int bufId = -1;
608 for (auto item = mDisplayedFrameMap.begin(); item != mDisplayedFrameMap.end(); item++) {
609 int64_t time = (int64_t)item->second;
610 if (time == displayTime) {
611 bufId = (int)item->first;
612 break;
613 }
614 }
615 return bufId;
616}
617
618bool WstClientPlugin::setCropFrameRect()
619{
620 if (mWayland) {
621 int frameWidth,frameHeight;
622 mWayland->getFrameSize(&frameWidth, &frameHeight);
623 if (frameWidth <= 0 || frameHeight <= 0) {
624 WARNING( "no set video frame size,set crop params later");
625 goto bad_param;
626 }
627
628 //correct crop rect if needed
629 if (frameWidth > 0 && (mCropFrameRect.x + mCropFrameRect.w) > frameWidth) {
630 if (mCropFrameRect.x < frameWidth) {
631 int oriX = mCropFrameRect.x;
632 int oriW = mCropFrameRect.w;
633 mCropFrameRect.w = frameWidth - mCropFrameRect.x;
634 WARNING( "correct crop x:%d, w:%d to x:%d, w:%d", \
635 oriX,oriW,mCropFrameRect.x,mCropFrameRect.w);
636 } else {
637 ERROR( "Error crop params (%d,%d,%d,%d) frame(%d,%d)", \
638 mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h,frameWidth,frameHeight);
639 goto bad_param;
640 }
641 }
642 if (frameHeight > 0 && (mCropFrameRect.y + mCropFrameRect.h) > frameHeight) {
643 if (mCropFrameRect.y < frameHeight) {
644 int oriY = mCropFrameRect.x;
645 int oriH = mCropFrameRect.w;
646 mCropFrameRect.h = frameHeight - mCropFrameRect.y;
647 WARNING( "correct crop y:%d, h:%d to y:%d, h:%d", \
648 oriY,oriH,mCropFrameRect.y,mCropFrameRect.h);
649 } else {
650 ERROR( "Error crop params (%d,%d,%d,%d) frame(%d,%d)", \
651 mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h,frameWidth,frameHeight);
652 goto bad_param;
653 }
654 }
655 INFO( "crop (%d,%d,%d,%d)", \
656 mCropFrameRect.x,mCropFrameRect.y,mCropFrameRect.w,mCropFrameRect.h);
657 }
658 if (mWstClientSocket && mSetCropFrameRect) {
659 mWstClientSocket->sendCropFrameSizeClientConnection(mCropFrameRect.x, mCropFrameRect.y, mCropFrameRect.w, mCropFrameRect.h);
660 mSetCropFrameRect = false;
661 }
662 return true;
663bad_param:
664 return false;
665}
666
667void *makePluginInstance(int id)
668{
669 char *env = getenv("VIDEO_RENDER_LOG_LEVEL");
670 if (env) {
671 int level = atoi(env);
672 Logger_set_level(level);
673 INFO("VIDEO_RENDER_LOG_LEVEL=%d",level);
674 }
675 WstClientPlugin *pluginInstance = new WstClientPlugin();
676 return static_cast<void *>(pluginInstance);
677}
678
679void destroyPluginInstance(void * plugin)
680{
681 WstClientPlugin *pluginInstance = static_cast<WstClientPlugin *>(plugin);
682 delete pluginInstance;
683}