blob: 50eb3ac84a84aae72899bd57d19d8cb0e54658a0 [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 "wayland_plugin.h"
17#include "wayland_display.h"
18#include "Logger.h"
19#include "Times.h"
fei.dengb9a1a572023-09-13 01:33:57 +000020#include "ErrorCode.h"
fei.dengf7a0cd32023-08-29 09:36:37 +000021
22#define TAG "rlib:wayland_plugin"
23
fei.dengb9a1a572023-09-13 01:33:57 +000024WaylandPlugin::WaylandPlugin(int logCatgory)
25 : mRenderLock("renderlock"),
26 mLogCategory(logCatgory)
fei.dengf7a0cd32023-08-29 09:36:37 +000027{
fei.dengb9a1a572023-09-13 01:33:57 +000028 mDisplay = new WaylandDisplay(this, logCatgory);
fei.dengf7a0cd32023-08-29 09:36:37 +000029 mQueue = new Tls::Queue();
30 mPaused = false;
31 mImmediatelyOutput = false;
32}
33
34WaylandPlugin::~WaylandPlugin()
35{
36 if (mDisplay) {
37 delete mDisplay;
38 }
39 if (mQueue) {
40 mQueue->flush();
41 delete mQueue;
42 mQueue = NULL;
43 }
fei.dengb9a1a572023-09-13 01:33:57 +000044 TRACE(mLogCategory,"desconstruct");
fei.dengf7a0cd32023-08-29 09:36:37 +000045}
46
47void WaylandPlugin::init()
48{
fei.dengb9a1a572023-09-13 01:33:57 +000049 INFO(mLogCategory,"\n--------------------------------\n"
fei.dengf7a0cd32023-08-29 09:36:37 +000050 "plugin : weston\n"
51 "ARCH : %s\n"
52 "branch name : %s\n"
53 "git version : %s\n"
54 "change id : %s \n"
55 "ID : %s \n"
56 "last changed: %s\n"
57 "build-time : %s\n"
58 "build-name : %s\n"
59 "--------------------------------\n",
60#if defined(__aarch64__)
61 "arm64",
62#else
63 "arm",
64#endif
65 BRANCH_NAME,
66 GIT_VERSION,
67 COMMIT_CHANGEID,
68 COMMIT_PD,
69 LAST_CHANGED,
70 BUILD_TIME,
71 BUILD_NAME
72 );
73}
74
75void WaylandPlugin::release()
76{
77}
78
79void WaylandPlugin::setCallback(void *userData, PluginCallback *callback)
80{
81 mUserData = userData;
82 mCallback = callback;
83}
84
85int WaylandPlugin::openDisplay()
86{
87 int ret;
88
fei.dengb9a1a572023-09-13 01:33:57 +000089 Tls::Mutex::Autolock _l(mRenderLock);
90 DEBUG(mLogCategory,"openDisplay");
fei.dengf7a0cd32023-08-29 09:36:37 +000091 ret = mDisplay->openDisplay();
fei.dengb9a1a572023-09-13 01:33:57 +000092 if (ret != NO_ERROR) {
93 ERROR(mLogCategory,"Error open display");
94 return ret;
fei.dengf7a0cd32023-08-29 09:36:37 +000095 }
fei.dengb9a1a572023-09-13 01:33:57 +000096 DEBUG(mLogCategory,"openDisplay end");
97 return ret;
fei.dengf7a0cd32023-08-29 09:36:37 +000098}
99
100int WaylandPlugin::openWindow()
101{
fei.dengb9a1a572023-09-13 01:33:57 +0000102 Tls::Mutex::Autolock _l(mRenderLock);
fei.dengf7a0cd32023-08-29 09:36:37 +0000103 /* if weston can't support pts feature,
104 * we should create a post buffer thread to
105 * send buffer by mono time
106 */
107 if (!mDisplay->isSentPtsToWeston()) {
fei.dengb9a1a572023-09-13 01:33:57 +0000108 DEBUG(mLogCategory,"run frame post thread");
fei.dengf7a0cd32023-08-29 09:36:37 +0000109 setThreadPriority(50);
110 run("waylandPostThread");
111 }
fei.dengb9a1a572023-09-13 01:33:57 +0000112 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000113}
114
115int WaylandPlugin::prepareFrame(RenderBuffer *buffer)
116{
117 mDisplay->prepareFrameBuffer(buffer);
fei.dengb9a1a572023-09-13 01:33:57 +0000118 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000119}
120
121int WaylandPlugin::displayFrame(RenderBuffer *buffer, int64_t displayTime)
122{
123 /* if weston can't support pts feature,
124 * push buffer to queue, the buffer will send to
125 * weston in post thread
126 */
127 if (!mDisplay->isSentPtsToWeston()) {
128 buffer->time = displayTime;
129 mQueue->push(buffer);
fei.dengb9a1a572023-09-13 01:33:57 +0000130 DEBUG(mLogCategory,"queue size:%d",mQueue->getCnt());
fei.dengf7a0cd32023-08-29 09:36:37 +0000131 } else {
132 mDisplay->displayFrameBuffer(buffer, displayTime);
133 }
fei.dengb9a1a572023-09-13 01:33:57 +0000134 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000135}
136
137void WaylandPlugin::queueFlushCallback(void *userdata,void *data)
138{
139 WaylandPlugin* plugin = static_cast<WaylandPlugin *>(userdata);
140 plugin->handleFrameDropped((RenderBuffer *)data);
141 plugin->handleBufferRelease((RenderBuffer *)data);
142}
143
144int WaylandPlugin::flush()
145{
146 RenderBuffer *entity;
147 mQueue->flushAndCallback(this, WaylandPlugin::queueFlushCallback);
148 mDisplay->flushBuffers();
fei.dengb9a1a572023-09-13 01:33:57 +0000149 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000150}
151
152int WaylandPlugin::pause()
153{
154 mPaused = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000155 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000156}
157int WaylandPlugin::resume()
158{
159 mPaused = false;
fei.dengb9a1a572023-09-13 01:33:57 +0000160 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000161}
162
163int WaylandPlugin::closeDisplay()
164{
165 RenderBuffer *entity;
fei.dengb9a1a572023-09-13 01:33:57 +0000166 Tls::Mutex::Autolock _l(mRenderLock);
fei.dengf7a0cd32023-08-29 09:36:37 +0000167 mDisplay->closeDisplay();
168 while (mQueue->pop((void **)&entity) == Q_OK)
169 {
170 handleBufferRelease(entity);
171 }
172
fei.dengb9a1a572023-09-13 01:33:57 +0000173 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000174}
175
176int WaylandPlugin::closeWindow()
177{
fei.dengb9a1a572023-09-13 01:33:57 +0000178 Tls::Mutex::Autolock _l(mRenderLock);
fei.dengf7a0cd32023-08-29 09:36:37 +0000179 if (isRunning()) {
fei.dengb9a1a572023-09-13 01:33:57 +0000180 DEBUG(mLogCategory,"stop frame post thread");
fei.dengf7a0cd32023-08-29 09:36:37 +0000181 requestExitAndWait();
182 }
fei.dengb9a1a572023-09-13 01:33:57 +0000183 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000184}
185
186
187int WaylandPlugin::getValue(PluginKey key, void *value)
188{
189 switch (key) {
190 case PLUGIN_KEY_SELECT_DISPLAY_OUTPUT: {
191 *(int *)(value) = mDisplay->getDisplayOutput();
fei.dengb9a1a572023-09-13 01:33:57 +0000192 TRACE(mLogCategory,"get select display output:%d",*(int *)value);
fei.dengf7a0cd32023-08-29 09:36:37 +0000193 } break;
194 }
fei.dengb9a1a572023-09-13 01:33:57 +0000195 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000196}
197
198int WaylandPlugin::setValue(PluginKey key, void *value)
199{
200 switch (key) {
201 case PLUGIN_KEY_WINDOW_SIZE: {
202 RenderRect* rect = static_cast<RenderRect*>(value);
203 if (mDisplay) {
204 mDisplay->setWindowSize(rect->x, rect->y, rect->w, rect->h);
205 }
206 } break;
207 case PLUGIN_KEY_FRAME_SIZE: {
208 RenderFrameSize * frameSize = static_cast<RenderFrameSize * >(value);
209 if (mDisplay) {
210 mDisplay->setFrameSize(frameSize->width, frameSize->height);
211 }
212 } break;
213 case PLUGIN_KEY_VIDEO_FORMAT: {
214 int videoFormat = *(int *)(value);
fei.dengb9a1a572023-09-13 01:33:57 +0000215 DEBUG(mLogCategory,"Set video format :%d",videoFormat);
fei.dengf7a0cd32023-08-29 09:36:37 +0000216 mDisplay->setVideoBufferFormat((RenderVideoFormat)videoFormat);
217 } break;
218 case PLUGIN_KEY_SELECT_DISPLAY_OUTPUT: {
219 int outputIndex = *(int *)(value);
fei.dengb9a1a572023-09-13 01:33:57 +0000220 DEBUG(mLogCategory,"Set select display output :%d",outputIndex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000221 mDisplay->setDisplayOutput(outputIndex);
222 } break;
223 case PLUGIN_KEY_VIDEO_PIP: {
224 int pip = *(int *) (value);
225 pip = pip > 0? 1: 0;
226 mDisplay->setPip(pip);
227 } break;
228 case PLUGIN_KEY_IMMEDIATELY_OUTPUT: {
229 bool mImmediatelyOutput = (*(int *)(value)) > 0? true: false;
fei.dengb9a1a572023-09-13 01:33:57 +0000230 DEBUG(mLogCategory, "Set immediately output:%d",mImmediatelyOutput);
fei.dengf7a0cd32023-08-29 09:36:37 +0000231 } break;
232 }
233 return 0;
234}
235
236void WaylandPlugin::handleBufferRelease(RenderBuffer *buffer)
237{
238 if (mCallback) {
239 mCallback->doBufferReleaseCallback(mUserData, (void *)buffer);
240 }
241}
242
243void WaylandPlugin::handleFrameDisplayed(RenderBuffer *buffer)
244{
245 if (mCallback) {
246 mCallback->doBufferDisplayedCallback(mUserData, (void *)buffer);
247 }
248}
249
250void WaylandPlugin::handleFrameDropped(RenderBuffer *buffer)
251{
252 if (mCallback) {
253 mCallback->doBufferDropedCallback(mUserData, (void *)buffer);
254 }
255}
256
257void WaylandPlugin::readyToRun()
258{
259}
260
261bool WaylandPlugin::threadLoop()
262{
263 RenderBuffer *curFrameEntity = NULL;
264 RenderBuffer *expiredFrameEntity = NULL;
265 int64_t nowMonotime = Tls::Times::getSystemTimeUs();
266
267 //if queue is empty or paused, loop next
268 if (mQueue->isEmpty() || mPaused) {
269 goto tag_next;
270 }
271
fei.deng1cfb2752023-10-26 08:01:25 +0000272 //if weston has no wl_outout,it means weston can't display frames
273 //so we should display buffer to display to drop buffers
274 if (mDisplay->getWlOutput() == NULL) {
275 mQueue->pop((void **)&expiredFrameEntity);
276 goto tag_post;
277 }
278
fei.dengf7a0cd32023-08-29 09:36:37 +0000279 //if weston obtains a buffer rendering,we can't send buffer to weston
280 if (mDisplay->isRedrawingPending()) {
281 goto tag_next;
282 }
283
284 //we output video frame asap
285 if (mImmediatelyOutput) {
286 //pop the peeked frame
287 mQueue->pop((void **)&expiredFrameEntity);
288 goto tag_post;
289 }
290
291 while (mQueue->peek((void **)&curFrameEntity, 0) == Q_OK)
292 {
293 //no frame expired,loop next
294 if (nowMonotime < curFrameEntity->time) {
295 break;
296 }
297
298 //pop the peeked frame
299 mQueue->pop((void **)&curFrameEntity);
300
301 //drop last expired frame,got a new expired frame
302 if (expiredFrameEntity) {
fei.dengb9a1a572023-09-13 01:33:57 +0000303 WARNING(mLogCategory,"drop,now:%lld,display:%lld(pts:%lld ms),n-d:%lld ms",
fei.dengf7a0cd32023-08-29 09:36:37 +0000304 nowMonotime,expiredFrameEntity->time,expiredFrameEntity->pts/1000000,
305 (nowMonotime - expiredFrameEntity->time)/1000);
306 handleFrameDropped(expiredFrameEntity);
307 handleBufferRelease(expiredFrameEntity);
308 expiredFrameEntity = NULL;
309 }
310
311 expiredFrameEntity = curFrameEntity;
312 }
313
314tag_post:
315 if (!expiredFrameEntity) {
316 //TRACE(mLogCategory,"no frame expire");
317 goto tag_next;
318 }
319
320 if (mDisplay) {
fei.dengb9a1a572023-09-13 01:33:57 +0000321 TRACE(mLogCategory,"post,now:%lld,display:%lld(pts:%lld ms),n-d::%lld ms",
fei.dengf7a0cd32023-08-29 09:36:37 +0000322 nowMonotime,expiredFrameEntity->time,expiredFrameEntity->pts/1000000,
323 (nowMonotime - expiredFrameEntity->time)/1000);
324 mDisplay->displayFrameBuffer(expiredFrameEntity, expiredFrameEntity->time);
325 }
326
327tag_next:
328 usleep(4*1000);
329 return true;
330}
331
332void *makePluginInstance(int id)
333{
fei.dengb9a1a572023-09-13 01:33:57 +0000334 int category =Logger_init(id);
fei.dengc4677852023-10-09 07:21:04 +0000335 char *env = getenv("VIDEO_RENDER_PLUGIN_LOG_LEVEL");
fei.dengf7a0cd32023-08-29 09:36:37 +0000336 if (env) {
337 int level = atoi(env);
338 Logger_set_level(level);
fei.dengc4677852023-10-09 07:21:04 +0000339 INFO(category,"VIDEO_RENDER_PLUGIN_LOG_LEVEL=%d",level);
fei.dengf7a0cd32023-08-29 09:36:37 +0000340 }
fei.dengb9a1a572023-09-13 01:33:57 +0000341 WaylandPlugin *pluginInstance = new WaylandPlugin(category);
fei.dengf7a0cd32023-08-29 09:36:37 +0000342 return static_cast<void *>(pluginInstance);
343}
344
345void destroyPluginInstance(void * plugin)
346{
fei.dengb9a1a572023-09-13 01:33:57 +0000347 int category;
348
fei.dengf7a0cd32023-08-29 09:36:37 +0000349 WaylandPlugin *pluginInstance = static_cast<WaylandPlugin *>(plugin);
fei.dengb9a1a572023-09-13 01:33:57 +0000350 category = pluginInstance->getLogCategory();
fei.dengf7a0cd32023-08-29 09:36:37 +0000351 delete pluginInstance;
fei.dengb9a1a572023-09-13 01:33:57 +0000352 Logger_exit(category);
fei.dengf7a0cd32023-08-29 09:36:37 +0000353}