blob: 66603a04de8d6b37be2037e3e9d087996c26894f [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"
20
21#define TAG "rlib:wayland_plugin"
22
23WaylandPlugin::WaylandPlugin()
24{
25 mDisplay = new WaylandDisplay(this);
26 mQueue = new Tls::Queue();
27 mPaused = false;
28 mImmediatelyOutput = false;
29}
30
31WaylandPlugin::~WaylandPlugin()
32{
33 if (mDisplay) {
34 delete mDisplay;
35 }
36 if (mQueue) {
37 mQueue->flush();
38 delete mQueue;
39 mQueue = NULL;
40 }
41 TRACE("desconstruct");
42}
43
44void WaylandPlugin::init()
45{
46 INFO("\n--------------------------------\n"
47 "plugin : weston\n"
48 "ARCH : %s\n"
49 "branch name : %s\n"
50 "git version : %s\n"
51 "change id : %s \n"
52 "ID : %s \n"
53 "last changed: %s\n"
54 "build-time : %s\n"
55 "build-name : %s\n"
56 "--------------------------------\n",
57#if defined(__aarch64__)
58 "arm64",
59#else
60 "arm",
61#endif
62 BRANCH_NAME,
63 GIT_VERSION,
64 COMMIT_CHANGEID,
65 COMMIT_PD,
66 LAST_CHANGED,
67 BUILD_TIME,
68 BUILD_NAME
69 );
70}
71
72void WaylandPlugin::release()
73{
74}
75
76void WaylandPlugin::setCallback(void *userData, PluginCallback *callback)
77{
78 mUserData = userData;
79 mCallback = callback;
80}
81
82int WaylandPlugin::openDisplay()
83{
84 int ret;
85
86 std::lock_guard<std::mutex> lck(mRenderLock);
87 DEBUG("openDisplay");
88 ret = mDisplay->openDisplay();
89 if (ret != 0) {
90 ERROR("Error open display");
91 return -1;
92 }
93 DEBUG("openDisplay end");
94 return 0;
95}
96
97int WaylandPlugin::openWindow()
98{
99 std::lock_guard<std::mutex> lck(mRenderLock);
100 /* if weston can't support pts feature,
101 * we should create a post buffer thread to
102 * send buffer by mono time
103 */
104 if (!mDisplay->isSentPtsToWeston()) {
105 DEBUG("run frame post thread");
106 setThreadPriority(50);
107 run("waylandPostThread");
108 }
109 return 0;
110}
111
112int WaylandPlugin::prepareFrame(RenderBuffer *buffer)
113{
114 mDisplay->prepareFrameBuffer(buffer);
115 return 0;
116}
117
118int WaylandPlugin::displayFrame(RenderBuffer *buffer, int64_t displayTime)
119{
120 /* if weston can't support pts feature,
121 * push buffer to queue, the buffer will send to
122 * weston in post thread
123 */
124 if (!mDisplay->isSentPtsToWeston()) {
125 buffer->time = displayTime;
126 mQueue->push(buffer);
127 DEBUG("queue size:%d",mQueue->getCnt());
128 } else {
129 mDisplay->displayFrameBuffer(buffer, displayTime);
130 }
131 return 0;
132}
133
134void WaylandPlugin::queueFlushCallback(void *userdata,void *data)
135{
136 WaylandPlugin* plugin = static_cast<WaylandPlugin *>(userdata);
137 plugin->handleFrameDropped((RenderBuffer *)data);
138 plugin->handleBufferRelease((RenderBuffer *)data);
139}
140
141int WaylandPlugin::flush()
142{
143 RenderBuffer *entity;
144 mQueue->flushAndCallback(this, WaylandPlugin::queueFlushCallback);
145 mDisplay->flushBuffers();
146 return 0;
147}
148
149int WaylandPlugin::pause()
150{
151 mPaused = true;
152 return 0;
153}
154int WaylandPlugin::resume()
155{
156 mPaused = false;
157 return 0;
158}
159
160int WaylandPlugin::closeDisplay()
161{
162 RenderBuffer *entity;
163 std::lock_guard<std::mutex> lck(mRenderLock);
164 mDisplay->closeDisplay();
165 while (mQueue->pop((void **)&entity) == Q_OK)
166 {
167 handleBufferRelease(entity);
168 }
169
170 return 0;
171}
172
173int WaylandPlugin::closeWindow()
174{
175 std::lock_guard<std::mutex> lck(mRenderLock);
176 if (isRunning()) {
177 DEBUG("stop frame post thread");
178 requestExitAndWait();
179 }
180 return 0;
181}
182
183
184int WaylandPlugin::getValue(PluginKey key, void *value)
185{
186 switch (key) {
187 case PLUGIN_KEY_SELECT_DISPLAY_OUTPUT: {
188 *(int *)(value) = mDisplay->getDisplayOutput();
189 TRACE("get select display output:%d",*(int *)value);
190 } break;
191 }
192 return 0;
193}
194
195int WaylandPlugin::setValue(PluginKey key, void *value)
196{
197 switch (key) {
198 case PLUGIN_KEY_WINDOW_SIZE: {
199 RenderRect* rect = static_cast<RenderRect*>(value);
200 if (mDisplay) {
201 mDisplay->setWindowSize(rect->x, rect->y, rect->w, rect->h);
202 }
203 } break;
204 case PLUGIN_KEY_FRAME_SIZE: {
205 RenderFrameSize * frameSize = static_cast<RenderFrameSize * >(value);
206 if (mDisplay) {
207 mDisplay->setFrameSize(frameSize->width, frameSize->height);
208 }
209 } break;
210 case PLUGIN_KEY_VIDEO_FORMAT: {
211 int videoFormat = *(int *)(value);
212 DEBUG("Set video format :%d",videoFormat);
213 mDisplay->setVideoBufferFormat((RenderVideoFormat)videoFormat);
214 } break;
215 case PLUGIN_KEY_SELECT_DISPLAY_OUTPUT: {
216 int outputIndex = *(int *)(value);
217 DEBUG("Set select display output :%d",outputIndex);
218 mDisplay->setDisplayOutput(outputIndex);
219 } break;
220 case PLUGIN_KEY_VIDEO_PIP: {
221 int pip = *(int *) (value);
222 pip = pip > 0? 1: 0;
223 mDisplay->setPip(pip);
224 } break;
225 case PLUGIN_KEY_IMMEDIATELY_OUTPUT: {
226 bool mImmediatelyOutput = (*(int *)(value)) > 0? true: false;
227 DEBUG("Set immediately output:%d",mImmediatelyOutput);
228 } break;
229 }
230 return 0;
231}
232
233void WaylandPlugin::handleBufferRelease(RenderBuffer *buffer)
234{
235 if (mCallback) {
236 mCallback->doBufferReleaseCallback(mUserData, (void *)buffer);
237 }
238}
239
240void WaylandPlugin::handleFrameDisplayed(RenderBuffer *buffer)
241{
242 if (mCallback) {
243 mCallback->doBufferDisplayedCallback(mUserData, (void *)buffer);
244 }
245}
246
247void WaylandPlugin::handleFrameDropped(RenderBuffer *buffer)
248{
249 if (mCallback) {
250 mCallback->doBufferDropedCallback(mUserData, (void *)buffer);
251 }
252}
253
254void WaylandPlugin::readyToRun()
255{
256}
257
258bool WaylandPlugin::threadLoop()
259{
260 RenderBuffer *curFrameEntity = NULL;
261 RenderBuffer *expiredFrameEntity = NULL;
262 int64_t nowMonotime = Tls::Times::getSystemTimeUs();
263
264 //if queue is empty or paused, loop next
265 if (mQueue->isEmpty() || mPaused) {
266 goto tag_next;
267 }
268
269 //if weston obtains a buffer rendering,we can't send buffer to weston
270 if (mDisplay->isRedrawingPending()) {
271 goto tag_next;
272 }
273
274 //we output video frame asap
275 if (mImmediatelyOutput) {
276 //pop the peeked frame
277 mQueue->pop((void **)&expiredFrameEntity);
278 goto tag_post;
279 }
280
281 while (mQueue->peek((void **)&curFrameEntity, 0) == Q_OK)
282 {
283 //no frame expired,loop next
284 if (nowMonotime < curFrameEntity->time) {
285 break;
286 }
287
288 //pop the peeked frame
289 mQueue->pop((void **)&curFrameEntity);
290
291 //drop last expired frame,got a new expired frame
292 if (expiredFrameEntity) {
293 WARNING("drop,now:%lld,display:%lld(pts:%lld ms),n-d:%lld ms",
294 nowMonotime,expiredFrameEntity->time,expiredFrameEntity->pts/1000000,
295 (nowMonotime - expiredFrameEntity->time)/1000);
296 handleFrameDropped(expiredFrameEntity);
297 handleBufferRelease(expiredFrameEntity);
298 expiredFrameEntity = NULL;
299 }
300
301 expiredFrameEntity = curFrameEntity;
302 }
303
304tag_post:
305 if (!expiredFrameEntity) {
306 //TRACE(mLogCategory,"no frame expire");
307 goto tag_next;
308 }
309
310 if (mDisplay) {
311 TRACE("post,now:%lld,display:%lld(pts:%lld ms),n-d::%lld ms",
312 nowMonotime,expiredFrameEntity->time,expiredFrameEntity->pts/1000000,
313 (nowMonotime - expiredFrameEntity->time)/1000);
314 mDisplay->displayFrameBuffer(expiredFrameEntity, expiredFrameEntity->time);
315 }
316
317tag_next:
318 usleep(4*1000);
319 return true;
320}
321
322void *makePluginInstance(int id)
323{
324 char *env = getenv("VIDEO_RENDER_LOG_LEVEL");
325 if (env) {
326 int level = atoi(env);
327 Logger_set_level(level);
328 INFO("VIDEO_RENDER_LOG_LEVEL=%d",level);
329 }
330 WaylandPlugin *pluginInstance = new WaylandPlugin();
331 return static_cast<void *>(pluginInstance);
332}
333
334void destroyPluginInstance(void * plugin)
335{
336 WaylandPlugin *pluginInstance = static_cast<WaylandPlugin *>(plugin);
337 delete pluginInstance;
338}