]> git.vomp.tv Git - vompclient.git/blob - omx/omxeglrender.cc
Disable copious logging from new ImageOMX code
[vompclient.git] / omx / omxeglrender.cc
1 /*
2     Copyright 2021 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include <VG/openvg.h>
21 #include <EGL/egl.h>
22 #include <EGL/eglext.h>
23
24 #include "../log.h"
25
26 #include "omxeglrender.h"
27
28 static const char* TAG = "OMX_EGL_Render";
29
30
31 OMX_EGL_Render::OMX_EGL_Render()
32 {
33   omx_egl_render = this;
34 }
35
36 OMX_EGL_Render::~OMX_EGL_Render()
37 {
38   omx_image_decode = NULL;
39   handle_egl_render = 0;
40 }
41
42 bool OMX_EGL_Render::init()
43 {
44   initEventsProcessing();
45
46   OMX_CALLBACKTYPE callbacks = {&scb_EventHandler, &scb_EmptyBufferDone, &scb_FillBufferDone};
47
48   char* componentName;
49   asprintf(&componentName, "%s", componentName_egl_render);
50   OMX_ERRORTYPE error = OMX_GetHandle(&componentHandle, componentName, NULL, &callbacks);
51   free(componentName);
52 //   log->debug(TAG, "HANDLE ALLOC: OMX_EGL_Render: {} error: {:#x}", static_cast<void*>(componentHandle), error);
53   if (error != OMX_ErrorNone) return false;
54
55   handle_egl_render = componentHandle;
56
57   OMX_PORT_PARAM_TYPE p_param;
58   memset(&p_param, 0, sizeof(p_param));
59   p_param.nSize = sizeof(p_param);
60   p_param.nVersion.nVersion = OMX_VERSION;
61
62   error = OMX_GetParameter(componentHandle, OMX_IndexParamVideoInit, &p_param);
63   if (error != OMX_ErrorNone) return false;
64
65   inputPort = p_param.nStartPortNumber;
66   outputPort = p_param.nStartPortNumber + 1;
67
68 //   log->debug(TAG, "IN: {}, OUT: {}", inputPort, outputPort);
69   return true;
70 }
71
72 void OMX_EGL_Render::shutdown()
73 {
74   stopEventsProcessing();
75   OMX_ERRORTYPE error = OMX_FreeHandle(componentHandle);
76   if (error != OMX_ErrorNone) throw OMX_Exception("OMX_FreeHandle in OMX_EGL_Render::shutdown()", error);
77 }
78
79 void OMX_EGL_Render::prepareInputPort(OMX_U32 frameWidth, OMX_U32 frameHeight, OMX_U32 stride)
80 {
81 //   log->debug(TAG, "prepareInputPort");
82
83   // Calculate a slice height. It must be divisible by 16 and >= frameHeight
84   // Temporarily use sliceHeight for remainder
85   int sliceHeight = frameHeight % 16;
86   if (sliceHeight == 0)
87     sliceHeight = frameHeight;
88   else
89     sliceHeight = frameHeight + 16 - sliceHeight;
90
91   // Buffer size IS THE SLICE HEIGHT multiplied by the stride
92   inputPortBufferSize = sliceHeight * stride;
93
94
95   OMX_PARAM_PORTDEFINITIONTYPE portConfig;
96   memset(&portConfig, 0, sizeof(portConfig));
97   portConfig.nSize = sizeof(portConfig);
98   portConfig.nVersion.nVersion = OMX_VERSION;
99   portConfig.nPortIndex = inputPort;
100
101   OMX_ERRORTYPE error = OMX_GetParameter(componentHandle, OMX_IndexParamPortDefinition, &portConfig);
102   if (error != OMX_ErrorNone) throw OMX_Exception("OMX_GetParameter in OMX_EGL_Render::prepareInputPort()", error);
103
104   /*
105   log->debug(TAG, "Recv from get:");
106   log->debug(TAG, "nPortIndex: {}", portConfig.nPortIndex);
107   log->debug(TAG, "eDir: {}", portConfig.eDir);
108   log->debug(TAG, "buffer count actual: {}", portConfig.nBufferCountActual);
109   log->debug(TAG, "buffer count min: {}", portConfig.nBufferCountMin);
110   log->debug(TAG, "nBufferSize: {}", portConfig.nBufferSize);
111   log->debug(TAG, "bEnabled: {}", portConfig.bEnabled);
112   log->debug(TAG, "bPopulated: {}", portConfig.bPopulated);
113   log->debug(TAG, "eDomain: {}", portConfig.eDomain);
114   */
115
116   portConfig.nBufferCountActual = 1;
117   portConfig.nBufferSize = inputPortBufferSize;
118   portConfig.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
119   portConfig.format.video.eColorFormat = OMX_COLOR_Format32bitABGR8888;
120   portConfig.format.video.nFrameWidth = frameWidth;
121   portConfig.format.video.nStride = stride;
122   portConfig.format.video.nFrameHeight = frameHeight;
123   portConfig.format.video.nSliceHeight = sliceHeight;
124
125 //   log->debug(TAG, "Setting buf count actual: {}, buf size: {}", portConfig.nBufferCountActual, portConfig.nBufferSize);
126 //   log->debug(TAG, "calling setParameter: w {} h {} str {} sli {}", portConfig.format.video.nFrameWidth, portConfig.format.video.nFrameHeight,
127 //     portConfig.format.video.nStride, portConfig.format.video.nSliceHeight);
128
129   error = OMX_SetParameter(componentHandle, OMX_IndexParamPortDefinition, &portConfig);
130   if (error != OMX_ErrorNone) throw OMX_Exception("OMX_SetParameter in OMX_EGL_Render::prepareInputPort()", error);
131
132 //   printPortSettings(false);
133 }
134
135 void OMX_EGL_Render::prepareOutputPort(EGLDisplay egldisplay)
136 {
137   OMX_PARAM_PORTDEFINITIONTYPE port_def_type;
138   memset(&port_def_type, 0, sizeof(port_def_type));
139   port_def_type.nSize = sizeof(port_def_type);
140   port_def_type.nVersion.nVersion = OMX_VERSION;
141   port_def_type.nPortIndex = outputPort;
142
143   OMX_ERRORTYPE error = OMX_GetParameter(componentHandle, OMX_IndexParamPortDefinition, &port_def_type);
144   if (error != OMX_ErrorNone) throw OMX_Exception("OMX_GetParameter in OMX_EGL_Render::prep()", error);
145
146   port_def_type.nBufferCountActual = 1;
147   port_def_type.format.video.pNativeWindow = egldisplay;
148
149   error = OMX_SetParameter(componentHandle, OMX_IndexParamPortDefinition, &port_def_type);  // set port def: buffer count actual = 1
150   if (error != OMX_ErrorNone) throw OMX_Exception("OMX_SetParameter in OMX_EGL_Render::prep()", error);
151 }
152
153 void OMX_EGL_Render::allocateInputBuffers(char* data)
154 {
155   inBuffer1 = NULL;
156
157 //   log->debug(TAG, "Calling OMX_UseBuffer with data = {}", static_cast<void*>(data));
158   OMX_ERRORTYPE error = OMX_UseBuffer(componentHandle, &inBuffer1, inputPort, static_cast<OMX_PTR>(0), inputPortBufferSize, reinterpret_cast<OMX_U8*>(data));
159   if (error != OMX_ErrorNone) throw OMX_Exception("OMX_UseBuffer in OMX_EGL_Render::allocateInputBuffers()", error);
160
161   /*
162   log->debug(TAG, "OMX_UseBuffer:");
163   log->debug(TAG, "  nSize = {}", inBuffer1->nSize);
164   log->debug(TAG, "  pBuffer = {}", static_cast<void*>(inBuffer1->pBuffer));
165   log->debug(TAG, "  nAllocLen = {}", inBuffer1->nAllocLen);
166   log->debug(TAG, "  nFilledLen = {}", inBuffer1->nFilledLen);
167   log->debug(TAG, "  nOffset = {}", inBuffer1->nOffset);
168   log->debug(TAG, "  nInputPortIndex = {}", inBuffer1->nInputPortIndex);
169   log->debug(TAG, "  nOutputPortIndex = {}", inBuffer1->nOutputPortIndex);
170   log->debug(TAG, "  nFlags = {:#x}", inBuffer1->nFlags);
171
172   printPortSettings(false);
173   */
174 }
175
176 void OMX_EGL_Render::allocateEGLImageKHR(EGLImageKHR eglimagekhr)
177 {
178   OMX_ERRORTYPE error = OMX_UseEGLImage(componentHandle, &eglRenderOutputBufferHeader, outputPort, this, static_cast<void*>(eglimagekhr));
179   if (error != OMX_ErrorNone) throw OMX_Exception("OMX_UseEGLImage in OMX_EGL_Render::allocateEGLImageKHR()", error);
180
181 //   printPortSettings(true);
182 }
183
184 void OMX_EGL_Render::deallocateInputBuffers()
185 {
186   OMX_ERRORTYPE error = OMX_FreeBuffer(componentHandle, inputPort, inBuffer1);
187   if (error != OMX_ErrorNone) throw OMX_Exception("OMX_FreeBuffer in OMX_EGL_Render::deallocateInputBuffers()", error);
188
189   inBuffer1 = NULL;
190 }
191
192 void OMX_EGL_Render::deallocateEGLImageKHR()
193 {
194   OMX_ERRORTYPE error = OMX_FreeBuffer(componentHandle, outputPort, eglRenderOutputBufferHeader);
195   if (error != OMX_ErrorNone) throw OMX_Exception("OMX_FreeBuffer in OMX_EGL_Render::deallocateEGLImageKHR()", error);
196
197   eglRenderOutputBufferHeader = NULL;
198 }
199
200 void OMX_EGL_Render::sendToInput(char* data, int dataSize)
201 {
202 //   log->debug(TAG, "Starting sendToInput {}", dataSize);
203
204   inBuffer1->nFilledLen = dataSize;
205   inBuffer1->nOffset = 0;
206   inBuffer1->nTimeStamp = { 0, 0 };
207   inBuffer1->pAppPrivate = static_cast<OMX_PTR>(0);
208   inBuffer1->nFlags |= OMX_BUFFERFLAG_EOS;
209   inBuffer1->pBuffer = reinterpret_cast<OMX_U8*>(data);
210
211 //   log->debug(TAG, "calling emptythisbuffer");
212   OMX_ERRORTYPE error = OMX_EmptyThisBuffer(componentHandle, inBuffer1);
213   if (error != OMX_ErrorNone) throw OMX_Exception("OMX_EmptyThisBuffer in OMX_EGL_Render::sendToInput()", error);
214 //   log->debug(TAG, "sendToInput done");
215 }
216
217 void OMX_EGL_Render::render()
218 {
219   struct BufferWithOutputPort* bufferWithOutputPort{};
220
221   try
222   {
223     bufferWithOutputPort = new BufferWithOutputPort();
224     bufferWithOutputPort->bufhead = eglRenderOutputBufferHeader;
225     eglRenderOutputBufferHeader->pAppPrivate = static_cast<OMX_PTR>(bufferWithOutputPort);
226
227     /*
228     log->debug(TAG, "render: egl buffer header:");
229     log->debug(TAG, "{}", static_cast<void*>(eglRenderOutputBufferHeader->pBuffer));
230     log->debug(TAG, "{}", eglRenderOutputBufferHeader->nAllocLen);
231     log->debug(TAG, "{}", eglRenderOutputBufferHeader->nFilledLen);
232     log->debug(TAG, "{}", eglRenderOutputBufferHeader->nOffset);
233     log->debug(TAG, "{:#x}", eglRenderOutputBufferHeader->nFlags);
234     log->debug(TAG, "{}", eglRenderOutputBufferHeader->nInputPortIndex);
235     log->debug(TAG, "{}", eglRenderOutputBufferHeader->nOutputPortIndex);
236     log->debug(TAG, "{}", static_cast<void*>(eglRenderOutputBufferHeader->pAppPrivate));
237     */
238
239     std::unique_lock<std::mutex> ul(bufferWithOutputPort->mutex);
240
241 //     log->debug(TAG, "calling fillthisbuffer. bufhead: {}, BufferWithOutput: {}", static_cast<void*>(eglRenderOutputBufferHeader), static_cast<void*>(bufferWithOutputPort));
242
243     OMX_ERRORTYPE error = OMX_FillThisBuffer(componentHandle, eglRenderOutputBufferHeader);
244     if (error != OMX_ErrorNone) throw OMX_Exception("OMX_FillThisBuffer in OMX_EGL_Render::render()", error);
245
246 //     log->debug(TAG, "done fillthisbuffer. bufhead: {}, BufferWithOutput: {}", static_cast<void*>(eglRenderOutputBufferHeader), static_cast<void*>(bufferWithOutputPort));
247
248     bufferWithOutputPort->cond.wait(ul, [bufferWithOutputPort] { return bufferWithOutputPort->done; });
249     ul.unlock();
250
251     /*
252     log->debug(TAG, "receiveFromOutputPort signalled");
253
254     log->debug(TAG, "receiveFromOutput:");
255     log->debug(TAG, "  nSize = {}", eglRenderOutputBufferHeader->nSize);
256     log->debug(TAG, "  nAllocLen = {}", eglRenderOutputBufferHeader->nAllocLen);
257     log->debug(TAG, "  nFilledLen = {}", eglRenderOutputBufferHeader->nFilledLen);
258     log->debug(TAG, "  nOffset = {}", eglRenderOutputBufferHeader->nOffset);
259     log->debug(TAG, "  nInputPortIndex = {}", eglRenderOutputBufferHeader->nInputPortIndex);
260     log->debug(TAG, "  nOutputPortIndex = {}", eglRenderOutputBufferHeader->nOutputPortIndex);
261     log->debug(TAG, "  nFlags = {:#x}", eglRenderOutputBufferHeader->nFlags);
262     */
263
264     delete bufferWithOutputPort;
265     bufferWithOutputPort = NULL;
266   }
267   catch(...)
268   {
269     if (bufferWithOutputPort)
270     {
271       free(bufferWithOutputPort);
272       bufferWithOutputPort = NULL;
273     }
274     throw;
275   }
276 }
277
278 void OMX_EGL_Render::printPortSettings(bool which)
279 {
280   OMX_PARAM_PORTDEFINITIONTYPE portSettings;
281
282   memset(&portSettings, 0, sizeof(portSettings));
283   portSettings.nSize = sizeof(portSettings);
284   portSettings.nVersion.nVersion = OMX_VERSION;
285
286   if (which)
287   {
288     log->debug(TAG, "------ Port settings for OUTPUT:");
289     portSettings.nPortIndex = outputPort;
290   }
291   else
292   {
293     log->debug(TAG, "------ Port settings for INPUT:");
294     portSettings.nPortIndex = inputPort;
295   }
296
297   OMX_ERRORTYPE error = OMX_GetParameter(componentHandle, OMX_IndexParamPortDefinition, &portSettings);
298   if (error != OMX_ErrorNone) throw OMX_Exception("OMX_GetParameter in OMX_EGL_Render::printPortSettings()", error);
299
300   log->debug(TAG, "  nPortIndex: {}", portSettings.nPortIndex);
301   log->debug(TAG, "  buffer count min, actual, size: {} {} {}", portSettings.nBufferCountMin, portSettings.nBufferCountActual, portSettings.nBufferSize);
302   log->debug(TAG, "  eDir: {}", portSettings.eDir);
303   log->debug(TAG, "  bEnabled: {}", portSettings.bEnabled);
304   log->debug(TAG, "  bPopulated: {}", portSettings.bPopulated);
305   log->debug(TAG, "  eDomain: {}", portSettings.eDomain);
306
307   log->debug(TAG, "  cMIMEType: {}", static_cast<void*>(portSettings.format.video.cMIMEType));
308   log->debug(TAG, "  pNativeRender: {}", static_cast<void*>(portSettings.format.video.pNativeRender));
309   log->debug(TAG, "  nFrameWidth: {}", portSettings.format.video.nFrameWidth);
310   log->debug(TAG, "  nFrameHeight: {}", portSettings.format.video.nFrameHeight);
311   log->debug(TAG, "  nStride: {}", portSettings.format.video.nStride);
312   log->debug(TAG, "  nSliceHeight: {}", portSettings.format.video.nSliceHeight);
313   log->debug(TAG, "  nBitrate: {}", portSettings.format.video.nBitrate);
314   log->debug(TAG, "  xFramerate: {}", portSettings.format.video.xFramerate);
315   log->debug(TAG, "  eCompressionFormat: {:#x}", portSettings.format.video.eCompressionFormat);
316   log->debug(TAG, "  eColorFormat: {:#x}", portSettings.format.video.eColorFormat);
317 }
318
319 OMX_ERRORTYPE OMX_EGL_Render::cb_EmptyBufferDone(OMX_IN OMX_HANDLETYPE /*hcomp*/, OMX_IN OMX_PTR /*appdata*/, OMX_IN OMX_BUFFERHEADERTYPE* buffer)
320 {
321   /*
322   log->debug(TAG, "CB: EmptyBufferDone");
323   log->debug(TAG, "  nSize = {}", buffer->nSize);
324   log->debug(TAG, "  nAllocLen = {}", buffer->nAllocLen);
325   log->debug(TAG, "  nFilledLen = {}", buffer->nFilledLen);
326   log->debug(TAG, "  nOffset = {}", buffer->nOffset);
327   log->debug(TAG, "  nInputPortIndex = {}", buffer->nInputPortIndex);
328   log->debug(TAG, "  nOutputPortIndex = {}", buffer->nOutputPortIndex);
329   log->debug(TAG, "  nFlags = {:#x}", buffer->nFlags);
330   */
331   return OMX_ErrorNone;
332 }
333
334 OMX_ERRORTYPE OMX_EGL_Render::cb_FillBufferDone(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata, OMX_IN OMX_BUFFERHEADERTYPE* buffer)
335 {
336 //   log->debug(TAG, "CB: FillBufferDone, handle: {}, appdata: {}, buffer: {}", static_cast<void*>(hcomp), static_cast<void*>(appdata), static_cast<void*>(buffer));
337
338   struct BufferWithOutputPort* bufferWithOutputPort = static_cast<struct BufferWithOutputPort*>(buffer->pAppPrivate);
339   bufferWithOutputPort->mutex.lock();
340   bufferWithOutputPort->done = true;
341   bufferWithOutputPort->mutex.unlock();
342   bufferWithOutputPort->cond.notify_one();
343
344   return OMX_ErrorNone;
345 }