blob: 37fcaceb9d4626a0a4db1c7a2f1b8ace9e37932e [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;
fei.dengf1f5fc32023-12-06 06:22:20 +0000194 case PLUGIN_KEY_CURRENT_OUTPUT: {
195 *(int *)(value) = mDisplay->getCurrentOutputCrtcIndex();
196 //DEBUG(mLogCategory,"get current crtc output index:%d",*(int *)value);
197 } break;
fei.dengf7a0cd32023-08-29 09:36:37 +0000198 }
fei.dengb9a1a572023-09-13 01:33:57 +0000199 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000200}
201
202int WaylandPlugin::setValue(PluginKey key, void *value)
203{
204 switch (key) {
205 case PLUGIN_KEY_WINDOW_SIZE: {
206 RenderRect* rect = static_cast<RenderRect*>(value);
207 if (mDisplay) {
208 mDisplay->setWindowSize(rect->x, rect->y, rect->w, rect->h);
209 }
210 } break;
211 case PLUGIN_KEY_FRAME_SIZE: {
212 RenderFrameSize * frameSize = static_cast<RenderFrameSize * >(value);
213 if (mDisplay) {
214 mDisplay->setFrameSize(frameSize->width, frameSize->height);
215 }
216 } break;
217 case PLUGIN_KEY_VIDEO_FORMAT: {
218 int videoFormat = *(int *)(value);
fei.dengb9a1a572023-09-13 01:33:57 +0000219 DEBUG(mLogCategory,"Set video format :%d",videoFormat);
fei.dengf7a0cd32023-08-29 09:36:37 +0000220 mDisplay->setVideoBufferFormat((RenderVideoFormat)videoFormat);
221 } break;
222 case PLUGIN_KEY_SELECT_DISPLAY_OUTPUT: {
223 int outputIndex = *(int *)(value);
fei.dengb9a1a572023-09-13 01:33:57 +0000224 DEBUG(mLogCategory,"Set select display output :%d",outputIndex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000225 mDisplay->setDisplayOutput(outputIndex);
226 } break;
227 case PLUGIN_KEY_VIDEO_PIP: {
228 int pip = *(int *) (value);
229 pip = pip > 0? 1: 0;
230 mDisplay->setPip(pip);
231 } break;
232 case PLUGIN_KEY_IMMEDIATELY_OUTPUT: {
233 bool mImmediatelyOutput = (*(int *)(value)) > 0? true: false;
fei.dengb9a1a572023-09-13 01:33:57 +0000234 DEBUG(mLogCategory, "Set immediately output:%d",mImmediatelyOutput);
fei.dengf7a0cd32023-08-29 09:36:37 +0000235 } break;
236 }
237 return 0;
238}
239
240void WaylandPlugin::handleBufferRelease(RenderBuffer *buffer)
241{
242 if (mCallback) {
243 mCallback->doBufferReleaseCallback(mUserData, (void *)buffer);
244 }
245}
246
247void WaylandPlugin::handleFrameDisplayed(RenderBuffer *buffer)
248{
249 if (mCallback) {
250 mCallback->doBufferDisplayedCallback(mUserData, (void *)buffer);
251 }
252}
253
254void WaylandPlugin::handleFrameDropped(RenderBuffer *buffer)
255{
256 if (mCallback) {
257 mCallback->doBufferDropedCallback(mUserData, (void *)buffer);
258 }
259}
260
261void WaylandPlugin::readyToRun()
262{
263}
264
265bool WaylandPlugin::threadLoop()
266{
267 RenderBuffer *curFrameEntity = NULL;
268 RenderBuffer *expiredFrameEntity = NULL;
269 int64_t nowMonotime = Tls::Times::getSystemTimeUs();
270
271 //if queue is empty or paused, loop next
272 if (mQueue->isEmpty() || mPaused) {
273 goto tag_next;
274 }
275
fei.deng1cfb2752023-10-26 08:01:25 +0000276 //if weston has no wl_outout,it means weston can't display frames
277 //so we should display buffer to display to drop buffers
278 if (mDisplay->getWlOutput() == NULL) {
279 mQueue->pop((void **)&expiredFrameEntity);
280 goto tag_post;
281 }
282
fei.dengf7a0cd32023-08-29 09:36:37 +0000283 //if weston obtains a buffer rendering,we can't send buffer to weston
284 if (mDisplay->isRedrawingPending()) {
285 goto tag_next;
286 }
287
288 //we output video frame asap
289 if (mImmediatelyOutput) {
290 //pop the peeked frame
291 mQueue->pop((void **)&expiredFrameEntity);
292 goto tag_post;
293 }
294
295 while (mQueue->peek((void **)&curFrameEntity, 0) == Q_OK)
296 {
297 //no frame expired,loop next
298 if (nowMonotime < curFrameEntity->time) {
299 break;
300 }
301
302 //pop the peeked frame
303 mQueue->pop((void **)&curFrameEntity);
304
305 //drop last expired frame,got a new expired frame
306 if (expiredFrameEntity) {
fei.dengb9a1a572023-09-13 01:33:57 +0000307 WARNING(mLogCategory,"drop,now:%lld,display:%lld(pts:%lld ms),n-d:%lld ms",
fei.dengf7a0cd32023-08-29 09:36:37 +0000308 nowMonotime,expiredFrameEntity->time,expiredFrameEntity->pts/1000000,
309 (nowMonotime - expiredFrameEntity->time)/1000);
310 handleFrameDropped(expiredFrameEntity);
311 handleBufferRelease(expiredFrameEntity);
312 expiredFrameEntity = NULL;
313 }
314
315 expiredFrameEntity = curFrameEntity;
316 }
317
318tag_post:
319 if (!expiredFrameEntity) {
320 //TRACE(mLogCategory,"no frame expire");
321 goto tag_next;
322 }
323
324 if (mDisplay) {
fei.dengb9a1a572023-09-13 01:33:57 +0000325 TRACE(mLogCategory,"post,now:%lld,display:%lld(pts:%lld ms),n-d::%lld ms",
fei.dengf7a0cd32023-08-29 09:36:37 +0000326 nowMonotime,expiredFrameEntity->time,expiredFrameEntity->pts/1000000,
327 (nowMonotime - expiredFrameEntity->time)/1000);
328 mDisplay->displayFrameBuffer(expiredFrameEntity, expiredFrameEntity->time);
329 }
330
331tag_next:
332 usleep(4*1000);
333 return true;
334}
335
336void *makePluginInstance(int id)
337{
fei.dengb9a1a572023-09-13 01:33:57 +0000338 int category =Logger_init(id);
fei.dengc4677852023-10-09 07:21:04 +0000339 char *env = getenv("VIDEO_RENDER_PLUGIN_LOG_LEVEL");
fei.dengf7a0cd32023-08-29 09:36:37 +0000340 if (env) {
341 int level = atoi(env);
342 Logger_set_level(level);
fei.dengc4677852023-10-09 07:21:04 +0000343 INFO(category,"VIDEO_RENDER_PLUGIN_LOG_LEVEL=%d",level);
fei.dengf7a0cd32023-08-29 09:36:37 +0000344 }
fei.dengb9a1a572023-09-13 01:33:57 +0000345 WaylandPlugin *pluginInstance = new WaylandPlugin(category);
fei.dengf7a0cd32023-08-29 09:36:37 +0000346 return static_cast<void *>(pluginInstance);
347}
348
349void destroyPluginInstance(void * plugin)
350{
fei.dengb9a1a572023-09-13 01:33:57 +0000351 int category;
352
fei.dengf7a0cd32023-08-29 09:36:37 +0000353 WaylandPlugin *pluginInstance = static_cast<WaylandPlugin *>(plugin);
fei.dengb9a1a572023-09-13 01:33:57 +0000354 category = pluginInstance->getLogCategory();
fei.dengf7a0cd32023-08-29 09:36:37 +0000355 delete pluginInstance;
fei.dengb9a1a572023-09-13 01:33:57 +0000356 Logger_exit(category);
fei.dengf7a0cd32023-08-29 09:36:37 +0000357}