blob: d3c65cc1e1dce05ce22e0fb3be909709bcc5f217 [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 */
fei.dengdd910ef2024-06-07 10:25:30 +080016#include <fcntl.h>
17#include <string.h>
fei.dengf7a0cd32023-08-29 09:36:37 +000018#include "wayland_plugin.h"
19#include "wayland_display.h"
20#include "Logger.h"
21#include "Times.h"
fei.dengb9a1a572023-09-13 01:33:57 +000022#include "ErrorCode.h"
fei.dengf7a0cd32023-08-29 09:36:37 +000023
24#define TAG "rlib:wayland_plugin"
25
le.handb98beb2024-09-09 08:39:09 +000026#define UNDER_FLOW_EXPIRED_TIME_MS 83
27
fei.dengb9a1a572023-09-13 01:33:57 +000028WaylandPlugin::WaylandPlugin(int logCatgory)
29 : mRenderLock("renderlock"),
30 mLogCategory(logCatgory)
fei.dengf7a0cd32023-08-29 09:36:37 +000031{
fei.dengb9a1a572023-09-13 01:33:57 +000032 mDisplay = new WaylandDisplay(this, logCatgory);
fei.dengf7a0cd32023-08-29 09:36:37 +000033 mQueue = new Tls::Queue();
34 mPaused = false;
35 mImmediatelyOutput = false;
le.handb98beb2024-09-09 08:39:09 +000036 mUnderFlowDetect = false;
fei.dengf862f9c2024-10-24 16:46:55 +080037 mWaiting = false;
fei.dengf7a0cd32023-08-29 09:36:37 +000038}
39
40WaylandPlugin::~WaylandPlugin()
41{
42 if (mDisplay) {
43 delete mDisplay;
44 }
45 if (mQueue) {
46 mQueue->flush();
47 delete mQueue;
48 mQueue = NULL;
49 }
fei.dengb9a1a572023-09-13 01:33:57 +000050 TRACE(mLogCategory,"desconstruct");
fei.dengf7a0cd32023-08-29 09:36:37 +000051}
52
53void WaylandPlugin::init()
54{
fei.dengb9a1a572023-09-13 01:33:57 +000055 INFO(mLogCategory,"\n--------------------------------\n"
fei.dengf7a0cd32023-08-29 09:36:37 +000056 "plugin : weston\n"
57 "ARCH : %s\n"
58 "branch name : %s\n"
59 "git version : %s\n"
60 "change id : %s \n"
61 "ID : %s \n"
62 "last changed: %s\n"
63 "build-time : %s\n"
64 "build-name : %s\n"
65 "--------------------------------\n",
66#if defined(__aarch64__)
67 "arm64",
68#else
69 "arm",
70#endif
71 BRANCH_NAME,
72 GIT_VERSION,
73 COMMIT_CHANGEID,
74 COMMIT_PD,
75 LAST_CHANGED,
76 BUILD_TIME,
77 BUILD_NAME
78 );
79}
80
81void WaylandPlugin::release()
82{
83}
84
85void WaylandPlugin::setCallback(void *userData, PluginCallback *callback)
86{
87 mUserData = userData;
88 mCallback = callback;
89}
90
91int WaylandPlugin::openDisplay()
92{
93 int ret;
94
fei.dengb9a1a572023-09-13 01:33:57 +000095 Tls::Mutex::Autolock _l(mRenderLock);
96 DEBUG(mLogCategory,"openDisplay");
fei.dengf7a0cd32023-08-29 09:36:37 +000097 ret = mDisplay->openDisplay();
fei.dengb9a1a572023-09-13 01:33:57 +000098 if (ret != NO_ERROR) {
99 ERROR(mLogCategory,"Error open display");
100 return ret;
fei.dengf7a0cd32023-08-29 09:36:37 +0000101 }
fei.dengb9a1a572023-09-13 01:33:57 +0000102 DEBUG(mLogCategory,"openDisplay end");
103 return ret;
fei.dengf7a0cd32023-08-29 09:36:37 +0000104}
105
106int WaylandPlugin::openWindow()
107{
fei.dengb9a1a572023-09-13 01:33:57 +0000108 Tls::Mutex::Autolock _l(mRenderLock);
fei.dengf7a0cd32023-08-29 09:36:37 +0000109 /* if weston can't support pts feature,
110 * we should create a post buffer thread to
111 * send buffer by mono time
112 */
fei.deng640c3c92024-04-12 08:31:19 +0000113 WaylandDisplay::AmlConfigAPIList *amlconfig = mDisplay->getAmlConfigAPIList();
114 if (!amlconfig->enableSetPts) {
fei.dengdd910ef2024-06-07 10:25:30 +0800115 DEBUG(mLogCategory,"run frame post thread");
fei.dengf862f9c2024-10-24 16:46:55 +0800116 setThreadPriority(45);
117 run("waylandPostBufferThread");
fei.dengf7a0cd32023-08-29 09:36:37 +0000118 }
fei.dengb9a1a572023-09-13 01:33:57 +0000119 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000120}
121
122int WaylandPlugin::prepareFrame(RenderBuffer *buffer)
123{
124 mDisplay->prepareFrameBuffer(buffer);
fei.dengb9a1a572023-09-13 01:33:57 +0000125 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000126}
127
128int WaylandPlugin::displayFrame(RenderBuffer *buffer, int64_t displayTime)
129{
130 /* if weston can't support pts feature,
131 * push buffer to queue, the buffer will send to
132 * weston in post thread
133 */
fei.deng640c3c92024-04-12 08:31:19 +0000134 WaylandDisplay::AmlConfigAPIList *amlconfig = mDisplay->getAmlConfigAPIList();
135 if (!amlconfig->enableSetPts) {
le.handb98beb2024-09-09 08:39:09 +0000136 if (mUnderFlowDetect) {
137 mUnderFlowDetect = false;
138 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000139 buffer->time = displayTime;
140 mQueue->push(buffer);
fei.dengf862f9c2024-10-24 16:46:55 +0800141 //let post thread to post buffer asap
142 if (mQueue->getCnt() == 1) {
143 signalWaitTimeout();
144 }
145 DEBUG(mLogCategory,"queue size:%d,pts:%lld us,time:%lld us",mQueue->getCnt(),buffer->pts/1000,displayTime);
fei.dengf7a0cd32023-08-29 09:36:37 +0000146 } else {
fei.dengae8c90a2024-06-27 13:39:53 +0800147 buffer->time = displayTime;
fei.dengf7a0cd32023-08-29 09:36:37 +0000148 mDisplay->displayFrameBuffer(buffer, displayTime);
149 }
fei.dengb9a1a572023-09-13 01:33:57 +0000150 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000151}
152
153void WaylandPlugin::queueFlushCallback(void *userdata,void *data)
154{
155 WaylandPlugin* plugin = static_cast<WaylandPlugin *>(userdata);
156 plugin->handleFrameDropped((RenderBuffer *)data);
157 plugin->handleBufferRelease((RenderBuffer *)data);
158}
159
160int WaylandPlugin::flush()
161{
162 RenderBuffer *entity;
163 mQueue->flushAndCallback(this, WaylandPlugin::queueFlushCallback);
164 mDisplay->flushBuffers();
fei.dengf862f9c2024-10-24 16:46:55 +0800165 signalWaitTimeout();
fei.dengb9a1a572023-09-13 01:33:57 +0000166 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000167}
168
169int WaylandPlugin::pause()
170{
fei.deng19b48692024-08-13 14:17:55 +0800171 /*pause and resume can cause frame dropped.
172 those frames ready to send to weston in queue will drop
173 when resume*/
174 //mPaused = true;
fei.deng649b0e22024-09-03 18:57:13 +0800175 mDisplay->pause();
fei.dengb9a1a572023-09-13 01:33:57 +0000176 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000177}
178int WaylandPlugin::resume()
179{
fei.deng19b48692024-08-13 14:17:55 +0800180 //mPaused = false;
fei.dengb9a1a572023-09-13 01:33:57 +0000181 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000182}
183
184int WaylandPlugin::closeDisplay()
185{
186 RenderBuffer *entity;
fei.dengb9a1a572023-09-13 01:33:57 +0000187 Tls::Mutex::Autolock _l(mRenderLock);
fei.dengf7a0cd32023-08-29 09:36:37 +0000188 mDisplay->closeDisplay();
fei.dengf7a0cd32023-08-29 09:36:37 +0000189
fei.dengb9a1a572023-09-13 01:33:57 +0000190 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000191}
192
193int WaylandPlugin::closeWindow()
194{
fei.dengb9a1a572023-09-13 01:33:57 +0000195 Tls::Mutex::Autolock _l(mRenderLock);
fei.dengf7a0cd32023-08-29 09:36:37 +0000196 if (isRunning()) {
fei.dengf862f9c2024-10-24 16:46:55 +0800197 signalWaitTimeout();
fei.dengb9a1a572023-09-13 01:33:57 +0000198 DEBUG(mLogCategory,"stop frame post thread");
fei.dengf7a0cd32023-08-29 09:36:37 +0000199 requestExitAndWait();
200 }
fei.dengdd910ef2024-06-07 10:25:30 +0800201 mQueue->flushAndCallback(this, WaylandPlugin::queueFlushCallback);
fei.dengb9a1a572023-09-13 01:33:57 +0000202 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000203}
204
205
206int WaylandPlugin::getValue(PluginKey key, void *value)
207{
208 switch (key) {
209 case PLUGIN_KEY_SELECT_DISPLAY_OUTPUT: {
210 *(int *)(value) = mDisplay->getDisplayOutput();
fei.dengb9a1a572023-09-13 01:33:57 +0000211 TRACE(mLogCategory,"get select display output:%d",*(int *)value);
fei.dengf7a0cd32023-08-29 09:36:37 +0000212 } break;
fei.dengf1f5fc32023-12-06 06:22:20 +0000213 case PLUGIN_KEY_CURRENT_OUTPUT: {
214 *(int *)(value) = mDisplay->getCurrentOutputCrtcIndex();
215 //DEBUG(mLogCategory,"get current crtc output index:%d",*(int *)value);
216 } break;
fei.deng1c94a342024-08-05 19:33:28 +0800217 case PLUGIN_KEY_ZORDER: {
218 *(int *)(value) = mDisplay->getVideoPlaneZorder();
219 } break;
fei.dengf862f9c2024-10-24 16:46:55 +0800220 case PLUGIN_KET_VIDEO_HWC_LATENCY: {
221 //*(int *)(value) = 3; //set weston latency to 3
222 } break;
fei.dengf7a0cd32023-08-29 09:36:37 +0000223 }
fei.dengb9a1a572023-09-13 01:33:57 +0000224 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000225}
226
227int WaylandPlugin::setValue(PluginKey key, void *value)
228{
229 switch (key) {
230 case PLUGIN_KEY_WINDOW_SIZE: {
231 RenderRect* rect = static_cast<RenderRect*>(value);
232 if (mDisplay) {
233 mDisplay->setWindowSize(rect->x, rect->y, rect->w, rect->h);
234 }
235 } break;
236 case PLUGIN_KEY_FRAME_SIZE: {
237 RenderFrameSize * frameSize = static_cast<RenderFrameSize * >(value);
238 if (mDisplay) {
239 mDisplay->setFrameSize(frameSize->width, frameSize->height);
240 }
241 } break;
242 case PLUGIN_KEY_VIDEO_FORMAT: {
243 int videoFormat = *(int *)(value);
fei.dengb9a1a572023-09-13 01:33:57 +0000244 DEBUG(mLogCategory,"Set video format :%d",videoFormat);
fei.dengf7a0cd32023-08-29 09:36:37 +0000245 mDisplay->setVideoBufferFormat((RenderVideoFormat)videoFormat);
246 } break;
247 case PLUGIN_KEY_SELECT_DISPLAY_OUTPUT: {
248 int outputIndex = *(int *)(value);
fei.dengb9a1a572023-09-13 01:33:57 +0000249 DEBUG(mLogCategory,"Set select display output :%d",outputIndex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000250 mDisplay->setDisplayOutput(outputIndex);
251 } break;
252 case PLUGIN_KEY_VIDEO_PIP: {
253 int pip = *(int *) (value);
254 pip = pip > 0? 1: 0;
255 mDisplay->setPip(pip);
256 } break;
257 case PLUGIN_KEY_IMMEDIATELY_OUTPUT: {
fei.deng234e5f62024-09-30 15:27:48 +0800258 int enableImmediately = (*(int *)(value));
259 mImmediatelyOutput = enableImmediately > 0? true: false;
260 mDisplay->setImmediatelyOutput(enableImmediately);
fei.dengb9a1a572023-09-13 01:33:57 +0000261 DEBUG(mLogCategory, "Set immediately output:%d",mImmediatelyOutput);
fei.dengf7a0cd32023-08-29 09:36:37 +0000262 } break;
fei.deng640c3c92024-04-12 08:31:19 +0000263 case PLUGIN_KEY_KEEP_LAST_FRAME: {
264 int keep = *(int *) (value);
265 DEBUG(mLogCategory, "Set keep last frame:%d",keep);
266 mDisplay->setKeepLastFrame(keep);
267 } break;
le.hane8c8fdd2024-09-19 09:28:50 +0000268 case PLUGIN_KEY_KEEP_LAST_FRAME_ON_FLUSH: {
269 int keepOnFlush = *(int *) (value);
270 DEBUG(mLogCategory, "Set keep last frame on flush:%d",keepOnFlush);
271 mDisplay->setKeepLastFrameOnFlush(keepOnFlush);
272 } break;
fei.denga4abbd52024-07-11 19:17:50 +0800273 case PLUGIN_KEY_FORCE_ASPECT_RATIO: {
274 int forceAspectRatio = *(int *)(value);
275 DEBUG(mLogCategory, "force aspect ratio:%d, TODO ",forceAspectRatio);
276 } break;
277 case PLUGIN_KEY_PIXEL_ASPECT_RATIO: {
278 double ratio = *(double *)(value);
279 INFO(mLogCategory,"pixel aspect ratio :%f",ratio);
280 mDisplay->setPixelAspectRatio((double)ratio);
281 } break;
fei.deng6c425232024-07-19 16:15:31 +0800282 case PLUGIN_KEY_VIDEO_FRAME_RATE: {
283 RenderFraction * fraction = static_cast<RenderFraction*>(value);
284 INFO(mLogCategory,"frame rate,num:%d,denom:%d",fraction->num,fraction->denom);
285 mDisplay->setFrameRate(fraction->num, fraction->denom);
286 } break;
fei.deng1c94a342024-08-05 19:33:28 +0800287 case PLUGIN_KEY_ZORDER: {
288 int zorder = *(int *)(value);
289 INFO(mLogCategory,"set video plane zorder:%d",zorder);
290 mDisplay->setVideoPlaneZorder(zorder);
291 } break;
fei.deng96aa7f72024-09-29 15:46:52 +0800292 case PLUGIN_KEY_ROTATE_VIDEO: {
293 int degree = *(int *)(value);
294 INFO(mLogCategory,"set rotate video to:%d",degree);
295 mDisplay->setRotateVideo(degree);
296 } break;
fei.dengf7a0cd32023-08-29 09:36:37 +0000297 }
298 return 0;
299}
300
fei.dengf862f9c2024-10-24 16:46:55 +0800301void WaylandPlugin::waitTimeoutUs(int64_t timeoutUs)
302{
303 if (!mWaiting && mTimeMutex.lock() == 0) { //success
304 mWaiting = true;
305 mTimeCond.waitRelativeUs(mTimeMutex, timeoutUs);
306 mWaiting = false;
307 mTimeMutex.unlock();
308 }
309}
310
311void WaylandPlugin::signalWaitTimeout()
312{
313 if (mWaiting && mTimeMutex.lock() == 0) { //success
314 mTimeCond.signal();
315 mTimeMutex.unlock();
316 }
317}
318
fei.dengf7a0cd32023-08-29 09:36:37 +0000319void WaylandPlugin::handleBufferRelease(RenderBuffer *buffer)
320{
321 if (mCallback) {
322 mCallback->doBufferReleaseCallback(mUserData, (void *)buffer);
323 }
324}
325
326void WaylandPlugin::handleFrameDisplayed(RenderBuffer *buffer)
327{
328 if (mCallback) {
329 mCallback->doBufferDisplayedCallback(mUserData, (void *)buffer);
330 }
331}
332
333void WaylandPlugin::handleFrameDropped(RenderBuffer *buffer)
334{
335 if (mCallback) {
336 mCallback->doBufferDropedCallback(mUserData, (void *)buffer);
337 }
338}
339
fei.deng3287c082024-04-23 09:29:22 +0000340void WaylandPlugin::handleMsgNotify(int type, void *detail)
341{
342 if (mCallback) {
343 mCallback->doMsgCallback(mUserData, type, detail);
344 }
345}
346
fei.dengf7a0cd32023-08-29 09:36:37 +0000347void WaylandPlugin::readyToRun()
348{
349}
350
351bool WaylandPlugin::threadLoop()
352{
353 RenderBuffer *curFrameEntity = NULL;
354 RenderBuffer *expiredFrameEntity = NULL;
355 int64_t nowMonotime = Tls::Times::getSystemTimeUs();
fei.dengf862f9c2024-10-24 16:46:55 +0800356 int64_t waitTimeUs = 4*1000;
fei.dengf7a0cd32023-08-29 09:36:37 +0000357
358 //if queue is empty or paused, loop next
fei.dengf862f9c2024-10-24 16:46:55 +0800359 if ((mQueue->getCnt() < 1) || mPaused) {
360 if ((mQueue->getCnt() < 1) &&
le.handb98beb2024-09-09 08:39:09 +0000361 Tls::Times::getSystemTimeMs() - mLastDisplayTime > UNDER_FLOW_EXPIRED_TIME_MS &&
362 !mUnderFlowDetect) {
363 mUnderFlowDetect = true;
364 handleMsgNotify(MSG_UNDER_FLOW, NULL);
365 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000366 goto tag_next;
367 }
368
fei.dengf7a0cd32023-08-29 09:36:37 +0000369 //we output video frame asap
370 if (mImmediatelyOutput) {
371 //pop the peeked frame
372 mQueue->pop((void **)&expiredFrameEntity);
373 goto tag_post;
374 }
375
le.hanb9ac4fe2024-10-28 03:31:16 +0000376 //if weston obtains a buffer rendering,we can't send buffer to weston
377 if (mDisplay->isRedrawingPending()) {
378 goto tag_next;
379 }
380
fei.dengf7a0cd32023-08-29 09:36:37 +0000381 while (mQueue->peek((void **)&curFrameEntity, 0) == Q_OK)
382 {
fei.dengf862f9c2024-10-24 16:46:55 +0800383 //pop buffer when display time - now less than 1 ms
fei.dengf7a0cd32023-08-29 09:36:37 +0000384 //no frame expired,loop next
fei.dengf862f9c2024-10-24 16:46:55 +0800385 if ((curFrameEntity->time - nowMonotime) > 1000 ) {
386 waitTimeUs = curFrameEntity->time - nowMonotime;
fei.dengf7a0cd32023-08-29 09:36:37 +0000387 break;
388 }
389
390 //pop the peeked frame
391 mQueue->pop((void **)&curFrameEntity);
392
393 //drop last expired frame,got a new expired frame
394 if (expiredFrameEntity) {
fei.dengb9a1a572023-09-13 01:33:57 +0000395 WARNING(mLogCategory,"drop,now:%lld,display:%lld(pts:%lld ms),n-d:%lld ms",
fei.dengf7a0cd32023-08-29 09:36:37 +0000396 nowMonotime,expiredFrameEntity->time,expiredFrameEntity->pts/1000000,
397 (nowMonotime - expiredFrameEntity->time)/1000);
398 handleFrameDropped(expiredFrameEntity);
399 handleBufferRelease(expiredFrameEntity);
400 expiredFrameEntity = NULL;
401 }
402
403 expiredFrameEntity = curFrameEntity;
404 }
405
406tag_post:
407 if (!expiredFrameEntity) {
408 //TRACE(mLogCategory,"no frame expire");
409 goto tag_next;
410 }
411
412 if (mDisplay) {
le.handb98beb2024-09-09 08:39:09 +0000413 mLastDisplayTime = Tls::Times::getSystemTimeMs();
fei.dengf862f9c2024-10-24 16:46:55 +0800414 TRACE(mLogCategory,"post,now:%lld,display:%lld(pts:%lld us),n-d::%lld ms, size:%d",
415 nowMonotime,expiredFrameEntity->time,expiredFrameEntity->pts/1000,
fei.dengdd910ef2024-06-07 10:25:30 +0800416 (nowMonotime - expiredFrameEntity->time)/1000,mQueue->getCnt());
fei.dengf7a0cd32023-08-29 09:36:37 +0000417 mDisplay->displayFrameBuffer(expiredFrameEntity, expiredFrameEntity->time);
418 }
419
420tag_next:
fei.dengf862f9c2024-10-24 16:46:55 +0800421 waitTimeoutUs(waitTimeUs);
fei.dengf7a0cd32023-08-29 09:36:37 +0000422 return true;
423}
424
425void *makePluginInstance(int id)
426{
fei.dengdd910ef2024-06-07 10:25:30 +0800427 int fd= -1;
428 const char *levelPath = "/run/rlib_plugin_level";
429
fei.dengb9a1a572023-09-13 01:33:57 +0000430 int category =Logger_init(id);
fei.dengc4677852023-10-09 07:21:04 +0000431 char *env = getenv("VIDEO_RENDER_PLUGIN_LOG_LEVEL");
fei.dengf7a0cd32023-08-29 09:36:37 +0000432 if (env) {
433 int level = atoi(env);
434 Logger_set_level(level);
fei.dengdd910ef2024-06-07 10:25:30 +0800435 INFO(category,"env set VIDEO_RENDER_PLUGIN_LOG_LEVEL=%d",level);
fei.dengf7a0cd32023-08-29 09:36:37 +0000436 }
fei.dengdd910ef2024-06-07 10:25:30 +0800437
438 //get log level from /run/rlib_plugin_level
439 fd= open(levelPath, O_RDONLY|O_CLOEXEC);
440 if ( fd >= 0 )
441 {
442 char valstr[64];
443 uint32_t val= 0;
444 int nRead;
445
446 memset(valstr, 0, sizeof(valstr));
447 nRead = read(fd, valstr, sizeof(valstr) - 1);
448 valstr[strlen(valstr)] = '\0';
449 if (sscanf(valstr, "%u", &val) > 0)
450 {
451 Logger_set_level(val);
452 INFO(category,"set VIDEO_RENDER_LOG_LEVEL=%d",val);
453 }
454 close(fd);
455 fd = -1;
456 }
fei.dengdd910ef2024-06-07 10:25:30 +0800457
fei.dengb9a1a572023-09-13 01:33:57 +0000458 WaylandPlugin *pluginInstance = new WaylandPlugin(category);
fei.dengf7a0cd32023-08-29 09:36:37 +0000459 return static_cast<void *>(pluginInstance);
460}
461
462void destroyPluginInstance(void * plugin)
463{
fei.dengb9a1a572023-09-13 01:33:57 +0000464 int category;
465
fei.dengf7a0cd32023-08-29 09:36:37 +0000466 WaylandPlugin *pluginInstance = static_cast<WaylandPlugin *>(plugin);
fei.dengb9a1a572023-09-13 01:33:57 +0000467 category = pluginInstance->getLogCategory();
fei.dengf7a0cd32023-08-29 09:36:37 +0000468 delete pluginInstance;
fei.dengb9a1a572023-09-13 01:33:57 +0000469 Logger_exit(category);
fei.dengf7a0cd32023-08-29 09:36:37 +0000470}