1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010 - 2020, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of The Linux Foundation nor
12 the names of its contributors may be used to endorse or promote
13 products derived from this software without specific prior written
14 permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28
29 /*============================================================================
30 O p e n M A X w r a p p e r s
31 O p e n M A X C o r e
32
33 This module contains the implementation of the OpenMAX core & component.
34
35 *//*========================================================================*/
36
37 //////////////////////////////////////////////////////////////////////////////
38 // Include Files
39 //////////////////////////////////////////////////////////////////////////////
40
41 #define __STDC_FORMAT_MACROS
42 #include <inttypes.h>
43
44 #include <string.h>
45 #include <pthread.h>
46 #include <sys/prctl.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <errno.h>
50 #include "omx_vdec.h"
51 #include "vidc_common.h"
52 #include <fcntl.h>
53 #include <limits.h>
54 #include <stdlib.h>
55 #ifdef HYPERVISOR
56 #include "hypv_intercept.h"
57 #endif
58 #include <media/hardware/HardwareAPI.h>
59 #include <sys/eventfd.h>
60 #include "PlatformConfig.h"
61 #include <linux/dma-buf.h>
62 #include <linux/videodev2.h>
63
64 #if !defined(_ANDROID_) || defined(SYS_IOCTL)
65 #include <sys/ioctl.h>
66 #include <sys/mman.h>
67 #endif
68
69 #ifdef _ANDROID_
70 #include <cutils/properties.h>
71
72 #ifdef _QUERY_DISP_RES_
73 #include "display_config.h"
74 #endif
75 #endif
76
77 #ifdef _USE_GLIB_
78 #include <glib.h>
79 #define strlcpy g_strlcpy
80 #endif
81
82 #include <qdMetaData.h>
83 #include <gralloc_priv.h>
84
85 #ifdef ANDROID_JELLYBEAN_MR2
86 #include "QComOMXMetadata.h"
87 #endif
88
89 #define BUFFER_LOG_LOC "/data/vendor/media"
90
91 #ifdef OUTPUT_EXTRADATA_LOG
92 FILE *outputExtradataFile;
93 char output_extradata_filename [] = "/data/vendor/media/extradata";
94 #endif
95
96 #define DEFAULT_FPS 30
97 #define MAX_SUPPORTED_FPS 240
98 #define DEFAULT_WIDTH_ALIGNMENT 128
99 #define DEFAULT_HEIGHT_ALIGNMENT 32
100
101 #define POLL_TIMEOUT 0x7fffffff
102
103 #ifdef _ANDROID_
104 extern "C" {
105 #include<utils/Log.h>
106 }
107 #endif//_ANDROID_
108
109 #define SZ_4K 0x1000
110 #define SZ_1M 0x100000
111
112 #define PREFETCH_PIXEL_BUFFER_COUNT 16
113 #define PREFETCH_NON_PIXEL_BUFFER_COUNT 1
114
115 #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } }
116 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); }
117 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
118 #undef ALIGN
119 #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1))
120
121 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_OUTPUTCROP_EXTRADATA \
122 | OMX_DISPLAY_INFO_EXTRADATA | OMX_UBWC_CR_STATS_INFO_EXTRADATA)
123
124 // Y=16(0-9bits), Cb(10-19bits)=Cr(20-29bits)=128, black by default
125 #define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8020010
126
127 #ifndef ION_FLAG_CP_BITSTREAM
128 #define ION_FLAG_CP_BITSTREAM 0
129 #endif
130
131 #ifndef ION_FLAG_CP_PIXEL
132 #define ION_FLAG_CP_PIXEL 0
133 #endif
134
135 #ifdef SLAVE_SIDE_CP
136 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
137 #define SECURE_ALIGN SZ_1M
138 #define SECURE_FLAGS_INPUT_BUFFER ION_FLAG_SECURE
139 #define SECURE_FLAGS_OUTPUT_BUFFER ION_FLAG_SECURE
140 #else //MASTER_SIDE_CP
141 #define MEM_HEAP_ID ION_SECURE_HEAP_ID
142 #define SECURE_ALIGN SZ_4K
143 #define SECURE_FLAGS_INPUT_BUFFER (ION_FLAG_SECURE | ION_FLAG_CP_BITSTREAM)
144 #define SECURE_FLAGS_OUTPUT_BUFFER (ION_FLAG_SECURE | ION_FLAG_CP_PIXEL)
145 #endif
146
147 #define LUMINANCE_DIV_FACTOR 10000.0
148 #define LUMINANCE_MAXDISPLAY_CDM2 1000
149
150 /* defined in mp-ctl.h */
151 #define MPCTLV3_VIDEO_DECODE_PB_HINT 0x41C04000
152
153 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
154 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
155
156 /*
157 To enable sending vp9/hevc hdr10plus metadata via private gralloc
158 handle to display, define HDR10PLUS_SETMETADATA_ENABLE as 1.This
159 disables sending metadata via framework. To enable sending vp9/hevc
160 hdr10plus metadata via framework, define HDR10PLUS_SETMETADATA_ENABLE
161 as 0. This disables sending metadata via gralloc handle.
162 */
163 #define HDR10_SETMETADATA_ENABLE 0
164
165 using namespace android;
166
167 #ifdef HYPERVISOR
168 #define ioctl(x, y, z) hypv_ioctl(x, y, z)
169 #define poll(x, y, z) hypv_poll(x, y, z)
170 #endif
171
172 static OMX_U32 maxSmoothStreamingWidth = 1920;
173 static OMX_U32 maxSmoothStreamingHeight = 1088;
174
print_omx_buffer(const char * str,OMX_BUFFERHEADERTYPE * pHeader)175 void print_omx_buffer(const char *str, OMX_BUFFERHEADERTYPE *pHeader)
176 {
177 if (!pHeader)
178 return;
179
180 DEBUG_PRINT_HIGH("%s: Header %p buffer %p alloclen %d offset %d filledlen %d timestamp %lld flags %#x",
181 str, pHeader, pHeader->pBuffer, pHeader->nAllocLen,
182 pHeader->nOffset, pHeader->nFilledLen,
183 pHeader->nTimeStamp, pHeader->nFlags);
184 }
185
print_v4l2_buffer(const char * str,struct v4l2_buffer * v4l2)186 void print_v4l2_buffer(const char *str, struct v4l2_buffer *v4l2)
187 {
188 if (!v4l2)
189 return;
190
191 if (v4l2->length == 1)
192 DEBUG_PRINT_HIGH(
193 "%s: %s: idx %2d userptr %#lx fd %d off %d size %d filled %d flags %#x\n",
194 str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
195 "OUTPUT" : "CAPTURE", v4l2->index,
196 v4l2->m.planes[0].m.userptr, v4l2->m.planes[0].reserved[0],
197 v4l2->m.planes[0].reserved[1], v4l2->m.planes[0].length,
198 v4l2->m.planes[0].bytesused, v4l2->flags);
199 else
200 DEBUG_PRINT_HIGH(
201 "%s: %s: idx %2d userptr %#lx fd %d off %d size %d filled %d flags %#x, extradata: fd %d off %d size %d filled %d\n",
202 str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
203 "OUTPUT" : "CAPTURE", v4l2->index,
204 v4l2->m.planes[0].m.userptr, v4l2->m.planes[0].reserved[0],
205 v4l2->m.planes[0].reserved[1], v4l2->m.planes[0].length,
206 v4l2->m.planes[0].bytesused, v4l2->m.planes[1].reserved[0],
207 v4l2->flags, v4l2->m.planes[1].reserved[1],
208 v4l2->m.planes[1].length, v4l2->m.planes[1].bytesused);
209 }
210
async_message_thread(void * input)211 void* async_message_thread (void *input)
212 {
213 OMX_BUFFERHEADERTYPE *buffer;
214 struct v4l2_plane plane[VIDEO_MAX_PLANES];
215 struct pollfd pfds[2];
216 struct v4l2_buffer v4l2_buf;
217 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
218 struct v4l2_event dqevent;
219 omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
220 pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
221 pfds[1].events = POLLIN | POLLERR;
222 pfds[0].fd = omx->drv_ctx.video_driver_fd;
223 pfds[1].fd = omx->m_poll_efd;
224 int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
225 DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
226 prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
227 while (!omx->async_thread_force_stop) {
228 rc = poll(pfds, 2, POLL_TIMEOUT);
229 if (!rc) {
230 DEBUG_PRINT_ERROR("Poll timedout");
231 break;
232 } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
233 DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
234 break;
235 }
236 if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
237 DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited");
238 break;
239 }
240 if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
241 struct vdec_msginfo vdec_msg;
242 memset(&vdec_msg, 0, sizeof(vdec_msg));
243 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
244 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
245 v4l2_buf.length = omx->drv_ctx.num_planes;
246 v4l2_buf.m.planes = plane;
247 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
248 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
249 vdec_msg.status_code=VDEC_S_SUCCESS;
250 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
251 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
252 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
253 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
254 (uint64_t)v4l2_buf.timestamp.tv_usec;
255
256 if (omx->async_message_process(input,&vdec_msg) < 0) {
257 DEBUG_PRINT_HIGH("async_message_thread Exited");
258 break;
259 }
260 }
261 }
262 if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
263 struct vdec_msginfo vdec_msg;
264 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
265 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
266 v4l2_buf.length = 1;
267 v4l2_buf.m.planes = plane;
268 while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
269 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
270 vdec_msg.status_code=VDEC_S_SUCCESS;
271 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
272 if (omx->async_message_process(input,&vdec_msg) < 0) {
273 DEBUG_PRINT_HIGH("async_message_thread Exited");
274 break;
275 }
276 }
277 }
278 if (pfds[0].revents & POLLPRI) {
279 rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
280 if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
281 struct vdec_msginfo vdec_msg;
282 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
283
284 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
285 vdec_msg.status_code=VDEC_S_SUCCESS;
286 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
287 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
288 vdec_msg.msgdata.output_frame.flags = true; // INSUFFICIENT event
289 DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient");
290 omx->dpb_bit_depth = ptr[2];
291 DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth - %d", ptr[3]);
292 omx->m_progressive = ptr[3];
293 DEBUG_PRINT_HIGH("VIDC Port Reconfig PicStruct - %d", ptr[4]);
294 omx->m_color_space = (ptr[4] == MSM_VIDC_BT2020 ? (omx_vdec::BT2020):
295 (omx_vdec:: EXCEPT_BT2020));
296 DEBUG_PRINT_HIGH("VIDC Port Reconfig ColorSpace - %d", omx->m_color_space);
297 if (omx->async_message_process(input,&vdec_msg) < 0) {
298 DEBUG_PRINT_HIGH("async_message_thread Exited");
299 break;
300 }
301 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT) {
302
303 bool event_fields_changed = false;
304 bool send_msg = false;
305 omx_vdec::color_space_type tmp_color_space;
306 struct vdec_msginfo vdec_msg;
307 DEBUG_PRINT_HIGH("VIDC Port Reconfig received sufficient");
308 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
309 int tmp_profile = 0;
310 int tmp_level = 0;
311 int codec = omx->get_session_codec_type();
312 event_fields_changed |= (omx->dpb_bit_depth != (int)ptr[2]);
313 event_fields_changed |= (omx->m_progressive != (int)ptr[3]);
314 tmp_color_space = (ptr[4] == MSM_VIDC_BT2020 ? (omx_vdec::BT2020):
315 (omx_vdec:: EXCEPT_BT2020));
316 event_fields_changed |= (omx->m_color_space != tmp_color_space);
317
318 /*
319 * If the resolution is different due to 16\32 pixel alignment,
320 * let's handle as Sufficient. Ex : 1080 & 1088 or 2160 & 2176.
321 * When FBD comes, component updates the clients with actual
322 * resolution through set_buffer_geometry.
323 */
324
325 event_fields_changed |= (omx->drv_ctx.video_resolution.frame_height != ptr[0]);
326 event_fields_changed |= (omx->drv_ctx.video_resolution.frame_width != ptr[1]);
327
328 if ((codec == V4L2_PIX_FMT_H264) ||
329 (codec == V4L2_PIX_FMT_HEVC)) {
330 if (profile_level_converter::convert_v4l2_profile_to_omx(
331 codec, ptr[9], &tmp_profile) &&
332 profile_level_converter::convert_v4l2_level_to_omx(
333 codec, ptr[10], &tmp_level)) {
334 event_fields_changed |= (omx->mClientSessionForSufficiency &&
335 ((tmp_profile != (int)omx->mClientSetProfile) ||
336 (tmp_level > (int)omx->mClientSetLevel)));
337 }
338 }
339
340 if (!omx->is_down_scalar_enabled && omx->m_is_split_mode &&
341 (omx->drv_ctx.video_resolution.frame_height != ptr[0] ||
342 omx->drv_ctx.video_resolution.frame_width != ptr[1])) {
343 event_fields_changed = true;
344 }
345
346 if (event_fields_changed) {
347 DEBUG_PRINT_HIGH("VIDC Port Reconfig Old Resolution(H,W) = (%d,%d) New Resolution(H,W) = (%d,%d))",
348 omx->drv_ctx.video_resolution.frame_height,
349 omx->drv_ctx.video_resolution.frame_width,
350 ptr[0], ptr[1]);
351 DEBUG_PRINT_HIGH("VIDC Port Reconfig Old bitdepth = %d New bitdepth = %d",
352 omx->dpb_bit_depth, ptr[2]);
353 DEBUG_PRINT_HIGH("VIDC Port Reconfig Old picstruct = %d New picstruct = %d",
354 omx->m_progressive, ptr[3]);
355 DEBUG_PRINT_HIGH("VIDC Port Reconfig Old colorSpace = %s New colorspace = %s",
356 (omx->m_color_space == omx_vdec::BT2020 ? "BT2020": "EXCEPT_BT2020"),
357 (tmp_color_space == omx_vdec::BT2020 ? "BT2020": "EXCEPT_BT2020"));
358 DEBUG_PRINT_HIGH("Client Session for sufficiency feature is %s", omx->mClientSessionForSufficiency ? "enabled": "disabled");
359 DEBUG_PRINT_HIGH("VIDC Port Reconfig Client (Profile,Level) = (%d,%d) bitstream(Profile,Level) = (%d,%d))",
360 omx->mClientSetProfile,
361 omx->mClientSetLevel,
362 tmp_profile, tmp_level);
363 omx->dpb_bit_depth = ptr[2];
364 omx->m_progressive = ptr[3];
365 omx->m_color_space = (ptr[4] == MSM_VIDC_BT2020 ? (omx_vdec::BT2020):
366 (omx_vdec:: EXCEPT_BT2020));
367 send_msg = true;
368 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
369 vdec_msg.status_code=VDEC_S_SUCCESS;
370 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
371 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
372 vdec_msg.msgdata.output_frame.flags = false; // SUFFICIENT event
373 } else {
374 struct v4l2_decoder_cmd dec;
375 memset(&dec, 0, sizeof(dec));
376 dec.cmd = V4L2_QCOM_CMD_SESSION_CONTINUE;
377 rc = ioctl(pfds[0].fd, VIDIOC_DECODER_CMD, &dec);
378 if (rc < 0) {
379 DEBUG_PRINT_ERROR("Session continue failed");
380 send_msg = true;
381 vdec_msg.msgcode=VDEC_MSG_EVT_HW_ERROR;
382 vdec_msg.status_code=VDEC_S_SUCCESS;
383 } else {
384 DEBUG_PRINT_HIGH("Sent Session continue");
385 }
386 }
387
388 if (send_msg) {
389 if (omx->async_message_process(input,&vdec_msg) < 0) {
390 DEBUG_PRINT_HIGH("async_message_thread Exited");
391 break;
392 }
393 }
394
395 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
396 struct vdec_msginfo vdec_msg;
397 uint32_t flush_type = *(uint32_t *)dqevent.u.data;
398 // Old driver doesn't send flushType information.
399 // To make this backward compatible fallback to old approach
400 // if the flush_type is not present.
401 vdec_msg.status_code=VDEC_S_SUCCESS;
402 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_OUTPUT)) {
403 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
404 DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
405 if (omx->async_message_process(input,&vdec_msg) < 0) {
406 DEBUG_PRINT_HIGH("async_message_thread Exited");
407 break;
408 }
409 }
410
411 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_CAPTURE)) {
412 vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
413 DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
414 if (omx->async_message_process(input,&vdec_msg) < 0) {
415 DEBUG_PRINT_HIGH("async_message_thread Exited");
416 break;
417 }
418 }
419 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
420 struct vdec_msginfo vdec_msg;
421 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
422 vdec_msg.status_code=VDEC_S_SUCCESS;
423 DEBUG_PRINT_ERROR("HW Overload received");
424 if (omx->async_message_process(input,&vdec_msg) < 0) {
425 DEBUG_PRINT_HIGH("async_message_thread Exited");
426 break;
427 }
428 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
429 struct vdec_msginfo vdec_msg;
430 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
431 vdec_msg.status_code=VDEC_S_SUCCESS;
432 DEBUG_PRINT_ERROR("HW Unsupported received");
433 if (omx->async_message_process(input,&vdec_msg) < 0) {
434 DEBUG_PRINT_HIGH("async_message_thread Exited");
435 break;
436 }
437 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
438 struct vdec_msginfo vdec_msg;
439 vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR;
440 vdec_msg.status_code = VDEC_S_SUCCESS;
441 DEBUG_PRINT_HIGH("SYS Error Recieved");
442 if (omx->async_message_process(input,&vdec_msg) < 0) {
443 DEBUG_PRINT_HIGH("async_message_thread Exited");
444 break;
445 }
446 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) {
447 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
448
449 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
450 } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
451 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
452 struct vdec_msginfo vdec_msg;
453
454 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
455
456 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
457 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
458 v4l2_buf.length = omx->drv_ctx.num_planes;
459 v4l2_buf.m.planes = plane;
460 v4l2_buf.index = ptr[5];
461 v4l2_buf.flags = 0;
462
463 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
464 vdec_msg.status_code = VDEC_S_SUCCESS;
465 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
466 vdec_msg.msgdata.output_frame.len = 0;
467 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
468 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
469 (uint64_t)ptr[4];
470 if (omx->async_message_process(input,&vdec_msg) < 0) {
471 DEBUG_PRINT_HIGH("async_message_thread Exitedn");
472 break;
473 }
474 } else {
475 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
476 continue;
477 }
478 }
479 }
480 DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
481 return NULL;
482 }
483
message_thread_dec(void * input)484 void* message_thread_dec(void *input)
485 {
486 omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
487 int res = 0;
488
489 DEBUG_PRINT_HIGH("omx_vdec: message thread start");
490 prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
491 while (!omx->message_thread_stop) {
492 res = omx->signal.wait(2 * 1000000000);
493 if (res == ETIMEDOUT || omx->message_thread_stop) {
494 continue;
495 } else if (res) {
496 DEBUG_PRINT_ERROR("omx_vdec: message_thread_dec wait on condition failed, exiting");
497 break;
498 }
499 omx->process_event_cb(omx);
500 }
501 DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
502 return 0;
503 }
504
post_message(omx_vdec * omx,unsigned char id)505 void post_message(omx_vdec *omx, unsigned char id)
506 {
507 (void)id;
508 omx->signal.signal();
509 }
510
511 // omx_cmd_queue destructor
~omx_cmd_queue()512 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
513 {
514 // Nothing to do
515 }
516
517 // omx cmd queue constructor
omx_cmd_queue()518 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
519 {
520 memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
521 }
522
523 // omx cmd queue insert
insert_entry(unsigned long p1,unsigned long p2,unsigned long id)524 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
525 {
526 bool ret = true;
527 if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
528 m_q[m_write].id = id;
529 m_q[m_write].param1 = p1;
530 m_q[m_write].param2 = p2;
531 m_write++;
532 m_size ++;
533 if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
534 m_write = 0;
535 }
536 } else {
537 ret = false;
538 DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
539 }
540 return ret;
541 }
542
543 // omx cmd queue pop
pop_entry(unsigned long * p1,unsigned long * p2,unsigned long * id)544 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
545 {
546 bool ret = true;
547 if (m_size > 0) {
548 *id = m_q[m_read].id;
549 *p1 = m_q[m_read].param1;
550 *p2 = m_q[m_read].param2;
551 // Move the read pointer ahead
552 ++m_read;
553 --m_size;
554 if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
555 m_read = 0;
556 }
557 } else {
558 ret = false;
559 }
560 return ret;
561 }
562
563 // Retrieve the first mesg type in the queue
get_q_msg_type()564 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
565 {
566 return m_q[m_read].id;
567 }
568
569 #ifdef _ANDROID_
ts_arr_list()570 omx_vdec::ts_arr_list::ts_arr_list()
571 {
572 //initialize timestamps array
573 memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
574 }
~ts_arr_list()575 omx_vdec::ts_arr_list::~ts_arr_list()
576 {
577 //free m_ts_arr_list?
578 }
579
insert_ts(OMX_TICKS ts)580 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
581 {
582 bool ret = true;
583 bool duplicate_ts = false;
584 int idx = 0;
585
586 //insert at the first available empty location
587 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
588 if (!m_ts_arr_list[idx].valid) {
589 //found invalid or empty entry, save timestamp
590 m_ts_arr_list[idx].valid = true;
591 m_ts_arr_list[idx].timestamp = ts;
592 DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
593 ts, idx);
594 break;
595 }
596 }
597
598 if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
599 DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
600 ret = false;
601 }
602 return ret;
603 }
604
pop_min_ts(OMX_TICKS & ts)605 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
606 {
607 bool ret = true;
608 int min_idx = -1;
609 OMX_TICKS min_ts = 0;
610 int idx = 0;
611
612 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
613
614 if (m_ts_arr_list[idx].valid) {
615 //found valid entry, save index
616 if (min_idx < 0) {
617 //first valid entry
618 min_ts = m_ts_arr_list[idx].timestamp;
619 min_idx = idx;
620 } else if (m_ts_arr_list[idx].timestamp < min_ts) {
621 min_ts = m_ts_arr_list[idx].timestamp;
622 min_idx = idx;
623 }
624 }
625
626 }
627
628 if (min_idx < 0) {
629 //no valid entries found
630 DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
631 ts = 0;
632 ret = false;
633 } else {
634 ts = m_ts_arr_list[min_idx].timestamp;
635 m_ts_arr_list[min_idx].valid = false;
636 DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
637 ts, min_idx);
638 }
639
640 return ret;
641
642 }
643
644
reset_ts_list()645 bool omx_vdec::ts_arr_list::reset_ts_list()
646 {
647 bool ret = true;
648 int idx = 0;
649
650 DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
651 for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
652 m_ts_arr_list[idx].valid = false;
653 }
654 return ret;
655 }
656 #endif
657
658 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)659 void *get_omx_component_factory_fn(void)
660 {
661 return (new omx_vdec);
662 }
663
is_platform_tp10capture_supported()664 bool is_platform_tp10capture_supported()
665 {
666 DEBUG_PRINT_HIGH("TP10 on capture port is supported");
667 return true;
668 }
669
get_session_codec_type()670 inline int omx_vdec::get_session_codec_type()
671 {
672 return output_capability;
673 }
674 /* ======================================================================
675 FUNCTION
676 omx_vdec::omx_vdec
677
678 DESCRIPTION
679 Constructor
680
681 PARAMETERS
682 None
683
684 RETURN VALUE
685 None.
686 ========================================================================== */
omx_vdec()687 omx_vdec::omx_vdec(): m_error_propogated(false),
688 m_state(OMX_StateInvalid),
689 m_app_data(NULL),
690 m_inp_mem_ptr(NULL),
691 m_out_mem_ptr(NULL),
692 m_intermediate_out_mem_ptr(NULL),
693 m_client_output_extradata_mem_ptr(NULL),
694 input_flush_progress (false),
695 output_flush_progress (false),
696 input_use_buffer (false),
697 output_use_buffer (false),
698 ouput_egl_buffers(false),
699 m_use_output_pmem(OMX_FALSE),
700 pending_input_buffers(0),
701 pending_output_buffers(0),
702 m_out_bm_count(0),
703 m_inp_bm_count(0),
704 m_out_extradata_bm_count(0),
705 m_inp_bPopulated(OMX_FALSE),
706 m_out_bPopulated(OMX_FALSE),
707 m_flags(0),
708 m_inp_bEnabled(OMX_TRUE),
709 m_out_bEnabled(OMX_TRUE),
710 m_in_alloc_cnt(0),
711 m_platform_list(NULL),
712 m_platform_entry(NULL),
713 m_pmem_info(NULL),
714 h264_parser(NULL),
715 arbitrary_bytes (false),
716 psource_frame (NULL),
717 pdest_frame (NULL),
718 m_inp_heap_ptr (NULL),
719 m_phdr_pmem_ptr(NULL),
720 m_heap_inp_bm_count (0),
721 codec_type_parse ((codec_type)0),
722 first_frame_meta (true),
723 frame_count (0),
724 nal_count (0),
725 nal_length(0),
726 look_ahead_nal (false),
727 first_frame(0),
728 first_buffer(NULL),
729 first_frame_size (0),
730 m_device_file_ptr(NULL),
731 h264_last_au_ts(LLONG_MAX),
732 h264_last_au_flags(0),
733 m_disp_hor_size(0),
734 m_disp_vert_size(0),
735 prev_ts(LLONG_MAX),
736 prev_ts_actual(LLONG_MAX),
737 rst_prev_ts(true),
738 frm_int(0),
739 m_fps_received(0),
740 m_fps_prev(0),
741 m_drc_enable(0),
742 in_reconfig(false),
743 c2d_enable_pending(false),
744 m_display_id(NULL),
745 client_extradata(0),
746 #ifdef _ANDROID_
747 m_enable_android_native_buffers(OMX_FALSE),
748 m_use_android_native_buffers(OMX_FALSE),
749 #endif
750 m_disable_dynamic_buf_mode(0),
751 m_desc_buffer_ptr(NULL),
752 secure_mode(false),
753 allocate_native_handle(false),
754 client_set_fps(false),
755 stereo_output_mode(HAL_NO_3D),
756 m_last_rendered_TS(-1),
757 m_dec_hfr_fps(0),
758 m_dec_secure_prefetch_size_internal(0),
759 m_dec_secure_prefetch_size_output(0),
760 m_arb_mode_override(0),
761 m_queued_codec_config_count(0),
762 secure_scaling_to_non_secure_opb(false),
763 m_force_compressed_for_dpb(true),
764 m_is_display_session(false),
765 m_prefetch_done(0),
766 m_is_split_mode(false),
767 m_buffer_error(false)
768 {
769 m_poll_efd = -1;
770 memset(&drv_ctx, 0, sizeof(drv_ctx));
771 drv_ctx.video_driver_fd = -1;
772 drv_ctx.extradata_info.ion.data_fd = -1;
773 drv_ctx.extradata_info.ion.dev_fd = -1;
774 /* Assumption is that , to begin with , we have all the frames with decoder */
775 DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
776 memset(&m_debug,0,sizeof(m_debug));
777 #ifdef _ANDROID_
778
779 char property_value[PROPERTY_VALUE_MAX] = {0};
780 property_get("vendor.vidc.debug.level", property_value, "1");
781 debug_level = strtoul(property_value, NULL, 16);
782 property_value[0] = '\0';
783
784 DEBUG_PRINT_HIGH("In OMX vdec Constructor");
785
786 // TODO: Support in XML
787 perf_flag = 0;
788 if (perf_flag) {
789 DEBUG_PRINT_HIGH("perf flag is %d", perf_flag);
790 dec_time.start();
791 }
792 proc_frms = latency = 0;
793 prev_n_filled_len = 0;
794
795 Platform::Config::getInt32(Platform::vidc_dec_log_in,
796 (int32_t *)&m_debug.in_buffer_log, 0);
797 Platform::Config::getInt32(Platform::vidc_dec_log_out,
798 (int32_t *)&m_debug.out_buffer_log, 0);
799
800 Platform::Config::getInt32(Platform::vidc_dec_sec_prefetch_size_internal,
801 (int32_t *)&m_dec_secure_prefetch_size_internal, 0);
802 Platform::Config::getInt32(Platform::vidc_dec_sec_prefetch_size_output,
803 (int32_t *)&m_dec_secure_prefetch_size_output, 0);
804
805 DEBUG_PRINT_HIGH("Prefetch size internal = %d, output = %d",
806 m_dec_secure_prefetch_size_internal, m_dec_secure_prefetch_size_output);
807
808 Platform::Config::getInt32(Platform::vidc_dec_arb_mode_override,
809 (int32_t *)&m_arb_mode_override, 0);
810
811 Platform::Config::getInt32(Platform::vidc_perf_control_enable,
812 (int32_t *)&m_perf_control.m_perf_control_enable, 0);
813 if (m_perf_control.m_perf_control_enable) {
814 DEBUG_PRINT_HIGH("perf cotrol enabled");
815 m_perf_control.load_perf_library();
816 }
817
818 property_value[0] = '\0';
819 property_get("vendor.vidc.dec.log.in", property_value, "0");
820 m_debug.in_buffer_log |= atoi(property_value);
821
822 DEBUG_PRINT_HIGH("vendor.vidc.dec.log.in value is %d", m_debug.in_buffer_log);
823
824 property_value[0] = '\0';
825 property_get("vendor.vidc.dec.log.out", property_value, "0");
826 m_debug.out_buffer_log |= atoi(property_value);
827
828 DEBUG_PRINT_HIGH("vendor.vidc.dec.log.out value is %d", m_debug.out_buffer_log);
829
830 property_value[0] = '\0';
831 property_get("vendor.vidc.dec.log.cc.out", property_value, "0");
832 m_debug.out_cc_buffer_log |= atoi(property_value);
833
834 DEBUG_PRINT_HIGH("vendor.vidc.dec.log.cc.out value is %d", m_debug.out_buffer_log);
835
836 property_value[0] = '\0';
837 property_get("vendor.vidc.dec.meta.log.out", property_value, "0");
838 m_debug.out_meta_buffer_log = atoi(property_value);
839
840 property_value[0] = '\0';
841 property_get("vendor.vidc.log.loc", property_value, BUFFER_LOG_LOC);
842 if (*property_value)
843 strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
844
845 struct timeval te;
846 gettimeofday(&te, NULL);
847 m_debug.session_id = te.tv_sec*1000LL + te.tv_usec/1000;
848 m_debug.seq_count = 0;
849
850 #ifdef _UBWC_
851 property_value[0] = '\0';
852 property_get("vendor.gralloc.disable_ubwc", property_value, "0");
853 m_disable_ubwc_mode = atoi(property_value);
854 DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
855 #else
856 m_disable_ubwc_mode = true;
857 #endif
858 #endif
859 memset(&m_cmp,0,sizeof(m_cmp));
860 memset(&m_cb,0,sizeof(m_cb));
861 memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
862 memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
863 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
864 memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
865 memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
866 memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
867 memset(&m_client_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
868 memset(&m_internal_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
869 m_demux_entries = 0;
870 msg_thread_id = 0;
871 async_thread_id = 0;
872 msg_thread_created = false;
873 async_thread_created = false;
874 async_thread_force_stop = false;
875 message_thread_stop = false;
876 #ifdef _ANDROID_ICS_
877 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
878 #endif
879
880 /* invalidate m_frame_pack_arrangement */
881 memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
882 m_frame_pack_arrangement.cancel_flag = 1;
883
884 drv_ctx.timestamp_adjust = false;
885 m_vendor_config.pData = NULL;
886 pthread_mutex_init(&m_lock, NULL);
887 pthread_mutex_init(&c_lock, NULL);
888 pthread_mutex_init(&buf_lock, NULL);
889 pthread_mutex_init(&m_hdr10pluslock, NULL);
890 sem_init(&m_cmd_lock,0,0);
891 sem_init(&m_safe_flush, 0, 0);
892 streaming[CAPTURE_PORT] =
893 streaming[OUTPUT_PORT] = false;
894 #ifdef _ANDROID_
895 // TODO: Support in XML
896 m_debug_extradata = 0;
897 #endif
898 m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
899 client_buffers.set_vdec_client(this);
900 dynamic_buf_mode = false;
901 is_down_scalar_enabled = false;
902 m_downscalar_width = 0;
903 m_downscalar_height = 0;
904 m_force_down_scalar = 0;
905 m_reconfig_height = 0;
906 m_reconfig_width = 0;
907 m_smoothstreaming_mode = false;
908 m_smoothstreaming_width = 0;
909 m_smoothstreaming_height = 0;
910 m_decode_order_mode = false;
911 m_perf_control.perf_lock_acquire();
912 m_client_req_turbo_mode = false;
913 is_q6_platform = false;
914 m_input_pass_buffer_fd = false;
915 memset(&m_extradata_info, 0, sizeof(m_extradata_info));
916 m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
917 m_client_color_space.sAspects.mRange = ColorAspects::RangeUnspecified;
918 m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
919 m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
920 m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
921
922 m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
923 m_internal_color_space.sAspects.mRange = ColorAspects::RangeUnspecified;
924 m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
925 m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
926 m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
927 m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams);
928
929 m_client_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
930 m_internal_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
931
932 m_dither_config = DITHER_DISABLE;
933
934 DEBUG_PRINT_HIGH("Dither config is %d", m_dither_config);
935 m_etb_count = 0;
936 m_etb_timestamp = 0;
937
938 m_color_space = EXCEPT_BT2020;
939
940 init_color_aspects_map();
941
942 profile_level_converter::init();
943 mClientSessionForSufficiency = false;
944 mClientSetProfile = 0;
945 mClientSetLevel = 0;
946 #ifdef USE_GBM
947 drv_ctx.gbm_device_fd = -1;
948 #endif
949 }
950
951 static const int event_type[] = {
952 V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
953 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
954 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
955 V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
956 V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
957 V4L2_EVENT_MSM_VIDC_SYS_ERROR,
958 V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
959 V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
960 };
961
subscribe_to_events(int fd)962 static OMX_ERRORTYPE subscribe_to_events(int fd)
963 {
964 OMX_ERRORTYPE eRet = OMX_ErrorNone;
965 struct v4l2_event_subscription sub;
966 int array_sz = sizeof(event_type)/sizeof(int);
967 int i,rc;
968 if (fd < 0) {
969 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
970 return OMX_ErrorBadParameter;
971 }
972
973 for (i = 0; i < array_sz; ++i) {
974 memset(&sub, 0, sizeof(sub));
975 sub.type = event_type[i];
976 rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
977 if (rc) {
978 DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
979 break;
980 }
981 }
982 if (i < array_sz) {
983 for (--i; i >=0 ; i--) {
984 memset(&sub, 0, sizeof(sub));
985 sub.type = event_type[i];
986 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
987 if (rc)
988 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
989 }
990 eRet = OMX_ErrorNotImplemented;
991 }
992 return eRet;
993 }
994
995
unsubscribe_to_events(int fd)996 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
997 {
998 OMX_ERRORTYPE eRet = OMX_ErrorNone;
999 struct v4l2_event_subscription sub;
1000 int array_sz = sizeof(event_type)/sizeof(int);
1001 int i,rc;
1002 if (fd < 0) {
1003 DEBUG_PRINT_ERROR("Invalid input: %d", fd);
1004 return OMX_ErrorBadParameter;
1005 }
1006
1007 for (i = 0; i < array_sz; ++i) {
1008 memset(&sub, 0, sizeof(sub));
1009 sub.type = event_type[i];
1010 rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
1011 if (rc) {
1012 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
1013 break;
1014 }
1015 }
1016 return eRet;
1017 }
1018
1019 /* ======================================================================
1020 FUNCTION
1021 omx_vdec::~omx_vdec
1022
1023 DESCRIPTION
1024 Destructor
1025
1026 PARAMETERS
1027 None
1028
1029 RETURN VALUE
1030 None.
1031 ========================================================================== */
~omx_vdec()1032 omx_vdec::~omx_vdec()
1033 {
1034 m_pmem_info = NULL;
1035 DEBUG_PRINT_HIGH("In OMX vdec Destructor");
1036 if (msg_thread_created) {
1037 DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
1038 message_thread_stop = true;
1039 post_message(this, OMX_COMPONENT_CLOSE_MSG);
1040 DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
1041 pthread_join(msg_thread_id,NULL);
1042 }
1043 DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
1044 if(eventfd_write(m_poll_efd, 1)) {
1045 DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
1046 async_thread_force_stop = true;
1047 }
1048 if (async_thread_created)
1049 pthread_join(async_thread_id,NULL);
1050
1051 if (m_prefetch_done & 0x1)
1052 prefetch_buffers(PREFETCH_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_output, ION_IOC_DRAIN, ION_FLAG_CP_PIXEL);
1053 if (m_prefetch_done & 0x2)
1054 prefetch_buffers(PREFETCH_NON_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_internal, ION_IOC_DRAIN, ION_FLAG_CP_NON_PIXEL);
1055
1056 unsubscribe_to_events(drv_ctx.video_driver_fd);
1057 close(m_poll_efd);
1058 #ifdef HYPERVISOR
1059 hypv_close(drv_ctx.video_driver_fd);
1060 #else
1061 close(drv_ctx.video_driver_fd);
1062 #endif
1063 clear_hdr10plusinfo();
1064 pthread_mutex_destroy(&m_lock);
1065 pthread_mutex_destroy(&c_lock);
1066 pthread_mutex_destroy(&buf_lock);
1067 pthread_mutex_destroy(&m_hdr10pluslock);
1068 sem_destroy(&m_cmd_lock);
1069 if (perf_flag) {
1070 DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
1071 dec_time.end();
1072 }
1073 DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
1074 m_perf_control.perf_lock_release();
1075 }
1076
set_dpb(bool is_split_mode)1077 OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode)
1078 {
1079 int rc = 0;
1080 struct v4l2_ext_control ctrl[1];
1081 struct v4l2_ext_controls controls;
1082
1083 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
1084 if (is_split_mode) {
1085 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
1086 } else {
1087 ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY;
1088 }
1089
1090 controls.count = 1;
1091 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
1092 controls.controls = ctrl;
1093
1094 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
1095 if (rc) {
1096 DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc);
1097 return OMX_ErrorUnsupportedSetting;
1098 }
1099 m_is_split_mode = is_split_mode;
1100 return OMX_ErrorNone;
1101
1102 }
1103
decide_dpb_buffer_mode()1104 OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode()
1105 {
1106 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1107 struct v4l2_format fmt;
1108 int rc = 0;
1109
1110 // Default is Combined Mode
1111 bool enable_split = false;
1112 bool is_client_dest_format_non_ubwc = (
1113 capture_capability != V4L2_PIX_FMT_NV12_UBWC &&
1114 capture_capability != V4L2_PIX_FMT_NV12_TP10_UBWC);
1115 bool dither_enable = false;
1116 bool capability_changed = false;
1117
1118 switch (m_dither_config) {
1119 case DITHER_DISABLE:
1120 dither_enable = false;
1121 break;
1122 case DITHER_COLORSPACE_EXCEPTBT2020:
1123 dither_enable = (m_color_space == EXCEPT_BT2020);
1124 break;
1125 case DITHER_ALL_COLORSPACE:
1126 dither_enable = true;
1127 break;
1128 default:
1129 DEBUG_PRINT_ERROR("Unsupported dither configuration:%d", m_dither_config);
1130 }
1131
1132 // Reset v4l2_foramt struct object
1133 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1134
1135 if (is_client_dest_format_non_ubwc){
1136 // Assuming all the else blocks are for 8 bit depth
1137 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1138 enable_split = true;
1139 if(is_flexible_format){ // if flexible formats are expected, P010 is set for 10bit cases here
1140 drv_ctx.output_format = VDEC_YUV_FORMAT_P010_VENUS;
1141 capture_capability = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
1142 capability_changed = true;
1143 }
1144 } else if (m_progressive == MSM_VIDC_PIC_STRUCT_PROGRESSIVE &&
1145 eCompressionFormat != OMX_VIDEO_CodingMPEG2) {
1146 enable_split = true;
1147 } else {
1148 // Hardware does not support NV12+interlace clips.
1149 // Request NV12_UBWC and convert it to NV12+interlace using C2D
1150 // in combined mode
1151 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
1152 capture_capability = V4L2_PIX_FMT_NV12_UBWC;
1153 capability_changed = true;
1154 }
1155 } else {
1156 if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1157 enable_split = dither_enable;
1158
1159 if (dither_enable) {
1160 capture_capability = m_disable_ubwc_mode ?
1161 V4L2_PIX_FMT_NV12 : V4L2_PIX_FMT_NV12_UBWC;
1162 capability_changed = true;
1163 } else {
1164 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_TP10_UBWC;
1165 capture_capability = V4L2_PIX_FMT_NV12_TP10_UBWC;
1166 capability_changed = true;
1167 }
1168 }
1169 // 8 bit depth uses the default.
1170 // Combined mode
1171 // V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE
1172 }
1173
1174 if (capability_changed == true) {
1175 // Get format for CAPTURE port
1176 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1177 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1178 if (rc) {
1179 DEBUG_PRINT_ERROR("%s: Failed get format on capture mplane", __func__);
1180 return OMX_ErrorUnsupportedSetting;
1181 }
1182
1183 // Set Capability for CAPTURE port if there is a change
1184 fmt.fmt.pix_mp.pixelformat = capture_capability;
1185 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1186 if (rc) {
1187 DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1188 return OMX_ErrorUnsupportedSetting;
1189 }
1190 }
1191 // Check the component for its valid current state
1192 if (!BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_IDLE_PENDING) &&
1193 !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
1194 DEBUG_PRINT_LOW("Invalid state to decide on dpb-opb split");
1195 return OMX_ErrorNone;
1196 }
1197 eRet = set_dpb(enable_split);
1198 if (eRet) {
1199 DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet);
1200 }
1201
1202 return eRet;
1203 }
1204
check_supported_flexible_formats(OMX_COLOR_FORMATTYPE required_format)1205 bool omx_vdec::check_supported_flexible_formats(OMX_COLOR_FORMATTYPE required_format)
1206 {
1207 if(required_format == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
1208 required_format == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus) {
1209 //for now, the flexible formats should be NV12 by default for 8bit cases
1210 //it will change to P010 after 10bit port-reconfig accordingly
1211 return TRUE;
1212 }
1213 else {
1214 return FALSE;
1215 }
1216 }
1217
enable_downscalar()1218 int omx_vdec::enable_downscalar()
1219 {
1220 int rc = 0;
1221 struct v4l2_control control;
1222 struct v4l2_format fmt;
1223
1224 if (is_down_scalar_enabled) {
1225 DEBUG_PRINT_LOW("%s: already enabled", __func__);
1226 return 0;
1227 }
1228
1229 DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
1230 rc = decide_dpb_buffer_mode();
1231 if (rc) {
1232 DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
1233 return rc;
1234 }
1235 is_down_scalar_enabled = true;
1236
1237 return 0;
1238 }
1239
disable_downscalar()1240 int omx_vdec::disable_downscalar()
1241 {
1242 int rc = 0;
1243 struct v4l2_control control;
1244
1245 if (!is_down_scalar_enabled) {
1246 DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
1247 return 0;
1248 }
1249 rc = decide_dpb_buffer_mode();
1250 if (rc < 0) {
1251 DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
1252 return rc;
1253 }
1254 is_down_scalar_enabled = false;
1255
1256 return rc;
1257 }
1258
decide_downscalar()1259 int omx_vdec::decide_downscalar()
1260 {
1261 int rc = 0;
1262 struct v4l2_format fmt;
1263 enum color_fmts color_format;
1264 OMX_U32 width, height;
1265 OMX_BOOL isPortraitVideo = OMX_FALSE;
1266
1267 if (capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC) {
1268 rc = disable_downscalar();
1269 if (rc) {
1270 DEBUG_PRINT_ERROR("Disable downscalar failed!");
1271 return rc;
1272 }
1273 return 0;
1274 }
1275
1276 #ifdef _QUERY_DISP_RES_
1277 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1278 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1279 fmt.fmt.pix_mp.pixelformat = capture_capability;
1280 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1281 if (rc < 0) {
1282 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1283 return rc;
1284 }
1285 isPortraitVideo = fmt.fmt.pix_mp.width < fmt.fmt.pix_mp.height ? OMX_TRUE : OMX_FALSE;
1286 if (!m_downscalar_width || !m_downscalar_height) {
1287 qdutils::DisplayAttributes dpa = {}, dsa = {}, dva = {};
1288 int prim_config, ext_config, virt_config;
1289
1290 prim_config = qdutils::getActiveConfig(qdutils::DISPLAY_PRIMARY);
1291 dpa = qdutils::getDisplayAttributes(prim_config, qdutils::DISPLAY_PRIMARY);
1292 DEBUG_PRINT_HIGH("%s: Primary dpa.xres = %d dpa.yres=%d dpa.xdpi = %f dpa.ydpi = %f ",
1293 __func__, dpa.xres, dpa.yres, dpa.xdpi, dpa.ydpi);
1294
1295 ext_config = qdutils::getActiveConfig(qdutils::DISPLAY_EXTERNAL);
1296 dsa = qdutils::getDisplayAttributes(ext_config, qdutils::DISPLAY_EXTERNAL);
1297 DEBUG_PRINT_HIGH("%s: HDMI dsa.xres = %d dsa.yres = %d dsa.xdpi = %f dsa.ydpi = %f ",
1298 __func__, dsa.xres, dsa.yres, dsa.xdpi, dsa.ydpi);
1299
1300 virt_config = qdutils::getActiveConfig(qdutils::DISPLAY_VIRTUAL);
1301 dva = qdutils::getDisplayAttributes(virt_config, qdutils::DISPLAY_VIRTUAL);
1302 DEBUG_PRINT_HIGH("%s: Virtual dva.xres = %d dva.yres = %d dva.xdpi = %f dva.ydpi = %f ",
1303 __func__, dva.xres, dva.yres, dva.xdpi, dva.ydpi);
1304
1305 /* Below logic takes care of following conditions:
1306 * 1. Choose display resolution as maximum resolution of all the connected
1307 * displays (secondary, primary, virtual), so that we do not downscale
1308 * unnecessarily which might be supported on one of the display losing quality.
1309 * 2. Displays connected might be in landscape or portrait mode, so the xres might
1310 * be smaller or greater than the yres. So we first take the max of the two
1311 * in width and min of two in height and then rotate it if below point is true.
1312 * 3. Video might also be in portrait mode, so invert the downscalar width and
1313 * height for such cases.
1314 */
1315 if (dsa.xres * dsa.yres > dpa.xres * dpa.yres) {
1316 m_downscalar_width = MAX(dsa.xres, dsa.yres);
1317 m_downscalar_height = MIN(dsa.xres, dsa.yres);
1318 } else if (dva.xres * dva.yres > dpa.xres * dpa.yres) {
1319 m_downscalar_width = MAX(dva.xres, dva.yres);
1320 m_downscalar_height = MIN(dva.xres, dva.yres);
1321
1322 } else {
1323 m_downscalar_width = MAX(dpa.xres, dpa.yres);
1324 m_downscalar_height = MIN(dpa.xres, dpa.yres);
1325 }
1326 if (isPortraitVideo) {
1327 // Swap width and height
1328 m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
1329 m_downscalar_height = m_downscalar_width ^ m_downscalar_height;
1330 m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
1331 }
1332 }
1333 m_downscalar_width = ALIGN(m_downscalar_width, 128);
1334 m_downscalar_height = ALIGN(m_downscalar_height, 32);
1335 #endif
1336
1337 if (!m_downscalar_width || !m_downscalar_height) {
1338 DEBUG_PRINT_LOW("%s: Invalid downscalar configuration", __func__);
1339 return 0;
1340 }
1341
1342 if (m_force_down_scalar) {
1343 DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
1344 return 0;
1345 }
1346
1347 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1348 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1349 fmt.fmt.pix_mp.pixelformat = capture_capability;
1350 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1351 if (rc < 0) {
1352 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1353 return rc;
1354 }
1355
1356 height = fmt.fmt.pix_mp.height;
1357 width = fmt.fmt.pix_mp.width;
1358
1359 DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d m_is_display_session = %d", __func__,
1360 fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height, m_is_display_session);
1361
1362 if ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) &&
1363 m_is_display_session) {
1364 rc = enable_downscalar();
1365 if (rc < 0) {
1366 DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
1367 return rc;
1368 }
1369
1370 width = m_downscalar_width > fmt.fmt.pix_mp.width ?
1371 fmt.fmt.pix_mp.width : m_downscalar_width;
1372 height = m_downscalar_height > fmt.fmt.pix_mp.height ?
1373 fmt.fmt.pix_mp.height : m_downscalar_height;
1374 switch (capture_capability) {
1375 case V4L2_PIX_FMT_NV12:
1376 color_format = COLOR_FMT_NV12;
1377 break;
1378 case V4L2_PIX_FMT_NV12_UBWC:
1379 color_format = COLOR_FMT_NV12_UBWC;
1380 break;
1381 case V4L2_PIX_FMT_NV12_TP10_UBWC:
1382 color_format = COLOR_FMT_NV12_BPP10_UBWC;
1383 break;
1384 default:
1385 DEBUG_PRINT_ERROR("Color format not recognized\n");
1386 rc = OMX_ErrorUndefined;
1387 return rc;
1388 }
1389 } else {
1390
1391 rc = disable_downscalar();
1392 if (rc < 0) {
1393 DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
1394 return rc;
1395 }
1396 }
1397
1398 memset(&fmt, 0x0, sizeof(struct v4l2_format));
1399 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1400 fmt.fmt.pix_mp.height = height;
1401 fmt.fmt.pix_mp.width = width;
1402 fmt.fmt.pix_mp.pixelformat = capture_capability;
1403 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1404 if (rc) {
1405 DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1406 return rc;
1407 }
1408
1409 rc = get_buffer_req(&drv_ctx.op_buf);
1410 if (rc) {
1411 DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__);
1412 return rc;
1413 }
1414
1415 return rc;
1416 }
1417
1418 /* ======================================================================
1419 FUNCTION
1420 omx_vdec::OMXCntrlProcessMsgCb
1421
1422 DESCRIPTION
1423 IL Client callbacks are generated through this routine. The decoder
1424 provides the thread context for this routine.
1425
1426 PARAMETERS
1427 ctxt -- Context information related to the self.
1428 id -- Event identifier. This could be any of the following:
1429 1. Command completion event
1430 2. Buffer done callback event
1431 3. Frame done callback event
1432
1433 RETURN VALUE
1434 None.
1435
1436 ========================================================================== */
process_event_cb(void * ctxt)1437 void omx_vdec::process_event_cb(void *ctxt)
1438 {
1439 unsigned long p1; // Parameter - 1
1440 unsigned long p2; // Parameter - 2
1441 unsigned long ident;
1442 unsigned qsize=0; // qsize
1443 omx_vdec *pThis = (omx_vdec *) ctxt;
1444
1445 if (!pThis) {
1446 DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
1447 __func__);
1448 return;
1449 }
1450
1451 // Protect the shared queue data structure
1452 do {
1453 /*Read the message id's from the queue*/
1454 pthread_mutex_lock(&pThis->m_lock);
1455 qsize = pThis->m_cmd_q.m_size;
1456 if (qsize) {
1457 pThis->m_cmd_q.pop_entry(&p1, &p2, &ident);
1458 }
1459
1460 if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1461 qsize = pThis->m_ftb_q.m_size;
1462 if (qsize) {
1463 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident);
1464 }
1465 }
1466
1467 if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1468 qsize = pThis->m_etb_q.m_size;
1469 if (qsize) {
1470 pThis->m_etb_q.pop_entry(&p1, &p2, &ident);
1471 }
1472 }
1473 pthread_mutex_unlock(&pThis->m_lock);
1474
1475 /*process message if we have one*/
1476 if (qsize > 0) {
1477 switch (ident) {
1478 case OMX_COMPONENT_GENERATE_EVENT:
1479 if (pThis->m_cb.EventHandler) {
1480 switch (p1) {
1481 case OMX_CommandStateSet:
1482 pThis->m_state = (OMX_STATETYPE) p2;
1483 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
1484 pThis->m_state);
1485 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1486 OMX_EventCmdComplete, p1, p2, NULL);
1487 break;
1488
1489 case OMX_EventError:
1490 if (p2 == OMX_StateInvalid) {
1491 DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
1492 pThis->m_state = (OMX_STATETYPE) p2;
1493 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1494 OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
1495 } else if (p2 == (unsigned long)OMX_ErrorHardware) {
1496 pThis->omx_report_error();
1497 } else {
1498 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1499 OMX_EventError, p2, (OMX_U32)NULL, NULL );
1500 }
1501 break;
1502
1503 case OMX_CommandPortDisable:
1504 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
1505 if (BITMASK_PRESENT(&pThis->m_flags,
1506 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1507 BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1508 break;
1509 }
1510 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
1511 OMX_ERRORTYPE eRet = OMX_ErrorNone;
1512 pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
1513 OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
1514 pThis->in_reconfig = false;
1515 pThis->client_buffers.enable_color_conversion(pThis->c2d_enable_pending);
1516 if (eRet != OMX_ErrorNone) {
1517 DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
1518 pThis->omx_report_error();
1519 break;
1520 }
1521 }
1522 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1523 OMX_EventCmdComplete, p1, p2, NULL );
1524 break;
1525 case OMX_CommandPortEnable:
1526 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
1527 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
1528 OMX_EventCmdComplete, p1, p2, NULL );
1529 break;
1530
1531 default:
1532 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1533 OMX_EventCmdComplete, p1, p2, NULL );
1534 break;
1535
1536 }
1537 } else {
1538 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1539 }
1540 break;
1541 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
1542 if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
1543 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1544 DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
1545 pThis->omx_report_error ();
1546 }
1547 break;
1548 case OMX_COMPONENT_GENERATE_ETB: {
1549 OMX_ERRORTYPE iret;
1550 iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
1551 if (iret == OMX_ErrorInsufficientResources) {
1552 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
1553 pThis->omx_report_hw_overload ();
1554 } else if (iret != OMX_ErrorNone) {
1555 DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
1556 pThis->omx_report_error ();
1557 }
1558 }
1559 break;
1560
1561 case OMX_COMPONENT_GENERATE_FTB:
1562 if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
1563 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1564 DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
1565 pThis->omx_report_error ();
1566 }
1567 break;
1568
1569 case OMX_COMPONENT_GENERATE_COMMAND:
1570 pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1571 (OMX_U32)p2,(OMX_PTR)NULL);
1572 break;
1573
1574 case OMX_COMPONENT_GENERATE_EBD:
1575
1576 if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1577 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1578 pThis->omx_report_error ();
1579 } else {
1580 if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1581 pThis->time_stamp_dts.remove_time_stamp(
1582 ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
1583 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1584 ?true:false);
1585 }
1586
1587 if ( pThis->empty_buffer_done(&pThis->m_cmp,
1588 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1589 DEBUG_PRINT_ERROR("empty_buffer_done failure");
1590 pThis->omx_report_error ();
1591 }
1592 }
1593 break;
1594 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
1595 int64_t *timestamp = (int64_t *)(intptr_t)p1;
1596 if (p1) {
1597 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
1598 (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1599 ?true:false);
1600 free(timestamp);
1601 }
1602 }
1603 break;
1604 case OMX_COMPONENT_GENERATE_FBD:
1605 if (p2 != VDEC_S_SUCCESS) {
1606 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1607 pThis->omx_report_error ();
1608 break;
1609 }
1610 if (pThis->fill_buffer_done(&pThis->m_cmp,
1611 (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1612 DEBUG_PRINT_ERROR("fill_buffer_done failure");
1613 pThis->omx_report_error ();
1614 break;
1615 }
1616 //#if !HDR10_SETMETADATA_ENABLE
1617 if (pThis->output_capability != V4L2_PIX_FMT_VP9 &&
1618 pThis->output_capability != V4L2_PIX_FMT_HEVC)
1619 break;
1620
1621 if (!pThis->m_cb.EventHandler) {
1622 DEBUG_PRINT_ERROR("fill_buffer_done: null event handler");
1623 break;
1624 }
1625 bool is_list_empty;
1626 is_list_empty = false;
1627 pthread_mutex_lock(&pThis->m_hdr10pluslock);
1628 is_list_empty = pThis->m_hdr10pluslist.empty();
1629 pthread_mutex_unlock(&pThis->m_hdr10pluslock);
1630 if (!is_list_empty) {
1631 DEBUG_PRINT_LOW("fill_buffer_done: event config update");
1632 pThis->m_cb.EventHandler(&pThis->m_cmp,
1633 pThis->m_app_data,
1634 OMX_EventConfigUpdate,
1635 OMX_CORE_OUTPUT_PORT_INDEX,
1636 OMX_QTIIndexConfigDescribeHDR10PlusInfo, NULL);
1637 }
1638 //#endif
1639 break;
1640
1641 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1642 DEBUG_PRINT_HIGH("Driver flush i/p Port complete, flags %#llx",
1643 (unsigned long long)pThis->m_flags);
1644 if (!pThis->input_flush_progress) {
1645 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1646 } else {
1647 pThis->execute_input_flush();
1648 if (pThis->m_cb.EventHandler) {
1649 if (p2 != VDEC_S_SUCCESS) {
1650 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1651 pThis->omx_report_error ();
1652 } else {
1653 /*Check if we need generate event for Flush done*/
1654 pThis->notify_flush_done(ctxt);
1655
1656 if (BITMASK_PRESENT(&pThis->m_flags,
1657 OMX_COMPONENT_IDLE_PENDING)) {
1658 if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1659 DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1660 pThis->omx_report_error ();
1661 } else {
1662 pThis->streaming[OUTPUT_PORT] = false;
1663 }
1664 if (!pThis->output_flush_progress) {
1665 DEBUG_PRINT_LOW("Input flush done hence issue stop");
1666 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1667 OMX_COMPONENT_GENERATE_STOP_DONE);
1668 }
1669 }
1670 }
1671 } else {
1672 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1673 }
1674 }
1675 break;
1676
1677 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1678 DEBUG_PRINT_HIGH("Driver flush o/p Port complete, flags %#llx",
1679 (unsigned long long)pThis->m_flags);
1680 if (!pThis->output_flush_progress) {
1681 DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1682 } else {
1683 pThis->execute_output_flush();
1684 if (pThis->m_cb.EventHandler) {
1685 if (p2 != VDEC_S_SUCCESS) {
1686 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1687 pThis->omx_report_error ();
1688 } else {
1689 /*Check if we need generate event for Flush done*/
1690 pThis->notify_flush_done(ctxt);
1691
1692 if (BITMASK_PRESENT(&pThis->m_flags,
1693 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1694 DEBUG_PRINT_LOW("Internal flush complete");
1695 BITMASK_CLEAR (&pThis->m_flags,
1696 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1697 if (BITMASK_PRESENT(&pThis->m_flags,
1698 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1699 pThis->post_event(OMX_CommandPortDisable,
1700 OMX_CORE_OUTPUT_PORT_INDEX,
1701 OMX_COMPONENT_GENERATE_EVENT);
1702 BITMASK_CLEAR (&pThis->m_flags,
1703 OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1704 BITMASK_CLEAR (&pThis->m_flags,
1705 OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1706
1707 }
1708 }
1709
1710 if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1711 if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1712 DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1713 pThis->omx_report_error ();
1714 break;
1715 }
1716 pThis->streaming[CAPTURE_PORT] = false;
1717 if (!pThis->input_flush_progress) {
1718 DEBUG_PRINT_LOW("Output flush done hence issue stop");
1719 pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1720 OMX_COMPONENT_GENERATE_STOP_DONE);
1721 }
1722 }
1723 }
1724 } else {
1725 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1726 }
1727 }
1728 break;
1729
1730 case OMX_COMPONENT_GENERATE_START_DONE:
1731 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE, flags %#llx",
1732 (unsigned long long)pThis->m_flags);
1733 if (pThis->m_cb.EventHandler) {
1734 if (p2 != VDEC_S_SUCCESS) {
1735 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1736 pThis->omx_report_error ();
1737 } else {
1738 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1739 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1740 DEBUG_PRINT_LOW("Move to executing");
1741 // Send the callback now
1742 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1743 pThis->m_state = OMX_StateExecuting;
1744 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1745 OMX_EventCmdComplete,OMX_CommandStateSet,
1746 OMX_StateExecuting, NULL);
1747 } else if (BITMASK_PRESENT(&pThis->m_flags,
1748 OMX_COMPONENT_PAUSE_PENDING)) {
1749 if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1750 VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1751 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1752 pThis->omx_report_error ();
1753 }
1754 }
1755 }
1756 } else {
1757 DEBUG_PRINT_LOW("Event Handler callback is NULL");
1758 }
1759 break;
1760
1761 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1762 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1763 if (pThis->m_cb.EventHandler) {
1764 if (p2 != VDEC_S_SUCCESS) {
1765 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1766 pThis->omx_report_error ();
1767 } else {
1768 pThis->complete_pending_buffer_done_cbs();
1769 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1770 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1771 //Send the callback now
1772 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1773 pThis->m_state = OMX_StatePause;
1774 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1775 OMX_EventCmdComplete,OMX_CommandStateSet,
1776 OMX_StatePause, NULL);
1777 }
1778 }
1779 } else {
1780 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1781 }
1782
1783 break;
1784
1785 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1786 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1787 if (pThis->m_cb.EventHandler) {
1788 if (p2 != VDEC_S_SUCCESS) {
1789 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1790 pThis->omx_report_error ();
1791 } else {
1792 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1793 DEBUG_PRINT_LOW("Moving the decoder to execute state");
1794 // Send the callback now
1795 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1796 pThis->m_state = OMX_StateExecuting;
1797 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1798 OMX_EventCmdComplete,OMX_CommandStateSet,
1799 OMX_StateExecuting,NULL);
1800 }
1801 }
1802 } else {
1803 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1804 }
1805
1806 break;
1807
1808 case OMX_COMPONENT_GENERATE_STOP_DONE:
1809 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1810 if (pThis->m_cb.EventHandler) {
1811 if (p2 != VDEC_S_SUCCESS) {
1812 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1813 pThis->omx_report_error ();
1814 } else {
1815 pThis->complete_pending_buffer_done_cbs();
1816 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1817 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1818 // Send the callback now
1819 BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1820 pThis->m_state = OMX_StateIdle;
1821 DEBUG_PRINT_LOW("Move to Idle State");
1822 pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1823 OMX_EventCmdComplete,OMX_CommandStateSet,
1824 OMX_StateIdle,NULL);
1825 }
1826 }
1827 } else {
1828 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1829 }
1830
1831 break;
1832
1833 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1834 if (p2 == OMX_IndexParamPortDefinition) {
1835 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1836 pThis->in_reconfig = true;
1837 pThis->prev_n_filled_len = 0;
1838 } else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1839 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1840
1841 /* Check if resolution is changed in smooth streaming mode */
1842 if (pThis->m_smoothstreaming_mode &&
1843 (pThis->framesize.nWidth !=
1844 pThis->drv_ctx.video_resolution.frame_width) ||
1845 (pThis->framesize.nHeight !=
1846 pThis->drv_ctx.video_resolution.frame_height)) {
1847
1848 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
1849 pThis->framesize.nWidth,
1850 pThis->framesize.nHeight,
1851 pThis->drv_ctx.video_resolution.frame_width,
1852 pThis->drv_ctx.video_resolution.frame_height);
1853
1854 /* Update new resolution */
1855 pThis->framesize.nWidth =
1856 pThis->drv_ctx.video_resolution.frame_width;
1857 pThis->framesize.nHeight =
1858 pThis->drv_ctx.video_resolution.frame_height;
1859
1860 /* Update C2D with new resolution */
1861 if (!pThis->client_buffers.update_buffer_req()) {
1862 DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
1863 }
1864 }
1865
1866 /* Update new crop information */
1867 pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1868 pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1869 pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1870 pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1871
1872 /* Validate the new crop information */
1873 if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1874 pThis->drv_ctx.video_resolution.frame_width) {
1875
1876 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1877 pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1878 pThis->drv_ctx.video_resolution.frame_width);
1879 pThis->rectangle.nLeft = 0;
1880
1881 if (pThis->rectangle.nWidth >
1882 pThis->drv_ctx.video_resolution.frame_width) {
1883
1884 DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1885 pThis->rectangle.nWidth,
1886 pThis->drv_ctx.video_resolution.frame_width);
1887 pThis->rectangle.nWidth =
1888 pThis->drv_ctx.video_resolution.frame_width;
1889 }
1890 }
1891 if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1892 pThis->drv_ctx.video_resolution.frame_height) {
1893
1894 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1895 pThis->rectangle.nTop, pThis->rectangle.nHeight,
1896 pThis->drv_ctx.video_resolution.frame_height);
1897 pThis->rectangle.nTop = 0;
1898
1899 if (pThis->rectangle.nHeight >
1900 pThis->drv_ctx.video_resolution.frame_height) {
1901
1902 DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1903 pThis->rectangle.nHeight,
1904 pThis->drv_ctx.video_resolution.frame_height);
1905 pThis->rectangle.nHeight =
1906 pThis->drv_ctx.video_resolution.frame_height;
1907 }
1908 }
1909 DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1910 pThis->rectangle.nLeft, pThis->rectangle.nTop,
1911 pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1912 } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
1913 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
1914 } else if (p2 == OMX_QTIIndexConfigDescribeHDRColorInfo) {
1915 DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeHDRcolorinfo");
1916 } else {
1917 DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1918 break;
1919 }
1920 if (pThis->m_debug.outfile) {
1921 fclose(pThis->m_debug.outfile);
1922 pThis->m_debug.outfile = NULL;
1923 }
1924 if (pThis->m_debug.ccoutfile) {
1925 fclose(pThis->m_debug.ccoutfile);
1926 pThis->m_debug.ccoutfile = NULL;
1927 }
1928 if (pThis->m_debug.out_ymeta_file) {
1929 fclose(pThis->m_debug.out_ymeta_file);
1930 pThis->m_debug.out_ymeta_file = NULL;
1931 }
1932 if (pThis->m_debug.out_uvmeta_file) {
1933 fclose(pThis->m_debug.out_uvmeta_file);
1934 pThis->m_debug.out_uvmeta_file = NULL;
1935 }
1936 pThis->m_debug.seq_count++;
1937
1938 if (pThis->m_cb.EventHandler) {
1939 void *frame_data = NULL;
1940 reconfig_client_data port_data;
1941 reconfig_client_crop_data crop_data;
1942 if (p2 == OMX_IndexConfigCommonOutputCrop) {
1943 crop_data.width = pThis->rectangle.nWidth;
1944 crop_data.height = pThis->rectangle.nHeight;
1945 crop_data.left = pThis->rectangle.nLeft;
1946 crop_data.top = pThis->rectangle.nTop;
1947 crop_data.isPortReconfigInsufficient = pThis->isPortReconfigInsufficient;
1948 frame_data = (void*)&crop_data;
1949 } else if (p2 == OMX_IndexParamPortDefinition){
1950 port_data.width = pThis->m_reconfig_width;
1951 port_data.height = pThis->m_reconfig_height;
1952 port_data.dpb_bit_depth = pThis->dpb_bit_depth;
1953 port_data.m_progressive = pThis->m_progressive;
1954 port_data.isPortReconfigInsufficient = pThis->isPortReconfigInsufficient;
1955 frame_data = (void*)&port_data;
1956 }
1957 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1958 OMX_EventPortSettingsChanged, p1, p2, (void*)frame_data);
1959 } else {
1960 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1961 }
1962 break;
1963
1964 case OMX_COMPONENT_GENERATE_EOS_DONE:
1965 DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1966 if (pThis->m_cb.EventHandler) {
1967 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1968 OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1969 } else {
1970 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1971 }
1972 pThis->prev_ts = LLONG_MAX;
1973 pThis->rst_prev_ts = true;
1974 break;
1975
1976 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1977 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1978 pThis->omx_report_error();
1979 break;
1980
1981 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1982 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1983 pThis->omx_report_unsupported_setting();
1984 break;
1985
1986 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1987 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1988 pThis->omx_report_hw_overload();
1989 break;
1990
1991 case OMX_COMPONENT_GENERATE_ION_PREFETCH_PIXEL:
1992 DEBUG_PRINT_HIGH("OMX_COMPONENT_GENERATE_ION_PREFETCH_PIXEL");
1993 pThis->m_prefetch_done |= pThis->prefetch_buffers(p1, p2, ION_IOC_PREFETCH, ION_FLAG_CP_PIXEL);
1994 break;
1995
1996 case OMX_COMPONENT_GENERATE_ION_PREFETCH_NON_PIXEL:
1997 DEBUG_PRINT_HIGH("OMX_COMPONENT_GENERATE_ION_PREFETCH_NON_PIXEL");
1998 pThis->m_prefetch_done |= pThis->prefetch_buffers(p1, p2, ION_IOC_PREFETCH, ION_FLAG_CP_NON_PIXEL) << 1;
1999 break;
2000
2001 default:
2002 break;
2003 }
2004 }
2005 pthread_mutex_lock(&pThis->m_lock);
2006 qsize = pThis->m_cmd_q.m_size;
2007 if (pThis->m_state != OMX_StatePause)
2008 qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
2009 pthread_mutex_unlock(&pThis->m_lock);
2010 } while (qsize>0);
2011
2012 }
2013
update_resolution(int width,int height,int stride,int scan_lines)2014 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
2015 {
2016 int format_changed = 0;
2017 if ((height != (int)drv_ctx.video_resolution.frame_height) ||
2018 (width != (int)drv_ctx.video_resolution.frame_width)) {
2019 DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
2020 width, drv_ctx.video_resolution.frame_width,
2021 height,drv_ctx.video_resolution.frame_height);
2022 format_changed = 1;
2023 }
2024 drv_ctx.video_resolution.frame_height = height;
2025 drv_ctx.video_resolution.frame_width = width;
2026 drv_ctx.video_resolution.scan_lines = scan_lines;
2027 drv_ctx.video_resolution.stride = stride;
2028
2029 if (!is_down_scalar_enabled) {
2030 rectangle.nLeft = m_extradata_info.output_crop_rect.nLeft;
2031 rectangle.nTop = m_extradata_info.output_crop_rect.nTop;
2032 rectangle.nWidth = m_extradata_info.output_crop_rect.nWidth;
2033 rectangle.nHeight = m_extradata_info.output_crop_rect.nHeight;
2034 }
2035 return format_changed;
2036 }
2037
log_input_buffers(const char * buffer_addr,int buffer_len,uint64_t timeStamp,int fd)2038 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len, uint64_t timeStamp, int fd)
2039 {
2040 if (!m_debug.in_buffer_log)
2041 return 0;
2042
2043 #ifdef USE_ION
2044 do_cache_operations(fd);
2045 #else
2046 (void)fd;
2047 #endif
2048 if (m_debug.in_buffer_log && !m_debug.infile) {
2049 if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
2050 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p_%" PRId64 ".mpg", m_debug.log_loc,
2051 drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this, m_debug.session_id);
2052 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
2053 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
2054 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
2055 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2056 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
2057 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
2058 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2059 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
2060 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
2061 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2062 } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2063 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
2064 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2065 } else {
2066 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.bin",
2067 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2068 }
2069 m_debug.infile = fopen (m_debug.infile_name, "ab");
2070 if (!m_debug.infile) {
2071 DEBUG_PRINT_HIGH("Failed to open input file: %s for logging (%d:%s)",
2072 m_debug.infile_name, errno, strerror(errno));
2073 m_debug.infile_name[0] = '\0';
2074 #ifdef USE_ION
2075 do_cache_operations(fd);
2076 #endif
2077 return -1;
2078 }
2079 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
2080 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2081 bool isVp9 = drv_ctx.decoder_format == VDEC_CODECTYPE_VP9;
2082 int width = drv_ctx.video_resolution.frame_width;
2083 int height = drv_ctx.video_resolution.frame_height;
2084 int fps = drv_ctx.frame_rate.fps_numerator;
2085 IvfFileHeader ivfHeader(isVp9, width, height, 1, fps, 0);
2086 fwrite((const char *)&ivfHeader,
2087 sizeof(ivfHeader),1,m_debug.infile);
2088 }
2089 }
2090 if (m_debug.infile && buffer_addr && buffer_len) {
2091 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
2092 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2093 IvfFrameHeader ivfFrameHeader(buffer_len, timeStamp);
2094 fwrite(&ivfFrameHeader, sizeof(ivfFrameHeader), 1, m_debug.infile);
2095 }
2096 fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
2097 }
2098 #ifdef USE_ION
2099 do_cache_operations(fd);
2100 #endif
2101 return 0;
2102 }
2103
log_cc_output_buffers(OMX_BUFFERHEADERTYPE * buffer)2104 int omx_vdec::log_cc_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
2105 if (client_buffers.client_buffers_invalid() ||
2106 !m_debug.out_cc_buffer_log || !buffer || !buffer->nFilledLen)
2107 return 0;
2108
2109 if (m_debug.out_cc_buffer_log && !m_debug.ccoutfile) {
2110 snprintf(m_debug.ccoutfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_cc_%d_%d_%p_%" PRId64 "_%d.yuv",
2111 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this,
2112 m_debug.session_id, m_debug.seq_count);
2113 m_debug.ccoutfile = fopen (m_debug.ccoutfile_name, "ab");
2114 if (!m_debug.ccoutfile) {
2115 DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
2116 m_debug.ccoutfile_name[0] = '\0';
2117 return -1;
2118 }
2119 DEBUG_PRINT_HIGH("Opened CC output file: %s for logging", m_debug.ccoutfile_name);
2120 }
2121
2122 fwrite(buffer->pBuffer, buffer->nFilledLen, 1, m_debug.ccoutfile);
2123 return 0;
2124 }
2125
log_output_buffers(OMX_BUFFERHEADERTYPE * buffer)2126 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
2127 int buf_index = 0;
2128 char *temp = NULL;
2129 char *bufaddr = NULL;
2130
2131 if (!(m_debug.out_buffer_log || m_debug.out_meta_buffer_log) || !buffer || !buffer->nFilledLen)
2132 return 0;
2133
2134 if (m_debug.out_buffer_log && !m_debug.outfile) {
2135 snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p_%" PRId64 "_%d.yuv",
2136 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this,
2137 m_debug.session_id, m_debug.seq_count);
2138 m_debug.outfile = fopen (m_debug.outfile_name, "ab");
2139 if (!m_debug.outfile) {
2140 DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
2141 m_debug.outfile_name[0] = '\0';
2142 return -1;
2143 }
2144 DEBUG_PRINT_HIGH("Opened output file: %s for logging", m_debug.outfile_name);
2145 }
2146
2147 if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file) {
2148 snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
2149 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2150 snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
2151 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2152 m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
2153 m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
2154 if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
2155 DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
2156 m_debug.out_ymetafile_name[0] = '\0';
2157 m_debug.out_uvmetafile_name[0] = '\0';
2158 return -1;
2159 }
2160 }
2161
2162 buf_index = buffer - m_out_mem_ptr;
2163 bufaddr = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
2164 if (dynamic_buf_mode && !secure_mode) {
2165 bufaddr = ion_map(drv_ctx.ptr_outputbuffer[buf_index].pmem_fd,
2166 drv_ctx.ptr_outputbuffer[buf_index].buffer_len);
2167 //mmap returns (void *)-1 on failure and sets error code in errno.
2168 if (bufaddr == MAP_FAILED) {
2169 DEBUG_PRINT_ERROR("mmap failed - errno: %d", errno);
2170 return -1;
2171 }
2172 }
2173 temp = bufaddr;
2174
2175 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC ||
2176 drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
2177 DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
2178 drv_ctx.video_resolution.frame_width,
2179 drv_ctx.video_resolution.frame_height);
2180
2181 if (m_debug.outfile)
2182 fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
2183
2184 if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
2185 unsigned int width = 0, height = 0;
2186 unsigned int y_plane, y_meta_plane;
2187 int y_stride = 0, y_sclines = 0;
2188 int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
2189 int color_fmt = (drv_ctx.output_format== VDEC_YUV_FORMAT_NV12_UBWC)? COLOR_FMT_NV12_UBWC: COLOR_FMT_NV12_BPP10_UBWC;
2190 int i;
2191 int bytes_written = 0;
2192
2193 width = drv_ctx.video_resolution.frame_width;
2194 height = drv_ctx.video_resolution.frame_height;
2195 y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
2196 y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
2197 y_stride = VENUS_Y_STRIDE(color_fmt, width);
2198 y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
2199 uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
2200 uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
2201
2202 y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
2203 y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
2204
2205 for (i = 0; i < y_meta_scanlines; i++) {
2206 bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
2207 temp += y_meta_stride;
2208 }
2209
2210 temp = bufaddr + y_meta_plane + y_plane;
2211 for(i = 0; i < uv_meta_scanlines; i++) {
2212 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
2213 temp += uv_meta_stride;
2214 }
2215 }
2216 } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
2217 int stride = drv_ctx.video_resolution.stride;
2218 int scanlines = drv_ctx.video_resolution.scan_lines;
2219 if (m_smoothstreaming_mode) {
2220 stride = drv_ctx.video_resolution.frame_width;
2221 scanlines = drv_ctx.video_resolution.frame_height;
2222 stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
2223 scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
2224 }
2225 unsigned i;
2226 DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
2227 drv_ctx.video_resolution.frame_width,
2228 drv_ctx.video_resolution.frame_height, stride, scanlines);
2229 int bytes_written = 0;
2230 for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
2231 bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2232 temp += stride;
2233 }
2234 temp = bufaddr + stride * scanlines;
2235 int stride_c = stride;
2236 for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
2237 bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2238 temp += stride_c;
2239 }
2240 } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_P010_VENUS) {
2241 int stride = drv_ctx.video_resolution.stride;
2242 int scanlines = drv_ctx.video_resolution.scan_lines;
2243 if (m_smoothstreaming_mode) {
2244 stride = drv_ctx.video_resolution.frame_width * 2;
2245 scanlines = drv_ctx.video_resolution.frame_height;
2246 stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
2247 scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
2248 }
2249 unsigned i;
2250 DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
2251 drv_ctx.video_resolution.frame_width,
2252 drv_ctx.video_resolution.frame_height, stride, scanlines);
2253 int bytes_written = 0;
2254 for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
2255 bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 2, m_debug.outfile);
2256 temp += stride;
2257 }
2258 temp = bufaddr + stride * scanlines;
2259 int stride_c = stride;
2260 for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
2261 bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 2, m_debug.outfile);
2262 temp += stride_c;
2263 }
2264 }
2265
2266 if (dynamic_buf_mode && !secure_mode) {
2267 ion_unmap(drv_ctx.ptr_outputbuffer[buf_index].pmem_fd, bufaddr,
2268 drv_ctx.ptr_outputbuffer[buf_index].buffer_len);
2269 }
2270 return 0;
2271 }
2272
init_color_aspects_map()2273 void omx_vdec::init_color_aspects_map()
2274 {
2275 mPrimariesMap.insert({
2276 {ColorAspects::PrimariesUnspecified, (ColorPrimaries)(2)},
2277 {ColorAspects::PrimariesBT709_5, ColorPrimaries_BT709_5},
2278 {ColorAspects::PrimariesBT470_6M, ColorPrimaries_BT470_6M},
2279 {ColorAspects::PrimariesBT601_6_625, ColorPrimaries_BT601_6_625},
2280 {ColorAspects::PrimariesBT601_6_525, ColorPrimaries_BT601_6_525},
2281 {ColorAspects::PrimariesGenericFilm, ColorPrimaries_GenericFilm},
2282 {ColorAspects::PrimariesBT2020, ColorPrimaries_BT2020},
2283 });
2284 mTransferMap.insert({
2285 {ColorAspects::TransferUnspecified, (GammaTransfer)(2)},
2286 {ColorAspects::TransferLinear, Transfer_Linear},
2287 {ColorAspects::TransferSRGB, Transfer_sRGB},
2288 {ColorAspects::TransferSMPTE170M, Transfer_SMPTE_170M},
2289 {ColorAspects::TransferGamma22, Transfer_Gamma2_2},
2290 {ColorAspects::TransferGamma28, Transfer_Gamma2_8},
2291 {ColorAspects::TransferST2084, Transfer_SMPTE_ST2084},
2292 {ColorAspects::TransferHLG, Transfer_HLG},
2293 {ColorAspects::TransferSMPTE240M, Transfer_SMPTE_240M},
2294 {ColorAspects::TransferXvYCC, Transfer_XvYCC},
2295 {ColorAspects::TransferBT1361, Transfer_BT1361},
2296 {ColorAspects::TransferST428, Transfer_ST_428},
2297 });
2298 mMatrixCoeffMap.insert({
2299 {ColorAspects::MatrixUnspecified, (MatrixCoEfficients)(2)},
2300 {ColorAspects::MatrixBT709_5, MatrixCoEff_BT709_5},
2301 {ColorAspects::MatrixBT470_6M, MatrixCoeff_FCC_73_682},
2302 {ColorAspects::MatrixBT601_6, MatrixCoEff_BT601_6_625},
2303 {ColorAspects::MatrixSMPTE240M, MatrixCoEff_SMPTE240M},
2304 {ColorAspects::MatrixBT2020, MatrixCoEff_BT2020},
2305 {ColorAspects::MatrixBT2020Constant, MatrixCoEff_BT2020Constant},
2306 });
2307 mColorRangeMap.insert({
2308 {ColorAspects::RangeUnspecified, (ColorRange)(2)},
2309 {ColorAspects::RangeFull, Range_Full},
2310 {ColorAspects::RangeLimited, Range_Limited},
2311 });
2312 }
2313 /* ======================================================================
2314 FUNCTION
2315 omx_vdec::ComponentInit
2316
2317 DESCRIPTION
2318 Initialize the component.
2319
2320 PARAMETERS
2321 ctxt -- Context information related to the self.
2322 id -- Event identifier. This could be any of the following:
2323 1. Command completion event
2324 2. Buffer done callback event
2325 3. Frame done callback event
2326
2327 RETURN VALUE
2328 None.
2329
2330 ========================================================================== */
component_init(OMX_STRING role)2331 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
2332 {
2333
2334 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2335 struct v4l2_fmtdesc fdesc;
2336 struct v4l2_format fmt;
2337 struct v4l2_requestbuffers bufreq;
2338 struct v4l2_control control;
2339 struct v4l2_frmsizeenum frmsize;
2340 struct v4l2_queryctrl query;
2341 unsigned int alignment = 0,buffer_size = 0;
2342 int fds[2];
2343 int r,ret=0;
2344 bool codec_ambiguous = false;
2345 OMX_STRING device_name = (OMX_STRING)"/dev/video32";
2346 char property_value[PROPERTY_VALUE_MAX] = {0};
2347 FILE *soc_file = NULL;
2348 char buffer[10];
2349 struct v4l2_ext_control ctrl[2];
2350 struct v4l2_ext_controls controls;
2351 int conceal_color_8bit = 0, conceal_color_10bit = 0;
2352
2353 #ifdef _ANDROID_
2354 char platform_name[PROPERTY_VALUE_MAX];
2355 property_get("ro.board.platform", platform_name, "0");
2356 if (!strncmp(platform_name, "msm8610", 7)) {
2357 device_name = (OMX_STRING)"/dev/video/q6_dec";
2358 is_q6_platform = true;
2359 maxSmoothStreamingWidth = 1280;
2360 maxSmoothStreamingHeight = 720;
2361 }
2362 #endif
2363
2364 if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
2365 OMX_MAX_STRINGNAME_SIZE)) {
2366 secure_mode = true;
2367 role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
2368 } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
2369 OMX_MAX_STRINGNAME_SIZE)) {
2370 secure_mode = true;
2371 role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
2372 } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
2373 OMX_MAX_STRINGNAME_SIZE)) {
2374 secure_mode = true;
2375 role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
2376 } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
2377 OMX_MAX_STRINGNAME_SIZE)) {
2378 secure_mode = true;
2379 role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
2380 }
2381
2382 #ifdef HYPERVISOR
2383 drv_ctx.video_driver_fd = hypv_open(device_name, O_RDWR);
2384 #else
2385 drv_ctx.video_driver_fd = open(device_name, O_RDWR);
2386 #endif
2387
2388 DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
2389
2390 if (drv_ctx.video_driver_fd < 0) {
2391 DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
2392 return OMX_ErrorInsufficientResources;
2393 }
2394 drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
2395 drv_ctx.frame_rate.fps_denominator = 1;
2396 operating_frame_rate = DEFAULT_FPS;
2397 m_poll_efd = eventfd(0, 0);
2398 if (m_poll_efd < 0) {
2399 DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
2400 return OMX_ErrorInsufficientResources;
2401 }
2402 ret = subscribe_to_events(drv_ctx.video_driver_fd);
2403 if (!ret) {
2404 async_thread_created = true;
2405 ret = pthread_create(&async_thread_id,0,async_message_thread,this);
2406 }
2407 if (ret) {
2408 DEBUG_PRINT_ERROR("Failed to create async_message_thread");
2409 async_thread_created = false;
2410 return OMX_ErrorInsufficientResources;
2411 }
2412
2413 #ifdef OUTPUT_EXTRADATA_LOG
2414 outputExtradataFile = fopen (output_extradata_filename, "ab");
2415 #endif
2416
2417 // Copy the role information which provides the decoder kind
2418 strlcpy(drv_ctx.kind,role,128);
2419
2420
2421 if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
2422 OMX_MAX_STRINGNAME_SIZE)) {
2423 strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
2424 OMX_MAX_STRINGNAME_SIZE);
2425 drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
2426 output_capability = V4L2_PIX_FMT_MPEG2;
2427 eCompressionFormat = OMX_VIDEO_CodingMPEG2;
2428 /*Initialize Start Code for MPEG2*/
2429 codec_type_parse = CODEC_TYPE_MPEG2;
2430 m_frame_parser.init_start_codes(codec_type_parse);
2431 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
2432 OMX_MAX_STRINGNAME_SIZE)) {
2433 strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2434 drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
2435 output_capability=V4L2_PIX_FMT_H264;
2436 eCompressionFormat = OMX_VIDEO_CodingAVC;
2437 codec_type_parse = CODEC_TYPE_H264;
2438 m_frame_parser.init_start_codes(codec_type_parse);
2439 m_frame_parser.init_nal_length(nal_length);
2440 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
2441 OMX_MAX_STRINGNAME_SIZE)) {
2442 strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
2443 drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
2444 output_capability = V4L2_PIX_FMT_H264_MVC;
2445 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
2446 codec_type_parse = CODEC_TYPE_H264;
2447 m_frame_parser.init_start_codes(codec_type_parse);
2448 m_frame_parser.init_nal_length(nal_length);
2449 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
2450 OMX_MAX_STRINGNAME_SIZE)) {
2451 strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2452 drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
2453 output_capability = V4L2_PIX_FMT_HEVC;
2454 eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
2455 codec_type_parse = CODEC_TYPE_HEVC;
2456 m_frame_parser.init_start_codes(codec_type_parse);
2457 m_frame_parser.init_nal_length(nal_length);
2458 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", \
2459 OMX_MAX_STRINGNAME_SIZE)) {
2460 strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2461 drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
2462 output_capability = V4L2_PIX_FMT_VP8;
2463 eCompressionFormat = OMX_VIDEO_CodingVP8;
2464 codec_type_parse = CODEC_TYPE_VP8;
2465 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", \
2466 OMX_MAX_STRINGNAME_SIZE)) {
2467 strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
2468 drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
2469 output_capability = V4L2_PIX_FMT_VP9;
2470 eCompressionFormat = OMX_VIDEO_CodingVP9;
2471 codec_type_parse = CODEC_TYPE_VP9;
2472 } else {
2473 DEBUG_PRINT_ERROR("ERROR:Unknown Component");
2474 eRet = OMX_ErrorInvalidComponentName;
2475 }
2476
2477 m_progressive = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
2478
2479 if (eRet == OMX_ErrorNone) {
2480 OMX_COLOR_FORMATTYPE dest_color_format;
2481 if (m_disable_ubwc_mode) {
2482 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
2483 } else {
2484 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
2485 }
2486 if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
2487 dest_color_format = (OMX_COLOR_FORMATTYPE)
2488 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
2489 else
2490 dest_color_format = (OMX_COLOR_FORMATTYPE)
2491 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2492 if (!client_buffers.set_color_format(dest_color_format)) {
2493 DEBUG_PRINT_ERROR("Setting color format failed");
2494 eRet = OMX_ErrorInsufficientResources;
2495 }
2496
2497 dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
2498 is_flexible_format = FALSE;
2499 is_mbaff = FALSE;
2500
2501 if (m_disable_ubwc_mode) {
2502 capture_capability = V4L2_PIX_FMT_NV12;
2503 } else {
2504 capture_capability = V4L2_PIX_FMT_NV12_UBWC;
2505 }
2506
2507 struct v4l2_capability cap;
2508 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
2509 if (ret) {
2510 DEBUG_PRINT_ERROR("Failed to query capabilities");
2511 /*TODO: How to handle this case */
2512 } else {
2513 DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
2514 " version = %d, capabilities = %x", cap.driver, cap.card,
2515 cap.bus_info, cap.version, cap.capabilities);
2516 }
2517 ret=0;
2518 fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2519 fdesc.index=0;
2520 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2521 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2522 fdesc.pixelformat, fdesc.flags);
2523 fdesc.index++;
2524 }
2525 fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2526 fdesc.index=0;
2527 while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2528
2529 DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2530 fdesc.pixelformat, fdesc.flags);
2531 fdesc.index++;
2532 }
2533 m_extradata_info.output_crop_rect.nLeft = 0;
2534 m_extradata_info.output_crop_rect.nTop = 0;
2535 m_extradata_info.output_crop_rect.nWidth = 320;
2536 m_extradata_info.output_crop_rect.nHeight = 240;
2537 update_resolution(320, 240, 320, 240);
2538
2539 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2540 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2541 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2542 fmt.fmt.pix_mp.pixelformat = output_capability;
2543 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2544 if (ret) {
2545 /*TODO: How to handle this case */
2546 DEBUG_PRINT_ERROR("Failed to set format on output port");
2547 return OMX_ErrorInsufficientResources;
2548 }
2549 DEBUG_PRINT_HIGH("Set Format was successful");
2550
2551 /*
2552 * refer macro DEFAULT_CONCEAL_COLOR to set conceal color values
2553 */
2554 Platform::Config::getInt32(Platform::vidc_dec_conceal_color_8bit, &conceal_color_8bit, DEFAULT_VIDEO_CONCEAL_COLOR_BLACK);
2555 Platform::Config::getInt32(Platform::vidc_dec_conceal_color_10bit, &conceal_color_10bit, DEFAULT_VIDEO_CONCEAL_COLOR_BLACK);
2556 memset(&controls, 0, sizeof(controls));
2557 memset(ctrl, 0, sizeof(ctrl));
2558 ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_8BIT;
2559 ctrl[0].value = conceal_color_8bit;
2560 ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_10BIT;
2561 ctrl[1].value = conceal_color_10bit;
2562
2563 controls.count = 2;
2564 controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
2565 controls.controls = ctrl;
2566 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
2567 if (ret) {
2568 DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
2569 }
2570
2571 //Get the hardware capabilities
2572 memset((void *)&frmsize,0,sizeof(frmsize));
2573 frmsize.index = 0;
2574 frmsize.pixel_format = output_capability;
2575 ret = ioctl(drv_ctx.video_driver_fd,
2576 VIDIOC_ENUM_FRAMESIZES, &frmsize);
2577 if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
2578 DEBUG_PRINT_ERROR("Failed to get framesizes");
2579 return OMX_ErrorHardware;
2580 }
2581
2582 if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
2583 m_decoder_capability.min_width = frmsize.stepwise.min_width;
2584 m_decoder_capability.max_width = frmsize.stepwise.max_width;
2585 m_decoder_capability.min_height = frmsize.stepwise.min_height;
2586 m_decoder_capability.max_height = frmsize.stepwise.max_height;
2587 }
2588
2589 /* Based on UBWC enable, decide split mode to driver before calling S_FMT */
2590 eRet = set_dpb(m_disable_ubwc_mode);
2591
2592 memset(&fmt, 0x0, sizeof(struct v4l2_format));
2593 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2594 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2595 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2596 fmt.fmt.pix_mp.pixelformat = capture_capability;
2597 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2598 if (ret) {
2599 /*TODO: How to handle this case */
2600 DEBUG_PRINT_ERROR("Failed to set format on capture port");
2601 }
2602 memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
2603 framesize.nWidth = drv_ctx.video_resolution.frame_width;
2604 framesize.nHeight = drv_ctx.video_resolution.frame_height;
2605
2606 memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
2607 rectangle.nWidth = drv_ctx.video_resolution.frame_width;
2608 rectangle.nHeight = drv_ctx.video_resolution.frame_height;
2609
2610 DEBUG_PRINT_HIGH("Set Format was successful");
2611 if (secure_mode) {
2612 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
2613 control.value = 1;
2614 DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
2615 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
2616 if (ret) {
2617 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
2618 return OMX_ErrorInsufficientResources;
2619 }
2620 }
2621
2622 /*Get the Buffer requirements for input and output ports*/
2623 drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
2624 drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
2625
2626 if (secure_mode) {
2627 drv_ctx.op_buf.alignment = SECURE_ALIGN;
2628 drv_ctx.ip_buf.alignment = SECURE_ALIGN;
2629 } else {
2630 drv_ctx.op_buf.alignment = SZ_4K;
2631 drv_ctx.ip_buf.alignment = SZ_4K;
2632 }
2633
2634 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
2635 drv_ctx.extradata = 0;
2636 drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
2637 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
2638 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
2639 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2640 drv_ctx.idr_only_decoding = 0;
2641
2642 #ifdef _ANDROID_
2643 if (m_dec_hfr_fps) {
2644 memset(&query, 0, sizeof(struct v4l2_queryctrl));
2645
2646 query.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE;
2647 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCTRL, &query);
2648 if (!ret)
2649 m_dec_hfr_fps = MIN(query.maximum, m_dec_hfr_fps);
2650
2651 DEBUG_PRINT_HIGH("Updated HFR fps value = %d", m_dec_hfr_fps);
2652 }
2653
2654 #endif
2655 m_state = OMX_StateLoaded;
2656
2657 unsigned long long extradata_mask = DEFAULT_EXTRADATA;
2658 if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc) {
2659 extradata_mask |= OMX_HDR_COLOR_INFO_EXTRADATA | OMX_EXTNUSER_EXTRADATA;
2660 }
2661 enable_extradata(extradata_mask, true, true);
2662
2663 eRet = get_buffer_req(&drv_ctx.ip_buf);
2664 DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2665 get_buffer_req(&drv_ctx.op_buf);
2666 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2667 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC ||
2668 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2669 h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
2670 h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
2671 h264_scratch.nFilledLen = 0;
2672 h264_scratch.nOffset = 0;
2673
2674 if (h264_scratch.pBuffer == NULL) {
2675 DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
2676 return OMX_ErrorInsufficientResources;
2677 }
2678 }
2679 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2680 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2681 if (m_frame_parser.mutils == NULL) {
2682 m_frame_parser.mutils = new H264_Utils();
2683 if (m_frame_parser.mutils == NULL) {
2684 DEBUG_PRINT_ERROR("parser utils Allocation failed ");
2685 eRet = OMX_ErrorInsufficientResources;
2686 } else {
2687 m_frame_parser.mutils->initialize_frame_checking_environment();
2688 m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
2689 }
2690 }
2691
2692 h264_parser = new h264_stream_parser();
2693 if (!h264_parser) {
2694 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
2695 eRet = OMX_ErrorInsufficientResources;
2696 }
2697 }
2698 msg_thread_created = true;
2699 r = pthread_create(&msg_thread_id,0,message_thread_dec,this);
2700
2701 if (r < 0) {
2702 DEBUG_PRINT_ERROR("component_init(): message_thread_dec creation failed");
2703 msg_thread_created = false;
2704 eRet = OMX_ErrorInsufficientResources;
2705 } else if (secure_mode) {
2706 this->post_event(PREFETCH_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_output, OMX_COMPONENT_GENERATE_ION_PREFETCH_PIXEL);
2707 this->post_event(PREFETCH_NON_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_internal, OMX_COMPONENT_GENERATE_ION_PREFETCH_NON_PIXEL);
2708 }
2709 }
2710
2711 {
2712 VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore);
2713 init_vendor_extensions(*extStore);
2714 mVendorExtensionStore.dumpExtensions((const char *)role);
2715 }
2716
2717 if (eRet != OMX_ErrorNone) {
2718 DEBUG_PRINT_ERROR("Component Init Failed");
2719 } else {
2720 DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2721 drv_ctx.video_driver_fd);
2722 }
2723 //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
2724
2725 OMX_INIT_STRUCT(&m_sParamLowLatency, QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE);
2726 m_sParamLowLatency.nNumFrames = 0;
2727 m_sParamLowLatency.bEnableLowLatencyMode = OMX_FALSE;
2728
2729 return eRet;
2730 }
2731
2732 /* ======================================================================
2733 FUNCTION
2734 omx_vdec::GetComponentVersion
2735
2736 DESCRIPTION
2737 Returns the component version.
2738
2739 PARAMETERS
2740 TBD.
2741
2742 RETURN VALUE
2743 OMX_ErrorNone.
2744
2745 ========================================================================== */
get_component_version(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STRING componentName,OMX_OUT OMX_VERSIONTYPE * componentVersion,OMX_OUT OMX_VERSIONTYPE * specVersion,OMX_OUT OMX_UUIDTYPE * componentUUID)2746 OMX_ERRORTYPE omx_vdec::get_component_version
2747 (
2748 OMX_IN OMX_HANDLETYPE hComp,
2749 OMX_OUT OMX_STRING componentName,
2750 OMX_OUT OMX_VERSIONTYPE* componentVersion,
2751 OMX_OUT OMX_VERSIONTYPE* specVersion,
2752 OMX_OUT OMX_UUIDTYPE* componentUUID
2753 )
2754 {
2755 (void) hComp;
2756 (void) componentName;
2757 (void) componentVersion;
2758 (void) componentUUID;
2759 if (m_state == OMX_StateInvalid) {
2760 DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2761 return OMX_ErrorInvalidState;
2762 }
2763 /* TBD -- Return the proper version */
2764 if (specVersion) {
2765 specVersion->nVersion = OMX_SPEC_VERSION;
2766 }
2767 return OMX_ErrorNone;
2768 }
2769 /* ======================================================================
2770 FUNCTION
2771 omx_vdec::SendCommand
2772
2773 DESCRIPTION
2774 Returns zero if all the buffers released..
2775
2776 PARAMETERS
2777 None.
2778
2779 RETURN VALUE
2780 true/false
2781
2782 ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2783 OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2784 OMX_IN OMX_COMMANDTYPE cmd,
2785 OMX_IN OMX_U32 param1,
2786 OMX_IN OMX_PTR cmdData
2787 )
2788 {
2789 (void) hComp;
2790 (void) cmdData;
2791 DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2792 if (m_state == OMX_StateInvalid) {
2793 DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2794 return OMX_ErrorInvalidState;
2795 }
2796 if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2797 && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2798 DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2799 "to invalid port: %u", (unsigned int)param1);
2800 return OMX_ErrorBadPortIndex;
2801 }
2802
2803 post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2804 sem_wait(&m_cmd_lock);
2805 DEBUG_PRINT_LOW("send_command: Command Processed");
2806 return OMX_ErrorNone;
2807 }
2808
2809 /* ======================================================================
2810 FUNCTION
2811 omx_vdec::SendCommand
2812
2813 DESCRIPTION
2814 Returns zero if all the buffers released..
2815
2816 PARAMETERS
2817 None.
2818
2819 RETURN VALUE
2820 true/false
2821
2822 ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2823 OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2824 OMX_IN OMX_COMMANDTYPE cmd,
2825 OMX_IN OMX_U32 param1,
2826 OMX_IN OMX_PTR cmdData
2827 )
2828 {
2829 (void) hComp;
2830 (void) cmdData;
2831 OMX_ERRORTYPE eRet = OMX_ErrorNone;
2832 OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2833 int bFlag = 1,sem_posted = 0,ret=0;
2834
2835 DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2836 DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2837 m_state, eState);
2838
2839 if (cmd == OMX_CommandStateSet) {
2840 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2841 DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2842 /***************************/
2843 /* Current State is Loaded */
2844 /***************************/
2845 if (m_state == OMX_StateLoaded) {
2846 if (eState == OMX_StateIdle) {
2847 //if all buffers are allocated or all ports disabled
2848 if (allocate_done() ||
2849 (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2850 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2851 } else {
2852 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2853 BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2854 // Skip the event notification
2855 bFlag = 0;
2856 }
2857 }
2858 /* Requesting transition from Loaded to Loaded */
2859 else if (eState == OMX_StateLoaded) {
2860 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2861 post_event(OMX_EventError,OMX_ErrorSameState,\
2862 OMX_COMPONENT_GENERATE_EVENT);
2863 eRet = OMX_ErrorSameState;
2864 }
2865 /* Requesting transition from Loaded to WaitForResources */
2866 else if (eState == OMX_StateWaitForResources) {
2867 /* Since error is None , we will post an event
2868 at the end of this function definition */
2869 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2870 }
2871 /* Requesting transition from Loaded to Executing */
2872 else if (eState == OMX_StateExecuting) {
2873 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2874 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2875 OMX_COMPONENT_GENERATE_EVENT);
2876 eRet = OMX_ErrorIncorrectStateTransition;
2877 }
2878 /* Requesting transition from Loaded to Pause */
2879 else if (eState == OMX_StatePause) {
2880 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2881 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2882 OMX_COMPONENT_GENERATE_EVENT);
2883 eRet = OMX_ErrorIncorrectStateTransition;
2884 }
2885 /* Requesting transition from Loaded to Invalid */
2886 else if (eState == OMX_StateInvalid) {
2887 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2888 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2889 eRet = OMX_ErrorInvalidState;
2890 } else {
2891 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2892 eState);
2893 eRet = OMX_ErrorBadParameter;
2894 }
2895 }
2896
2897 /***************************/
2898 /* Current State is IDLE */
2899 /***************************/
2900 else if (m_state == OMX_StateIdle) {
2901 if (eState == OMX_StateLoaded) {
2902 if (release_done()) {
2903 /*
2904 * Since error is None , we will post an event at the end
2905 * of this function definition
2906 * Reset buffer requirements here to ensure setting buffer requirement
2907 * when component move to executing state from loaded state via Idle.
2908 */
2909 drv_ctx.op_buf.buffer_size = 0;
2910 drv_ctx.op_buf.actualcount = 0;
2911 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2912 } else {
2913 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2914 BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2915 // Skip the event notification
2916 bFlag = 0;
2917 }
2918 }
2919 /* Requesting transition from Idle to Executing */
2920 else if (eState == OMX_StateExecuting) {
2921 bFlag = 1;
2922 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2923 m_state=OMX_StateExecuting;
2924 }
2925 /* Requesting transition from Idle to Idle */
2926 else if (eState == OMX_StateIdle) {
2927 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2928 post_event(OMX_EventError,OMX_ErrorSameState,\
2929 OMX_COMPONENT_GENERATE_EVENT);
2930 eRet = OMX_ErrorSameState;
2931 }
2932 /* Requesting transition from Idle to WaitForResources */
2933 else if (eState == OMX_StateWaitForResources) {
2934 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2935 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2936 OMX_COMPONENT_GENERATE_EVENT);
2937 eRet = OMX_ErrorIncorrectStateTransition;
2938 }
2939 /* Requesting transition from Idle to Pause */
2940 else if (eState == OMX_StatePause) {
2941 /*To pause the Video core we need to start the driver*/
2942 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
2943 NULL) < */0) {
2944 DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
2945 omx_report_error ();
2946 eRet = OMX_ErrorHardware;
2947 } else {
2948 BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
2949 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
2950 bFlag = 0;
2951 }
2952 }
2953 /* Requesting transition from Idle to Invalid */
2954 else if (eState == OMX_StateInvalid) {
2955 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
2956 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2957 eRet = OMX_ErrorInvalidState;
2958 } else {
2959 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
2960 eRet = OMX_ErrorBadParameter;
2961 }
2962 }
2963
2964 /******************************/
2965 /* Current State is Executing */
2966 /******************************/
2967 else if (m_state == OMX_StateExecuting) {
2968 DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
2969 /* Requesting transition from Executing to Idle */
2970 if (eState == OMX_StateIdle) {
2971 /* Since error is None , we will post an event
2972 at the end of this function definition
2973 */
2974 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
2975 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2976 if (!sem_posted) {
2977 sem_posted = 1;
2978 sem_post (&m_cmd_lock);
2979 execute_omx_flush(OMX_ALL);
2980 }
2981 bFlag = 0;
2982 }
2983 /* Requesting transition from Executing to Paused */
2984 else if (eState == OMX_StatePause) {
2985 DEBUG_PRINT_LOW("PAUSE Command Issued");
2986 m_state = OMX_StatePause;
2987 bFlag = 1;
2988 }
2989 /* Requesting transition from Executing to Loaded */
2990 else if (eState == OMX_StateLoaded) {
2991 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
2992 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2993 OMX_COMPONENT_GENERATE_EVENT);
2994 eRet = OMX_ErrorIncorrectStateTransition;
2995 }
2996 /* Requesting transition from Executing to WaitForResources */
2997 else if (eState == OMX_StateWaitForResources) {
2998 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
2999 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3000 OMX_COMPONENT_GENERATE_EVENT);
3001 eRet = OMX_ErrorIncorrectStateTransition;
3002 }
3003 /* Requesting transition from Executing to Executing */
3004 else if (eState == OMX_StateExecuting) {
3005 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
3006 post_event(OMX_EventError,OMX_ErrorSameState,\
3007 OMX_COMPONENT_GENERATE_EVENT);
3008 eRet = OMX_ErrorSameState;
3009 }
3010 /* Requesting transition from Executing to Invalid */
3011 else if (eState == OMX_StateInvalid) {
3012 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
3013 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3014 eRet = OMX_ErrorInvalidState;
3015 } else {
3016 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
3017 eRet = OMX_ErrorBadParameter;
3018 }
3019 }
3020 /***************************/
3021 /* Current State is Pause */
3022 /***************************/
3023 else if (m_state == OMX_StatePause) {
3024 /* Requesting transition from Pause to Executing */
3025 if (eState == OMX_StateExecuting) {
3026 DEBUG_PRINT_LOW("Pause --> Executing");
3027 m_state = OMX_StateExecuting;
3028 bFlag = 1;
3029 }
3030 /* Requesting transition from Pause to Idle */
3031 else if (eState == OMX_StateIdle) {
3032 /* Since error is None , we will post an event
3033 at the end of this function definition */
3034 DEBUG_PRINT_LOW("Pause --> Idle");
3035 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
3036 if (!sem_posted) {
3037 sem_posted = 1;
3038 sem_post (&m_cmd_lock);
3039 execute_omx_flush(OMX_ALL);
3040 }
3041 bFlag = 0;
3042 }
3043 /* Requesting transition from Pause to loaded */
3044 else if (eState == OMX_StateLoaded) {
3045 DEBUG_PRINT_ERROR("Pause --> loaded");
3046 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3047 OMX_COMPONENT_GENERATE_EVENT);
3048 eRet = OMX_ErrorIncorrectStateTransition;
3049 }
3050 /* Requesting transition from Pause to WaitForResources */
3051 else if (eState == OMX_StateWaitForResources) {
3052 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
3053 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3054 OMX_COMPONENT_GENERATE_EVENT);
3055 eRet = OMX_ErrorIncorrectStateTransition;
3056 }
3057 /* Requesting transition from Pause to Pause */
3058 else if (eState == OMX_StatePause) {
3059 DEBUG_PRINT_ERROR("Pause --> Pause");
3060 post_event(OMX_EventError,OMX_ErrorSameState,\
3061 OMX_COMPONENT_GENERATE_EVENT);
3062 eRet = OMX_ErrorSameState;
3063 }
3064 /* Requesting transition from Pause to Invalid */
3065 else if (eState == OMX_StateInvalid) {
3066 DEBUG_PRINT_ERROR("Pause --> Invalid");
3067 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3068 eRet = OMX_ErrorInvalidState;
3069 } else {
3070 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
3071 eRet = OMX_ErrorBadParameter;
3072 }
3073 }
3074 /***************************/
3075 /* Current State is WaitForResources */
3076 /***************************/
3077 else if (m_state == OMX_StateWaitForResources) {
3078 /* Requesting transition from WaitForResources to Loaded */
3079 if (eState == OMX_StateLoaded) {
3080 /* Since error is None , we will post an event
3081 at the end of this function definition */
3082 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
3083 }
3084 /* Requesting transition from WaitForResources to WaitForResources */
3085 else if (eState == OMX_StateWaitForResources) {
3086 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
3087 post_event(OMX_EventError,OMX_ErrorSameState,
3088 OMX_COMPONENT_GENERATE_EVENT);
3089 eRet = OMX_ErrorSameState;
3090 }
3091 /* Requesting transition from WaitForResources to Executing */
3092 else if (eState == OMX_StateExecuting) {
3093 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
3094 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3095 OMX_COMPONENT_GENERATE_EVENT);
3096 eRet = OMX_ErrorIncorrectStateTransition;
3097 }
3098 /* Requesting transition from WaitForResources to Pause */
3099 else if (eState == OMX_StatePause) {
3100 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
3101 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3102 OMX_COMPONENT_GENERATE_EVENT);
3103 eRet = OMX_ErrorIncorrectStateTransition;
3104 }
3105 /* Requesting transition from WaitForResources to Invalid */
3106 else if (eState == OMX_StateInvalid) {
3107 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
3108 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3109 eRet = OMX_ErrorInvalidState;
3110 }
3111 /* Requesting transition from WaitForResources to Loaded -
3112 is NOT tested by Khronos TS */
3113
3114 } else {
3115 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
3116 eRet = OMX_ErrorBadParameter;
3117 }
3118 }
3119 /********************************/
3120 /* Current State is Invalid */
3121 /*******************************/
3122 else if (m_state == OMX_StateInvalid) {
3123 /* State Transition from Inavlid to any state */
3124 if ((eState == OMX_StateLoaded) ||
3125 (eState == OMX_StateWaitForResources) ||
3126 (eState == OMX_StateIdle) ||
3127 (eState == OMX_StateExecuting) ||
3128 (eState == OMX_StatePause) ||
3129 (eState == OMX_StateInvalid)
3130 ) {
3131 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
3132 post_event(OMX_EventError,OMX_ErrorInvalidState,\
3133 OMX_COMPONENT_GENERATE_EVENT);
3134 eRet = OMX_ErrorInvalidState;
3135 }
3136 } else if (cmd == OMX_CommandFlush) {
3137 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
3138 "with param1: %u", (unsigned int)param1);
3139 send_codec_config();
3140 if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
3141 param1 == OMX_ALL)) {
3142 if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
3143 struct timespec ts;
3144
3145 clock_gettime(CLOCK_REALTIME, &ts);
3146 ts.tv_sec += 1;
3147 DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
3148 m_queued_codec_config_count);
3149 BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
3150 if (sem_timedwait(&m_safe_flush, &ts)) {
3151 DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
3152 }
3153 BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
3154 }
3155 }
3156
3157 if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3158 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
3159 }
3160 if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3161 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3162 }
3163 if (!sem_posted) {
3164 sem_posted = 1;
3165 DEBUG_PRINT_LOW("Set the Semaphore");
3166 sem_post (&m_cmd_lock);
3167 execute_omx_flush(param1);
3168 }
3169 bFlag = 0;
3170 } else if ( cmd == OMX_CommandPortEnable) {
3171 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
3172 "with param1: %u", (unsigned int)param1);
3173 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3174 m_inp_bEnabled = OMX_TRUE;
3175
3176 if ( (m_state == OMX_StateLoaded &&
3177 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3178 || allocate_input_done()) {
3179 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
3180 OMX_COMPONENT_GENERATE_EVENT);
3181 } else {
3182 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3183 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
3184 // Skip the event notification
3185 bFlag = 0;
3186 }
3187 }
3188 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3189 DEBUG_PRINT_LOW("Enable output Port command recieved");
3190 m_out_bEnabled = OMX_TRUE;
3191
3192 if ( (m_state == OMX_StateLoaded &&
3193 !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3194 || (allocate_output_done())) {
3195 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
3196 OMX_COMPONENT_GENERATE_EVENT);
3197
3198 } else {
3199 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3200 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3201 // Skip the event notification
3202 bFlag = 0;
3203 /* enable/disable downscaling if required */
3204 ret = decide_downscalar();
3205 if (ret) {
3206 DEBUG_PRINT_LOW("decide_downscalar failed\n");
3207 }
3208 }
3209 }
3210 } else if (cmd == OMX_CommandPortDisable) {
3211 DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
3212 "with param1: %u", (unsigned int)param1);
3213 if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3214 codec_config_flag = false;
3215 m_inp_bEnabled = OMX_FALSE;
3216 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3217 && release_input_done()) {
3218 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
3219 OMX_COMPONENT_GENERATE_EVENT);
3220 } else {
3221 DEBUG_PRINT_HIGH("Set input port disable pending");
3222 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
3223 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3224 if (!sem_posted) {
3225 sem_posted = 1;
3226 sem_post (&m_cmd_lock);
3227 }
3228 execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
3229 }
3230
3231 // Skip the event notification
3232 bFlag = 0;
3233 }
3234 }
3235 if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3236 m_out_bEnabled = OMX_FALSE;
3237 DEBUG_PRINT_LOW("Disable output Port command recieved");
3238 if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3239 && release_output_done()) {
3240 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
3241 OMX_COMPONENT_GENERATE_EVENT);
3242 } else {
3243 DEBUG_PRINT_HIGH("Set output port disable pending");
3244 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
3245 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3246 if (!sem_posted) {
3247 sem_posted = 1;
3248 sem_post (&m_cmd_lock);
3249 }
3250 DEBUG_PRINT_HIGH("Set output port flush in disable pending");
3251 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
3252 execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
3253 }
3254 // Skip the event notification
3255 bFlag = 0;
3256
3257 }
3258 }
3259 } else {
3260 DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
3261 eRet = OMX_ErrorNotImplemented;
3262 }
3263 if (eRet == OMX_ErrorNone && bFlag) {
3264 post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
3265 }
3266 if (!sem_posted) {
3267 sem_post(&m_cmd_lock);
3268 }
3269
3270 return eRet;
3271 }
3272
3273 /* ======================================================================
3274 FUNCTION
3275 omx_vdec::ExecuteOmxFlush
3276
3277 DESCRIPTION
3278 Executes the OMX flush.
3279
3280 PARAMETERS
3281 flushtype - input flush(1)/output flush(0)/ both.
3282
3283 RETURN VALUE
3284 true/false
3285
3286 ========================================================================== */
execute_omx_flush(OMX_U32 flushType)3287 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
3288 {
3289 bool bRet = false;
3290 struct v4l2_plane plane;
3291 struct v4l2_buffer v4l2_buf;
3292 struct v4l2_decoder_cmd dec;
3293 DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
3294 memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
3295 dec.cmd = V4L2_QCOM_CMD_FLUSH;
3296
3297 DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
3298
3299 if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
3300 output_flush_progress = true;
3301 dec.flags = V4L2_QCOM_CMD_FLUSH_CAPTURE;
3302 } else {
3303 /* XXX: The driver/hardware does not support flushing of individual ports
3304 * in all states. So we pretty much need to flush both ports internally,
3305 * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
3306 * requested. Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
3307 * we automatically omit sending the FLUSH done for the "opposite" port. */
3308 input_flush_progress = true;
3309 output_flush_progress = true;
3310 dec.flags = V4L2_QCOM_CMD_FLUSH_OUTPUT | V4L2_QCOM_CMD_FLUSH_CAPTURE;
3311 }
3312
3313 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
3314 DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
3315 bRet = false;
3316 }
3317
3318 return bRet;
3319 }
3320 /*=========================================================================
3321 FUNCTION : execute_output_flush
3322
3323 DESCRIPTION
3324 Executes the OMX flush at OUTPUT PORT.
3325
3326 PARAMETERS
3327 None.
3328
3329 RETURN VALUE
3330 true/false
3331 ==========================================================================*/
execute_output_flush()3332 bool omx_vdec::execute_output_flush()
3333 {
3334 unsigned long p1 = 0; // Parameter - 1
3335 unsigned long p2 = 0; // Parameter - 2
3336 unsigned long ident = 0;
3337 bool bRet = true;
3338
3339 /*Generate FBD for all Buffers in the FTBq*/
3340 pthread_mutex_lock(&m_lock);
3341 DEBUG_PRINT_LOW("Initiate Output Flush");
3342
3343 //reset last render TS
3344 if(m_last_rendered_TS > 0) {
3345 m_last_rendered_TS = 0;
3346 }
3347
3348 while (m_ftb_q.m_size) {
3349 m_ftb_q.pop_entry(&p1,&p2,&ident);
3350 if (ident == m_fill_output_msg ) {
3351 print_omx_buffer("Flush FBD", (OMX_BUFFERHEADERTYPE *)p2);
3352 m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
3353 } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
3354 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
3355 }
3356 }
3357 pthread_mutex_unlock(&m_lock);
3358 output_flush_progress = false;
3359
3360 if (arbitrary_bytes) {
3361 prev_ts = LLONG_MAX;
3362 rst_prev_ts = true;
3363 }
3364 DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
3365 return bRet;
3366 }
3367 /*=========================================================================
3368 FUNCTION : execute_input_flush
3369
3370 DESCRIPTION
3371 Executes the OMX flush at INPUT PORT.
3372
3373 PARAMETERS
3374 None.
3375
3376 RETURN VALUE
3377 true/false
3378 ==========================================================================*/
execute_input_flush()3379 bool omx_vdec::execute_input_flush()
3380 {
3381 unsigned i =0;
3382 unsigned long p1 = 0; // Parameter - 1
3383 unsigned long p2 = 0; // Parameter - 2
3384 unsigned long ident = 0;
3385 bool bRet = true;
3386
3387 /*Generate EBD for all Buffers in the ETBq*/
3388 DEBUG_PRINT_LOW("Initiate Input Flush");
3389
3390 pthread_mutex_lock(&m_lock);
3391 DEBUG_PRINT_LOW("Check if the Queue is empty");
3392 while (m_etb_q.m_size) {
3393 m_etb_q.pop_entry(&p1,&p2,&ident);
3394
3395 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
3396 print_omx_buffer("Flush ETB_ARBITRARY", (OMX_BUFFERHEADERTYPE *)p2);
3397 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
3398 } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
3399 pending_input_buffers++;
3400 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
3401 print_omx_buffer("Flush ETB", (OMX_BUFFERHEADERTYPE *)p2);
3402 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
3403 } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
3404 print_omx_buffer("Flush EBD", (OMX_BUFFERHEADERTYPE *)p1);
3405 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
3406 }
3407 }
3408 time_stamp_dts.flush_timestamp();
3409 /*Check if Heap Buffers are to be flushed*/
3410 if (arbitrary_bytes && !(codec_config_flag)) {
3411 DEBUG_PRINT_LOW("Reset all the variables before flusing");
3412 h264_scratch.nFilledLen = 0;
3413 nal_count = 0;
3414 look_ahead_nal = false;
3415 frame_count = 0;
3416 h264_last_au_ts = LLONG_MAX;
3417 h264_last_au_flags = 0;
3418 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
3419 m_demux_entries = 0;
3420 DEBUG_PRINT_LOW("Initialize parser");
3421 if (m_frame_parser.mutils) {
3422 m_frame_parser.mutils->initialize_frame_checking_environment();
3423 }
3424
3425 while (m_input_pending_q.m_size) {
3426 m_input_pending_q.pop_entry(&p1,&p2,&ident);
3427 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
3428 }
3429
3430 if (psource_frame) {
3431 m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
3432 psource_frame = NULL;
3433 }
3434
3435 if (pdest_frame) {
3436 pdest_frame->nFilledLen = 0;
3437 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL,
3438 (unsigned int)NULL);
3439 pdest_frame = NULL;
3440 }
3441 m_frame_parser.flush();
3442 } else if (codec_config_flag) {
3443 DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
3444 "is not sent to the driver yet");
3445 }
3446 pthread_mutex_unlock(&m_lock);
3447 input_flush_progress = false;
3448 if (!arbitrary_bytes) {
3449 prev_ts = LLONG_MAX;
3450 rst_prev_ts = true;
3451 }
3452
3453 DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
3454 return bRet;
3455 }
3456
3457 /*=========================================================================
3458 FUNCTION : notify_flush_done
3459
3460 DESCRIPTION
3461 Notifies flush done to the OMX Client.
3462
3463 PARAMETERS
3464 ctxt -- Context information related to the self..
3465
3466 RETURN VALUE
3467 NONE
3468 ==========================================================================*/
notify_flush_done(void * ctxt)3469 void omx_vdec::notify_flush_done(void *ctxt) {
3470
3471 omx_vdec *pThis = (omx_vdec *) ctxt;
3472
3473 if (!pThis->input_flush_progress && !pThis->output_flush_progress) {
3474 if (BITMASK_PRESENT(&pThis->m_flags,
3475 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
3476 DEBUG_PRINT_LOW("Notify Output Flush done");
3477 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3478 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3479 OMX_EventCmdComplete,OMX_CommandFlush,
3480 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
3481 }
3482
3483 if (BITMASK_PRESENT(&pThis->m_flags,
3484 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
3485 BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
3486 DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
3487 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3488 OMX_EventCmdComplete,OMX_CommandFlush,
3489 OMX_CORE_INPUT_PORT_INDEX,NULL );
3490 //clear hdr10plusinfo list upon input flush done
3491 clear_hdr10plusinfo();
3492 }
3493 }
3494 }
3495
3496 /* ======================================================================
3497 FUNCTION
3498 omx_vdec::SendCommandEvent
3499
3500 DESCRIPTION
3501 Send the event to decoder pipe. This is needed to generate the callbacks
3502 in decoder thread context.
3503
3504 PARAMETERS
3505 None.
3506
3507 RETURN VALUE
3508 true/false
3509
3510 ========================================================================== */
post_event(unsigned long p1,unsigned long p2,unsigned long id)3511 bool omx_vdec::post_event(unsigned long p1,
3512 unsigned long p2,
3513 unsigned long id)
3514 {
3515 bool bRet = false;
3516
3517 /* Just drop messages typically generated by hardware (w/o client request),
3518 * if we've reported an error to client. */
3519 if (m_error_propogated) {
3520 switch (id) {
3521 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
3522 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
3523 DEBUG_PRINT_ERROR("Dropping message %lx "
3524 "since client expected to be in error state", id);
3525 return false;
3526 default:
3527 /* whatever */
3528 break;
3529 }
3530 }
3531
3532 pthread_mutex_lock(&m_lock);
3533
3534 if (id == m_fill_output_msg ||
3535 id == OMX_COMPONENT_GENERATE_FBD ||
3536 id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
3537 id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
3538 m_ftb_q.insert_entry(p1,p2,id);
3539 } else if (id == OMX_COMPONENT_GENERATE_ETB ||
3540 id == OMX_COMPONENT_GENERATE_EBD ||
3541 id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY ||
3542 id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
3543 m_etb_q.insert_entry(p1,p2,id);
3544 } else {
3545 DEBUG_PRINT_HIGH("post_event(%ld, %ld, %ld)", p1, p2, id);
3546 m_cmd_q.insert_entry(p1,p2,id);
3547 }
3548
3549 bRet = true;
3550 post_message(this, id);
3551
3552 pthread_mutex_unlock(&m_lock);
3553
3554 return bRet;
3555 }
3556
vdec_query_cap(struct v4l2_queryctrl & cap)3557 bool inline omx_vdec::vdec_query_cap(struct v4l2_queryctrl &cap) {
3558
3559 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCTRL, &cap)) {
3560 DEBUG_PRINT_ERROR("Query caps for id = %u failed\n", cap.id);
3561 return false;
3562 }
3563 return true;
3564 }
3565
get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)3566 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
3567 {
3568 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3569 struct v4l2_queryctrl profile_cap, level_cap;
3570 int v4l2_profile;
3571 int avc_profiles[5] = { QOMX_VIDEO_AVCProfileConstrainedBaseline,
3572 QOMX_VIDEO_AVCProfileBaseline,
3573 QOMX_VIDEO_AVCProfileMain,
3574 QOMX_VIDEO_AVCProfileConstrainedHigh,
3575 QOMX_VIDEO_AVCProfileHigh };
3576 int hevc_profiles[3] = { OMX_VIDEO_HEVCProfileMain,
3577 OMX_VIDEO_HEVCProfileMain10,
3578 OMX_VIDEO_HEVCProfileMain10HDR10 };
3579 int mpeg2_profiles[2] = { OMX_VIDEO_MPEG2ProfileSimple,
3580 OMX_VIDEO_MPEG2ProfileMain};
3581 int vp9_profiles[4] = { OMX_VIDEO_VP9Profile0,
3582 OMX_VIDEO_VP9Profile2,
3583 OMX_VIDEO_VP9Profile2HDR,
3584 OMX_VIDEO_VP9Profile2HDR10Plus};
3585
3586 if (!profileLevelType)
3587 return OMX_ErrorBadParameter;
3588
3589 memset(&level_cap, 0, sizeof(struct v4l2_queryctrl));
3590 memset(&profile_cap, 0, sizeof(struct v4l2_queryctrl));
3591
3592 if (output_capability == V4L2_PIX_FMT_H264) {
3593 level_cap.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3594 profile_cap.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3595 } else if (output_capability == V4L2_PIX_FMT_VP8) {
3596 level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL;
3597 } else if (output_capability == V4L2_PIX_FMT_VP9) {
3598 level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP9_LEVEL;
3599 profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP9_PROFILE;
3600 } else if (output_capability == V4L2_PIX_FMT_HEVC) {
3601 level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL;
3602 profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE;
3603 } else if (output_capability == V4L2_PIX_FMT_MPEG2) {
3604 level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL;
3605 profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE;
3606 } else {
3607 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported Invalid codec");
3608 return OMX_ErrorInvalidComponent;
3609 }
3610
3611 if (profile_cap.id) {
3612 if(!vdec_query_cap(profile_cap)) {
3613 DEBUG_PRINT_ERROR("Getting capabilities for profile failed");
3614 return OMX_ErrorHardware;
3615 }
3616 }
3617
3618 if (level_cap.id) {
3619 if(!vdec_query_cap(level_cap)) {
3620 DEBUG_PRINT_ERROR("Getting capabilities for level failed");
3621 return OMX_ErrorHardware;
3622 }
3623 }
3624
3625 /* Get the corresponding omx level from v4l2 level */
3626 if (!profile_level_converter::convert_v4l2_level_to_omx(output_capability, level_cap.maximum, (int *)&profileLevelType->eLevel)) {
3627 DEBUG_PRINT_ERROR("Invalid level, cannot find corresponding v4l2 level : %d ", level_cap.maximum);
3628 return OMX_ErrorHardware;
3629 }
3630
3631 /* For given profile index get corresponding profile that needs to be supported */
3632 if (profileLevelType->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
3633 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on Input port only %u", (unsigned int)profileLevelType->nPortIndex);
3634 return OMX_ErrorBadPortIndex;
3635 }
3636
3637 if (output_capability == V4L2_PIX_FMT_H264) {
3638 if (profileLevelType->nProfileIndex < (sizeof(avc_profiles)/sizeof(int))) {
3639 profileLevelType->eProfile = avc_profiles[profileLevelType->nProfileIndex];
3640 } else {
3641 DEBUG_PRINT_LOW("AVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3642 (unsigned int)profileLevelType->nProfileIndex);
3643 return OMX_ErrorNoMore;
3644 }
3645 } else if (output_capability == V4L2_PIX_FMT_VP8) {
3646 if (profileLevelType->nProfileIndex == 0) {
3647 profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain;
3648 } else {
3649 DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3650 (unsigned int)profileLevelType->nProfileIndex);
3651 return OMX_ErrorNoMore;
3652 }
3653 /* Driver has no notion of VP8 profile. Only one profile is supported. Return this */
3654 return OMX_ErrorNone;
3655 } else if (output_capability == V4L2_PIX_FMT_VP9) {
3656 if (profileLevelType->nProfileIndex < (sizeof(vp9_profiles)/sizeof(int))) {
3657 profileLevelType->eProfile = vp9_profiles[profileLevelType->nProfileIndex];
3658 } else {
3659 DEBUG_PRINT_LOW("VP9: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3660 (unsigned int)profileLevelType->nProfileIndex);
3661 return OMX_ErrorNoMore;
3662 }
3663 } else if (output_capability == V4L2_PIX_FMT_HEVC) {
3664 if (profileLevelType->nProfileIndex < (sizeof(hevc_profiles)/sizeof(int))) {
3665 profileLevelType->eProfile = hevc_profiles[profileLevelType->nProfileIndex];
3666 } else {
3667 DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3668 (unsigned int)profileLevelType->nProfileIndex);
3669 return OMX_ErrorNoMore;
3670 }
3671 } else if (output_capability == V4L2_PIX_FMT_MPEG2) {
3672 if (profileLevelType->nProfileIndex < (sizeof(mpeg2_profiles)/sizeof(int))) {
3673 profileLevelType->eProfile = mpeg2_profiles[profileLevelType->nProfileIndex];
3674 } else {
3675 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3676 (unsigned int)profileLevelType->nProfileIndex);
3677 return OMX_ErrorNoMore;
3678 }
3679 }
3680
3681 /* Check if the profile is supported by driver or not */
3682 /* During query caps of profile driver sends a mask of */
3683 /* of all v4l2 profiles supported(in the flags field) */
3684 if((output_capability != V4L2_PIX_FMT_HEVC) &&
3685 (output_capability != V4L2_PIX_FMT_VP9)) {
3686 if (!profile_level_converter::convert_omx_profile_to_v4l2(output_capability, profileLevelType->eProfile, &v4l2_profile)) {
3687 DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
3688 return OMX_ErrorHardware;
3689 }
3690 }else if(output_capability == V4L2_PIX_FMT_HEVC) { //convert omx profile to v4l2 profile for HEVC Main10 and Main10HDR10 profiles,seperately
3691 switch (profileLevelType->eProfile) {
3692 case OMX_VIDEO_HEVCProfileMain:
3693 v4l2_profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN;
3694 break;
3695 case OMX_VIDEO_HEVCProfileMain10:
3696 case OMX_VIDEO_HEVCProfileMain10HDR10:
3697 v4l2_profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10;
3698 break;
3699 default:
3700 DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
3701 return OMX_ErrorHardware;
3702 }
3703 }else { //convert omx profile to v4l2 profile for VP9 Profile2 and VP9 Profile2HDR profiles,seperately
3704 switch (profileLevelType->eProfile) {
3705 case OMX_VIDEO_VP9Profile0:
3706 v4l2_profile = V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_P0;
3707 break;
3708 case OMX_VIDEO_VP9Profile2:
3709 case OMX_VIDEO_VP9Profile2HDR:
3710 v4l2_profile = V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_P2_10;
3711 break;
3712 default:
3713 DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
3714 return OMX_ErrorHardware;
3715 }
3716 }
3717 if(!((profile_cap.flags >> v4l2_profile) & 0x1)) {
3718 DEBUG_PRINT_ERROR("%s: Invalid index corresponding profile not supported : %d ",__FUNCTION__, profileLevelType->eProfile);
3719 eRet = OMX_ErrorNoMore;
3720 }
3721
3722 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u",
3723 (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel);
3724 return eRet;
3725 }
3726
3727 /* ======================================================================
3728 FUNCTION
3729 omx_vdec::GetParameter
3730
3731 DESCRIPTION
3732 OMX Get Parameter method implementation
3733
3734 PARAMETERS
3735 <TBD>.
3736
3737 RETURN VALUE
3738 Error None if successful.
3739
3740 ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)3741 OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
3742 OMX_IN OMX_INDEXTYPE paramIndex,
3743 OMX_INOUT OMX_PTR paramData)
3744 {
3745 (void) hComp;
3746 OMX_ERRORTYPE eRet = OMX_ErrorNone;
3747
3748 DEBUG_PRINT_LOW("get_parameter:");
3749 if (m_state == OMX_StateInvalid) {
3750 DEBUG_PRINT_ERROR("Get Param in Invalid State");
3751 return OMX_ErrorInvalidState;
3752 }
3753 if (paramData == NULL) {
3754 DEBUG_PRINT_LOW("Get Param in Invalid paramData");
3755 return OMX_ErrorBadParameter;
3756 }
3757 switch ((unsigned long)paramIndex) {
3758 case OMX_IndexParamPortDefinition: {
3759 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3760 OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
3761 (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3762 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
3763
3764 OMX_COLOR_FORMATTYPE drv_color_format;
3765 bool status = false;
3766
3767 if (!client_buffers.is_color_conversion_enabled()) {
3768 status = client_buffers.get_color_format(drv_color_format);
3769 }
3770
3771 if (decide_dpb_buffer_mode()) {
3772 DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed", __func__);
3773 return OMX_ErrorBadParameter;
3774 }
3775
3776 if (status) {
3777 if (!client_buffers.is_color_conversion_enabled()) {
3778 client_buffers.set_client_buffers_disabled(true);
3779 client_buffers.set_color_format(drv_color_format);
3780 }
3781 }
3782
3783 eRet = update_portdef(portDefn);
3784 if (eRet == OMX_ErrorNone)
3785 m_port_def = *portDefn;
3786 break;
3787 }
3788 case OMX_IndexParamVideoInit: {
3789 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3790 OMX_PORT_PARAM_TYPE *portParamType =
3791 (OMX_PORT_PARAM_TYPE *) paramData;
3792 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
3793
3794 portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3795 portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3796 portParamType->nPorts = 2;
3797 portParamType->nStartPortNumber = 0;
3798 break;
3799 }
3800 case OMX_IndexParamVideoPortFormat: {
3801 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3802 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3803 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3804 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
3805
3806 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
3807 portFmt->nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
3808
3809 if (0 == portFmt->nPortIndex) {
3810 if (0 == portFmt->nIndex) {
3811 portFmt->eColorFormat = OMX_COLOR_FormatUnused;
3812 portFmt->eCompressionFormat = eCompressionFormat;
3813 } else {
3814 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
3815 " NoMore compression formats");
3816 eRet = OMX_ErrorNoMore;
3817 }
3818 } else if (1 == portFmt->nPortIndex) {
3819 portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused;
3820
3821 // Distinguish non-surface mode from normal playback use-case based on
3822 // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
3823 // For non-android, use the default list
3824 // Also use default format-list if FLEXIBLE YUV is supported,
3825 // as the client negotiates the standard color-format if it needs to
3826 bool useNonSurfaceMode = false;
3827 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED) && !defined(USE_GBM)
3828 useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
3829 #endif
3830 portFmt->eColorFormat = useNonSurfaceMode ?
3831 getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
3832 getPreferredColorFormatDefaultMode(portFmt->nIndex);
3833
3834 if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
3835 eRet = OMX_ErrorNoMore;
3836 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
3837 " NoMore Color formats");
3838 }
3839 DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
3840 } else {
3841 DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
3842 (int)portFmt->nPortIndex);
3843 eRet = OMX_ErrorBadPortIndex;
3844 }
3845 break;
3846 }
3847 /*Component should support this port definition*/
3848 case OMX_IndexParamAudioInit: {
3849 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3850 OMX_PORT_PARAM_TYPE *audioPortParamType =
3851 (OMX_PORT_PARAM_TYPE *) paramData;
3852 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
3853 audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3854 audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3855 audioPortParamType->nPorts = 0;
3856 audioPortParamType->nStartPortNumber = 0;
3857 break;
3858 }
3859 /*Component should support this port definition*/
3860 case OMX_IndexParamImageInit: {
3861 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3862 OMX_PORT_PARAM_TYPE *imagePortParamType =
3863 (OMX_PORT_PARAM_TYPE *) paramData;
3864 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
3865 imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3866 imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3867 imagePortParamType->nPorts = 0;
3868 imagePortParamType->nStartPortNumber = 0;
3869 break;
3870
3871 }
3872 /*Component should support this port definition*/
3873 case OMX_IndexParamOtherInit: {
3874 DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
3875 paramIndex);
3876 eRet =OMX_ErrorUnsupportedIndex;
3877 break;
3878 }
3879 case OMX_IndexParamStandardComponentRole: {
3880 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3881 OMX_PARAM_COMPONENTROLETYPE *comp_role;
3882 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3883 comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
3884 comp_role->nSize = sizeof(*comp_role);
3885
3886 DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
3887 paramIndex);
3888 strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
3889 OMX_MAX_STRINGNAME_SIZE);
3890 break;
3891 }
3892 /* Added for parameter test */
3893 case OMX_IndexParamPriorityMgmt: {
3894 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3895 OMX_PRIORITYMGMTTYPE *priorityMgmType =
3896 (OMX_PRIORITYMGMTTYPE *) paramData;
3897 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
3898 priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
3899 priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
3900
3901 break;
3902 }
3903 /* Added for parameter test */
3904 case OMX_IndexParamCompBufferSupplier: {
3905 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3906 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
3907 (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3908 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
3909
3910 bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE);
3911 bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
3912 if (0 == bufferSupplierType->nPortIndex)
3913 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3914 else if (1 == bufferSupplierType->nPortIndex)
3915 bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3916 else
3917 eRet = OMX_ErrorBadPortIndex;
3918
3919
3920 break;
3921 }
3922 case OMX_IndexParamVideoAvc: {
3923 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
3924 paramIndex);
3925 break;
3926 }
3927 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3928 DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
3929 paramIndex);
3930 break;
3931 }
3932 case OMX_IndexParamVideoMpeg2: {
3933 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
3934 paramIndex);
3935 break;
3936 }
3937 case OMX_IndexParamVideoProfileLevelQuerySupported: {
3938 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3939 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
3940 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
3941 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
3942 eRet = get_supported_profile_level(profileLevelType);
3943 break;
3944 }
3945 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3946 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
3947 VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
3948 DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
3949 GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
3950 if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3951
3952 if (secure_mode && !secure_scaling_to_non_secure_opb) {
3953 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
3954 GRALLOC_USAGE_PRIVATE_UNCACHED);
3955 } else {
3956 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED;
3957 }
3958 } else {
3959 DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
3960 eRet = OMX_ErrorBadParameter;
3961 }
3962 }
3963 break;
3964 #endif
3965
3966 #ifdef FLEXYUV_SUPPORTED
3967 case OMX_QcomIndexFlexibleYUVDescription: {
3968 DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
3969 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
3970 eRet = describeColorFormat(paramData);
3971 if (eRet == OMX_ErrorUnsupportedSetting) {
3972 DEBUG_PRINT_LOW("The standard OMX linear formats are understood by client. Please ignore this Unsupported Setting (0x80001019).");
3973 }
3974 break;
3975 }
3976 #endif
3977 case OMX_IndexParamVideoProfileLevelCurrent: {
3978 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3979 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
3980 struct v4l2_control profile_control, level_control;
3981
3982 switch (drv_ctx.decoder_format) {
3983 case VDEC_CODECTYPE_H264:
3984 profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3985 level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3986 break;
3987 default:
3988 DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264");
3989 eRet = OMX_ErrorNotImplemented;
3990 break;
3991 }
3992
3993 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) {
3994 switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) {
3995 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
3996 pParam->eProfile = OMX_VIDEO_AVCProfileBaseline;
3997 break;
3998 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
3999 pParam->eProfile = OMX_VIDEO_AVCProfileConstrainedBaseline;
4000 break;
4001 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
4002 pParam->eProfile = OMX_VIDEO_AVCProfileConstrainedHigh;
4003 break;
4004 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
4005 pParam->eProfile = OMX_VIDEO_AVCProfileMain;
4006 break;
4007 case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
4008 pParam->eProfile = OMX_VIDEO_AVCProfileExtended;
4009 break;
4010 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
4011 pParam->eProfile = OMX_VIDEO_AVCProfileHigh;
4012 break;
4013 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
4014 pParam->eProfile = OMX_VIDEO_AVCProfileHigh10;
4015 break;
4016 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
4017 pParam->eProfile = OMX_VIDEO_AVCProfileHigh422;
4018 break;
4019 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
4020 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
4021 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
4022 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
4023 case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
4024 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
4025 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
4026 case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
4027 case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
4028 case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
4029 eRet = OMX_ErrorUnsupportedIndex;
4030 break;
4031 }
4032 } else {
4033 eRet = OMX_ErrorUnsupportedIndex;
4034 }
4035
4036
4037 if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) {
4038 switch ((enum v4l2_mpeg_video_h264_level)level_control.value) {
4039 case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
4040 pParam->eLevel = OMX_VIDEO_AVCLevel1;
4041 break;
4042 case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
4043 pParam->eLevel = OMX_VIDEO_AVCLevel1b;
4044 break;
4045 case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
4046 pParam->eLevel = OMX_VIDEO_AVCLevel11;
4047 break;
4048 case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
4049 pParam->eLevel = OMX_VIDEO_AVCLevel12;
4050 break;
4051 case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
4052 pParam->eLevel = OMX_VIDEO_AVCLevel13;
4053 break;
4054 case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
4055 pParam->eLevel = OMX_VIDEO_AVCLevel2;
4056 break;
4057 case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
4058 pParam->eLevel = OMX_VIDEO_AVCLevel21;
4059 break;
4060 case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
4061 pParam->eLevel = OMX_VIDEO_AVCLevel22;
4062 break;
4063 case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
4064 pParam->eLevel = OMX_VIDEO_AVCLevel3;
4065 break;
4066 case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
4067 pParam->eLevel = OMX_VIDEO_AVCLevel31;
4068 break;
4069 case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
4070 pParam->eLevel = OMX_VIDEO_AVCLevel32;
4071 break;
4072 case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
4073 pParam->eLevel = OMX_VIDEO_AVCLevel4;
4074 break;
4075 case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
4076 pParam->eLevel = OMX_VIDEO_AVCLevel41;
4077 break;
4078 case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
4079 pParam->eLevel = OMX_VIDEO_AVCLevel42;
4080 break;
4081 case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
4082 pParam->eLevel = OMX_VIDEO_AVCLevel5;
4083 break;
4084 case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
4085 pParam->eLevel = OMX_VIDEO_AVCLevel51;
4086 break;
4087 case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
4088 pParam->eLevel = OMX_VIDEO_AVCLevel52;
4089 break;
4090 case V4L2_MPEG_VIDEO_H264_LEVEL_6_0:
4091 pParam->eLevel = OMX_VIDEO_AVCLevel6;
4092 break;
4093 case V4L2_MPEG_VIDEO_H264_LEVEL_6_1:
4094 pParam->eLevel = OMX_VIDEO_AVCLevel61;
4095 break;
4096 case V4L2_MPEG_VIDEO_H264_LEVEL_6_2:
4097 pParam->eLevel = OMX_VIDEO_AVCLevel62;
4098 break;
4099 default:
4100 eRet = OMX_ErrorUnsupportedIndex;
4101 break;
4102 }
4103 } else {
4104 eRet = OMX_ErrorUnsupportedIndex;
4105 }
4106
4107 break;
4108
4109 }
4110 case OMX_QTIIndexParamVideoClientExtradata:
4111 {
4112 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
4113 DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVideoClientExtradata");
4114 QOMX_EXTRADATA_ENABLE *pParam =
4115 (QOMX_EXTRADATA_ENABLE *)paramData;
4116 if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
4117 pParam->bEnable = client_extradata ? OMX_TRUE : OMX_FALSE;
4118 eRet = OMX_ErrorNone;
4119 } else {
4120 eRet = OMX_ErrorUnsupportedIndex;
4121 }
4122 break;
4123 }
4124 case OMX_QTIIndexParamDitherControl:
4125 {
4126 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
4127 DEBUG_PRINT_LOW("get_parameter: QOMX_VIDEO_DITHER_CONTROL");
4128 QOMX_VIDEO_DITHER_CONTROL *pParam =
4129 (QOMX_VIDEO_DITHER_CONTROL *) paramData;
4130 pParam->eDitherType = (QOMX_VIDEO_DITHERTYPE) m_dither_config;
4131 eRet = OMX_ErrorNone;
4132 break;
4133 }
4134 case OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency:
4135 {
4136 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
4137 DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency");
4138 OMX_VIDEO_PARAM_PROFILELEVELTYPE *pParam =
4139 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) paramData;
4140 pParam->eProfile = mClientSetProfile;
4141 pParam->eLevel = mClientSetLevel;
4142 eRet = OMX_ErrorNone;
4143 break;
4144 }
4145 default: {
4146 DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
4147 eRet =OMX_ErrorUnsupportedIndex;
4148 }
4149
4150 }
4151
4152 DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
4153 drv_ctx.video_resolution.frame_width,
4154 drv_ctx.video_resolution.frame_height,
4155 drv_ctx.video_resolution.stride,
4156 drv_ctx.video_resolution.scan_lines);
4157
4158 return eRet;
4159 }
4160
4161 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)4162 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
4163 {
4164 DEBUG_PRINT_LOW("Inside use_android_native_buffer");
4165 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4166 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
4167
4168 if ((params == NULL) ||
4169 (params->nativeBuffer == NULL) ||
4170 (params->nativeBuffer->handle == NULL) ||
4171 !m_enable_android_native_buffers)
4172 return OMX_ErrorBadParameter;
4173 m_use_android_native_buffers = OMX_TRUE;
4174 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
4175 private_handle_t *handle = (private_handle_t *)nBuf->handle;
4176 if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
4177 OMX_U8 *buffer = NULL;
4178 if (!secure_mode) {
4179 buffer = (OMX_U8*)mmap(0, handle->size,
4180 PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
4181 if (buffer == MAP_FAILED) {
4182 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
4183 return OMX_ErrorInsufficientResources;
4184 }
4185 }
4186 eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
4187 } else {
4188 eRet = OMX_ErrorBadParameter;
4189 }
4190 return eRet;
4191 }
4192 #endif
4193
enable_smoothstreaming()4194 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
4195 struct v4l2_control control;
4196 struct v4l2_format fmt;
4197 /*control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
4198 control.value = 1;
4199 int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
4200 if (rc < 0) {
4201 DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
4202 return OMX_ErrorHardware;
4203 }*/
4204 m_smoothstreaming_mode = true;
4205 return OMX_ErrorNone;
4206 }
4207
4208 /* ======================================================================
4209 FUNCTION
4210 omx_vdec::Setparameter
4211
4212 DESCRIPTION
4213 OMX Set Parameter method implementation.
4214
4215 PARAMETERS
4216 <TBD>.
4217
4218 RETURN VALUE
4219 OMX Error None if successful.
4220
4221 ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)4222 OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
4223 OMX_IN OMX_INDEXTYPE paramIndex,
4224 OMX_IN OMX_PTR paramData)
4225 {
4226 OMX_ERRORTYPE eRet = OMX_ErrorNone;
4227 int ret=0;
4228 struct v4l2_format fmt;
4229 #ifdef _ANDROID_
4230 char property_value[PROPERTY_VALUE_MAX] = {0};
4231 #endif
4232 if (m_state == OMX_StateInvalid) {
4233 DEBUG_PRINT_ERROR("Set Param in Invalid State");
4234 return OMX_ErrorInvalidState;
4235 }
4236 if (paramData == NULL) {
4237 DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
4238 return OMX_ErrorBadParameter;
4239 }
4240 if ((m_state != OMX_StateLoaded) &&
4241 BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
4242 (m_out_bEnabled == OMX_TRUE) &&
4243 BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
4244 (m_inp_bEnabled == OMX_TRUE)) {
4245 DEBUG_PRINT_ERROR("Set Param in Invalid State");
4246 return OMX_ErrorIncorrectStateOperation;
4247 }
4248 switch ((unsigned long)paramIndex) {
4249 case OMX_IndexParamPortDefinition: {
4250 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
4251 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
4252 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
4253 //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
4254 //been called.
4255 DEBUG_PRINT_LOW(
4256 "set_parameter: OMX_IndexParamPortDefinition: dir %d port %d wxh %dx%d count: min %d actual %d size %d",
4257 (int)portDefn->eDir, (int)portDefn->nPortIndex,
4258 (int)portDefn->format.video.nFrameWidth,
4259 (int)portDefn->format.video.nFrameHeight,
4260 (int)portDefn->nBufferCountMin,
4261 (int)portDefn->nBufferCountActual,
4262 (int)portDefn->nBufferSize);
4263
4264 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4265 DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
4266 portDefn->nBufferCountActual);
4267 eRet = OMX_ErrorBadParameter;
4268 break;
4269 }
4270 if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) {
4271 if (portDefn->nBufferCountActual < MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS ||
4272 portDefn->nBufferSize != m_client_out_extradata_info.getSize()) {
4273 DEBUG_PRINT_ERROR("ERROR: Bad parameeters request for extradata limit %d size - %d",
4274 portDefn->nBufferCountActual, portDefn->nBufferSize);
4275 eRet = OMX_ErrorBadParameter;
4276 break;
4277 }
4278 m_client_out_extradata_info.set_extradata_info(portDefn->nBufferSize,
4279 portDefn->nBufferCountActual);
4280 break;
4281 }
4282
4283 if (OMX_DirOutput == portDefn->eDir) {
4284 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
4285 bool port_format_changed = false;
4286 m_display_id = portDefn->format.video.pNativeWindow;
4287 unsigned int buffer_size;
4288 /* update output port resolution with client supplied dimensions
4289 in case scaling is enabled, else it follows input resolution set
4290 */
4291 if (decide_dpb_buffer_mode()) {
4292 DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed", __func__);
4293 return OMX_ErrorBadParameter;
4294 }
4295 if (is_down_scalar_enabled) {
4296 DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
4297 (unsigned int)portDefn->format.video.nFrameWidth,
4298 (unsigned int)portDefn->format.video.nFrameHeight);
4299 if (portDefn->format.video.nFrameHeight != 0x0 &&
4300 portDefn->format.video.nFrameWidth != 0x0) {
4301 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4302 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4303 fmt.fmt.pix_mp.pixelformat = capture_capability;
4304 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4305 if (ret) {
4306 DEBUG_PRINT_ERROR("Get Resolution failed");
4307 eRet = OMX_ErrorHardware;
4308 break;
4309 }
4310 if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
4311 (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
4312 port_format_changed = true;
4313 }
4314
4315 /* set crop info */
4316 rectangle.nLeft = 0;
4317 rectangle.nTop = 0;
4318 rectangle.nWidth = portDefn->format.video.nFrameWidth;
4319 rectangle.nHeight = portDefn->format.video.nFrameHeight;
4320
4321 m_extradata_info.output_crop_rect.nLeft = 0;
4322 m_extradata_info.output_crop_rect.nTop = 0;
4323 m_extradata_info.output_crop_rect.nWidth = rectangle.nWidth;
4324 m_extradata_info.output_crop_rect.nHeight = rectangle.nHeight;
4325
4326 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4327 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4328 fmt.fmt.pix_mp.height = (unsigned int)portDefn->format.video.nFrameHeight;
4329 fmt.fmt.pix_mp.width = (unsigned int)portDefn->format.video.nFrameWidth;
4330 fmt.fmt.pix_mp.pixelformat = capture_capability;
4331 DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
4332 fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
4333 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4334 if (ret) {
4335 DEBUG_PRINT_ERROR("Set Resolution failed");
4336 eRet = errno == EBUSY ? OMX_ErrorInsufficientResources : OMX_ErrorUnsupportedSetting;
4337 } else
4338 eRet = get_buffer_req(&drv_ctx.op_buf);
4339 }
4340
4341 if (eRet) {
4342 break;
4343 }
4344 }
4345
4346 if (eRet) {
4347 break;
4348 }
4349
4350 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4351 DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
4352 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4353 eRet = OMX_ErrorBadParameter;
4354 } else if (!client_buffers.get_buffer_req(buffer_size)) {
4355 DEBUG_PRINT_ERROR("Error in getting buffer requirements");
4356 eRet = OMX_ErrorBadParameter;
4357 } else if (!port_format_changed) {
4358
4359 // Buffer count can change only when port is unallocated
4360 if (m_out_mem_ptr &&
4361 (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount ||
4362 portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) {
4363
4364 DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
4365 eRet = OMX_ErrorInvalidState;
4366 break;
4367 }
4368
4369 // route updating of buffer requirements via c2d proxy.
4370 // Based on whether c2d is enabled, requirements will be handed
4371 // to the vidc driver appropriately
4372 eRet = client_buffers.set_buffer_req(portDefn->nBufferSize,
4373 portDefn->nBufferCountActual);
4374 if (eRet == OMX_ErrorNone) {
4375 m_port_def = *portDefn;
4376 } else {
4377 DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
4378 drv_ctx.op_buf.mincount, (unsigned int)buffer_size,
4379 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4380 eRet = OMX_ErrorBadParameter;
4381 }
4382 }
4383 } else if (OMX_DirInput == portDefn->eDir) {
4384 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
4385 bool port_format_changed = false;
4386 if ((portDefn->format.video.xFramerate >> 16) > 0 &&
4387 (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
4388 // Frame rate only should be set if this is a "known value" or to
4389 // activate ts prediction logic (arbitrary mode only) sending input
4390 // timestamps with max value (LLONG_MAX).
4391 m_fps_received = portDefn->format.video.xFramerate;
4392 DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
4393 (unsigned int)portDefn->format.video.xFramerate >> 16);
4394 Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
4395 drv_ctx.frame_rate.fps_denominator);
4396 if (!drv_ctx.frame_rate.fps_numerator) {
4397 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
4398 drv_ctx.frame_rate.fps_numerator = 30;
4399 }
4400 if (drv_ctx.frame_rate.fps_denominator)
4401 drv_ctx.frame_rate.fps_numerator = (int)
4402 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
4403 drv_ctx.frame_rate.fps_denominator = 1;
4404 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
4405 drv_ctx.frame_rate.fps_numerator;
4406 DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
4407 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
4408 (float)drv_ctx.frame_rate.fps_denominator);
4409
4410 struct v4l2_outputparm oparm;
4411 /*XXX: we're providing timing info as seconds per frame rather than frames
4412 * per second.*/
4413 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
4414 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
4415
4416 struct v4l2_streamparm sparm;
4417 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4418 sparm.parm.output = oparm;
4419 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
4420 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
4421 eRet = OMX_ErrorHardware;
4422 break;
4423 }
4424 }
4425
4426 if (drv_ctx.video_resolution.frame_height !=
4427 portDefn->format.video.nFrameHeight ||
4428 drv_ctx.video_resolution.frame_width !=
4429 portDefn->format.video.nFrameWidth) {
4430 DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
4431 (unsigned int)portDefn->format.video.nFrameWidth,
4432 (unsigned int)portDefn->format.video.nFrameHeight);
4433 port_format_changed = true;
4434 OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
4435 OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
4436 if (frameHeight != 0x0 && frameWidth != 0x0) {
4437 if (m_smoothstreaming_mode &&
4438 ((frameWidth * frameHeight) <
4439 (m_smoothstreaming_width * m_smoothstreaming_height))) {
4440 frameWidth = m_smoothstreaming_width;
4441 frameHeight = m_smoothstreaming_height;
4442 DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
4443 "for adaptive-playback/smooth-streaming",
4444 (unsigned int)frameWidth, (unsigned int)frameHeight);
4445 }
4446
4447 m_extradata_info.output_crop_rect.nLeft = 0;
4448 m_extradata_info.output_crop_rect.nTop = 0;
4449 m_extradata_info.output_crop_rect.nWidth = frameWidth;
4450 m_extradata_info.output_crop_rect.nHeight = frameHeight;
4451
4452 update_resolution(frameWidth, frameHeight,
4453 frameWidth, frameHeight);
4454 if (is_down_scalar_enabled) {
4455 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4456 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4457 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4458 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4459 fmt.fmt.pix_mp.pixelformat = output_capability;
4460 DEBUG_PRINT_LOW("DS Enabled : height = %d , width = %d",
4461 fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4462 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4463 } else {
4464 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4465 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4466 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4467 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4468 fmt.fmt.pix_mp.pixelformat = output_capability;
4469 DEBUG_PRINT_LOW("DS Disabled : height = %d , width = %d",
4470 fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4471 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4472 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4473 fmt.fmt.pix_mp.pixelformat = capture_capability;
4474 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4475 }
4476 if (ret) {
4477 DEBUG_PRINT_ERROR("Set Resolution failed");
4478 eRet = errno == EBUSY ? OMX_ErrorInsufficientResources : OMX_ErrorUnsupportedSetting;
4479 } else {
4480 if (!is_down_scalar_enabled)
4481 eRet = get_buffer_req(&drv_ctx.op_buf);
4482 }
4483 if (eRet)
4484 break;
4485 }
4486 }
4487 if (m_custom_buffersize.input_buffersize
4488 && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
4489 DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
4490 m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
4491 eRet = OMX_ErrorBadParameter;
4492 break;
4493 }
4494 if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4495 DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
4496 portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4497 eRet = OMX_ErrorBadParameter;
4498 break;
4499 }
4500 // Buffer count can change only when port is unallocated
4501 if (m_inp_mem_ptr &&
4502 (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount ||
4503 portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) {
4504 DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
4505 eRet = OMX_ErrorInvalidState;
4506 break;
4507 }
4508
4509 if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
4510 || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
4511 port_format_changed = true;
4512 vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
4513 drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
4514 drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
4515 (~(buffer_prop->alignment - 1));
4516 eRet = set_buffer_req(buffer_prop);
4517 }
4518 if (false == port_format_changed) {
4519 DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
4520 drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
4521 (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4522 eRet = OMX_ErrorBadParameter;
4523 }
4524 } else if (portDefn->eDir == OMX_DirMax) {
4525 DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
4526 (int)portDefn->nPortIndex);
4527 eRet = OMX_ErrorBadPortIndex;
4528 }
4529 }
4530 break;
4531 case OMX_IndexParamVideoPortFormat: {
4532 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
4533 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
4534 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
4535 int ret=0;
4536 struct v4l2_format fmt;
4537 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
4538 portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
4539
4540 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4541 if (1 == portFmt->nPortIndex) {
4542 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4543 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4544 if (ret < 0) {
4545 DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
4546 return OMX_ErrorBadParameter;
4547 }
4548 enum vdec_output_format op_format;
4549 if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4550 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
4551 op_format = (enum vdec_output_format)VDEC_YUV_FORMAT_NV12;
4552 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12;
4553 //check if the required color format is a supported flexible format
4554 is_flexible_format = check_supported_flexible_formats(portFmt->eColorFormat);
4555 } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4556 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed ||
4557 portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
4558 portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
4559 op_format = (enum vdec_output_format)VDEC_YUV_FORMAT_NV12_UBWC;
4560 fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC;
4561 //check if the required color format is a supported flexible format
4562 is_flexible_format = check_supported_flexible_formats(portFmt->eColorFormat);
4563 } else {
4564 eRet = OMX_ErrorBadParameter;
4565 }
4566
4567 if (eRet == OMX_ErrorNone) {
4568 drv_ctx.output_format = op_format;
4569 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4570 if (ret) {
4571 DEBUG_PRINT_ERROR("Set output format failed");
4572 eRet = OMX_ErrorUnsupportedSetting;
4573 /*TODO: How to handle this case */
4574 } else {
4575 eRet = get_buffer_req(&drv_ctx.op_buf);
4576 }
4577 }
4578 if (eRet == OMX_ErrorNone) {
4579 if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
4580 DEBUG_PRINT_ERROR("Set color format failed");
4581 eRet = OMX_ErrorBadParameter;
4582 }
4583 }
4584 }
4585 }
4586 break;
4587 case OMX_QcomIndexPortDefn: {
4588 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
4589 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
4590 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
4591 DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u",
4592 (unsigned int)portFmt->nFramePackingFormat);
4593
4594 /* Input port */
4595 if (portFmt->nPortIndex == 0) {
4596 // arbitrary_bytes mode cannot be changed arbitrarily since this controls how:
4597 // - headers are allocated and
4598 // - headers-indices are derived
4599 // Avoid changing arbitrary_bytes when the port is already allocated
4600 if (m_inp_mem_ptr) {
4601 DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!");
4602 return OMX_ErrorUnsupportedSetting;
4603 }
4604 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
4605 if (secure_mode || m_input_pass_buffer_fd) {
4606 arbitrary_bytes = false;
4607 DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode");
4608 eRet = OMX_ErrorUnsupportedSetting;
4609 } else {
4610 arbitrary_bytes = true;
4611 }
4612 } else if (portFmt->nFramePackingFormat ==
4613 OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
4614 arbitrary_bytes = false;
4615 } else {
4616 DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u",
4617 (unsigned int)portFmt->nFramePackingFormat);
4618 eRet = OMX_ErrorUnsupportedSetting;
4619 }
4620 //Explicitly disable arb mode for unsupported codecs
4621 bool is_arb_supported = false;
4622 if (arbitrary_bytes) {
4623 switch (drv_ctx.decoder_format) {
4624 case VDEC_CODECTYPE_H264:
4625 is_arb_supported = m_arb_mode_override & VDEC_ARB_CODEC_H264;
4626 break;
4627 case VDEC_CODECTYPE_HEVC:
4628 is_arb_supported = m_arb_mode_override & VDEC_ARB_CODEC_HEVC;
4629 break;
4630 case VDEC_CODECTYPE_MPEG2:
4631 is_arb_supported = m_arb_mode_override & VDEC_ARB_CODEC_MPEG2;
4632 break;
4633 default:
4634 DEBUG_PRINT_HIGH("Arbitrary bytes mode not enabled for this Codec");
4635 break;
4636 }
4637
4638 if (!is_arb_supported) {
4639 DEBUG_PRINT_ERROR("Setparameter: Disabling arbitrary bytes mode explicitly");
4640 arbitrary_bytes = false;
4641 eRet = OMX_ErrorUnsupportedSetting;
4642 }
4643 }
4644 } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4645 DEBUG_PRINT_ERROR("Unsupported at O/P port");
4646 eRet = OMX_ErrorUnsupportedSetting;
4647 }
4648 break;
4649 }
4650 case OMX_QTIIndexParamVideoClientExtradata: {
4651 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
4652 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoClientExtradata");
4653 QOMX_EXTRADATA_ENABLE *pParam =
4654 (QOMX_EXTRADATA_ENABLE *)paramData;
4655
4656 if (m_state != OMX_StateLoaded) {
4657 DEBUG_PRINT_ERROR("Set Parameter called in Invalid state");
4658 return OMX_ErrorIncorrectStateOperation;
4659 }
4660
4661 if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
4662 m_client_out_extradata_info.enable_client_extradata(pParam->bEnable);
4663 } else {
4664 DEBUG_PRINT_ERROR("Incorrect portIndex - %d", pParam->nPortIndex);
4665 eRet = OMX_ErrorUnsupportedIndex;
4666 }
4667 break;
4668 }
4669 case OMX_IndexParamStandardComponentRole: {
4670 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
4671 OMX_PARAM_COMPONENTROLETYPE *comp_role;
4672 comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
4673 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
4674 comp_role->cRole);
4675
4676 if ((m_state == OMX_StateLoaded)&&
4677 !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) {
4678 DEBUG_PRINT_LOW("Set Parameter called in valid state");
4679 } else {
4680 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4681 return OMX_ErrorIncorrectStateOperation;
4682 }
4683
4684 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4685 if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4686 strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
4687 } else {
4688 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4689 eRet =OMX_ErrorUnsupportedSetting;
4690 }
4691 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4692 if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4693 strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
4694 } else {
4695 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4696 eRet = OMX_ErrorUnsupportedSetting;
4697 }
4698 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4699 if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4700 strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE);
4701 } else {
4702 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4703 eRet = OMX_ErrorUnsupportedSetting;
4704 }
4705 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
4706 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
4707 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4708 strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE);
4709 } else {
4710 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4711 eRet = OMX_ErrorUnsupportedSetting;
4712 }
4713 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
4714 if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) ||
4715 !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4716 strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE);
4717 } else {
4718 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4719 eRet = OMX_ErrorUnsupportedSetting;
4720 }
4721 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4722 if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4723 strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
4724 } else {
4725 DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4726 eRet = OMX_ErrorUnsupportedSetting;
4727 }
4728 } else {
4729 DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
4730 eRet = OMX_ErrorInvalidComponentName;
4731 }
4732 break;
4733 }
4734
4735 case OMX_IndexParamPriorityMgmt: {
4736 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
4737 if (m_state != OMX_StateLoaded) {
4738 DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4739 return OMX_ErrorIncorrectStateOperation;
4740 }
4741 OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
4742 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
4743 (unsigned int)priorityMgmtype->nGroupID);
4744
4745 DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
4746 (unsigned int)priorityMgmtype->nGroupPriority);
4747
4748 m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
4749 m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
4750
4751 break;
4752 }
4753
4754 case OMX_IndexParamCompBufferSupplier: {
4755 VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
4756 OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
4757 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
4758 bufferSupplierType->eBufferSupplier);
4759 if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
4760 m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
4761
4762 else
4763
4764 eRet = OMX_ErrorBadPortIndex;
4765
4766 break;
4767
4768 }
4769 case OMX_IndexParamVideoAvc: {
4770 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
4771 paramIndex);
4772 break;
4773 }
4774 case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
4775 DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
4776 paramIndex);
4777 break;
4778 }
4779 case OMX_IndexParamVideoMpeg2: {
4780 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
4781 paramIndex);
4782 break;
4783 }
4784 case OMX_QTIIndexParamLowLatencyMode: {
4785 struct v4l2_control control;
4786 int rc = 0;
4787 QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE* pParam =
4788 (QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE*)paramData;
4789 control.id = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE;
4790 if (pParam->bEnableLowLatencyMode)
4791 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
4792 else
4793 control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
4794
4795 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4796 if (rc) {
4797 DEBUG_PRINT_ERROR("Set low latency failed");
4798 eRet = OMX_ErrorUnsupportedSetting;
4799 } else {
4800 m_sParamLowLatency.bEnableLowLatencyMode = pParam->bEnableLowLatencyMode;
4801 }
4802 break;
4803 }
4804 case OMX_QcomIndexParamVideoDecoderPictureOrder: {
4805 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
4806 QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
4807 (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
4808 struct v4l2_control control;
4809 int pic_order,rc=0;
4810 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
4811 pictureOrder->eOutputPictureOrder);
4812 if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
4813 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
4814 } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
4815 pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4816 time_stamp_dts.set_timestamp_reorder_mode(false);
4817 } else
4818 eRet = OMX_ErrorBadParameter;
4819 if (eRet == OMX_ErrorNone) {
4820 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4821 control.value = pic_order;
4822 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4823 if (rc) {
4824 DEBUG_PRINT_ERROR("Set picture order failed");
4825 eRet = OMX_ErrorUnsupportedSetting;
4826 }
4827 }
4828 m_decode_order_mode =
4829 pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER;
4830 break;
4831 }
4832 case OMX_QcomIndexParamConcealMBMapExtraData:
4833 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4834 eRet = enable_extradata(OMX_MB_ERROR_MAP_EXTRADATA, false,
4835 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4836 break;
4837 case OMX_QcomIndexParamFrameInfoExtraData:
4838 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4839 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
4840 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4841 break;
4842 case OMX_ExtraDataFrameDimension:
4843 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4844 eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
4845 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4846 break;
4847 case OMX_QcomIndexParamInterlaceExtraData:
4848 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4849 eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
4850 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4851 break;
4852 case OMX_QcomIndexParamOutputCropExtraData:
4853 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4854 eRet = enable_extradata(OMX_OUTPUTCROP_EXTRADATA, false,
4855 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4856 break;
4857 case OMX_QcomIndexParamH264TimeInfo:
4858 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4859 eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
4860 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4861 break;
4862 case OMX_QcomIndexParamVideoFramePackingExtradata:
4863 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4864 eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
4865 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4866 break;
4867 case OMX_QcomIndexParamVideoQPExtraData:
4868 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4869 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4870 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4871 break;
4872 case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
4873 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4874 eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
4875 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4876 break;
4877 case OMX_QcomIndexEnableExtnUserData:
4878 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4879 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
4880 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4881 break;
4882 case OMX_QTIIndexParamVQZipSEIExtraData:
4883 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4884 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4885 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4886 break;
4887 case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
4888 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
4889 DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
4890 struct v4l2_control control;
4891 int rc;
4892 drv_ctx.idr_only_decoding = 1;
4893 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4894 control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4895 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4896 if (rc) {
4897 DEBUG_PRINT_ERROR("Set picture order failed");
4898 eRet = OMX_ErrorUnsupportedSetting;
4899 } else {
4900 control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
4901 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
4902 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4903 if (rc) {
4904 DEBUG_PRINT_ERROR("Sync frame setting failed");
4905 eRet = OMX_ErrorUnsupportedSetting;
4906 }
4907 /*Setting sync frame decoding on driver might change buffer
4908 * requirements so update them here*/
4909 if (get_buffer_req(&drv_ctx.ip_buf)) {
4910 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
4911 eRet = OMX_ErrorUnsupportedSetting;
4912 }
4913 if (get_buffer_req(&drv_ctx.op_buf)) {
4914 DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
4915 eRet = OMX_ErrorUnsupportedSetting;
4916 }
4917 }
4918 }
4919 break;
4920
4921 case OMX_QcomIndexParamIndexExtraDataType: {
4922 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
4923 QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
4924 if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
4925 (extradataIndexType->bEnabled == OMX_TRUE) &&
4926 (extradataIndexType->nPortIndex == 1)) {
4927 DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
4928 eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
4929 } else if ((extradataIndexType->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataOutputCropInfo) &&
4930 (extradataIndexType->bEnabled == OMX_TRUE) &&
4931 (extradataIndexType->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX)) {
4932 eRet = enable_extradata(OMX_OUTPUTCROP_EXTRADATA, false,
4933 ((QOMX_ENABLETYPE *)paramData)->bEnable);
4934 }
4935 }
4936 break;
4937 case OMX_QcomIndexParamEnableSmoothStreaming: {
4938 #ifndef SMOOTH_STREAMING_DISABLED
4939 eRet = enable_smoothstreaming();
4940 #else
4941 eRet = OMX_ErrorUnsupportedSetting;
4942 #endif
4943 }
4944 break;
4945 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4946 /* Need to allow following two set_parameters even in Idle
4947 * state. This is ANDROID architecture which is not in sync
4948 * with openmax standard. */
4949 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
4950 VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
4951 EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
4952 if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
4953 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!");
4954 eRet = OMX_ErrorUnsupportedSetting;
4955 break;
4956 } else if (m_out_mem_ptr) {
4957 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !");
4958 eRet = OMX_ErrorInvalidState;
4959 break;
4960 }
4961 if (enableNativeBuffers) {
4962 m_enable_android_native_buffers = enableNativeBuffers->enable;
4963 }
4964 #if !defined(FLEXYUV_SUPPORTED)
4965 if (m_enable_android_native_buffers) {
4966 // Use the most-preferred-native-color-format as surface-mode is hinted here
4967 if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
4968 DEBUG_PRINT_ERROR("Failed to set native color format!");
4969 eRet = OMX_ErrorUnsupportedSetting;
4970 }
4971 }
4972 #endif
4973 }
4974 break;
4975 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
4976 VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
4977 eRet = use_android_native_buffer(hComp, paramData);
4978 }
4979 break;
4980 #if ALLOCATE_OUTPUT_NATIVEHANDLE
4981 case OMX_GoogleAndroidIndexAllocateNativeHandle: {
4982
4983 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
4984 VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams);
4985
4986 if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
4987 DEBUG_PRINT_LOW("Enable/Disable allocate-native-handle allowed only on input port!. Please ignore this Unsupported Setting (0x80001019).");
4988 eRet = OMX_ErrorUnsupportedSetting;
4989 break;
4990 } else if (m_inp_mem_ptr) {
4991 DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !");
4992 eRet = OMX_ErrorInvalidState;
4993 break;
4994 }
4995
4996 if (allocateNativeHandleParams != NULL) {
4997 allocate_native_handle = allocateNativeHandleParams->enable;
4998 }
4999 }
5000 break;
5001 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE
5002 #endif
5003 case OMX_QcomIndexParamEnableTimeStampReorder: {
5004 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
5005 QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
5006 if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
5007 if (reorder->bEnable == OMX_TRUE) {
5008 frm_int =0;
5009 time_stamp_dts.set_timestamp_reorder_mode(true);
5010 } else
5011 time_stamp_dts.set_timestamp_reorder_mode(false);
5012 } else {
5013 time_stamp_dts.set_timestamp_reorder_mode(false);
5014 if (reorder->bEnable == OMX_TRUE) {
5015 eRet = OMX_ErrorUnsupportedSetting;
5016 }
5017 }
5018 }
5019 break;
5020 case OMX_IndexParamVideoProfileLevelCurrent: {
5021 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
5022 OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
5023 (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
5024 if (pParam) {
5025 m_profile_lvl.eProfile = pParam->eProfile;
5026 m_profile_lvl.eLevel = pParam->eLevel;
5027 }
5028 break;
5029
5030 }
5031 case OMX_QcomIndexParamVideoMetaBufferMode:
5032 {
5033 VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
5034 StoreMetaDataInBuffersParams *metabuffer =
5035 (StoreMetaDataInBuffersParams *)paramData;
5036 if (!metabuffer) {
5037 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
5038 eRet = OMX_ErrorBadParameter;
5039 break;
5040 }
5041 if (m_disable_dynamic_buf_mode) {
5042 DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled");
5043 eRet = OMX_ErrorUnsupportedSetting;
5044 break;
5045 }
5046 if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
5047
5048 if (m_out_mem_ptr) {
5049 DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !");
5050 eRet = OMX_ErrorInvalidState;
5051 break;
5052 }
5053
5054 dynamic_buf_mode = metabuffer->bStoreMetaData;
5055 DEBUG_PRINT_HIGH("%s buffer mode",
5056 (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
5057
5058 } else {
5059 DEBUG_PRINT_ERROR(
5060 "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
5061 (unsigned int)metabuffer->nPortIndex);
5062 eRet = OMX_ErrorUnsupportedSetting;
5063 }
5064 break;
5065 }
5066 case OMX_QcomIndexParamVideoDownScalar:
5067 {
5068 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
5069 QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
5070 struct v4l2_control control;
5071 int rc;
5072 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
5073
5074 if (pParam && pParam->bEnable) {
5075 rc = enable_downscalar();
5076 if (rc < 0) {
5077 DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
5078 return OMX_ErrorUnsupportedSetting;
5079 }
5080 m_force_down_scalar = pParam->bEnable;
5081 } else {
5082 rc = disable_downscalar();
5083 if (rc < 0) {
5084 DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
5085 return OMX_ErrorUnsupportedSetting;
5086 }
5087 m_force_down_scalar = pParam->bEnable;
5088 }
5089 break;
5090 }
5091 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5092 case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
5093 {
5094 VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
5095 DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
5096 PrepareForAdaptivePlaybackParams* pParams =
5097 (PrepareForAdaptivePlaybackParams *) paramData;
5098 if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
5099 if (!pParams->bEnable) {
5100 return OMX_ErrorNone;
5101 }
5102 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
5103 || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
5104 DEBUG_PRINT_ERROR(
5105 "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
5106 (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
5107 (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
5108 eRet = OMX_ErrorBadParameter;
5109 } else {
5110 eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
5111 }
5112 } else {
5113 DEBUG_PRINT_ERROR(
5114 "Prepare for adaptive playback supported only on output port");
5115 eRet = OMX_ErrorBadParameter;
5116 }
5117 break;
5118 }
5119
5120 case OMX_QTIIndexParamVideoPreferAdaptivePlayback:
5121 {
5122 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
5123 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback");
5124 m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable;
5125 if (m_disable_dynamic_buf_mode) {
5126 DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set");
5127 }
5128 break;
5129 }
5130 #endif
5131 case OMX_QcomIndexParamVideoCustomBufferSize:
5132 {
5133 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
5134 DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
5135 QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
5136 if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5137 struct v4l2_control control;
5138 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
5139 control.value = pParam->nBufferSize;
5140 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5141 DEBUG_PRINT_ERROR("Failed to set input buffer size");
5142 eRet = OMX_ErrorUnsupportedSetting;
5143 } else {
5144 eRet = get_buffer_req(&drv_ctx.ip_buf);
5145 if (eRet == OMX_ErrorNone) {
5146 m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
5147 DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
5148 m_custom_buffersize.input_buffersize);
5149 } else {
5150 DEBUG_PRINT_ERROR("Failed to get buffer requirement");
5151 }
5152 }
5153 } else {
5154 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
5155 eRet = OMX_ErrorBadParameter;
5156 }
5157 break;
5158 }
5159 case OMX_QTIIndexParamVQZIPSEIType:
5160 {
5161 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE);
5162 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType");
5163 OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
5164 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
5165 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
5166
5167 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
5168 ((QOMX_ENABLETYPE *)paramData)->bEnable);
5169 if (eRet != OMX_ErrorNone) {
5170 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
5171 eRet = OMX_ErrorBadParameter;
5172 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5173 break;
5174 }
5175 eRet = enable_extradata(OMX_QP_EXTRADATA, false,
5176 ((QOMX_ENABLETYPE *)paramData)->bEnable);
5177 if (eRet != OMX_ErrorNone) {
5178 DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
5179 eRet = OMX_ErrorBadParameter;
5180 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5181 client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
5182 break;
5183 }
5184 eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
5185 ((QOMX_ENABLETYPE *)paramData)->bEnable);
5186 if (eRet != OMX_ErrorNone) {
5187 DEBUG_PRINT_ERROR("ERROR: Failed to set FrameInfo Extradata");
5188 eRet = OMX_ErrorBadParameter;
5189 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5190 client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
5191 client_extradata = client_extradata & ~OMX_FRAMEINFO_EXTRADATA;
5192 }
5193 break;
5194 }
5195 case OMX_QTIIndexParamPassInputBufferFd:
5196 {
5197 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
5198 if (arbitrary_bytes) {
5199 DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode");
5200 eRet = OMX_ErrorUnsupportedSetting;
5201 break;
5202 }
5203
5204 m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable;
5205 if (m_input_pass_buffer_fd)
5206 DEBUG_PRINT_LOW("Enable passing input buffer FD");
5207 break;
5208 }
5209 case OMX_QTIIndexParamForceCompressedForDPB:
5210 {
5211 VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE);
5212 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB");
5213 OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam =
5214 (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData;
5215 if (m_disable_ubwc_mode) {
5216 DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled");
5217 eRet = OMX_ErrorUnsupportedSetting;
5218 break;
5219 }
5220 if (!paramData) {
5221 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL");
5222 eRet = OMX_ErrorBadParameter;
5223 break;
5224 }
5225
5226 m_force_compressed_for_dpb = pParam->bEnable;
5227 break;
5228 }
5229 case OMX_QTIIndexParamForceUnCompressedForOPB:
5230 {
5231 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB");
5232 OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam =
5233 (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData;
5234 if (!paramData) {
5235 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL");
5236 eRet = OMX_ErrorBadParameter;
5237 break;
5238 }
5239 m_disable_ubwc_mode = pParam->bEnable;
5240 DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled");
5241 break;
5242 }
5243 case OMX_QTIIndexParamDitherControl:
5244 {
5245 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
5246 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamDitherControl");
5247 QOMX_VIDEO_DITHER_CONTROL *pParam = (QOMX_VIDEO_DITHER_CONTROL *)paramData;
5248 DEBUG_PRINT_LOW("set_parameter: Dither Config from client is: %d", pParam->eDitherType);
5249 if (( pParam->eDitherType < QOMX_DITHER_DISABLE ) ||
5250 ( pParam->eDitherType > QOMX_DITHER_ALL_COLORSPACE)) {
5251 DEBUG_PRINT_ERROR("set_parameter: DitherType outside the range");
5252 eRet = OMX_ErrorBadParameter;
5253 break;
5254 }
5255 m_dither_config = is_platform_tp10capture_supported() ? (dither_type)pParam->eDitherType : DITHER_ALL_COLORSPACE;
5256 DEBUG_PRINT_LOW("set_parameter: Final Dither Config is: %d", m_dither_config);
5257 break;
5258 }
5259 case OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency:
5260 {
5261 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
5262 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency");
5263 OMX_VIDEO_PARAM_PROFILELEVELTYPE *pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
5264
5265 if ((output_capability != V4L2_PIX_FMT_H264) ||
5266 (output_capability != V4L2_PIX_FMT_HEVC)) {
5267 DEBUG_PRINT_ERROR("set_parameter: Unsupported codec for client configured profile and level");
5268 eRet = OMX_ErrorBadParameter;
5269 }
5270
5271 DEBUG_PRINT_LOW("set_parameter: Client set profile is: %d", pParam->eProfile);
5272 DEBUG_PRINT_LOW("set_parameter: Client set level is: %d", pParam->eLevel);
5273 mClientSessionForSufficiency = true;
5274 mClientSetProfile = pParam->eProfile;
5275 mClientSetLevel = pParam->eLevel;
5276 break;
5277 }
5278 case OMX_QTIIndexParamVideoDecoderOutputFrameRate:
5279 {
5280 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_OUTPUT_FRAME_RATE);
5281 DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoDecoderOutputFrameRate");
5282 QOMX_VIDEO_OUTPUT_FRAME_RATE *pParam = (QOMX_VIDEO_OUTPUT_FRAME_RATE*)paramData;
5283 DEBUG_PRINT_LOW("set_parameter: decoder output-frame-rate %d", pParam->fps);
5284 m_dec_hfr_fps=pParam->fps;
5285 DEBUG_PRINT_HIGH("output-frame-rate value = %d", m_dec_hfr_fps);
5286 if (m_dec_hfr_fps) {
5287 m_last_rendered_TS = 0;
5288 }
5289 break;
5290 }
5291 default: {
5292 DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
5293 eRet = OMX_ErrorUnsupportedIndex;
5294 }
5295 }
5296 if (eRet != OMX_ErrorNone)
5297 DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
5298 return eRet;
5299 }
5300
5301 /* ======================================================================
5302 FUNCTION
5303 omx_vdec::GetConfig
5304
5305 DESCRIPTION
5306 OMX Get Config Method implementation.
5307
5308 PARAMETERS
5309 <TBD>.
5310
5311 RETURN VALUE
5312 OMX Error None if successful.
5313
5314 ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)5315 OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp,
5316 OMX_IN OMX_INDEXTYPE configIndex,
5317 OMX_INOUT OMX_PTR configData)
5318 {
5319 (void) hComp;
5320 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5321
5322 if (m_state == OMX_StateInvalid) {
5323 DEBUG_PRINT_ERROR("Get Config in Invalid State");
5324 return OMX_ErrorInvalidState;
5325 }
5326
5327 switch ((unsigned long)configIndex) {
5328 case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
5329 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
5330 QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
5331 (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
5332 decoderinstances->nNumOfInstances = 16;
5333 /*TODO: How to handle this case */
5334 break;
5335 }
5336 case OMX_QcomIndexConfigVideoFramePackingArrangement: {
5337 if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
5338 VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
5339 OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
5340 (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
5341 memcpy(configFmt, &m_frame_pack_arrangement,
5342 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
5343 } else {
5344 DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
5345 }
5346 break;
5347 }
5348 case OMX_IndexConfigCommonOutputCrop: {
5349 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
5350 OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
5351 memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
5352 DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
5353 rectangle.nLeft, rectangle.nTop,
5354 rectangle.nWidth, rectangle.nHeight);
5355 break;
5356 }
5357 case OMX_QcomIndexConfigH264EntropyCodingCabac: {
5358 VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE);
5359 QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
5360 struct v4l2_control control;
5361
5362 if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
5363 DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
5364 eRet = OMX_ErrorNotImplemented;
5365 break;
5366 }
5367
5368 control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
5369 if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
5370 coding->bCabac = (OMX_BOOL)
5371 (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
5372 /* We can't query driver at the moment for the cabac mode, so
5373 * just use 0xff...f as a place holder for future improvement */
5374 coding->nCabacInitIdc = ~0;
5375 } else {
5376 eRet = OMX_ErrorUnsupportedIndex;
5377 }
5378
5379 break;
5380 }
5381 case OMX_QTIIndexConfigDescribeColorAspects:
5382 {
5383 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5384 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5385
5386 if (params->bRequestingDataSpace) {
5387 DEBUG_PRINT_LOW("Does not handle dataspace request. Please ignore this Unsupported Setting (0x80001019).");
5388 return OMX_ErrorUnsupportedSetting;
5389 }
5390
5391 print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client");
5392 print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal");
5393 get_preferred_color_aspects(params->sAspects);
5394 print_debug_color_aspects(&(params->sAspects), "Frameworks path GetConfig Color Aspects");
5395
5396 break;
5397 }
5398 case OMX_QTIIndexConfigDescribeHDRColorInfo:
5399 {
5400 VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5401 DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5402 print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "GetConfig Client HDR");
5403 print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "GetConfig Internal HDR");
5404 get_preferred_hdr_info(params->sInfo);
5405 print_debug_hdr_color_info(&(params->sInfo), "Frameworks path GetConfig HDR");
5406
5407 break;
5408 }
5409 case OMX_QTIIndexConfigDescribeHDR10PlusInfo:
5410 {
5411 VALIDATE_OMX_PARAM_DATA(configData, DescribeHDR10PlusInfoParams);
5412 DescribeHDR10PlusInfoParams *params = (DescribeHDR10PlusInfoParams *)configData;
5413 get_hdr10plusinfo(params);
5414 print_hdr10plusinfo(params);
5415 break;
5416 }
5417 case OMX_IndexConfigAndroidVendorExtension:
5418 {
5419 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5420
5421 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5422 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5423 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5424 return get_vendor_extension_config(ext);
5425 }
5426 default:
5427 {
5428 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
5429 eRet = OMX_ErrorBadParameter;
5430 }
5431
5432 }
5433
5434 return eRet;
5435 }
5436
5437 /* ======================================================================
5438 FUNCTION
5439 omx_vdec::SetConfig
5440
5441 DESCRIPTION
5442 OMX Set Config method implementation
5443
5444 PARAMETERS
5445 <TBD>.
5446
5447 RETURN VALUE
5448 OMX Error None if successful.
5449 ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)5450 OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp,
5451 OMX_IN OMX_INDEXTYPE configIndex,
5452 OMX_IN OMX_PTR configData)
5453 {
5454 (void) hComp;
5455 if (m_state == OMX_StateInvalid) {
5456 DEBUG_PRINT_ERROR("Get Config in Invalid State");
5457 return OMX_ErrorInvalidState;
5458 }
5459
5460 OMX_ERRORTYPE ret = OMX_ErrorNone;
5461 OMX_VIDEO_CONFIG_NALSIZE *pNal;
5462
5463 DEBUG_PRINT_LOW("Set Config Called");
5464
5465
5466 if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
5467 OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
5468 DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
5469
5470 if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5471 if (config->bEnabled) {
5472 if ((config->nFps >> 16) > 0 &&
5473 (config->nFps >> 16) <= MAX_SUPPORTED_FPS) {
5474 m_fps_received = config->nFps;
5475 DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
5476 (unsigned int)config->nFps >> 16);
5477 Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
5478 drv_ctx.frame_rate.fps_denominator);
5479
5480 if (!drv_ctx.frame_rate.fps_numerator) {
5481 DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
5482 drv_ctx.frame_rate.fps_numerator = 30;
5483 }
5484
5485 if (drv_ctx.frame_rate.fps_denominator) {
5486 drv_ctx.frame_rate.fps_numerator = (int)
5487 drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
5488 }
5489
5490 drv_ctx.frame_rate.fps_denominator = 1;
5491 frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
5492 drv_ctx.frame_rate.fps_numerator;
5493
5494 struct v4l2_outputparm oparm;
5495 /*XXX: we're providing timing info as seconds per frame rather than frames
5496 * per second.*/
5497 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
5498 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
5499
5500 struct v4l2_streamparm sparm;
5501 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5502 sparm.parm.output = oparm;
5503 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
5504 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
5505 performance might be affected");
5506 ret = OMX_ErrorHardware;
5507 }
5508 client_set_fps = true;
5509 } else {
5510 DEBUG_PRINT_ERROR("Frame rate not supported.");
5511 ret = OMX_ErrorUnsupportedSetting;
5512 }
5513 } else {
5514 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
5515 client_set_fps = false;
5516 }
5517 } else {
5518 DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
5519 (int)config->nPortIndex);
5520 ret = OMX_ErrorBadPortIndex;
5521 }
5522
5523 return ret;
5524 } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) {
5525 OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config =
5526 (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData;
5527 struct v4l2_control control;
5528 DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType);
5529 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE;
5530
5531 switch (config->eDecodeType) {
5532 case OMX_QCOM_PictypeDecode_I:
5533 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_I;
5534 break;
5535 case OMX_QCOM_PictypeDecode_IPB:
5536 default:
5537 control.value = (V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_I|
5538 V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_P|
5539 V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_B);
5540 break;
5541 }
5542
5543 ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5544 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5545 if (ret)
5546 DEBUG_PRINT_ERROR("Failed to set picture type decode");
5547
5548 return ret;
5549 } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
5550 OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
5551 DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
5552
5553 struct v4l2_control control;
5554
5555 control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
5556 if (priority->nU32 == 0)
5557 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
5558 else
5559 control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
5560
5561 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5562 DEBUG_PRINT_ERROR("Failed to set Priority");
5563 ret = OMX_ErrorUnsupportedSetting;
5564 }
5565 return ret;
5566 } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
5567 OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
5568 DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
5569
5570 struct v4l2_control control;
5571
5572 control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
5573 control.value = rate->nU32;
5574
5575 if (rate->nU32 == QOMX_VIDEO_HIGH_PERF_OPERATING_MODE) {
5576 DEBUG_PRINT_LOW("Turbo mode requested");
5577 m_client_req_turbo_mode = true;
5578 } else {
5579 operating_frame_rate = rate->nU32 >> 16;
5580 m_client_req_turbo_mode = false;
5581 DEBUG_PRINT_LOW("Operating Rate Set = %d fps", operating_frame_rate);
5582 }
5583
5584 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5585 ret = errno == EBUSY ? OMX_ErrorInsufficientResources :
5586 OMX_ErrorUnsupportedSetting;
5587 DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
5588 rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
5589 }
5590 return ret;
5591
5592 } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
5593 VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5594 DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5595 if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) {
5596 enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, false, true);
5597 }
5598
5599 print_debug_color_aspects(&(params->sAspects), "Set Config");
5600 memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
5601 return ret;
5602 } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeHDRColorInfo) {
5603 VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5604 DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5605 ret = enable_extradata(OMX_HDR_COLOR_INFO_EXTRADATA, false, true);
5606 if (ret != OMX_ErrorNone) {
5607 DEBUG_PRINT_ERROR("Failed to enable OMX_HDR_COLOR_INFO_EXTRADATA");
5608 return ret;
5609 }
5610
5611 print_debug_hdr_color_info(&(params->sInfo), "Set Config HDR");
5612 memcpy(&m_client_hdr_info, params, sizeof(DescribeHDRStaticInfoParams));
5613 return ret;
5614
5615 } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeHDR10PlusInfo) {
5616 VALIDATE_OMX_PARAM_DATA(configData, DescribeHDR10PlusInfoParams);
5617 if (!store_vp9_hdr10plusinfo((DescribeHDR10PlusInfoParams *)configData)) {
5618 DEBUG_PRINT_ERROR("Failed to set hdr10plus info");
5619 }
5620 return ret;
5621
5622 } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) {
5623 VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5624
5625 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5626 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5627 VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5628
5629 return set_vendor_extension_config(ext);
5630 } else if ((int)configIndex == (int)OMX_IndexConfigLowLatency) {
5631 OMX_CONFIG_BOOLEANTYPE *lowLatency = (OMX_CONFIG_BOOLEANTYPE *)configData;
5632 DEBUG_PRINT_LOW("Set_config: low-latency %u",(uint32_t)lowLatency->bEnabled);
5633 struct v4l2_control control;
5634 control.id = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE;
5635 if (lowLatency->bEnabled) {
5636 control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
5637 } else {
5638 control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
5639 }
5640 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5641 DEBUG_PRINT_ERROR("Set low latency failed");
5642 ret = OMX_ErrorUnsupportedSetting;
5643 } else {
5644 m_sParamLowLatency.bEnableLowLatencyMode = lowLatency->bEnabled;
5645 }
5646 return ret;
5647 }
5648
5649 return OMX_ErrorNotImplemented;
5650 }
5651
5652 #define extn_equals(param, extn) (!strcmp(param, extn))
5653
5654 /* ======================================================================
5655 FUNCTION
5656 omx_vdec::GetExtensionIndex
5657
5658 DESCRIPTION
5659 OMX GetExtensionIndex method implementaion. <TBD>
5660
5661 PARAMETERS
5662 <TBD>.
5663
5664 RETURN VALUE
5665 OMX Error None if everything successful.
5666
5667 ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)5668 OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
5669 OMX_IN OMX_STRING paramName,
5670 OMX_OUT OMX_INDEXTYPE* indexType)
5671 {
5672 (void) hComp;
5673 if (m_state == OMX_StateInvalid) {
5674 DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
5675 return OMX_ErrorInvalidState;
5676 } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
5677 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
5678 } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
5679 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
5680 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
5681 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
5682 } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
5683 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
5684 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
5685 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
5686 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
5687 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
5688 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
5689 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
5690 } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNOUTPUTCROP_EXTRADATA)) {
5691 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamOutputCropExtraData;
5692 }
5693 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
5694 else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
5695 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
5696 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
5697 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
5698 } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
5699 DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
5700 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
5701 } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
5702 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
5703 }
5704 #if ALLOCATE_OUTPUT_NATIVEHANDLE
5705 else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
5706 *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
5707 }
5708 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE
5709 #endif
5710 else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
5711 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
5712 }
5713 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5714 else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
5715 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
5716 } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
5717 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
5718 }
5719 #endif
5720 #ifdef FLEXYUV_SUPPORTED
5721 else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
5722 *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
5723 }
5724 #endif
5725 else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
5726 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
5727 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
5728 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
5729 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
5730 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
5731 } else if (extn_equals(paramName, "OMX.QTI.index.param.video.LowLatency")) {
5732 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode;
5733 } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) {
5734 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata;
5735 } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
5736 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
5737 } else if (extn_equals(paramName, "OMX.google.android.index.describeHDRStaticInfo")) {
5738 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDRColorInfo;
5739 } else if (extn_equals(paramName, "OMX.QTI.index.param.ClientConfiguredProfileLevel")) {
5740 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency;
5741 } else if (extn_equals(paramName, "OMX.google.android.index.describeHDR10PlusInfo")) {
5742 *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDR10PlusInfo;
5743 }else {
5744 DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
5745 return OMX_ErrorNotImplemented;
5746 }
5747 return OMX_ErrorNone;
5748 }
5749
5750 /* ======================================================================
5751 FUNCTION
5752 omx_vdec::GetState
5753
5754 DESCRIPTION
5755 Returns the state information back to the caller.<TBD>
5756
5757 PARAMETERS
5758 <TBD>.
5759
5760 RETURN VALUE
5761 Error None if everything is successful.
5762 ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)5763 OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp,
5764 OMX_OUT OMX_STATETYPE* state)
5765 {
5766 (void) hComp;
5767 *state = m_state;
5768 DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
5769 return OMX_ErrorNone;
5770 }
5771
5772 /* ======================================================================
5773 FUNCTION
5774 omx_vdec::ComponentTunnelRequest
5775
5776 DESCRIPTION
5777 OMX Component Tunnel Request method implementation. <TBD>
5778
5779 PARAMETERS
5780 None.
5781
5782 RETURN VALUE
5783 OMX Error None if everything successful.
5784
5785 ========================================================================== */
component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_HANDLETYPE peerComponent,OMX_IN OMX_U32 peerPort,OMX_INOUT OMX_TUNNELSETUPTYPE * tunnelSetup)5786 OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
5787 OMX_IN OMX_U32 port,
5788 OMX_IN OMX_HANDLETYPE peerComponent,
5789 OMX_IN OMX_U32 peerPort,
5790 OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
5791 {
5792 (void) hComp;
5793 (void) port;
5794 (void) peerComponent;
5795 (void) peerPort;
5796 (void) tunnelSetup;
5797 DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
5798 return OMX_ErrorNotImplemented;
5799 }
5800
5801
5802
5803 /* ======================================================================
5804 FUNCTION
5805 omx_vdec::ion_map
5806
5807 DESCRIPTION
5808 Map the memory and run the ioctl SYNC operations
5809 on ION fd with DMA_BUF_IOCTL_SYNC
5810
5811 PARAMETERS
5812 fd : ION fd
5813 len : Lenth of the memory
5814
5815 RETURN VALUE
5816 ERROR: mapped memory pointer
5817
5818 ========================================================================== */
ion_map(int fd,int len)5819 char *omx_vdec::ion_map(int fd, int len)
5820 {
5821 char *bufaddr = (char*)mmap(NULL, len, PROT_READ|PROT_WRITE,
5822 MAP_SHARED, fd, 0);
5823 if (bufaddr != MAP_FAILED) {
5824 #ifdef USE_ION
5825 do_cache_operations(fd);
5826 #endif
5827 }
5828 return bufaddr;
5829 }
5830
5831 /* ======================================================================
5832 FUNCTION
5833 omx_vdec::ion_unmap
5834
5835 DESCRIPTION
5836 Unmap the memory
5837
5838 PARAMETERS
5839 fd : ION fd
5840 bufaddr : buffer address
5841 len : Lenth of the memory
5842
5843 RETURN VALUE
5844 OMX_Error*
5845
5846 ========================================================================== */
ion_unmap(int fd,void * bufaddr,int len)5847 OMX_ERRORTYPE omx_vdec::ion_unmap(int fd, void *bufaddr, int len)
5848 {
5849 #ifdef USE_ION
5850 do_cache_operations(fd);
5851 #else
5852 (void)fd;
5853 #endif
5854 if (-1 == munmap(bufaddr, len)) {
5855 DEBUG_PRINT_ERROR("munmap failed.");
5856 return OMX_ErrorInsufficientResources;
5857 }
5858 return OMX_ErrorNone;
5859 }
5860
5861 /* ======================================================================
5862 FUNCTION
5863 omx_vdec::UseOutputBuffer
5864
5865 DESCRIPTION
5866 Helper function for Use buffer in the input pin
5867
5868 PARAMETERS
5869 None.
5870
5871 RETURN VALUE
5872 true/false
5873
5874 ========================================================================== */
allocate_extradata()5875 OMX_ERRORTYPE omx_vdec::allocate_extradata()
5876 {
5877 #ifdef USE_ION
5878 if (drv_ctx.extradata_info.buffer_size) {
5879 if (drv_ctx.extradata_info.ion.data_fd >= 0) {
5880 free_extradata();
5881 }
5882
5883 drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
5884 // Decoder extradata is always uncached as buffer sizes are very small
5885 bool status = alloc_map_ion_memory(
5886 drv_ctx.extradata_info.size, &drv_ctx.extradata_info.ion, 0);
5887 if (status == false) {
5888 DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
5889 return OMX_ErrorInsufficientResources;
5890 }
5891 DEBUG_PRINT_HIGH("Allocated extradata size : %d fd: %d",
5892 drv_ctx.extradata_info.size, drv_ctx.extradata_info.ion.data_fd);
5893 drv_ctx.extradata_info.uaddr = ion_map(drv_ctx.extradata_info.ion.data_fd,
5894 drv_ctx.extradata_info.size);
5895 if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
5896 DEBUG_PRINT_ERROR("Failed to map extradata memory");
5897 free_ion_memory(&drv_ctx.extradata_info.ion);
5898 return OMX_ErrorInsufficientResources;
5899 }
5900 }
5901 #endif
5902 return OMX_ErrorNone;
5903 }
5904
free_extradata()5905 void omx_vdec::free_extradata()
5906 {
5907 #ifdef USE_ION
5908 if (drv_ctx.extradata_info.uaddr) {
5909 ion_unmap(drv_ctx.extradata_info.ion.data_fd,
5910 (void *)drv_ctx.extradata_info.uaddr,
5911 drv_ctx.extradata_info.ion.alloc_data.len);
5912 free_ion_memory(&drv_ctx.extradata_info.ion);
5913 drv_ctx.extradata_info.uaddr = NULL;
5914 drv_ctx.extradata_info.ion.data_fd = -1;
5915 }
5916 #endif
5917 }
5918
use_output_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes,OMX_IN OMX_U8 * buffer)5919 OMX_ERRORTYPE omx_vdec::use_output_buffer(
5920 OMX_IN OMX_HANDLETYPE hComp,
5921 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5922 OMX_IN OMX_U32 port,
5923 OMX_IN OMX_PTR appData,
5924 OMX_IN OMX_U32 bytes,
5925 OMX_IN OMX_U8* buffer)
5926 {
5927 OMX_ERRORTYPE eRet = OMX_ErrorNone;
5928 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
5929 unsigned i= 0; // Temporary counter
5930 OMX_PTR privateAppData = NULL;
5931 private_handle_t *handle = NULL;
5932 OMX_U8 *buff = buffer;
5933 bool intermediate = client_buffers.is_color_conversion_enabled();
5934 (void) hComp;
5935 (void) port;
5936
5937 if (!m_out_mem_ptr) {
5938 DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers C2D(%d)",
5939 client_buffers.is_color_conversion_enabled());
5940 eRet = allocate_output_headers();
5941 if (eRet == OMX_ErrorNone)
5942 eRet = allocate_extradata();
5943 output_use_buffer = true;
5944 }
5945
5946 OMX_BUFFERHEADERTYPE **omx_base_address =
5947 intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
5948
5949 if (eRet == OMX_ErrorNone) {
5950 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
5951 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
5952 break;
5953 }
5954 }
5955 }
5956
5957 if (i >= drv_ctx.op_buf.actualcount) {
5958 DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
5959 return OMX_ErrorInsufficientResources;
5960 }
5961
5962 if (intermediate) {
5963 DEBUG_PRINT_HIGH("Use_op_buf:Allocating intermediate output. %d", i);
5964 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
5965 eRet = allocate_output_buffer(hComp, &temp_bufferHdr,
5966 port, appData,
5967 drv_ctx.op_buf.buffer_size,
5968 true, i);
5969 }
5970
5971 if (eRet == OMX_ErrorNone && dynamic_buf_mode) {
5972 *bufferHdr = (m_out_mem_ptr + i );
5973 (*bufferHdr)->pBuffer = NULL;
5974 if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
5975 enum v4l2_buf_type buf_type;
5976 int rr = 0;
5977 DEBUG_PRINT_LOW("USE intermediate bufferSTREAMON(CAPTURE_MPLANE)");
5978 set_buffer_req(&drv_ctx.op_buf);
5979 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5980 if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
5981 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
5982 return OMX_ErrorInsufficientResources;
5983 } else {
5984 streaming[CAPTURE_PORT] = true;
5985 DEBUG_PRINT_LOW("STREAMON Successful");
5986 }
5987 }
5988 BITMASK_SET(&m_out_bm_count,i);
5989 (*bufferHdr)->pAppPrivate = appData;
5990 (*bufferHdr)->pBuffer = buffer;
5991 (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
5992 return eRet;
5993 }
5994
5995 if (eRet == OMX_ErrorNone) {
5996 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
5997 if (m_enable_android_native_buffers) {
5998 if (m_use_android_native_buffers) {
5999 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
6000 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
6001 handle = (private_handle_t *)nBuf->handle;
6002 privateAppData = params->pAppPrivate;
6003 } else {
6004 handle = (private_handle_t *)buff;
6005 privateAppData = appData;
6006 }
6007 if (!handle) {
6008 DEBUG_PRINT_ERROR("handle is invalid");
6009 return OMX_ErrorBadParameter;
6010 }
6011
6012 if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
6013 if (secure_mode && secure_scaling_to_non_secure_opb) {
6014 DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
6015 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
6016 } else {
6017 DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
6018 " expected %u, got %u",
6019 (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
6020 return OMX_ErrorBadParameter;
6021 }
6022 }
6023
6024 drv_ctx.op_buf.buffer_size = handle->size;
6025
6026 if (!m_use_android_native_buffers) {
6027 if (!secure_mode) {
6028 buff = (OMX_U8*)ion_map(handle->fd, handle->size);
6029 if (buff == MAP_FAILED) {
6030 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
6031 return OMX_ErrorInsufficientResources;
6032 }
6033 }
6034 }
6035 #if defined(_ANDROID_ICS_)
6036 native_buffer[i].nativehandle = handle;
6037 native_buffer[i].privatehandle = handle;
6038 #endif
6039 if (!handle) {
6040 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
6041 return OMX_ErrorBadParameter;
6042 }
6043 drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
6044 drv_ctx.ptr_outputbuffer[i].offset = 0;
6045 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
6046 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
6047 drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
6048 } else
6049 #endif
6050 if (!ouput_egl_buffers && !m_use_output_pmem) {
6051 #ifdef USE_GBM
6052 bool status = alloc_map_gbm_memory(
6053 drv_ctx.video_resolution.frame_width,
6054 drv_ctx.video_resolution.frame_height,
6055 drv_ctx.gbm_device_fd,
6056 &drv_ctx.op_buf_gbm_info[i],
6057 secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
6058 if (status == false) {
6059 DEBUG_PRINT_ERROR("ION device fd is bad %d",
6060 (int) drv_ctx.op_buf_ion_info[i].data_fd);
6061 return OMX_ErrorInsufficientResources;
6062 }
6063 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
6064 drv_ctx.op_buf_gbm_info[i].bo_fd;
6065 if (intermediate)
6066 m_pmem_info[i].pmeta_fd = drv_ctx.op_buf_gbm_info[i].meta_fd;
6067 #elif defined USE_ION
6068 bool status = alloc_map_ion_memory(
6069 drv_ctx.op_buf.buffer_size, &drv_ctx.op_buf_ion_info[i],
6070 secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
6071 if (status == false) {
6072 DEBUG_PRINT_ERROR("ION device fd is bad %d",
6073 (int) drv_ctx.op_buf_ion_info[i].data_fd);
6074 return OMX_ErrorInsufficientResources;
6075 }
6076 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
6077 drv_ctx.op_buf_ion_info[i].data_fd;
6078 #endif
6079 if (!secure_mode) {
6080 drv_ctx.ptr_outputbuffer[i].bufferaddr =
6081 (unsigned char *)ion_map(drv_ctx.ptr_outputbuffer[i].pmem_fd,
6082 drv_ctx.op_buf.buffer_size);
6083 if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
6084 #ifdef USE_GBM
6085 free_gbm_memory(&drv_ctx.op_buf_gbm_info[i]);
6086 #elif defined USE_ION
6087 free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
6088 #endif
6089 DEBUG_PRINT_ERROR("Unable to mmap output buffer");
6090 return OMX_ErrorInsufficientResources;
6091 }
6092 }
6093 drv_ctx.ptr_outputbuffer[i].offset = 0;
6094 privateAppData = appData;
6095 } else {
6096 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
6097 if (!appData || !bytes ) {
6098 if (!secure_mode && !buffer) {
6099 DEBUG_PRINT_ERROR("Bad parameters for use buffer");
6100 return OMX_ErrorBadParameter;
6101 }
6102 }
6103
6104 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
6105 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
6106 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
6107 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
6108 !pmem_list->nEntries ||
6109 pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
6110 DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
6111 return OMX_ErrorBadParameter;
6112 }
6113 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6114 pmem_list->entryList->entry;
6115 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
6116 pmem_info->pmem_fd);
6117 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
6118 #ifdef USE_GBM
6119 if (intermediate)
6120 m_pmem_info[i].pmeta_fd = pmem_info->pmeta_fd;
6121 #endif
6122 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
6123 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
6124 drv_ctx.ptr_outputbuffer[i].mmaped_size =
6125 drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
6126 privateAppData = appData;
6127 }
6128 if (intermediate) {
6129 m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
6130 m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
6131 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
6132 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
6133 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
6134 }
6135 *bufferHdr = (m_out_mem_ptr + i );
6136
6137 if (secure_mode)
6138 drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
6139
6140 if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
6141 enum v4l2_buf_type buf_type;
6142 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6143 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
6144 return OMX_ErrorInsufficientResources;
6145 } else {
6146 streaming[CAPTURE_PORT] = true;
6147 DEBUG_PRINT_LOW("STREAMON Successful");
6148 }
6149 }
6150
6151 (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
6152 if (m_enable_android_native_buffers) {
6153 DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
6154 (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
6155 } else {
6156 (*bufferHdr)->pBuffer = buff;
6157 }
6158 (*bufferHdr)->pAppPrivate = privateAppData;
6159 BITMASK_SET(&m_out_bm_count,i);
6160 }
6161 return eRet;
6162 }
6163
allocate_client_output_extradata_headers()6164 OMX_ERRORTYPE omx_vdec::allocate_client_output_extradata_headers() {
6165 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6166 OMX_BUFFERHEADERTYPE *bufHdr = NULL;
6167 int i = 0;
6168
6169 if (!m_client_output_extradata_mem_ptr) {
6170 int nBufferCount = 0;
6171
6172 nBufferCount = m_client_out_extradata_info.getBufferCount();
6173 DEBUG_PRINT_HIGH("allocate_client_output_extradata_headers buffer_count - %d", nBufferCount);
6174
6175 m_client_output_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE));
6176
6177 if (m_client_output_extradata_mem_ptr) {
6178 bufHdr = m_client_output_extradata_mem_ptr;
6179 for (i=0; i < nBufferCount; i++) {
6180 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6181 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
6182 // Set the values when we determine the right HxW param
6183 bufHdr->nAllocLen = 0;
6184 bufHdr->nFilledLen = 0;
6185 bufHdr->pAppPrivate = NULL;
6186 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_EXTRADATA_INDEX;
6187 bufHdr->pBuffer = NULL;
6188 bufHdr->pOutputPortPrivate = NULL;
6189 bufHdr++;
6190 }
6191 } else {
6192 DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\
6193 m_client_output_extradata_mem_ptr);
6194 eRet = OMX_ErrorInsufficientResources;
6195 }
6196 }
6197 return eRet;
6198 }
use_client_output_extradata_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes,OMX_IN OMX_U8 * buffer)6199 OMX_ERRORTYPE omx_vdec::use_client_output_extradata_buffer(
6200 OMX_IN OMX_HANDLETYPE hComp,
6201 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6202 OMX_IN OMX_U32 port,
6203 OMX_IN OMX_PTR appData,
6204 OMX_IN OMX_U32 bytes,
6205 OMX_IN OMX_U8* buffer)
6206 {
6207 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6208 unsigned i = 0; // Temporary counter
6209 unsigned buffer_count = m_client_out_extradata_info.getBufferCount();;
6210 OMX_U32 buffer_size = m_client_out_extradata_info.getSize();
6211 (void) hComp;
6212
6213 if (port != OMX_CORE_OUTPUT_EXTRADATA_INDEX ||
6214 !client_extradata || bytes != buffer_size|| bufferHdr == NULL) {
6215 DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d,"
6216 "client_extradata - %d, bytes = %d expected is %d bufferHdr - %p", port,
6217 OMX_CORE_OUTPUT_EXTRADATA_INDEX, client_extradata, bytes, buffer_size, bufferHdr);
6218 eRet = OMX_ErrorBadParameter;
6219 return eRet;
6220 }
6221
6222 if (!m_client_output_extradata_mem_ptr) {
6223 eRet = allocate_client_output_extradata_headers();
6224 }
6225
6226 if (eRet == OMX_ErrorNone) {
6227 for (i = 0; i < buffer_count; i++) {
6228 if (BITMASK_ABSENT(&m_out_extradata_bm_count,i)) {
6229 break;
6230 }
6231 }
6232 }
6233
6234 if (i >= buffer_count) {
6235 DEBUG_PRINT_ERROR("Already using %d Extradata o/p buffers", buffer_count);
6236 eRet = OMX_ErrorInsufficientResources;
6237 }
6238
6239 if (eRet == OMX_ErrorNone) {
6240 BITMASK_SET(&m_out_extradata_bm_count,i);
6241 *bufferHdr = (m_client_output_extradata_mem_ptr + i );
6242 (*bufferHdr)->pAppPrivate = appData;
6243 (*bufferHdr)->pBuffer = buffer;
6244 (*bufferHdr)->nAllocLen = bytes;
6245 }
6246
6247 return eRet;
6248 }
6249 /* ======================================================================
6250 FUNCTION
6251 omx_vdec::use_input_heap_buffers
6252
6253 DESCRIPTION
6254 OMX Use Buffer Heap allocation method implementation.
6255
6256 PARAMETERS
6257 <TBD>.
6258
6259 RETURN VALUE
6260 OMX Error None , if everything successful.
6261
6262 ========================================================================== */
use_input_heap_buffers(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes,OMX_IN OMX_U8 * buffer)6263 OMX_ERRORTYPE omx_vdec::use_input_heap_buffers(
6264 OMX_IN OMX_HANDLETYPE hComp,
6265 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6266 OMX_IN OMX_U32 port,
6267 OMX_IN OMX_PTR appData,
6268 OMX_IN OMX_U32 bytes,
6269 OMX_IN OMX_U8* buffer)
6270 {
6271 DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
6272 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6273
6274 if (secure_mode) {
6275 DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode");
6276 return OMX_ErrorUndefined;
6277 }
6278
6279 if (!m_inp_heap_ptr)
6280 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
6281 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6282 drv_ctx.ip_buf.actualcount);
6283 if (!m_phdr_pmem_ptr)
6284 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
6285 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6286 drv_ctx.ip_buf.actualcount);
6287 if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
6288 DEBUG_PRINT_ERROR("Insufficent memory");
6289 eRet = OMX_ErrorInsufficientResources;
6290 } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
6291 input_use_buffer = true;
6292 memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
6293 m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
6294 m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
6295 m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
6296 m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
6297 m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
6298 *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
6299 eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
6300 DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
6301 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
6302 (unsigned)NULL, (unsigned)NULL)) {
6303 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6304 return OMX_ErrorInsufficientResources;
6305 }
6306 m_in_alloc_cnt++;
6307 } else {
6308 DEBUG_PRINT_ERROR("All i/p buffers have been set!");
6309 eRet = OMX_ErrorInsufficientResources;
6310 }
6311 return eRet;
6312 }
6313
6314 /* ======================================================================
6315 FUNCTION
6316 omx_vdec::UseBuffer
6317
6318 DESCRIPTION
6319 OMX Use Buffer method implementation.
6320
6321 PARAMETERS
6322 <TBD>.
6323
6324 RETURN VALUE
6325 OMX Error None , if everything successful.
6326
6327 ========================================================================== */
use_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes,OMX_IN OMX_U8 * buffer)6328 OMX_ERRORTYPE omx_vdec::use_buffer(
6329 OMX_IN OMX_HANDLETYPE hComp,
6330 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6331 OMX_IN OMX_U32 port,
6332 OMX_IN OMX_PTR appData,
6333 OMX_IN OMX_U32 bytes,
6334 OMX_IN OMX_U8* buffer)
6335 {
6336 OMX_ERRORTYPE error = OMX_ErrorNone;
6337
6338 if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
6339 DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
6340 return OMX_ErrorBadParameter;
6341 }
6342 if (m_state == OMX_StateInvalid) {
6343 DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
6344 return OMX_ErrorInvalidState;
6345 }
6346 if (port == OMX_CORE_INPUT_PORT_INDEX) {
6347 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
6348 // ensure that use-buffer was called for previous allocation.
6349 // Mix-and-match of useBuffer and allocateBuffer is not allowed
6350 if (m_inp_mem_ptr && !input_use_buffer) {
6351 DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !");
6352 return OMX_ErrorUndefined;
6353 }
6354 error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
6355 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6356 error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
6357 } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
6358 error = use_client_output_extradata_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
6359 } else {
6360 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
6361 error = OMX_ErrorBadPortIndex;
6362 }
6363 DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
6364 if (error == OMX_ErrorNone) {
6365 if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
6366 // Send the callback now
6367 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
6368 post_event(OMX_CommandStateSet,OMX_StateIdle,
6369 OMX_COMPONENT_GENERATE_EVENT);
6370 }
6371 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
6372 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
6373 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
6374 post_event(OMX_CommandPortEnable,
6375 OMX_CORE_INPUT_PORT_INDEX,
6376 OMX_COMPONENT_GENERATE_EVENT);
6377 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
6378 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
6379 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
6380 post_event(OMX_CommandPortEnable,
6381 OMX_CORE_OUTPUT_PORT_INDEX,
6382 OMX_COMPONENT_GENERATE_EVENT);
6383 }
6384 }
6385 return error;
6386 }
6387
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)6388 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
6389 OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
6390 {
6391 if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
6392 if (m_inp_heap_ptr[bufferindex].pBuffer)
6393 free(m_inp_heap_ptr[bufferindex].pBuffer);
6394 m_inp_heap_ptr[bufferindex].pBuffer = NULL;
6395 }
6396 if (pmem_bufferHdr)
6397 free_input_buffer(pmem_bufferHdr);
6398 return OMX_ErrorNone;
6399 }
6400
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)6401 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6402 {
6403 unsigned int index = 0;
6404 if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
6405 return OMX_ErrorBadParameter;
6406 }
6407 print_omx_buffer("free_input_buffer", bufferHdr);
6408
6409 index = bufferHdr - m_inp_mem_ptr;
6410 DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
6411
6412 bufferHdr->pInputPortPrivate = NULL;
6413
6414 if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
6415 if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
6416 if (!secure_mode) {
6417 ion_unmap(drv_ctx.ptr_inputbuffer[index].pmem_fd,
6418 drv_ctx.ptr_inputbuffer[index].bufferaddr,
6419 drv_ctx.ptr_inputbuffer[index].mmaped_size);
6420 }
6421
6422 if (allocate_native_handle){
6423 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
6424 native_handle_close(nh);
6425 native_handle_delete(nh);
6426 } else {
6427 #ifndef USE_ION
6428 // Close fd for non-secure and secure non-native-handle case
6429 close(drv_ctx.ptr_inputbuffer[index].pmem_fd);
6430 #endif
6431 }
6432 drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
6433
6434 if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
6435 free(m_desc_buffer_ptr[index].buf_addr);
6436 m_desc_buffer_ptr[index].buf_addr = NULL;
6437 m_desc_buffer_ptr[index].desc_data_size = 0;
6438 }
6439 #ifdef USE_ION
6440 free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
6441 #endif
6442 m_in_alloc_cnt--;
6443 } else {
6444 DEBUG_PRINT_ERROR("Invalid input buffer fd %d", drv_ctx.ptr_inputbuffer[index].pmem_fd);
6445 }
6446 } else {
6447 DEBUG_PRINT_ERROR("Invalid input buffer index %d, drv_ctx.ptr_inputbuffer %p",
6448 index, drv_ctx.ptr_inputbuffer);
6449 }
6450
6451 return OMX_ErrorNone;
6452 }
6453
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr,bool intermediate)6454 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr,
6455 bool intermediate)
6456 {
6457 unsigned int index = 0;
6458
6459 OMX_BUFFERHEADERTYPE *omx_base_address =
6460 intermediate?m_intermediate_out_mem_ptr:m_out_mem_ptr;
6461 vdec_bufferpayload *omx_ptr_outputbuffer =
6462 intermediate?drv_ctx.ptr_intermediate_outputbuffer:drv_ctx.ptr_outputbuffer;
6463 vdec_ion *omx_op_buf_ion_info =
6464 intermediate?drv_ctx.op_intermediate_buf_ion_info:drv_ctx.op_buf_ion_info;
6465 #ifdef USE_GBM
6466 vdec_gbm *omx_op_buf_gbm_info =
6467 intermediate?drv_ctx.op_intermediate_buf_gbm_info:drv_ctx.op_buf_gbm_info;
6468 #endif
6469 if (bufferHdr == NULL || omx_base_address == NULL) {
6470 return OMX_ErrorBadParameter;
6471 }
6472 print_omx_buffer("free_output_buffer", bufferHdr);
6473
6474 index = bufferHdr - omx_base_address;
6475
6476 if (index < drv_ctx.op_buf.actualcount
6477 && omx_ptr_outputbuffer) {
6478 DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
6479 omx_ptr_outputbuffer[index].bufferaddr);
6480
6481 if (!dynamic_buf_mode) {
6482 if (streaming[CAPTURE_PORT] &&
6483 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
6484 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
6485 DEBUG_PRINT_ERROR("STREAMOFF(CAPTURE_MPLANE) Failed");
6486 } else {
6487 DEBUG_PRINT_LOW("STREAMOFF(CAPTURE_MPLANE) Successful");
6488 }
6489 }
6490 #ifdef _ANDROID_
6491 if (m_enable_android_native_buffers) {
6492 if (!secure_mode) {
6493 if (omx_ptr_outputbuffer[index].pmem_fd > 0) {
6494 ion_unmap(omx_ptr_outputbuffer[index].pmem_fd,
6495 omx_ptr_outputbuffer[index].bufferaddr,
6496 omx_ptr_outputbuffer[index].mmaped_size);
6497 }
6498 }
6499 } else {
6500 #endif
6501 if (omx_ptr_outputbuffer[index].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
6502 if (!secure_mode) {
6503 ion_unmap(omx_ptr_outputbuffer[index].pmem_fd,
6504 omx_ptr_outputbuffer[index].bufferaddr,
6505 omx_ptr_outputbuffer[index].mmaped_size);
6506 omx_ptr_outputbuffer[index].bufferaddr = NULL;
6507 omx_ptr_outputbuffer[index].mmaped_size = 0;
6508 }
6509 #ifdef USE_GBM
6510 free_gbm_memory(&omx_op_buf_gbm_info[index]);
6511 #elif defined USE_ION
6512 free_ion_memory(&omx_op_buf_ion_info[index]);
6513 #endif
6514
6515 omx_ptr_outputbuffer[index].pmem_fd = -1;
6516 }
6517 #ifdef _ANDROID_
6518 }
6519 #endif
6520 } //!dynamic_buf_mode
6521 if (intermediate == false) {
6522 OMX_BUFFERHEADERTYPE *tempBufHdr = m_intermediate_out_mem_ptr + index;
6523 if (client_buffers.is_color_conversion_enabled() &&
6524 free_output_buffer(tempBufHdr, true) != OMX_ErrorNone) {
6525 return OMX_ErrorBadParameter;
6526 }
6527
6528 if (release_output_done()) {
6529 DEBUG_PRINT_HIGH("All output buffers released, free extradata");
6530 free_extradata();
6531 }
6532 }
6533 }
6534
6535 return OMX_ErrorNone;
6536 }
6537
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)6538 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp,
6539 OMX_BUFFERHEADERTYPE **bufferHdr,
6540 OMX_U32 port,
6541 OMX_PTR appData,
6542 OMX_U32 bytes)
6543 {
6544 OMX_BUFFERHEADERTYPE *input = NULL;
6545 unsigned char *buf_addr = NULL;
6546 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6547 unsigned i = 0;
6548
6549 /* Sanity Check*/
6550 if (bufferHdr == NULL) {
6551 return OMX_ErrorBadParameter;
6552 }
6553
6554 if (m_inp_heap_ptr == NULL) {
6555 m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
6556 calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6557 drv_ctx.ip_buf.actualcount);
6558 m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
6559 calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6560 drv_ctx.ip_buf.actualcount);
6561
6562 if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) {
6563 DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed ");
6564 return OMX_ErrorInsufficientResources;
6565 }
6566 }
6567
6568 /*Find a Free index*/
6569 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6570 if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
6571 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6572 break;
6573 }
6574 }
6575
6576 if (i < drv_ctx.ip_buf.actualcount) {
6577 buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
6578
6579 if (buf_addr == NULL) {
6580 return OMX_ErrorInsufficientResources;
6581 }
6582
6583 *bufferHdr = (m_inp_heap_ptr + i);
6584 input = *bufferHdr;
6585 BITMASK_SET(&m_heap_inp_bm_count,i);
6586
6587 input->pBuffer = (OMX_U8 *)buf_addr;
6588 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6589 input->nVersion.nVersion = OMX_SPEC_VERSION;
6590 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
6591 input->pAppPrivate = appData;
6592 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
6593 DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
6594 eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
6595 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
6596 /*Add the Buffers to freeq*/
6597 if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i],
6598 (unsigned)NULL, (unsigned)NULL)) {
6599 DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6600 return OMX_ErrorInsufficientResources;
6601 }
6602 } else {
6603 return OMX_ErrorBadParameter;
6604 }
6605
6606 return eRet;
6607 }
6608
6609
6610 /* ======================================================================
6611 FUNCTION
6612 omx_vdec::AllocateInputBuffer
6613
6614 DESCRIPTION
6615 Helper function for allocate buffer in the input pin
6616
6617 PARAMETERS
6618 None.
6619
6620 RETURN VALUE
6621 true/false
6622
6623 ========================================================================== */
allocate_input_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes)6624 OMX_ERRORTYPE omx_vdec::allocate_input_buffer(
6625 OMX_IN OMX_HANDLETYPE hComp,
6626 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6627 OMX_IN OMX_U32 port,
6628 OMX_IN OMX_PTR appData,
6629 OMX_IN OMX_U32 bytes)
6630 {
6631 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6632 OMX_BUFFERHEADERTYPE *input = NULL;
6633 unsigned i = 0;
6634 unsigned char *buf_addr = NULL;
6635 int pmem_fd = -1, ret = 0;
6636 unsigned int align_size = 0;
6637
6638 (void) hComp;
6639 (void) port;
6640
6641
6642 if (bytes != drv_ctx.ip_buf.buffer_size) {
6643 DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
6644 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
6645 return OMX_ErrorBadParameter;
6646 }
6647
6648 if (!m_inp_mem_ptr) {
6649 /* Currently buffer reqs is being set only in set port defn */
6650 /* Client need not do set port definition if he sees enough buffers in get port defn */
6651 /* In such cases we need to do a set buffer reqs to driver. Doing it here */
6652 struct v4l2_requestbuffers bufreq;
6653
6654 DEBUG_PRINT_HIGH("Calling REQBUFS in %s ",__FUNCTION__);
6655 bufreq.memory = V4L2_MEMORY_USERPTR;
6656 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6657 bufreq.count = drv_ctx.ip_buf.actualcount;
6658 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
6659 if (ret) {
6660 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
6661 /*TODO: How to handle this case */
6662 eRet = OMX_ErrorInsufficientResources;
6663 } else if (bufreq.count != drv_ctx.ip_buf.actualcount) {
6664 DEBUG_PRINT_ERROR("%s Count(%d) is not expected to change to %d",
6665 __FUNCTION__, drv_ctx.ip_buf.actualcount, bufreq.count);
6666 eRet = OMX_ErrorInsufficientResources;
6667 }
6668
6669 DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
6670 drv_ctx.ip_buf.actualcount,
6671 (unsigned int)drv_ctx.ip_buf.buffer_size);
6672
6673 m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
6674 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
6675
6676 if (m_inp_mem_ptr == NULL) {
6677 return OMX_ErrorInsufficientResources;
6678 }
6679
6680 drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
6681 calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
6682
6683 if (drv_ctx.ptr_inputbuffer == NULL) {
6684 return OMX_ErrorInsufficientResources;
6685 }
6686 #ifdef USE_ION
6687 drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
6688 calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
6689
6690 if (drv_ctx.ip_buf_ion_info == NULL) {
6691 return OMX_ErrorInsufficientResources;
6692 }
6693 #endif
6694
6695 for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
6696 drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
6697 #ifdef USE_ION
6698 drv_ctx.ip_buf_ion_info[i].data_fd = -1;
6699 drv_ctx.ip_buf_ion_info[i].dev_fd = -1;
6700 #endif
6701 }
6702 }
6703
6704 for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6705 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
6706 DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6707 break;
6708 }
6709 }
6710
6711 if (i < drv_ctx.ip_buf.actualcount) {
6712 int rc;
6713 DEBUG_PRINT_LOW("Allocate input Buffer");
6714 #ifdef USE_ION
6715 align_size = drv_ctx.ip_buf.buffer_size + 512;
6716 align_size = (align_size + drv_ctx.ip_buf.alignment - 1)&(~(drv_ctx.ip_buf.alignment - 1));
6717 // Input buffers are cached to make parsing faster
6718 bool status = alloc_map_ion_memory(
6719 align_size, &drv_ctx.ip_buf_ion_info[i],
6720 secure_mode ? SECURE_FLAGS_INPUT_BUFFER : ION_FLAG_CACHED);
6721 if (status == false) {
6722 return OMX_ErrorInsufficientResources;
6723 }
6724 pmem_fd = drv_ctx.ip_buf_ion_info[i].data_fd;
6725 #endif
6726 if (!secure_mode) {
6727 buf_addr = (unsigned char *)ion_map(pmem_fd, drv_ctx.ip_buf.buffer_size);
6728 if (buf_addr == MAP_FAILED) {
6729 #ifdef USE_ION
6730 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
6731 #endif
6732 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
6733 return OMX_ErrorInsufficientResources;
6734 }
6735 }
6736 *bufferHdr = (m_inp_mem_ptr + i);
6737 if (secure_mode)
6738 drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
6739 else
6740 drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
6741 drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
6742 drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
6743 drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
6744 drv_ctx.ptr_inputbuffer [i].offset = 0;
6745
6746 input = *bufferHdr;
6747 BITMASK_SET(&m_inp_bm_count,i);
6748 if (allocate_native_handle) {
6749 native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
6750 if (!nh) {
6751 DEBUG_PRINT_ERROR("Native handle create failed");
6752 return OMX_ErrorInsufficientResources;
6753 }
6754 nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
6755 input->pBuffer = (OMX_U8 *)nh;
6756 } else if (secure_mode || m_input_pass_buffer_fd) {
6757 /*Legacy method, pass ion fd stashed directly in pBuffer*/
6758 input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
6759 } else {
6760 input->pBuffer = (OMX_U8 *)buf_addr;
6761 }
6762 input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6763 input->nVersion.nVersion = OMX_SPEC_VERSION;
6764 input->nAllocLen = drv_ctx.ip_buf.buffer_size;
6765 input->pAppPrivate = appData;
6766 input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
6767 input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
6768
6769 if (drv_ctx.disable_dmx) {
6770 eRet = allocate_desc_buffer(i);
6771 }
6772 } else {
6773 DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
6774 eRet = OMX_ErrorInsufficientResources;
6775 }
6776
6777 if (eRet == OMX_ErrorNone)
6778 DEBUG_PRINT_HIGH("Allocate_input_buffer(%d): Header %p buffer %p allocLen %d offset %d fd = %d",
6779 i, input, input->pBuffer, input->nAllocLen,
6780 input->nOffset, drv_ctx.ptr_inputbuffer[i].pmem_fd);
6781
6782 return eRet;
6783 }
6784
6785
6786 /* ======================================================================
6787 FUNCTION
6788 omx_vdec::AllocateOutputBuffer
6789
6790 DESCRIPTION
6791 Helper fn for AllocateBuffer in the output pin
6792
6793 PARAMETERS
6794 <TBD>.
6795
6796 RETURN VALUE
6797 OMX Error None if everything went well.
6798
6799 ========================================================================== */
allocate_output_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes,OMX_IN bool intermediate,OMX_IN int index)6800 OMX_ERRORTYPE omx_vdec::allocate_output_buffer(
6801 OMX_IN OMX_HANDLETYPE hComp,
6802 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6803 OMX_IN OMX_U32 port,
6804 OMX_IN OMX_PTR appData,
6805 OMX_IN OMX_U32 bytes,
6806 OMX_IN bool intermediate,
6807 OMX_IN int index)
6808 {
6809 (void)hComp;
6810 (void)port;
6811
6812 OMX_ERRORTYPE eRet = OMX_ErrorNone;
6813 OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
6814 unsigned i= 0; // Temporary counter
6815 #ifdef USE_ION
6816 struct ion_allocation_data ion_alloc_data;
6817 #endif
6818 OMX_BUFFERHEADERTYPE **omx_base_address =
6819 intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
6820
6821 vdec_bufferpayload **omx_ptr_outputbuffer =
6822 intermediate?&drv_ctx.ptr_intermediate_outputbuffer:&drv_ctx.ptr_outputbuffer;
6823 vdec_output_frameinfo **omx_ptr_respbuffer =
6824 intermediate?&drv_ctx.ptr_intermediate_respbuffer:&drv_ctx.ptr_respbuffer;
6825 vdec_ion **omx_op_buf_ion_info =
6826 intermediate?&drv_ctx.op_intermediate_buf_ion_info:&drv_ctx.op_buf_ion_info;
6827 #ifdef USE_GBM
6828 vdec_gbm **omx_op_buf_gbm_info =
6829 intermediate?&drv_ctx.op_intermediate_buf_gbm_info:&drv_ctx.op_buf_gbm_info;
6830 #endif
6831
6832 if (!*omx_base_address) {
6833 DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
6834 drv_ctx.op_buf.actualcount,
6835 (unsigned int)drv_ctx.op_buf.buffer_size);
6836 int nBufHdrSize = 0;
6837 int nPlatformEntrySize = 0;
6838 int nPlatformListSize = 0;
6839 int nPMEMInfoSize = 0;
6840
6841 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
6842 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
6843 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
6844
6845 nBufHdrSize = drv_ctx.op_buf.actualcount *
6846 sizeof(OMX_BUFFERHEADERTYPE);
6847 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
6848 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
6849 nPlatformListSize = drv_ctx.op_buf.actualcount *
6850 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
6851 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
6852 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
6853
6854 *omx_base_address = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
6855 // Alloc mem for platform specific info
6856 char *pPtr=NULL;
6857 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
6858 nPMEMInfoSize,1);
6859 *omx_ptr_outputbuffer = (struct vdec_bufferpayload *) \
6860 calloc (sizeof(struct vdec_bufferpayload),
6861 drv_ctx.op_buf.actualcount);
6862 *omx_ptr_respbuffer = (struct vdec_output_frameinfo *)\
6863 calloc (sizeof (struct vdec_output_frameinfo),
6864 drv_ctx.op_buf.actualcount);
6865 if (!*omx_ptr_outputbuffer || !*omx_ptr_respbuffer) {
6866 DEBUG_PRINT_ERROR("Failed to alloc outputbuffer or respbuffer ");
6867 free(pPtr);
6868 return OMX_ErrorInsufficientResources;
6869 }
6870
6871 #ifdef USE_GBM
6872 *omx_op_buf_gbm_info = (struct vdec_gbm *)\
6873 calloc (sizeof(struct vdec_gbm),
6874 drv_ctx.op_buf.actualcount);
6875 if (!*omx_op_buf_gbm_info) {
6876 DEBUG_PRINT_ERROR("Failed to alloc op_buf_gbm_info");
6877 return OMX_ErrorInsufficientResources;
6878 }
6879 drv_ctx.gbm_device_fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC);
6880 if (drv_ctx.gbm_device_fd < 0) {
6881 DEBUG_PRINT_ERROR("opening dri device for gbm failed with fd = %d", drv_ctx.gbm_device_fd);
6882 return OMX_ErrorInsufficientResources;
6883 }
6884 #elif defined USE_ION
6885 *omx_op_buf_ion_info = (struct vdec_ion *)\
6886 calloc (sizeof(struct vdec_ion),
6887 drv_ctx.op_buf.actualcount);
6888 if (!*omx_op_buf_ion_info) {
6889 DEBUG_PRINT_ERROR("Failed to alloc op_buf_ion_info");
6890 return OMX_ErrorInsufficientResources;
6891 }
6892 #endif
6893
6894 if (*omx_base_address && pPtr && *omx_ptr_outputbuffer
6895 && *omx_ptr_respbuffer) {
6896 bufHdr = *omx_base_address;
6897 if (m_platform_list) {
6898 free(m_platform_list);
6899 }
6900 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
6901 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
6902 (((char *) m_platform_list) + nPlatformListSize);
6903 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6904 (((char *) m_platform_entry) + nPlatformEntrySize);
6905 pPlatformList = m_platform_list;
6906 pPlatformEntry = m_platform_entry;
6907 pPMEMInfo = m_pmem_info;
6908
6909 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p", *omx_base_address);
6910
6911 // Settting the entire storage nicely
6912 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
6913 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
6914 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
6915 // Set the values when we determine the right HxW param
6916 bufHdr->nAllocLen = bytes;
6917 bufHdr->nFilledLen = 0;
6918 bufHdr->pAppPrivate = appData;
6919 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
6920 // Platform specific PMEM Information
6921 // Initialize the Platform Entry
6922 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
6923 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
6924 pPlatformEntry->entry = pPMEMInfo;
6925 // Initialize the Platform List
6926 pPlatformList->nEntries = 1;
6927 pPlatformList->entryList = pPlatformEntry;
6928 // Keep pBuffer NULL till vdec is opened
6929 bufHdr->pBuffer = NULL;
6930 bufHdr->nOffset = 0;
6931 pPMEMInfo->offset = 0;
6932 pPMEMInfo->pmem_fd = -1;
6933 bufHdr->pPlatformPrivate = pPlatformList;
6934 /*Create a mapping between buffers*/
6935 bufHdr->pOutputPortPrivate = &(*omx_ptr_respbuffer)[i];
6936 (*omx_ptr_respbuffer)[i].client_data = (void *) \
6937 &(*omx_ptr_outputbuffer)[i];
6938 // Move the buffer and buffer header pointers
6939 bufHdr++;
6940 pPMEMInfo++;
6941 pPlatformEntry++;
6942 pPlatformList++;
6943 }
6944 } else {
6945 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
6946 *omx_base_address, pPtr);
6947 if (*omx_base_address) {
6948 free(*omx_base_address);
6949 *omx_base_address = NULL;
6950 }
6951 if (pPtr) {
6952 free(pPtr);
6953 pPtr = NULL;
6954 }
6955 if (*omx_ptr_outputbuffer) {
6956 free(*omx_ptr_outputbuffer);
6957 *omx_ptr_outputbuffer = NULL;
6958 }
6959 if (*omx_ptr_respbuffer) {
6960 free(*omx_ptr_respbuffer);
6961 *omx_ptr_respbuffer = NULL;
6962 }
6963 #ifdef USE_GBM
6964 if(drv_ctx.gbm_device_fd >= 0) {
6965 DEBUG_PRINT_LOW("Close gbm device");
6966 close(drv_ctx.gbm_device_fd);
6967 drv_ctx.gbm_device_fd = -1;
6968 }
6969 if (*omx_op_buf_gbm_info) {
6970 DEBUG_PRINT_LOW("Free o/p gbm context");
6971 free(*omx_op_buf_gbm_info);
6972 *omx_op_buf_gbm_info = NULL;
6973 }
6974 #elif defined USE_ION
6975 if (*omx_op_buf_ion_info) {
6976 DEBUG_PRINT_LOW("Free o/p ion context");
6977 free(*omx_op_buf_ion_info);
6978 *omx_op_buf_ion_info = NULL;
6979 }
6980 #endif
6981 eRet = OMX_ErrorInsufficientResources;
6982 }
6983 if (eRet == OMX_ErrorNone)
6984 eRet = allocate_extradata();
6985 }
6986
6987 if (intermediate == true && index != -1) {
6988 i = index;
6989 } else {
6990 for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
6991 if (BITMASK_ABSENT(&m_out_bm_count,i)) {
6992 break;
6993 }
6994 }
6995 }
6996
6997 if (eRet == OMX_ErrorNone) {
6998 if (i < drv_ctx.op_buf.actualcount) {
6999 int rc;
7000 int pmem_fd = -1;
7001 int fd = -1;
7002 unsigned char *pmem_baseaddress = NULL;
7003 #ifdef USE_GBM
7004 int pmeta_fd = -1;
7005 // Allocate output buffers as cached to improve performance of software-reading
7006 // of the YUVs. Output buffers are cache-invalidated in driver.
7007 // If color-conversion is involved, Only the C2D output buffers are cached, no
7008 // need to cache the decoder's output buffers
7009 int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
7010 bool status = alloc_map_gbm_memory(
7011 drv_ctx.video_resolution.frame_width,
7012 drv_ctx.video_resolution.frame_height,
7013 drv_ctx.gbm_device_fd,
7014 &(*omx_op_buf_gbm_info)[i],
7015 (secure_mode && !secure_scaling_to_non_secure_opb) ?
7016 SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
7017 if (status == false) {
7018 return OMX_ErrorInsufficientResources;
7019 }
7020 pmem_fd = (*omx_op_buf_gbm_info)[i].bo_fd;
7021 pmeta_fd = (*omx_op_buf_gbm_info)[i].meta_fd;
7022 #elif defined USE_ION
7023 // Allocate output buffers as cached to improve performance of software-reading
7024 // of the YUVs. Output buffers are cache-invalidated in driver.
7025 // If color-conversion is involved, Only the C2D output buffers are cached, no
7026 // need to cache the decoder's output buffers
7027 int cache_flag = ION_FLAG_CACHED;
7028 if (intermediate == true && client_buffers.is_color_conversion_enabled()) {
7029 cache_flag = 0;
7030 }
7031 bool status = alloc_map_ion_memory(drv_ctx.op_buf.buffer_size,
7032 &(*omx_op_buf_ion_info)[i],
7033 (secure_mode && !secure_scaling_to_non_secure_opb) ?
7034 SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
7035 if (status == false) {
7036 return OMX_ErrorInsufficientResources;
7037 }
7038 pmem_fd = (*omx_op_buf_ion_info)[i].data_fd;
7039 #endif
7040 if (!secure_mode) {
7041 pmem_baseaddress = (unsigned char *)ion_map(pmem_fd, drv_ctx.op_buf.buffer_size);
7042 if (pmem_baseaddress == MAP_FAILED) {
7043 DEBUG_PRINT_ERROR("MMAP failed for Size %u",
7044 (unsigned int)drv_ctx.op_buf.buffer_size);
7045 #ifdef USE_GBM
7046 free_gbm_memory(&(*omx_op_buf_gbm_info)[i]);
7047 #elif defined USE_ION
7048 free_ion_memory(&(*omx_op_buf_ion_info)[i]);
7049 #endif
7050 return OMX_ErrorInsufficientResources;
7051 }
7052 }
7053 (*omx_ptr_outputbuffer)[i].pmem_fd = pmem_fd;
7054 #ifdef USE_GBM
7055 m_pmem_info[i].pmeta_fd = pmeta_fd;
7056 #endif
7057 (*omx_ptr_outputbuffer)[i].offset = 0;
7058 (*omx_ptr_outputbuffer)[i].bufferaddr = pmem_baseaddress;
7059 (*omx_ptr_outputbuffer)[i].mmaped_size = drv_ctx.op_buf.buffer_size;
7060 (*omx_ptr_outputbuffer)[i].buffer_len = drv_ctx.op_buf.buffer_size;
7061 m_pmem_info[i].pmem_fd = pmem_fd;
7062 m_pmem_info[i].size = (*omx_ptr_outputbuffer)[i].buffer_len;
7063 m_pmem_info[i].mapped_size = (*omx_ptr_outputbuffer)[i].mmaped_size;
7064 m_pmem_info[i].buffer = (*omx_ptr_outputbuffer)[i].bufferaddr;
7065 m_pmem_info[i].offset = (*omx_ptr_outputbuffer)[i].offset;
7066
7067 *bufferHdr = (*omx_base_address + i );
7068 if (secure_mode) {
7069 #ifdef USE_GBM
7070 (*omx_ptr_outputbuffer)[i].bufferaddr =
7071 (OMX_U8 *)(intptr_t)(*omx_op_buf_gbm_info)[i].bo_fd;
7072 #elif defined USE_ION
7073 (*omx_ptr_outputbuffer)[i].bufferaddr =
7074 (OMX_U8 *)(intptr_t)(*omx_op_buf_ion_info)[i].data_fd;
7075 #endif
7076 }
7077 if (intermediate == false &&
7078 client_buffers.is_color_conversion_enabled()) {
7079 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
7080 eRet = allocate_output_buffer(hComp, &temp_bufferHdr,
7081 port, appData,
7082 drv_ctx.op_buf.buffer_size,
7083 true, i);
7084 }
7085 if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
7086 enum v4l2_buf_type buf_type;
7087
7088 set_buffer_req(&drv_ctx.op_buf);
7089 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7090 if (!client_buffers.is_color_conversion_enabled() ||
7091 (client_buffers.is_color_conversion_enabled() && intermediate == true)) {
7092 rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7093 if (rc) {
7094 DEBUG_PRINT_ERROR("STREAMON(CAPTURE_MPLANE) Failed");
7095 return OMX_ErrorInsufficientResources;
7096 } else {
7097 streaming[CAPTURE_PORT] = true;
7098 DEBUG_PRINT_LOW("STREAMON(CAPTURE_MPLANE) Successful");
7099 }
7100 }
7101 }
7102
7103 (*bufferHdr)->pBuffer = (OMX_U8*)(*omx_ptr_outputbuffer)[i].bufferaddr;
7104 (*bufferHdr)->pAppPrivate = appData;
7105 BITMASK_SET(&m_out_bm_count,i);
7106 } else {
7107 DEBUG_PRINT_ERROR("Faile to allocate output buffer (%d) maxcount %d",
7108 i, drv_ctx.op_buf.actualcount);
7109 eRet = OMX_ErrorInsufficientResources;
7110 }
7111 }
7112
7113 if (eRet == OMX_ErrorNone)
7114 DEBUG_PRINT_HIGH("Allocate_output_buffer(%d): Header %p buffer %p allocLen %d offset %d fd = %d intermediate %d",
7115 i, (*bufferHdr), (*bufferHdr)->pBuffer, (*bufferHdr)->nAllocLen,
7116 (*bufferHdr)->nOffset, (*omx_ptr_outputbuffer)[i].pmem_fd,
7117 intermediate);
7118 return eRet;
7119 }
7120
7121
7122 // AllocateBuffer -- API Call
7123 /* ======================================================================
7124 FUNCTION
7125 omx_vdec::AllocateBuffer
7126
7127 DESCRIPTION
7128 Returns zero if all the buffers released..
7129
7130 PARAMETERS
7131 None.
7132
7133 RETURN VALUE
7134 true/false
7135
7136 ========================================================================== */
allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN OMX_U32 bytes)7137 OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
7138 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
7139 OMX_IN OMX_U32 port,
7140 OMX_IN OMX_PTR appData,
7141 OMX_IN OMX_U32 bytes)
7142 {
7143 unsigned i = 0;
7144 OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
7145
7146 DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
7147 if (m_state == OMX_StateInvalid) {
7148 DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
7149 return OMX_ErrorInvalidState;
7150 }
7151
7152 if (port == OMX_CORE_INPUT_PORT_INDEX) {
7153 // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
7154 // ensure that use-buffer was never called.
7155 // Mix-and-match of useBuffer and allocateBuffer is not allowed
7156 if (m_inp_mem_ptr && input_use_buffer) {
7157 DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !");
7158 return OMX_ErrorUndefined;
7159 }
7160 if (arbitrary_bytes) {
7161 eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
7162 } else {
7163 eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
7164 }
7165 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7166 if (output_use_buffer) {
7167 DEBUG_PRINT_ERROR("Allocate output buffer not allowed after use buffer");
7168 return OMX_ErrorBadParameter;
7169 }
7170 eRet = allocate_output_buffer(hComp, bufferHdr, port, appData, bytes);
7171 } else {
7172 DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
7173 eRet = OMX_ErrorBadPortIndex;
7174 }
7175 if (eRet == OMX_ErrorNone) {
7176 if (allocate_done()) {
7177 DEBUG_PRINT_HIGH("Allocated all buffers on port %d", port);
7178 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
7179 // Send the callback now
7180 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
7181 post_event(OMX_CommandStateSet,OMX_StateIdle,
7182 OMX_COMPONENT_GENERATE_EVENT);
7183 }
7184 }
7185 if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
7186 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
7187 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
7188 post_event(OMX_CommandPortEnable,
7189 OMX_CORE_INPUT_PORT_INDEX,
7190 OMX_COMPONENT_GENERATE_EVENT);
7191 }
7192 }
7193 if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
7194 if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
7195 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
7196 post_event(OMX_CommandPortEnable,
7197 OMX_CORE_OUTPUT_PORT_INDEX,
7198 OMX_COMPONENT_GENERATE_EVENT);
7199 }
7200 }
7201 }
7202 return eRet;
7203 }
7204
7205 // Free Buffer - API call
7206 /* ======================================================================
7207 FUNCTION
7208 omx_vdec::FreeBuffer
7209
7210 DESCRIPTION
7211
7212 PARAMETERS
7213 None.
7214
7215 RETURN VALUE
7216 true/false
7217
7218 ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7219 OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
7220 OMX_IN OMX_U32 port,
7221 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7222 {
7223 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7224 unsigned int nPortIndex;
7225 (void) hComp;
7226
7227 auto_lock l(buf_lock);
7228 if (m_state == OMX_StateIdle &&
7229 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
7230 DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
7231 } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
7232 (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
7233 DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
7234 } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
7235 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
7236 (port == OMX_CORE_OUTPUT_PORT_INDEX &&
7237 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
7238 DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
7239 } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
7240 DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
7241 post_event(OMX_EventError,
7242 OMX_ErrorPortUnpopulated,
7243 OMX_COMPONENT_GENERATE_EVENT);
7244 m_buffer_error = true;
7245 return OMX_ErrorIncorrectStateOperation;
7246 } else if (m_state != OMX_StateInvalid) {
7247 DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
7248 post_event(OMX_EventError,
7249 OMX_ErrorPortUnpopulated,
7250 OMX_COMPONENT_GENERATE_EVENT);
7251 }
7252
7253 if (port == OMX_CORE_INPUT_PORT_INDEX) {
7254 /*Check if arbitrary bytes*/
7255 if (!arbitrary_bytes && !input_use_buffer)
7256 nPortIndex = buffer - m_inp_mem_ptr;
7257 else
7258 nPortIndex = buffer - m_inp_heap_ptr;
7259
7260 DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
7261 if (nPortIndex < drv_ctx.ip_buf.actualcount &&
7262 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
7263 // Clear the bit associated with it.
7264 BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
7265 BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
7266 if (input_use_buffer == true) {
7267
7268 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
7269 if (m_phdr_pmem_ptr)
7270 free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
7271 } else {
7272 if (arbitrary_bytes) {
7273 if (m_phdr_pmem_ptr)
7274 free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
7275 else
7276 free_input_buffer(nPortIndex,NULL);
7277 } else
7278 free_input_buffer(buffer);
7279 }
7280 m_inp_bPopulated = OMX_FALSE;
7281 /*Free the Buffer Header*/
7282 if (release_input_done()) {
7283 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
7284 free_input_buffer_header();
7285 }
7286 } else {
7287 DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
7288 eRet = OMX_ErrorBadPortIndex;
7289 }
7290
7291 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
7292 && release_input_done()) {
7293 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
7294 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
7295 post_event(OMX_CommandPortDisable,
7296 OMX_CORE_INPUT_PORT_INDEX,
7297 OMX_COMPONENT_GENERATE_EVENT);
7298 }
7299 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7300 // check if the buffer is valid
7301 OMX_BUFFERHEADERTYPE *omx_base_address =
7302 client_buffers.is_color_conversion_enabled()?
7303 m_intermediate_out_mem_ptr:m_out_mem_ptr;
7304 nPortIndex = buffer - m_out_mem_ptr;
7305 if (nPortIndex < drv_ctx.op_buf.actualcount &&
7306 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
7307 DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
7308 // Clear the bit associated with it.
7309 BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
7310 m_out_bPopulated = OMX_FALSE;
7311 free_output_buffer (buffer);
7312
7313 if (release_output_done()) {
7314 DEBUG_PRINT_HIGH("All output buffers released.");
7315 free_output_buffer_header();
7316 }
7317 } else {
7318 DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
7319 eRet = OMX_ErrorBadPortIndex;
7320 }
7321 if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
7322 && release_output_done()) {
7323 DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
7324 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
7325 #ifdef _ANDROID_ICS_
7326 if (m_enable_android_native_buffers) {
7327 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
7328 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
7329 }
7330 #endif
7331
7332 post_event(OMX_CommandPortDisable,
7333 OMX_CORE_OUTPUT_PORT_INDEX,
7334 OMX_COMPONENT_GENERATE_EVENT);
7335 }
7336 } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
7337 nPortIndex = buffer - m_client_output_extradata_mem_ptr;
7338 DEBUG_PRINT_LOW("free_buffer on extradata output port - Port idx %d", nPortIndex);
7339
7340 BITMASK_CLEAR(&m_out_extradata_bm_count,nPortIndex);
7341
7342 if (release_output_extradata_done()) {
7343 free_output_extradata_buffer_header();
7344 }
7345 } else {
7346 eRet = OMX_ErrorBadPortIndex;
7347 }
7348 if ((eRet == OMX_ErrorNone) &&
7349 (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
7350 if (release_done()) {
7351 /*
7352 * Reset buffer requirements here to ensure setting buffer requirement
7353 * when component move to executing state from loaded state via idle.
7354 */
7355 drv_ctx.op_buf.buffer_size = 0;
7356 drv_ctx.op_buf.actualcount = 0;
7357
7358 // Send the callback now
7359 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
7360 post_event(OMX_CommandStateSet, OMX_StateLoaded,
7361 OMX_COMPONENT_GENERATE_EVENT);
7362 m_buffer_error = false;
7363 }
7364 }
7365 return eRet;
7366 }
7367
7368
7369 /* ======================================================================
7370 FUNCTION
7371 omx_vdec::EmptyThisBuffer
7372
7373 DESCRIPTION
7374 This routine is used to push the encoded video frames to
7375 the video decoder.
7376
7377 PARAMETERS
7378 None.
7379
7380 RETURN VALUE
7381 OMX Error None if everything went successful.
7382
7383 ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7384 OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
7385 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7386 {
7387 OMX_ERRORTYPE ret1 = OMX_ErrorNone;
7388 unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
7389
7390 if (m_state != OMX_StateExecuting &&
7391 m_state != OMX_StatePause &&
7392 m_state != OMX_StateIdle) {
7393 DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
7394 return OMX_ErrorInvalidState;
7395 }
7396
7397 if (m_error_propogated) {
7398 DEBUG_PRINT_ERROR("Empty this buffer not allowed after error");
7399 return OMX_ErrorHardware;
7400 }
7401
7402 if (buffer == NULL) {
7403 DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
7404 return OMX_ErrorBadParameter;
7405 }
7406 print_omx_buffer("EmptyThisBuffer", buffer);
7407
7408 if (!m_inp_bEnabled) {
7409 DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
7410 return OMX_ErrorIncorrectStateOperation;
7411 }
7412
7413 if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
7414 DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
7415 return OMX_ErrorBadPortIndex;
7416 }
7417
7418 if (perf_flag) {
7419 if (!latency) {
7420 dec_time.stop();
7421 latency = dec_time.processing_time_us();
7422 dec_time.start();
7423 }
7424 }
7425
7426 if (arbitrary_bytes) {
7427 nBufferIndex = buffer - m_inp_heap_ptr;
7428 } else {
7429 if (input_use_buffer == true) {
7430 nBufferIndex = buffer - m_inp_heap_ptr;
7431 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7432 DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode");
7433 return OMX_ErrorBadParameter;
7434 }
7435 m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
7436 m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
7437 m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
7438 buffer = &m_inp_mem_ptr[nBufferIndex];
7439 DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
7440 &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
7441 } else {
7442 nBufferIndex = buffer - m_inp_mem_ptr;
7443 }
7444 }
7445
7446 if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7447 DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
7448 return OMX_ErrorBadParameter;
7449 }
7450
7451 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7452 codec_config_flag = true;
7453 DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
7454 }
7455
7456 /* The client should not set this when codec is in arbitrary bytes mode */
7457 if (m_input_pass_buffer_fd) {
7458 buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
7459 }
7460
7461 /* Check if the input timestamp in seconds is greater than LONG_MAX
7462 or lesser than LONG_MIN. */
7463 if (buffer->nTimeStamp / 1000000 > LONG_MAX ||
7464 buffer->nTimeStamp / 1000000 < LONG_MIN) {
7465 /* This timestamp cannot be contained in driver timestamp field */
7466 DEBUG_PRINT_ERROR("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u) >> Invalid timestamp",
7467 buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
7468 return OMX_ErrorBadParameter;
7469 }
7470
7471 m_etb_count++;
7472 //To handle wrap around case. m_etb_count++ to ensure value is non-zero.
7473 if (!m_etb_count)
7474 m_etb_count++;
7475 m_etb_timestamp = buffer->nTimeStamp;
7476 DEBUG_PRINT_LOW("[ETB] nCnt(%u) BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
7477 m_etb_count, buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
7478 buffer->pMarkData = (OMX_PTR)(unsigned long)m_etb_count;
7479 if (arbitrary_bytes) {
7480 post_event ((unsigned long)hComp,(unsigned long)buffer,
7481 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
7482 } else {
7483 post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
7484 }
7485
7486 time_stamp_dts.insert_timestamp(buffer);
7487 return OMX_ErrorNone;
7488 }
7489
7490 /* ======================================================================
7491 FUNCTION
7492 omx_vdec::empty_this_buffer_proxy
7493
7494 DESCRIPTION
7495 This routine is used to push the encoded video frames to
7496 the video decoder.
7497
7498 PARAMETERS
7499 None.
7500
7501 RETURN VALUE
7502 OMX Error None if everything went successful.
7503
7504 ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7505 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
7506 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7507 {
7508 VIDC_TRACE_NAME_HIGH("ETB");
7509 (void) hComp;
7510 int push_cnt = 0,i=0;
7511 unsigned nPortIndex = 0;
7512 OMX_ERRORTYPE ret = OMX_ErrorNone;
7513 struct vdec_bufferpayload *temp_buffer;
7514 bool port_setting_changed = true;
7515
7516 /*Should we generate a Aync error event*/
7517 if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
7518 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
7519 return OMX_ErrorBadParameter;
7520 }
7521
7522 nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
7523
7524 if (nPortIndex >= drv_ctx.ip_buf.actualcount) {
7525 DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
7526 nPortIndex);
7527 return OMX_ErrorBadParameter;
7528 }
7529
7530 pending_input_buffers++;
7531 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
7532
7533 /* return zero length and not an EOS buffer */
7534 if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
7535 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
7536 DEBUG_PRINT_HIGH("return zero length buffer");
7537 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7538 OMX_COMPONENT_GENERATE_EBD);
7539 return OMX_ErrorNone;
7540 }
7541
7542 if (input_flush_progress == true) {
7543 DEBUG_PRINT_LOW("Flush in progress return buffer ");
7544 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7545 OMX_COMPONENT_GENERATE_EBD);
7546 return OMX_ErrorNone;
7547 }
7548
7549 if (m_error_propogated == true) {
7550 DEBUG_PRINT_LOW("Return buffer in error state");
7551 post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7552 OMX_COMPONENT_GENERATE_EBD);
7553 return OMX_ErrorNone;
7554 }
7555
7556 auto_lock l(buf_lock);
7557 temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
7558
7559 if (!temp_buffer || (temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
7560 return OMX_ErrorBadParameter;
7561 }
7562
7563 if (BITMASK_ABSENT(&m_inp_bm_count, nPortIndex) || m_buffer_error) {
7564 DEBUG_PRINT_ERROR("ETBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
7565 return OMX_ErrorBadParameter;
7566 }
7567
7568 VIDC_TRACE_INT_LOW("ETB-TS", buffer->nTimeStamp / 1000);
7569 VIDC_TRACE_INT_LOW("ETB-size", buffer->nFilledLen);
7570 /*for use buffer we need to memcpy the data*/
7571 temp_buffer->buffer_len = buffer->nFilledLen;
7572
7573 if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) {
7574 if (buffer->nFilledLen <= temp_buffer->buffer_len) {
7575 if (arbitrary_bytes) {
7576 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
7577 } else {
7578 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
7579 buffer->nFilledLen);
7580 }
7581 } else {
7582 return OMX_ErrorBadParameter;
7583 }
7584
7585 }
7586
7587 if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
7588 DEBUG_PRINT_LOW("ETB: dmx enabled");
7589 if (m_demux_entries == 0) {
7590 extract_demux_addr_offsets(buffer);
7591 }
7592
7593 DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
7594 handle_demux_data(buffer);
7595 }
7596
7597 log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len, buffer->nTimeStamp, temp_buffer->pmem_fd);
7598
7599 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7600 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7601 }
7602
7603 if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7604 DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
7605 h264_scratch.nFilledLen = 0;
7606 nal_count = 0;
7607 look_ahead_nal = false;
7608 frame_count = 0;
7609 if (m_frame_parser.mutils)
7610 m_frame_parser.mutils->initialize_frame_checking_environment();
7611 m_frame_parser.flush();
7612 h264_last_au_ts = LLONG_MAX;
7613 h264_last_au_flags = 0;
7614 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
7615 m_demux_entries = 0;
7616 }
7617 struct v4l2_buffer buf;
7618 struct v4l2_plane plane;
7619 memset( (void *)&buf, 0, sizeof(buf));
7620 memset( (void *)&plane, 0, sizeof(plane));
7621 int rc;
7622 unsigned long print_count;
7623 if (temp_buffer->buffer_len == 0 && (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7624 struct v4l2_decoder_cmd dec;
7625
7626 if (!streaming[OUTPUT_PORT]) {
7627 enum v4l2_buf_type buf_type;
7628 int ret = 0;
7629
7630 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7631 DEBUG_PRINT_HIGH("Calling streamon before issuing stop command for EOS");
7632 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7633 if (!ret) {
7634 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7635 streaming[OUTPUT_PORT] = true;
7636 } else {
7637 DEBUG_PRINT_ERROR("Streamon failed before sending stop command");
7638 return OMX_ErrorHardware;
7639 }
7640 }
7641
7642 DEBUG_PRINT_HIGH("Input EOS reached. Converted to STOP command") ;
7643 memset(&dec, 0, sizeof(dec));
7644 dec.cmd = V4L2_DEC_CMD_STOP;
7645 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec);
7646 post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7647 OMX_COMPONENT_GENERATE_EBD);
7648 if (rc < 0) {
7649 DEBUG_PRINT_ERROR("Decoder CMD failed");
7650 return OMX_ErrorHardware;
7651 }
7652 return OMX_ErrorNone;
7653 }
7654
7655 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
7656 DEBUG_PRINT_HIGH("Input EOS reached") ;
7657 buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
7658 }
7659
7660 // update hdr10plusinfo list with cookie as pMarkData
7661 update_hdr10plusinfo_cookie_using_timestamp(buffer->pMarkData, buffer->nTimeStamp);
7662
7663 OMX_ERRORTYPE eRet = OMX_ErrorNone;
7664 buf.index = nPortIndex;
7665 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7666 buf.memory = V4L2_MEMORY_USERPTR;
7667 plane.bytesused = temp_buffer->buffer_len;
7668 plane.length = drv_ctx.ip_buf.buffer_size;
7669 plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
7670 (unsigned long)temp_buffer->offset;
7671 plane.reserved[0] = temp_buffer->pmem_fd;
7672 plane.reserved[1] = temp_buffer->offset;
7673 plane.reserved[3] = (unsigned long)buffer->pMarkData;
7674 plane.reserved[4] = (unsigned long)buffer->hMarkTargetComponent;
7675 plane.data_offset = 0;
7676 buf.m.planes = &plane;
7677 buf.length = 1;
7678 //assumption is that timestamp is in milliseconds
7679 buf.timestamp.tv_sec = buffer->nTimeStamp / 1000000;
7680 buf.timestamp.tv_usec = (buffer->nTimeStamp % 1000000);
7681 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
7682 #if NEED_TO_REVISIT
7683 buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
7684 #endif
7685
7686 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7687 DEBUG_PRINT_LOW("Increment codec_config buffer counter");
7688 android_atomic_inc(&m_queued_codec_config_count);
7689 }
7690
7691 print_v4l2_buffer("QBUF-ETB", &buf);
7692 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7693 if (rc) {
7694 DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver, send ETB back to client");
7695 print_v4l2_buffer("QBUF failed", &buf);
7696 print_omx_buffer("EBD on qbuf failed", buffer);
7697 m_cb.EmptyBufferDone(hComp, m_app_data, buffer);
7698 return OMX_ErrorHardware;
7699 }
7700
7701 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7702 codec_config_flag = false;
7703 }
7704 if (!streaming[OUTPUT_PORT]) {
7705 enum v4l2_buf_type buf_type;
7706 int ret,r;
7707
7708 buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7709 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
7710 ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7711 if (!ret) {
7712 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7713 streaming[OUTPUT_PORT] = true;
7714 } else if (errno == EBUSY) {
7715 DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
7716 post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7717 OMX_COMPONENT_GENERATE_EBD);
7718 return OMX_ErrorInsufficientResources;
7719 } else {
7720 DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
7721 DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
7722 post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7723 OMX_COMPONENT_GENERATE_EBD);
7724 return OMX_ErrorBadParameter;
7725 }
7726 }
7727
7728 return ret;
7729 }
7730
7731 /* ======================================================================
7732 FUNCTION
7733 omx_vdec::FillThisBuffer
7734
7735 DESCRIPTION
7736 IL client uses this method to release the frame buffer
7737 after displaying them.
7738
7739 PARAMETERS
7740 None.
7741
7742 RETURN VALUE
7743 true/false
7744
7745 ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7746 OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
7747 OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7748 {
7749 if (m_state != OMX_StateExecuting &&
7750 m_state != OMX_StatePause &&
7751 m_state != OMX_StateIdle) {
7752 DEBUG_PRINT_ERROR("FTB in Invalid State");
7753 return OMX_ErrorInvalidState;
7754 }
7755
7756 if (buffer == NULL || buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
7757 DEBUG_PRINT_ERROR("ERROR:FTB invalid buffer %p or PortIndex - %d",
7758 buffer, buffer ? (int)buffer->nOutputPortIndex : -1);
7759 return OMX_ErrorBadPortIndex;
7760 }
7761 print_omx_buffer("FillThisBuffer", buffer);
7762
7763 if (m_error_propogated) {
7764 DEBUG_PRINT_ERROR("Fill this buffer not allowed after error");
7765 return OMX_ErrorHardware;
7766 }
7767
7768 if (!m_out_bEnabled) {
7769 DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
7770 return OMX_ErrorIncorrectStateOperation;
7771 }
7772
7773 unsigned nPortIndex = buffer - m_out_mem_ptr;
7774 if (dynamic_buf_mode) {
7775 private_handle_t *handle = NULL;
7776 struct VideoDecoderOutputMetaData *meta = NULL;
7777
7778 if (!buffer || !buffer->pBuffer) {
7779 DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
7780 return OMX_ErrorBadParameter;
7781 }
7782
7783 meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
7784 handle = (private_handle_t *)meta->pHandle;
7785
7786 //get the buffer type and fd info
7787 DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ",
7788 meta, meta->eType, meta->pHandle);
7789
7790 if (!handle) {
7791 DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
7792 return OMX_ErrorBadParameter;
7793 }
7794
7795 //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
7796 if (nPortIndex < drv_ctx.op_buf.actualcount &&
7797 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
7798 drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
7799 drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
7800
7801 //Store private handle from GraphicBuffer
7802 native_buffer[nPortIndex].privatehandle = handle;
7803 native_buffer[nPortIndex].nativehandle = handle;
7804 } else {
7805 DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
7806 return OMX_ErrorBadParameter;
7807 }
7808
7809 if (handle->flags & private_handle_t::PRIV_FLAGS_DISP_CONSUMER) {
7810 m_is_display_session = true;
7811 } else {
7812 m_is_display_session = false;
7813 }
7814 buffer->nAllocLen = handle->size;
7815 DEBUG_PRINT_LOW("%s: buffer size = d-%d:b-%d",
7816 __func__, (int)drv_ctx.op_buf.buffer_size, (int)handle->size);
7817
7818 if (!client_buffers.is_color_conversion_enabled()) {
7819 drv_ctx.op_buf.buffer_size = handle->size;
7820 }
7821
7822 DEBUG_PRINT_LOW("%s: m_is_display_session = %d", __func__, m_is_display_session);
7823 }
7824
7825 if (client_buffers.is_color_conversion_enabled()) {
7826 buffer = m_intermediate_out_mem_ptr + nPortIndex;
7827 buffer->nAllocLen = drv_ctx.op_buf.buffer_size;
7828 }
7829
7830 //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
7831 //this with a more sane size so that we don't compensate in rest of code
7832 //We'll restore this size later on, so that it's transparent to client
7833 buffer->nFilledLen = 0;
7834
7835 post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
7836 return OMX_ErrorNone;
7837 }
7838
7839 /* ======================================================================
7840 FUNCTION
7841 omx_vdec::fill_this_buffer_proxy
7842
7843 DESCRIPTION
7844 IL client uses this method to release the frame buffer
7845 after displaying them.
7846
7847 PARAMETERS
7848 None.
7849
7850 RETURN VALUE
7851 true/false
7852
7853 ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)7854 OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy(
7855 OMX_IN OMX_HANDLETYPE hComp,
7856 OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
7857 {
7858 VIDC_TRACE_NAME_HIGH("FTB");
7859 OMX_ERRORTYPE nRet = OMX_ErrorNone;
7860 OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
7861 unsigned bufIndex = 0;
7862 struct vdec_bufferpayload *ptr_outputbuffer = NULL;
7863 struct vdec_output_frameinfo *ptr_respbuffer = NULL;
7864
7865 auto_lock l(buf_lock);
7866 OMX_BUFFERHEADERTYPE *omx_base_address =
7867 client_buffers.is_color_conversion_enabled()?
7868 m_intermediate_out_mem_ptr:m_out_mem_ptr;
7869 vdec_bufferpayload *omx_ptr_outputbuffer =
7870 client_buffers.is_color_conversion_enabled()?
7871 drv_ctx.ptr_intermediate_outputbuffer:drv_ctx.ptr_outputbuffer;
7872 bufIndex = buffer-omx_base_address;
7873
7874 if (bufferAdd == NULL || bufIndex >= drv_ctx.op_buf.actualcount) {
7875 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, bufIndex %u bufCount %u",
7876 bufIndex, drv_ctx.op_buf.actualcount);
7877 return OMX_ErrorBadParameter;
7878 }
7879
7880 if (BITMASK_ABSENT(&m_out_bm_count, bufIndex) || m_buffer_error) {
7881 DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer, bufIndex %u", bufIndex);
7882 return OMX_ErrorBadParameter;
7883 }
7884
7885 /*Return back the output buffer to client*/
7886 if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true || in_reconfig) {
7887 DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
7888 buffer->nFilledLen = 0;
7889 print_omx_buffer("FBD in FTBProxy", &m_out_mem_ptr[bufIndex]);
7890 m_cb.FillBufferDone (hComp,m_app_data,&m_out_mem_ptr[bufIndex]);
7891 return OMX_ErrorNone;
7892 }
7893 if (m_error_propogated == true) {
7894 DEBUG_PRINT_LOW("Return buffers in error state");
7895 buffer->nFilledLen = 0;
7896 print_omx_buffer("FBD in FTBProxy", &m_out_mem_ptr[bufIndex]);
7897 m_cb.FillBufferDone (hComp,m_app_data,&m_out_mem_ptr[bufIndex]);
7898 return OMX_ErrorNone;
7899 }
7900
7901 if (dynamic_buf_mode) {
7902 omx_ptr_outputbuffer[bufIndex].offset = 0;
7903 omx_ptr_outputbuffer[bufIndex].buffer_len = buffer->nAllocLen;
7904 omx_ptr_outputbuffer[bufIndex].mmaped_size = buffer->nAllocLen;
7905 }
7906
7907 pending_output_buffers++;
7908 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
7909 ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
7910 if (ptr_respbuffer) {
7911 ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
7912 }
7913
7914 if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
7915 DEBUG_PRINT_ERROR("Invalid ptr_respbuffer %p, ptr_outputbuffer %p",
7916 ptr_respbuffer, ptr_outputbuffer);
7917 buffer->nFilledLen = 0;
7918 print_omx_buffer("FBD in error", &m_out_mem_ptr[bufIndex]);
7919 m_cb.FillBufferDone (hComp,m_app_data,&m_out_mem_ptr[bufIndex]);
7920 pending_output_buffers--;
7921 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
7922 return OMX_ErrorBadParameter;
7923 }
7924
7925 int rc = 0;
7926 struct v4l2_buffer buf;
7927 struct v4l2_plane plane[VIDEO_MAX_PLANES];
7928 memset( (void *)&buf, 0, sizeof(buf));
7929 memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
7930 unsigned int extra_idx = 0;
7931
7932 buf.index = bufIndex;
7933 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7934 buf.memory = V4L2_MEMORY_USERPTR;
7935 plane[0].bytesused = buffer->nFilledLen;
7936 plane[0].length = buffer->nAllocLen;
7937 plane[0].m.userptr =
7938 (unsigned long)omx_ptr_outputbuffer[bufIndex].bufferaddr -
7939 (unsigned long)omx_ptr_outputbuffer[bufIndex].offset;
7940 plane[0].reserved[0] = omx_ptr_outputbuffer[bufIndex].pmem_fd;
7941 plane[0].reserved[1] = omx_ptr_outputbuffer[bufIndex].offset;
7942 plane[0].data_offset = 0;
7943 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7944 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7945 plane[extra_idx].bytesused = 0;
7946 plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
7947 plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + bufIndex * drv_ctx.extradata_info.buffer_size);
7948 #ifdef USE_ION
7949 plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.data_fd;
7950 #endif
7951 plane[extra_idx].reserved[1] = bufIndex * drv_ctx.extradata_info.buffer_size;
7952 plane[extra_idx].data_offset = 0;
7953 } else if (extra_idx >= VIDEO_MAX_PLANES) {
7954 DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
7955 return OMX_ErrorBadParameter;
7956 }
7957 buf.m.planes = plane;
7958 buf.length = drv_ctx.num_planes;
7959 print_v4l2_buffer("QBUF-FTB", &buf);
7960 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7961 if (rc) {
7962 buffer->nFilledLen = 0;
7963 DEBUG_PRINT_ERROR("Failed to qbuf to driver, error %s", strerror(errno));
7964 print_omx_buffer("FBD in error", &m_out_mem_ptr[bufIndex]);
7965 m_cb.FillBufferDone(hComp, m_app_data, &m_out_mem_ptr[bufIndex]);
7966 return OMX_ErrorHardware;
7967 }
7968
7969 return OMX_ErrorNone;
7970 }
7971
7972 /* ======================================================================
7973 FUNCTION
7974 omx_vdec::SetCallbacks
7975
7976 DESCRIPTION
7977 Set the callbacks.
7978
7979 PARAMETERS
7980 None.
7981
7982 RETURN VALUE
7983 OMX Error None if everything successful.
7984
7985 ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)7986 OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
7987 OMX_IN OMX_CALLBACKTYPE* callbacks,
7988 OMX_IN OMX_PTR appData)
7989 {
7990 (void) hComp;
7991
7992 if (!callbacks)
7993 return OMX_ErrorBadParameter;
7994
7995 m_cb = *callbacks;
7996 DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
7997 m_cb.EventHandler,m_cb.FillBufferDone);
7998 m_app_data = appData;
7999 return OMX_ErrorNone;
8000 }
8001
8002 /* ======================================================================
8003 FUNCTION
8004 omx_vdec::ComponentDeInit
8005
8006 DESCRIPTION
8007 Destroys the component and release memory allocated to the heap.
8008
8009 PARAMETERS
8010 <TBD>.
8011
8012 RETURN VALUE
8013 OMX Error None if everything successful.
8014
8015 ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)8016 OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
8017 {
8018 (void) hComp;
8019 OMX_ERRORTYPE nRet = OMX_ErrorNone;
8020 OMX_BUFFERHEADERTYPE *buffer;
8021
8022 unsigned i = 0;
8023 if (OMX_StateLoaded != m_state) {
8024 DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
8025 m_state);
8026 DEBUG_PRINT_ERROR("Playback Ended - FAILED");
8027 } else {
8028 DEBUG_PRINT_HIGH("Playback Ended - PASSED");
8029 }
8030
8031 /*Check if the output buffers have to be cleaned up*/
8032 buffer = m_out_mem_ptr;
8033 if (buffer) {
8034 DEBUG_PRINT_LOW("Freeing the Output Memory");
8035 for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
8036 if (BITMASK_PRESENT(&m_out_bm_count, i)) {
8037 BITMASK_CLEAR(&m_out_bm_count, i);
8038 nRet = free_output_buffer (buffer+i);
8039 if (OMX_ErrorNone != nRet)
8040 break;
8041 }
8042 if (release_output_done()) {
8043 DEBUG_PRINT_HIGH("All output buffers are released");
8044 break;
8045 }
8046 }
8047 #ifdef _ANDROID_ICS_
8048 memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
8049 #endif
8050 }
8051
8052 /*Check if the input buffers have to be cleaned up*/
8053 if (m_inp_mem_ptr || m_inp_heap_ptr) {
8054 DEBUG_PRINT_LOW("Freeing the Input Memory");
8055 for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
8056
8057 if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
8058 BITMASK_CLEAR(&m_inp_bm_count, i);
8059 if (m_inp_mem_ptr)
8060 free_input_buffer (i,&m_inp_mem_ptr[i]);
8061 else
8062 free_input_buffer (i,NULL);
8063 }
8064
8065 if (release_input_done()) {
8066 DEBUG_PRINT_HIGH("All input buffers released");
8067 break;
8068 }
8069 }
8070 }
8071 free_input_buffer_header();
8072 free_output_buffer_header();
8073 if (h264_scratch.pBuffer) {
8074 free(h264_scratch.pBuffer);
8075 h264_scratch.pBuffer = NULL;
8076 }
8077
8078 if (h264_parser) {
8079 delete h264_parser;
8080 h264_parser = NULL;
8081 }
8082
8083 if (m_frame_parser.mutils) {
8084 DEBUG_PRINT_LOW("Free utils parser");
8085 delete (m_frame_parser.mutils);
8086 m_frame_parser.mutils = NULL;
8087 }
8088
8089 if (m_platform_list) {
8090 free(m_platform_list);
8091 m_platform_list = NULL;
8092 }
8093 if (m_vendor_config.pData) {
8094 free(m_vendor_config.pData);
8095 m_vendor_config.pData = NULL;
8096 }
8097
8098 // Reset counters in mesg queues
8099 m_ftb_q.m_size=0;
8100 m_cmd_q.m_size=0;
8101 m_etb_q.m_size=0;
8102 m_ftb_q.m_read = m_ftb_q.m_write =0;
8103 m_cmd_q.m_read = m_cmd_q.m_write =0;
8104 m_etb_q.m_read = m_etb_q.m_write =0;
8105
8106 DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
8107 //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
8108 // NULL);
8109 DEBUG_PRINT_HIGH("Close the driver instance");
8110
8111 if (m_debug.infile) {
8112 fclose(m_debug.infile);
8113 m_debug.infile = NULL;
8114 }
8115 if (m_debug.outfile) {
8116 fclose(m_debug.outfile);
8117 m_debug.outfile = NULL;
8118 }
8119 if (m_debug.ccoutfile) {
8120 fclose(m_debug.ccoutfile);
8121 m_debug.ccoutfile = NULL;
8122 }
8123 if (m_debug.out_ymeta_file) {
8124 fclose(m_debug.out_ymeta_file);
8125 m_debug.out_ymeta_file = NULL;
8126 }
8127 if (m_debug.out_uvmeta_file) {
8128 fclose(m_debug.out_uvmeta_file);
8129 m_debug.out_uvmeta_file = NULL;
8130 }
8131 #ifdef OUTPUT_EXTRADATA_LOG
8132 if (outputExtradataFile)
8133 fclose (outputExtradataFile);
8134 #endif
8135 DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
8136 return OMX_ErrorNone;
8137 }
8138
8139 /* ======================================================================
8140 FUNCTION
8141 omx_vdec::UseEGLImage
8142
8143 DESCRIPTION
8144 OMX Use EGL Image method implementation <TBD>.
8145
8146 PARAMETERS
8147 <TBD>.
8148
8149 RETURN VALUE
8150 Not Implemented error.
8151
8152 ========================================================================== */
use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,OMX_INOUT OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_IN OMX_U32 port,OMX_IN OMX_PTR appData,OMX_IN void * eglImage)8153 OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
8154 OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
8155 OMX_IN OMX_U32 port,
8156 OMX_IN OMX_PTR appData,
8157 OMX_IN void* eglImage)
8158 {
8159 (void) appData;
8160 OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
8161 OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
8162 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
8163
8164 #ifdef USE_EGL_IMAGE_GPU
8165 PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
8166 EGLint fd = -1, offset = 0,pmemPtr = 0;
8167 #else
8168 int fd = -1, offset = 0;
8169 #endif
8170 DEBUG_PRINT_HIGH("use EGL image support for decoder");
8171 if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
8172 DEBUG_PRINT_ERROR("Invalid EGL image");
8173 }
8174 #ifdef USE_EGL_IMAGE_GPU
8175 if (m_display_id == NULL) {
8176 DEBUG_PRINT_ERROR("Display ID is not set by IL client");
8177 return OMX_ErrorInsufficientResources;
8178 }
8179 egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
8180 eglGetProcAddress("eglQueryImageKHR");
8181 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
8182 egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
8183 egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
8184 #else //with OMX test app
8185 struct temp_egl {
8186 int pmem_fd;
8187 int offset;
8188 };
8189 struct temp_egl *temp_egl_id = NULL;
8190 void * pmemPtr = (void *) eglImage;
8191 temp_egl_id = (struct temp_egl *)eglImage;
8192 if (temp_egl_id != NULL) {
8193 fd = temp_egl_id->pmem_fd;
8194 offset = temp_egl_id->offset;
8195 }
8196 #endif
8197 if (fd < 0) {
8198 DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
8199 return OMX_ErrorInsufficientResources;
8200 }
8201 pmem_info.pmem_fd = (OMX_U32) fd;
8202 pmem_info.offset = (OMX_U32) offset;
8203 pmem_entry.entry = (void *) &pmem_info;
8204 pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
8205 pmem_list.entryList = &pmem_entry;
8206 pmem_list.nEntries = 1;
8207 ouput_egl_buffers = true;
8208 if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
8209 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
8210 (OMX_U8 *)pmemPtr)) {
8211 DEBUG_PRINT_ERROR("use buffer call failed for egl image");
8212 return OMX_ErrorInsufficientResources;
8213 }
8214 return OMX_ErrorNone;
8215 }
8216
8217 /* ======================================================================
8218 FUNCTION
8219 omx_vdec::ComponentRoleEnum
8220
8221 DESCRIPTION
8222 OMX Component Role Enum method implementation.
8223
8224 PARAMETERS
8225 <TBD>.
8226
8227 RETURN VALUE
8228 OMX Error None if everything is successful.
8229 ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)8230 OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
8231 OMX_OUT OMX_U8* role,
8232 OMX_IN OMX_U32 index)
8233 {
8234 (void) hComp;
8235 OMX_ERRORTYPE eRet = OMX_ErrorNone;
8236
8237 if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
8238 if ((0 == index) && role) {
8239 strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
8240 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8241 } else {
8242 eRet = OMX_ErrorNoMore;
8243 }
8244 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
8245 if ((0 == index) && role) {
8246 strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
8247 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8248 } else {
8249 DEBUG_PRINT_LOW("No more roles");
8250 eRet = OMX_ErrorNoMore;
8251 }
8252 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
8253 if ((0 == index) && role) {
8254 strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
8255 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8256 } else {
8257 DEBUG_PRINT_LOW("No more roles");
8258 eRet = OMX_ErrorNoMore;
8259 }
8260 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
8261 if ((0 == index) && role) {
8262 strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
8263 DEBUG_PRINT_LOW("component_role_enum: role %s", role);
8264 } else {
8265 DEBUG_PRINT_LOW("No more roles");
8266 eRet = OMX_ErrorNoMore;
8267 }
8268 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
8269 if ((0 == index) && role) {
8270 strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
8271 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8272 } else {
8273 DEBUG_PRINT_LOW("No more roles");
8274 eRet = OMX_ErrorNoMore;
8275 }
8276 } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
8277 if ((0 == index) && role) {
8278 strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
8279 DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8280 } else {
8281 DEBUG_PRINT_LOW("No more roles");
8282 eRet = OMX_ErrorNoMore;
8283 }
8284 } else {
8285 DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
8286 eRet = OMX_ErrorInvalidComponentName;
8287 }
8288 return eRet;
8289 }
8290
8291
8292
8293
8294 /* ======================================================================
8295 FUNCTION
8296 omx_vdec::AllocateDone
8297
8298 DESCRIPTION
8299 Checks if entire buffer pool is allocated by IL Client or not.
8300 Need this to move to IDLE state.
8301
8302 PARAMETERS
8303 None.
8304
8305 RETURN VALUE
8306 true/false.
8307
8308 ========================================================================== */
allocate_done(void)8309 bool omx_vdec::allocate_done(void)
8310 {
8311 bool bRet = false;
8312 bool bRet_In = false;
8313 bool bRet_Out = false;
8314 bool bRet_Out_Extra = false;
8315
8316 bRet_In = allocate_input_done();
8317 bRet_Out = allocate_output_done();
8318 bRet_Out_Extra = allocate_output_extradata_done();
8319
8320 if (bRet_In && bRet_Out && bRet_Out_Extra) {
8321 DEBUG_PRINT_HIGH("All ports buffers are allocated");
8322 bRet = true;
8323 }
8324
8325 return bRet;
8326 }
8327 /* ======================================================================
8328 FUNCTION
8329 omx_vdec::AllocateInputDone
8330
8331 DESCRIPTION
8332 Checks if I/P buffer pool is allocated by IL Client or not.
8333
8334 PARAMETERS
8335 None.
8336
8337 RETURN VALUE
8338 true/false.
8339
8340 ========================================================================== */
allocate_input_done(void)8341 bool omx_vdec::allocate_input_done(void)
8342 {
8343 bool bRet = false;
8344 unsigned i=0;
8345
8346 if (m_inp_mem_ptr == NULL) {
8347 return bRet;
8348 }
8349 if (m_inp_mem_ptr ) {
8350 for (; i<drv_ctx.ip_buf.actualcount; i++) {
8351 if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
8352 break;
8353 }
8354 }
8355 }
8356 if (i == drv_ctx.ip_buf.actualcount) {
8357 bRet = true;
8358 }
8359 if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
8360 m_inp_bPopulated = OMX_TRUE;
8361 }
8362 return bRet;
8363 }
8364 /* ======================================================================
8365 FUNCTION
8366 omx_vdec::AllocateOutputDone
8367
8368 DESCRIPTION
8369 Checks if entire O/P buffer pool is allocated by IL Client or not.
8370
8371 PARAMETERS
8372 None.
8373
8374 RETURN VALUE
8375 true/false.
8376
8377 ========================================================================== */
allocate_output_done(void)8378 bool omx_vdec::allocate_output_done(void)
8379 {
8380 bool bRet = false;
8381 unsigned j=0;
8382
8383 if (m_out_mem_ptr == NULL) {
8384 return bRet;
8385 }
8386
8387 if (m_out_mem_ptr) {
8388 for (; j < drv_ctx.op_buf.actualcount; j++) {
8389 if (BITMASK_ABSENT(&m_out_bm_count,j)) {
8390 break;
8391 }
8392 }
8393 }
8394
8395 if (j == drv_ctx.op_buf.actualcount) {
8396 bRet = true;
8397 if (m_out_bEnabled)
8398 m_out_bPopulated = OMX_TRUE;
8399 }
8400
8401 return bRet;
8402 }
8403
allocate_output_extradata_done(void)8404 bool omx_vdec::allocate_output_extradata_done(void) {
8405 bool bRet = false;
8406 unsigned j=0;
8407 unsigned nBufferCount = 0;
8408
8409 nBufferCount = m_client_out_extradata_info.getBufferCount();
8410
8411 if (!m_client_out_extradata_info.is_client_extradata_enabled()) {
8412 return true;
8413 }
8414
8415 if (m_client_output_extradata_mem_ptr) {
8416 for (; j < nBufferCount; j++) {
8417 if (BITMASK_ABSENT(&m_out_extradata_bm_count,j)) {
8418 break;
8419 }
8420 }
8421
8422 if (j == nBufferCount) {
8423 bRet = true;
8424 DEBUG_PRINT_HIGH("Allocate done for all extradata o/p buffers");
8425 }
8426 }
8427
8428 return bRet;
8429 }
8430 /* ======================================================================
8431 FUNCTION
8432 omx_vdec::ReleaseDone
8433
8434 DESCRIPTION
8435 Checks if IL client has released all the buffers.
8436
8437 PARAMETERS
8438 None.
8439
8440 RETURN VALUE
8441 true/false
8442
8443 ========================================================================== */
release_done(void)8444 bool omx_vdec::release_done(void)
8445 {
8446 bool bRet = false;
8447
8448 if (release_input_done()) {
8449 if (release_output_done()) {
8450 if (release_output_extradata_done()) {
8451 DEBUG_PRINT_HIGH("All ports buffers are released");
8452 bRet = true;
8453 }
8454 }
8455 }
8456 return bRet;
8457 }
8458
8459
8460 /* ======================================================================
8461 FUNCTION
8462 omx_vdec::ReleaseOutputDone
8463
8464 DESCRIPTION
8465 Checks if IL client has released all the buffers.
8466
8467 PARAMETERS
8468 None.
8469
8470 RETURN VALUE
8471 true/false
8472
8473 ========================================================================== */
release_output_done(void)8474 bool omx_vdec::release_output_done(void)
8475 {
8476 bool bRet = false;
8477 unsigned i=0,j=0;
8478
8479 if (m_out_mem_ptr) {
8480 for (; j < drv_ctx.op_buf.actualcount ; j++) {
8481 if (BITMASK_PRESENT(&m_out_bm_count,j)) {
8482 break;
8483 }
8484 }
8485 if (j == drv_ctx.op_buf.actualcount) {
8486 m_out_bm_count = 0;
8487 bRet = true;
8488 }
8489 } else {
8490 m_out_bm_count = 0;
8491 bRet = true;
8492 }
8493 return bRet;
8494 }
8495 /* ======================================================================
8496 FUNCTION
8497 omx_vdec::ReleaseInputDone
8498
8499 DESCRIPTION
8500 Checks if IL client has released all the buffers.
8501
8502 PARAMETERS
8503 None.
8504
8505 RETURN VALUE
8506 true/false
8507
8508 ========================================================================== */
release_input_done(void)8509 bool omx_vdec::release_input_done(void)
8510 {
8511 bool bRet = false;
8512 unsigned i=0,j=0;
8513
8514 if (m_inp_mem_ptr) {
8515 for (; j<drv_ctx.ip_buf.actualcount; j++) {
8516 if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
8517 break;
8518 }
8519 }
8520 if (j==drv_ctx.ip_buf.actualcount) {
8521 bRet = true;
8522 }
8523 } else {
8524 bRet = true;
8525 }
8526 return bRet;
8527 }
8528
release_output_extradata_done(void)8529 bool omx_vdec::release_output_extradata_done(void) {
8530 bool bRet = false;
8531 unsigned i=0,j=0, buffer_count=0;
8532
8533 buffer_count = m_client_out_extradata_info.getBufferCount();
8534 DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d",
8535 m_client_output_extradata_mem_ptr, buffer_count);
8536
8537 if (m_client_output_extradata_mem_ptr) {
8538 for (; j<buffer_count; j++) {
8539 if ( BITMASK_PRESENT(&m_out_extradata_bm_count,j)) {
8540 break;
8541 }
8542 }
8543 if (j == buffer_count) {
8544 bRet = true;
8545 }
8546 } else {
8547 bRet = true;
8548 }
8549 return bRet;
8550 }
8551
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8552 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
8553 OMX_BUFFERHEADERTYPE * buffer)
8554 {
8555 VIDC_TRACE_NAME_HIGH("FBD");
8556 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
8557 OMX_BUFFERHEADERTYPE *omx_base_address =
8558 client_buffers.is_color_conversion_enabled()?
8559 m_intermediate_out_mem_ptr:m_out_mem_ptr;
8560 vdec_bufferpayload *omx_ptr_outputbuffer =
8561 client_buffers.is_color_conversion_enabled()?
8562 drv_ctx.ptr_intermediate_outputbuffer:drv_ctx.ptr_outputbuffer;
8563
8564 if (!buffer || (buffer - omx_base_address) >= (int)drv_ctx.op_buf.actualcount) {
8565 DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
8566 return OMX_ErrorBadParameter;
8567 } else if (output_flush_progress) {
8568 DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
8569 buffer->nFilledLen = 0;
8570 buffer->nTimeStamp = 0;
8571 buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
8572 buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8573 buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
8574 }
8575
8576 if (m_debug_extradata) {
8577 if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
8578 DEBUG_PRINT_HIGH("***************************************************");
8579 DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
8580 DEBUG_PRINT_HIGH("***************************************************");
8581 }
8582
8583 if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
8584 DEBUG_PRINT_HIGH("***************************************************");
8585 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
8586 DEBUG_PRINT_HIGH("***************************************************");
8587 }
8588 }
8589
8590 pending_output_buffers --;
8591 VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
8592
8593 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8594 DEBUG_PRINT_HIGH("Output EOS has been reached");
8595 if (!output_flush_progress)
8596 post_event((unsigned)NULL, (unsigned)NULL,
8597 OMX_COMPONENT_GENERATE_EOS_DONE);
8598
8599 if (psource_frame) {
8600 print_omx_buffer("EBD in FBD", psource_frame);
8601 m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
8602 psource_frame = NULL;
8603 }
8604 if (pdest_frame) {
8605 pdest_frame->nFilledLen = 0;
8606 m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
8607 (unsigned)NULL);
8608 pdest_frame = NULL;
8609 }
8610 }
8611
8612 #ifdef OUTPUT_EXTRADATA_LOG
8613 if (outputExtradataFile) {
8614 int buf_index = buffer - omx_base_address;
8615 OMX_U8 *pBuffer = (OMX_U8 *)(omx_ptr_outputbuffer[buf_index].bufferaddr);
8616
8617 OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
8618 p_extra = (OMX_OTHER_EXTRADATATYPE *)
8619 ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
8620
8621 while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
8622 DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
8623 p_extra->nSize, p_extra->eType);
8624 fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
8625
8626 if (p_extra->eType == OMX_ExtraDataNone) {
8627 break;
8628 }
8629 p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8630 }
8631 }
8632 #endif
8633
8634 /* For use buffer we need to copy the data */
8635 if (!output_flush_progress) {
8636 /* This is the error check for non-recoverable errros */
8637 bool is_duplicate_ts_valid = true;
8638 bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
8639
8640 if (output_capability == V4L2_PIX_FMT_MPEG4 ||
8641 output_capability == V4L2_PIX_FMT_MPEG2)
8642 is_duplicate_ts_valid = false;
8643
8644 if (buffer->nFilledLen > 0) {
8645 time_stamp_dts.get_next_timestamp(buffer,
8646 is_interlaced && is_duplicate_ts_valid && !is_mbaff);
8647 }
8648 }
8649 VIDC_TRACE_INT_LOW("FBD-TS", buffer->nTimeStamp / 1000);
8650
8651 if (m_cb.FillBufferDone) {
8652 if (buffer->nFilledLen > 0) {
8653 if (arbitrary_bytes)
8654 adjust_timestamp(buffer->nTimeStamp);
8655 else
8656 set_frame_rate(buffer->nTimeStamp);
8657
8658 proc_frms++;
8659 if (perf_flag) {
8660 if (1 == proc_frms) {
8661 dec_time.stop();
8662 latency = dec_time.processing_time_us() - latency;
8663 DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
8664 dec_time.start();
8665 fps_metrics.start();
8666 }
8667 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8668 OMX_U64 proc_time = 0;
8669 fps_metrics.stop();
8670 proc_time = fps_metrics.processing_time_us();
8671 DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
8672 (unsigned int)proc_frms, (float)proc_time / 1e6,
8673 (float)(1e6 * proc_frms) / proc_time);
8674 }
8675 }
8676 }
8677 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8678 prev_ts = LLONG_MAX;
8679 rst_prev_ts = true;
8680 proc_frms = 0;
8681 }
8682
8683 pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
8684 ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
8685 buffer->pPlatformPrivate)->entryList->entry;
8686 OMX_BUFFERHEADERTYPE *il_buffer;
8687 il_buffer = client_buffers.get_il_buf_hdr(buffer);
8688 OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
8689
8690 if (il_buffer && m_last_rendered_TS >= 0) {
8691 OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
8692 // Convert fps into ms value. 1 sec = 1000000 ms.
8693 OMX_U64 target_ts_delta = m_dec_hfr_fps ? 1000000 / m_dec_hfr_fps : ts_delta;
8694
8695 // Current frame can be send for rendering if
8696 // (a) current FPS is <= 60
8697 // (b) is the next frame after the frame with TS 0
8698 // (c) is the first frame after seek
8699 // (d) the delta TS b\w two consecutive frames is > 16 ms
8700 // (e) its TS is equal to previous frame TS
8701 // (f) if marked EOS
8702
8703 if(current_framerate <= (OMX_U32)m_dec_hfr_fps || m_last_rendered_TS == 0 ||
8704 il_buffer->nTimeStamp == 0 || ts_delta >= (OMX_TICKS)target_ts_delta||
8705 ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
8706 m_last_rendered_TS = il_buffer->nTimeStamp;
8707 } else {
8708 //mark for droping
8709 buffer->nFilledLen = 0;
8710 }
8711
8712 DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
8713 buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
8714 il_buffer->nTimeStamp,ts_delta);
8715
8716 //above code makes sure that delta b\w two consecutive frames is not
8717 //greater than 16ms, slow-mo feature, so cap fps to max 60
8718 if (current_framerate > (OMX_U32)m_dec_hfr_fps ) {
8719 current_framerate = m_dec_hfr_fps;
8720 }
8721 }
8722
8723 // add current framerate to gralloc meta data
8724 if ((buffer->nFilledLen > 0) && m_enable_android_native_buffers && omx_base_address) {
8725 // If valid fps was received, directly send it to display for the 1st fbd.
8726 // Otherwise, calculate fps using fbd timestamps
8727 float refresh_rate = m_fps_prev;
8728 if (m_fps_received) {
8729 if (1 == proc_frms) {
8730 refresh_rate = m_fps_received / (float)(1<<16);
8731 }
8732 } else {
8733 // calculate and set refresh rate for every frame from second frame onwards
8734 // display will assume the default refresh rate for first frame (which is 60 fps)
8735 if (m_fps_prev) {
8736 if (drv_ctx.frame_rate.fps_denominator) {
8737 refresh_rate = drv_ctx.frame_rate.fps_numerator /
8738 (float) drv_ctx.frame_rate.fps_denominator;
8739 }
8740 }
8741 }
8742 OMX_U32 fps_limit = m_dec_hfr_fps ? (OMX_U32)m_dec_hfr_fps : 60;
8743 if (refresh_rate > fps_limit) {
8744 refresh_rate = fps_limit;
8745 }
8746 DEBUG_PRINT_LOW("frc set refresh_rate %f, frame %d", refresh_rate, proc_frms);
8747 OMX_U32 buf_index = buffer - omx_base_address;
8748 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8749 UPDATE_REFRESH_RATE, (void*)&refresh_rate);
8750 m_fps_prev = refresh_rate;
8751 }
8752
8753 if (buffer->nFilledLen && m_enable_android_native_buffers && omx_base_address) {
8754 OMX_U32 buf_index = buffer - omx_base_address;
8755 DEBUG_PRINT_LOW("stereo_output_mode = %d",stereo_output_mode);
8756 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8757 S3D_FORMAT, (void*)&stereo_output_mode);
8758 }
8759
8760 if (il_buffer) {
8761 log_output_buffers(buffer);
8762 log_cc_output_buffers(il_buffer);
8763 if (dynamic_buf_mode) {
8764 unsigned int nPortIndex = 0;
8765 nPortIndex = buffer-omx_base_address;
8766
8767 // Since we're passing around handles, adjust nFilledLen and nAllocLen
8768 // to size of the handle. Do it _after_ log_output_buffers which
8769 // requires the respective sizes to be accurate.
8770
8771 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
8772 buffer->nFilledLen = buffer->nFilledLen ?
8773 sizeof(struct VideoDecoderOutputMetaData) : 0;
8774
8775 //Clear graphic buffer handles in dynamic mode
8776 if (nPortIndex < drv_ctx.op_buf.actualcount &&
8777 nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
8778 native_buffer[nPortIndex].privatehandle = NULL;
8779 native_buffer[nPortIndex].nativehandle = NULL;
8780 } else {
8781 DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
8782 return OMX_ErrorBadParameter;
8783 }
8784 }
8785 print_omx_buffer("FillBufferDone", buffer);
8786 m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
8787 } else {
8788 DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
8789 return OMX_ErrorBadParameter;
8790 }
8791 } else {
8792 DEBUG_PRINT_ERROR("NULL m_cb.FillBufferDone");
8793 return OMX_ErrorBadParameter;
8794 }
8795
8796 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
8797 if (m_smoothstreaming_mode && omx_base_address) {
8798 OMX_U32 buf_index = buffer - omx_base_address;
8799 BufferDim_t dim;
8800 private_handle_t *private_handle = NULL;
8801 dim.sliceWidth = framesize.nWidth;
8802 dim.sliceHeight = framesize.nHeight;
8803 if (buf_index < drv_ctx.op_buf.actualcount &&
8804 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
8805 native_buffer[buf_index].privatehandle)
8806 private_handle = native_buffer[buf_index].privatehandle;
8807 if (private_handle) {
8808 DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
8809 dim.sliceWidth, dim.sliceHeight);
8810 setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
8811 }
8812 }
8813 #endif
8814
8815 return OMX_ErrorNone;
8816 }
8817
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8818 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp,
8819 OMX_BUFFERHEADERTYPE* buffer)
8820 {
8821 VIDC_TRACE_NAME_HIGH("EBD");
8822 int nBufferIndex = buffer - m_inp_mem_ptr;
8823
8824 if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) {
8825 DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
8826 return OMX_ErrorBadParameter;
8827 }
8828
8829 pending_input_buffers--;
8830 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
8831
8832 if (arbitrary_bytes) {
8833 if (pdest_frame == NULL && input_flush_progress == false) {
8834 DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
8835 pdest_frame = buffer;
8836 buffer->nFilledLen = 0;
8837 buffer->nTimeStamp = LLONG_MAX;
8838 push_input_buffer (hComp);
8839 } else {
8840 DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
8841 buffer->nFilledLen = 0;
8842 if (!m_input_free_q.insert_entry((unsigned long)buffer,
8843 (unsigned)NULL, (unsigned)NULL)) {
8844 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
8845 }
8846 }
8847 } else if (m_cb.EmptyBufferDone) {
8848 buffer->nFilledLen = 0;
8849 if (input_use_buffer == true) {
8850 buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
8851 }
8852
8853 /* Restore the FD that we over-wrote in ETB */
8854 if (m_input_pass_buffer_fd) {
8855 buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
8856 }
8857
8858 print_omx_buffer("EmptyBufferDone", buffer);
8859 m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
8860 }
8861 return OMX_ErrorNone;
8862 }
8863
async_message_process(void * context,void * message)8864 int omx_vdec::async_message_process (void *context, void* message)
8865 {
8866 omx_vdec* omx = NULL;
8867 struct vdec_msginfo *vdec_msg = NULL;
8868 OMX_BUFFERHEADERTYPE* omxhdr = NULL;
8869 struct v4l2_buffer *v4l2_buf_ptr = NULL;
8870 struct v4l2_plane *plane = NULL;
8871 struct vdec_output_frameinfo *output_respbuf = NULL;
8872 int rc=1;
8873 bool reconfig_event_sent = false;
8874 if (context == NULL || message == NULL) {
8875 DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
8876 return -1;
8877 }
8878 vdec_msg = (struct vdec_msginfo *)message;
8879
8880 omx = reinterpret_cast<omx_vdec*>(context);
8881
8882 switch (vdec_msg->msgcode) {
8883
8884 case VDEC_MSG_EVT_HW_ERROR:
8885 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8886 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8887 break;
8888
8889 case VDEC_MSG_EVT_HW_OVERLOAD:
8890 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8891 OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
8892 break;
8893
8894 case VDEC_MSG_EVT_HW_UNSUPPORTED:
8895 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8896 OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
8897 break;
8898
8899 case VDEC_MSG_RESP_START_DONE:
8900 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8901 OMX_COMPONENT_GENERATE_START_DONE);
8902 break;
8903
8904 case VDEC_MSG_RESP_STOP_DONE:
8905 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8906 OMX_COMPONENT_GENERATE_STOP_DONE);
8907 break;
8908
8909 case VDEC_MSG_RESP_RESUME_DONE:
8910 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8911 OMX_COMPONENT_GENERATE_RESUME_DONE);
8912 break;
8913
8914 case VDEC_MSG_RESP_PAUSE_DONE:
8915 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8916 OMX_COMPONENT_GENERATE_PAUSE_DONE);
8917 break;
8918
8919 case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
8920 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8921 OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
8922 break;
8923 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
8924 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8925 OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
8926 break;
8927 case VDEC_MSG_RESP_INPUT_FLUSHED:
8928 case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
8929
8930 /* omxhdr = (OMX_BUFFERHEADERTYPE* )
8931 vdec_msg->msgdata.input_frame_clientdata; */
8932
8933 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
8934 if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
8935 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
8936 omxhdr = NULL;
8937 vdec_msg->status_code = VDEC_S_EFATAL;
8938 break;
8939
8940 }
8941 omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
8942
8943 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
8944 DEBUG_PRINT_HIGH("Unsupported input");
8945 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8946 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8947 }
8948 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_DATA_CORRUPT) {
8949 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8950 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
8951 }
8952 if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
8953
8954 DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
8955 android_atomic_dec(&omx->m_queued_codec_config_count);
8956 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
8957 BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
8958 DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
8959 sem_post(&omx->m_safe_flush);
8960 }
8961 }
8962 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
8963 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8964 }
8965 omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
8966 OMX_COMPONENT_GENERATE_EBD);
8967 break;
8968 case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
8969 int64_t *timestamp;
8970 timestamp = (int64_t *) malloc(sizeof(int64_t));
8971 if (timestamp) {
8972 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
8973 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
8974 OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
8975 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
8976 (long long)vdec_msg->msgdata.output_frame.time_stamp);
8977 }
8978 break;
8979 case VDEC_MSG_RESP_OUTPUT_FLUSHED:
8980 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: {
8981 v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
8982
8983 OMX_BUFFERHEADERTYPE *omx_base_address = omx->m_out_mem_ptr;
8984 vdec_bufferpayload *omx_ptr_outputbuffer = omx->drv_ctx.ptr_outputbuffer;
8985 vdec_output_frameinfo *omx_ptr_respbuffer = omx->drv_ctx.ptr_respbuffer;
8986
8987 if (omx->client_buffers.is_color_conversion_enabled()) {
8988 omx_base_address = omx->m_intermediate_out_mem_ptr;
8989 omx_ptr_outputbuffer = omx->drv_ctx.ptr_intermediate_outputbuffer;
8990 omx_ptr_respbuffer = omx->drv_ctx.ptr_intermediate_respbuffer;
8991 }
8992
8993 if (v4l2_buf_ptr == NULL || omx_base_address == NULL ||
8994 v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
8995 omxhdr = NULL;
8996 vdec_msg->status_code = VDEC_S_EFATAL;
8997 break;
8998 }
8999 plane = v4l2_buf_ptr->m.planes;
9000 omxhdr = omx_base_address + v4l2_buf_ptr->index;
9001
9002 if (omxhdr && omxhdr->pOutputPortPrivate &&
9003 ((omxhdr - omx_base_address) < (int)omx->drv_ctx.op_buf.actualcount) &&
9004 (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
9005 - omx_ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
9006
9007 omxhdr->pMarkData = (OMX_PTR)(unsigned long)plane[0].reserved[3];
9008 omxhdr->hMarkTargetComponent = (OMX_HANDLETYPE)(unsigned long)plane[0].reserved[4];
9009
9010 if (vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) {
9011 omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
9012 } else {
9013 DEBUG_PRINT_ERROR("Invalid filled length = %u, set it as buffer size = %u",
9014 (unsigned int)vdec_msg->msgdata.output_frame.len, omxhdr->nAllocLen);
9015 omxhdr->nFilledLen = omxhdr->nAllocLen;
9016 }
9017 omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
9018 omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
9019 omxhdr->nFlags = 0;
9020
9021 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
9022 omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
9023 //rc = -1;
9024 }
9025 if (omxhdr->nFilledLen) {
9026 omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
9027 }
9028 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
9029 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
9030 } else {
9031 omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
9032 }
9033 #if NEED_TO_REVISIT
9034 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
9035 omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
9036 }
9037 #endif
9038 if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
9039 omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
9040 DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
9041 omx_ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
9042 }
9043
9044 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_DATA_CORRUPT) {
9045 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
9046 }
9047
9048 output_respbuf = (struct vdec_output_frameinfo *)\
9049 omxhdr->pOutputPortPrivate;
9050 if (!output_respbuf) {
9051 DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
9052 return -1;
9053 }
9054 output_respbuf->len = vdec_msg->msgdata.output_frame.len;
9055 output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
9056
9057 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
9058 output_respbuf->pic_type = PICTURE_TYPE_I;
9059 }
9060 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
9061 output_respbuf->pic_type = PICTURE_TYPE_P;
9062 }
9063 if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
9064 output_respbuf->pic_type = PICTURE_TYPE_B;
9065 }
9066
9067 if (vdec_msg->msgdata.output_frame.len) {
9068 DEBUG_PRINT_LOW("Processing extradata");
9069 reconfig_event_sent = omx->handle_extradata(omxhdr);
9070
9071 if (omx->m_extradata_info.output_crop_updated) {
9072 DEBUG_PRINT_LOW("Read FBD crop from output extra data");
9073 vdec_msg->msgdata.output_frame.framesize.left = omx->m_extradata_info.output_crop_rect.nLeft;
9074 vdec_msg->msgdata.output_frame.framesize.top = omx->m_extradata_info.output_crop_rect.nTop;
9075 vdec_msg->msgdata.output_frame.framesize.right = omx->m_extradata_info.output_crop_rect.nWidth;
9076 vdec_msg->msgdata.output_frame.framesize.bottom = omx->m_extradata_info.output_crop_rect.nHeight;
9077 vdec_msg->msgdata.output_frame.picsize.frame_width = omx->m_extradata_info.output_width;
9078 vdec_msg->msgdata.output_frame.picsize.frame_height = omx->m_extradata_info.output_height;
9079 memcpy(vdec_msg->msgdata.output_frame.misrinfo,
9080 omx->m_extradata_info.misr_info, sizeof(vdec_misrinfo));
9081 } else {
9082 DEBUG_PRINT_LOW("Read FBD crop from v4l2 reserved fields");
9083 vdec_msg->msgdata.output_frame.framesize.left = plane[0].reserved[2];
9084 vdec_msg->msgdata.output_frame.framesize.top = plane[0].reserved[3];
9085 vdec_msg->msgdata.output_frame.framesize.right = plane[0].reserved[2] + plane[0].reserved[4];
9086 vdec_msg->msgdata.output_frame.framesize.bottom = plane[0].reserved[3] + plane[0].reserved[5];
9087 vdec_msg->msgdata.output_frame.picsize.frame_width = plane[0].reserved[6];
9088 vdec_msg->msgdata.output_frame.picsize.frame_height = plane[0].reserved[7];
9089
9090 /* Copy these values back to OMX internal variables to make both handlign same*/
9091
9092 omx->m_extradata_info.output_crop_rect.nLeft = vdec_msg->msgdata.output_frame.framesize.left;
9093 omx->m_extradata_info.output_crop_rect.nTop = vdec_msg->msgdata.output_frame.framesize.top;
9094 omx->m_extradata_info.output_crop_rect.nWidth = vdec_msg->msgdata.output_frame.framesize.right;
9095 omx->m_extradata_info.output_crop_rect.nHeight = vdec_msg->msgdata.output_frame.framesize.bottom;
9096 omx->m_extradata_info.output_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
9097 omx->m_extradata_info.output_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
9098 }
9099 }
9100
9101 vdec_msg->msgdata.output_frame.bufferaddr =
9102 omx_ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
9103
9104 DEBUG_PRINT_LOW("[RespBufDone] Fd(%d) Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x)"
9105 " FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
9106 omx_ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd,
9107 omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
9108 vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
9109 (unsigned int)vdec_msg->msgdata.output_frame.len,
9110 vdec_msg->msgdata.output_frame.framesize.left,
9111 vdec_msg->msgdata.output_frame.framesize.top,
9112 vdec_msg->msgdata.output_frame.framesize.right,
9113 vdec_msg->msgdata.output_frame.framesize.bottom);
9114
9115 /* Post event if resolution OR crop changed */
9116 /* filled length will be changed if resolution changed */
9117 /* Crop parameters can be changed even without resolution change */
9118 if (omxhdr->nFilledLen
9119 && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
9120 || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
9121 || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
9122 || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
9123 || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
9124 || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
9125 || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
9126
9127 DEBUG_PRINT_HIGH("Parameters Changed From: Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u --> Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u",
9128 omx->prev_n_filled_len,
9129 omx->drv_ctx.video_resolution.frame_width,
9130 omx->drv_ctx.video_resolution.frame_height,
9131 omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
9132 omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
9133 omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
9134 vdec_msg->msgdata.output_frame.picsize.frame_height,
9135 vdec_msg->msgdata.output_frame.framesize.left,
9136 vdec_msg->msgdata.output_frame.framesize.top,
9137 vdec_msg->msgdata.output_frame.framesize.right,
9138 vdec_msg->msgdata.output_frame.framesize.bottom);
9139
9140 memcpy(&omx->drv_ctx.frame_size,
9141 &vdec_msg->msgdata.output_frame.framesize,
9142 sizeof(struct vdec_framesize));
9143
9144 omx->drv_ctx.video_resolution.frame_width =
9145 vdec_msg->msgdata.output_frame.picsize.frame_width;
9146 omx->drv_ctx.video_resolution.frame_height =
9147 vdec_msg->msgdata.output_frame.picsize.frame_height;
9148 if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
9149 omx->drv_ctx.video_resolution.stride =
9150 VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
9151 omx->drv_ctx.video_resolution.scan_lines =
9152 VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
9153 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
9154 omx->drv_ctx.video_resolution.stride =
9155 VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width);
9156 omx->drv_ctx.video_resolution.scan_lines =
9157 VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height);
9158 } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
9159 omx->drv_ctx.video_resolution.stride =
9160 VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_width);
9161 omx->drv_ctx.video_resolution.scan_lines =
9162 VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_height);
9163 }
9164 else if(omx->drv_ctx.output_format == VDEC_YUV_FORMAT_P010_VENUS) {
9165 omx->drv_ctx.video_resolution.stride =
9166 VENUS_Y_STRIDE(COLOR_FMT_P010, omx->drv_ctx.video_resolution.frame_width);
9167 omx->drv_ctx.video_resolution.scan_lines =
9168 VENUS_Y_SCANLINES(COLOR_FMT_P010, omx->drv_ctx.video_resolution.frame_height);
9169 }
9170
9171 if(!reconfig_event_sent) {
9172 omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
9173 OMX_IndexConfigCommonOutputCrop,
9174 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
9175 reconfig_event_sent = true;
9176 } else {
9177 /* Update C2D with new resolution */
9178 if (!omx->client_buffers.update_buffer_req()) {
9179 DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
9180 }
9181 }
9182 }
9183
9184 if (omxhdr->nFilledLen)
9185 omx->prev_n_filled_len = omxhdr->nFilledLen;
9186
9187 if (!omx->m_enable_android_native_buffers && omx->output_use_buffer && omxhdr->pBuffer &&
9188 vdec_msg->msgdata.output_frame.bufferaddr)
9189 memcpy ( omxhdr->pBuffer, (void *)
9190 ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
9191 (unsigned long)vdec_msg->msgdata.output_frame.offset),
9192 vdec_msg->msgdata.output_frame.len);
9193
9194 omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
9195 OMX_COMPONENT_GENERATE_FBD);
9196
9197 } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
9198 omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
9199 OMX_COMPONENT_GENERATE_EOS_DONE);
9200 } else {
9201 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
9202 OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
9203 }
9204 break;
9205 }
9206 case VDEC_MSG_EVT_CONFIG_CHANGED:
9207 DEBUG_PRINT_HIGH("Port settings changed");
9208 omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
9209 omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
9210 omx->isPortReconfigInsufficient = vdec_msg->msgdata.output_frame.flags;
9211 omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
9212 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
9213 break;
9214 default:
9215 break;
9216 }
9217 return rc;
9218 }
9219
empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)9220 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
9221 OMX_HANDLETYPE hComp,
9222 OMX_BUFFERHEADERTYPE *buffer
9223 )
9224 {
9225 unsigned address,p2,id;
9226 DEBUG_PRINT_LOW("Empty this arbitrary");
9227
9228 if (buffer == NULL) {
9229 return OMX_ErrorBadParameter;
9230 }
9231 DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
9232 DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld",
9233 (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp);
9234
9235 /* return zero length and not an EOS buffer */
9236 /* return buffer if input flush in progress */
9237 if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
9238 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
9239 DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
9240 m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
9241 return OMX_ErrorNone;
9242 }
9243
9244 if (psource_frame == NULL) {
9245 DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp);
9246 psource_frame = buffer;
9247 DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
9248 push_input_buffer (hComp);
9249 } else {
9250 DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
9251 if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL,
9252 (unsigned)NULL)) {
9253 return OMX_ErrorBadParameter;
9254 }
9255 }
9256
9257 if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
9258 codec_config_flag = false;
9259 }
9260 return OMX_ErrorNone;
9261 }
9262
push_input_buffer(OMX_HANDLETYPE hComp)9263 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
9264 {
9265 unsigned long address,p2,id;
9266 OMX_ERRORTYPE ret = OMX_ErrorNone;
9267
9268 if (pdest_frame == NULL || psource_frame == NULL) {
9269 /*Check if we have a destination buffer*/
9270 if (pdest_frame == NULL) {
9271 DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
9272 if (m_input_free_q.m_size) {
9273 m_input_free_q.pop_entry(&address,&p2,&id);
9274 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
9275 pdest_frame->nFilledLen = 0;
9276 pdest_frame->nTimeStamp = LLONG_MAX;
9277 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
9278 }
9279 }
9280
9281 /*Check if we have a destination buffer*/
9282 if (psource_frame == NULL) {
9283 DEBUG_PRINT_LOW("Get a source buffer from the queue");
9284 if (m_input_pending_q.m_size) {
9285 m_input_pending_q.pop_entry(&address,&p2,&id);
9286 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
9287 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
9288 psource_frame->nTimeStamp);
9289 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
9290 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9291
9292 }
9293 }
9294
9295 }
9296
9297 while ((pdest_frame != NULL) && (psource_frame != NULL)) {
9298 switch (codec_type_parse) {
9299 case CODEC_TYPE_MPEG2:
9300 ret = push_input_sc_codec(hComp);
9301 break;
9302 case CODEC_TYPE_H264:
9303 ret = push_input_h264(hComp);
9304 break;
9305 case CODEC_TYPE_HEVC:
9306 ret = push_input_hevc(hComp);
9307 break;
9308 default:
9309 break;
9310 }
9311 if (ret != OMX_ErrorNone) {
9312 DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
9313 omx_report_error ();
9314 break;
9315 }
9316 }
9317
9318 return ret;
9319 }
9320
push_input_sc_codec(OMX_HANDLETYPE hComp)9321 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
9322 {
9323 OMX_U32 partial_frame = 1;
9324 OMX_BOOL generate_ebd = OMX_TRUE;
9325 unsigned long address = 0, p2 = 0, id = 0;
9326
9327 DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld",
9328 psource_frame,psource_frame->nTimeStamp);
9329 if (m_frame_parser.parse_sc_frame(psource_frame,
9330 pdest_frame,&partial_frame) == -1) {
9331 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9332 return OMX_ErrorBadParameter;
9333 }
9334
9335 if (partial_frame == 0) {
9336 DEBUG_PRINT_LOW("Frame size %u source %p frame count %d",
9337 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count);
9338
9339
9340 DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp);
9341 /*First Parsed buffer will have only header Hence skip*/
9342 if (frame_count == 0) {
9343 frame_count++;
9344 } else {
9345 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9346 if (pdest_frame->nFilledLen) {
9347 /*Push the frame to the Decoder*/
9348 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9349 return OMX_ErrorBadParameter;
9350 }
9351 frame_count++;
9352 pdest_frame = NULL;
9353
9354 if (m_input_free_q.m_size) {
9355 m_input_free_q.pop_entry(&address,&p2,&id);
9356 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9357 pdest_frame->nFilledLen = 0;
9358 }
9359 } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
9360 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
9361 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL,
9362 (unsigned)NULL);
9363 pdest_frame = NULL;
9364 }
9365 }
9366 } else {
9367 DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen);
9368 /*Check if Destination Buffer is full*/
9369 if (pdest_frame->nAllocLen ==
9370 pdest_frame->nFilledLen + pdest_frame->nOffset) {
9371 DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
9372 return OMX_ErrorStreamCorrupt;
9373 }
9374 }
9375
9376 if (psource_frame->nFilledLen == 0) {
9377 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9378 if (pdest_frame) {
9379 pdest_frame->nFlags |= psource_frame->nFlags;
9380 pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
9381 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld",
9382 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9383 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9384 (unsigned int)pdest_frame->nFilledLen,frame_count++);
9385 /*Push the frame to the Decoder*/
9386 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9387 return OMX_ErrorBadParameter;
9388 }
9389 frame_count++;
9390 pdest_frame = NULL;
9391 } else {
9392 DEBUG_PRINT_LOW("Last frame in else dest addr") ;
9393 generate_ebd = OMX_FALSE;
9394 }
9395 }
9396 if (generate_ebd) {
9397 DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
9398 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9399 psource_frame = NULL;
9400
9401 if (m_input_pending_q.m_size) {
9402 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9403 m_input_pending_q.pop_entry(&address,&p2,&id);
9404 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9405 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
9406 psource_frame->nTimeStamp);
9407 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
9408 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9409 }
9410 }
9411 }
9412 return OMX_ErrorNone;
9413 }
9414
push_input_h264(OMX_HANDLETYPE hComp)9415 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
9416 {
9417 OMX_U32 partial_frame = 1;
9418 unsigned long address = 0, p2 = 0, id = 0;
9419 OMX_BOOL isNewFrame = OMX_FALSE;
9420 OMX_BOOL generate_ebd = OMX_TRUE;
9421
9422 if (h264_scratch.pBuffer == NULL) {
9423 DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
9424 return OMX_ErrorBadParameter;
9425 }
9426 DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u "
9427 "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal);
9428 DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen);
9429 if (h264_scratch.nFilledLen && look_ahead_nal) {
9430 look_ahead_nal = false;
9431 if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9432 h264_scratch.nFilledLen) {
9433 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9434 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9435 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9436 DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
9437 h264_scratch.nFilledLen = 0;
9438 } else {
9439 DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
9440 return OMX_ErrorBadParameter;
9441 }
9442 }
9443
9444 /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result
9445 in EOS flag getting associated with the destination
9446 */
9447 if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) &&
9448 pdest_frame->nFilledLen) {
9449 DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'");
9450 generate_ebd = OMX_FALSE;
9451 }
9452
9453 if (nal_length == 0) {
9454 DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
9455 if (m_frame_parser.parse_sc_frame(psource_frame,
9456 &h264_scratch,&partial_frame) == -1) {
9457 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9458 return OMX_ErrorBadParameter;
9459 }
9460 } else {
9461 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
9462 if (m_frame_parser.parse_h264_nallength(psource_frame,
9463 &h264_scratch,&partial_frame) == -1) {
9464 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9465 return OMX_ErrorBadParameter;
9466 }
9467 }
9468
9469 if (partial_frame == 0) {
9470 if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9471 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9472 nal_count++;
9473 h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9474 h264_scratch.nFlags = psource_frame->nFlags;
9475 } else {
9476 DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen);
9477 if (h264_scratch.nFilledLen) {
9478 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
9479 NALU_TYPE_SPS);
9480 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9481 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
9482 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9483 h264_scratch.nFilledLen, NALU_TYPE_SEI);
9484 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9485 // If timeinfo is present frame info from SEI is already processed
9486 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9487 h264_scratch.nFilledLen, NALU_TYPE_SEI);
9488 #endif
9489 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9490 nal_count++;
9491 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
9492 pdest_frame->nTimeStamp = h264_last_au_ts;
9493 pdest_frame->nFlags = h264_last_au_flags;
9494 #ifdef PANSCAN_HDLR
9495 if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9496 h264_parser->update_panscan_data(h264_last_au_ts);
9497 #endif
9498 }
9499 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
9500 m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
9501 h264_last_au_ts = h264_scratch.nTimeStamp;
9502 h264_last_au_flags = h264_scratch.nFlags;
9503 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9504 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9505 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
9506 if (!VALID_TS(h264_last_au_ts))
9507 h264_last_au_ts = ts_in_sei;
9508 }
9509 #endif
9510 } else
9511 h264_last_au_ts = LLONG_MAX;
9512 }
9513
9514 if (!isNewFrame) {
9515 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9516 h264_scratch.nFilledLen) {
9517 DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u",
9518 (unsigned int)h264_scratch.nFilledLen);
9519 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9520 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9521 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9522 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
9523 pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
9524 h264_scratch.nFilledLen = 0;
9525 } else {
9526 DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
9527 return OMX_ErrorBadParameter;
9528 }
9529 } else if(h264_scratch.nFilledLen) {
9530 look_ahead_nal = true;
9531 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu",
9532 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9533 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9534 (unsigned int)pdest_frame->nFilledLen,frame_count++);
9535
9536 if (pdest_frame->nFilledLen == 0) {
9537 DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
9538 look_ahead_nal = false;
9539 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9540 h264_scratch.nFilledLen) {
9541 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9542 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9543 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9544 h264_scratch.nFilledLen = 0;
9545 } else {
9546 DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
9547 return OMX_ErrorBadParameter;
9548 }
9549 } else {
9550 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9551 DEBUG_PRINT_LOW("Reset the EOS Flag");
9552 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9553 }
9554 /*Push the frame to the Decoder*/
9555 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9556 return OMX_ErrorBadParameter;
9557 }
9558 //frame_count++;
9559 pdest_frame = NULL;
9560 if (m_input_free_q.m_size) {
9561 m_input_free_q.pop_entry(&address,&p2,&id);
9562 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9563 DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
9564 pdest_frame->nFilledLen = 0;
9565 pdest_frame->nFlags = 0;
9566 pdest_frame->nTimeStamp = LLONG_MAX;
9567 }
9568 }
9569 }
9570 }
9571 } else {
9572 DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen);
9573 /*Check if Destination Buffer is full*/
9574 if (h264_scratch.nAllocLen ==
9575 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9576 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9577 return OMX_ErrorStreamCorrupt;
9578 }
9579 }
9580
9581 if (!psource_frame->nFilledLen) {
9582 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
9583
9584 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9585 if (pdest_frame) {
9586 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9587 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9588 h264_scratch.nFilledLen) {
9589 if(pdest_frame->nFilledLen == 0) {
9590 /* No residual frame from before, send whatever
9591 * we have left */
9592 memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9593 h264_scratch.pBuffer, h264_scratch.nFilledLen);
9594 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9595 h264_scratch.nFilledLen = 0;
9596 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9597 } else {
9598 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9599 if(!isNewFrame) {
9600 /* Have a residual frame, but we know that the
9601 * AU in this frame is belonging to whatever
9602 * frame we had left over. So append it */
9603 memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9604 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9605 pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9606 h264_scratch.nFilledLen = 0;
9607 if (h264_last_au_ts != LLONG_MAX)
9608 pdest_frame->nTimeStamp = h264_last_au_ts;
9609 } else {
9610 /* Completely new frame, let's just push what
9611 * we have now. The resulting EBD would trigger
9612 * another push */
9613 generate_ebd = OMX_FALSE;
9614 pdest_frame->nTimeStamp = h264_last_au_ts;
9615 h264_last_au_ts = h264_scratch.nTimeStamp;
9616 }
9617 }
9618 } else {
9619 DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
9620 return OMX_ErrorBadParameter;
9621 }
9622
9623 /* Iff we coalesced two buffers, inherit the flags of both bufs */
9624 if(generate_ebd == OMX_TRUE) {
9625 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9626 }
9627
9628 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu",
9629 (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9630 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
9631 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9632 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9633 OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
9634 if (!VALID_TS(pdest_frame->nTimeStamp))
9635 pdest_frame->nTimeStamp = ts_in_sei;
9636 }
9637 #endif
9638 /*Push the frame to the Decoder*/
9639 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9640 return OMX_ErrorBadParameter;
9641 }
9642 frame_count++;
9643 pdest_frame = NULL;
9644 } else {
9645 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9646 pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9647 generate_ebd = OMX_FALSE;
9648 }
9649 }
9650 }
9651 if (generate_ebd && !psource_frame->nFilledLen) {
9652 m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9653 psource_frame = NULL;
9654 if (m_input_pending_q.m_size) {
9655 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9656 m_input_pending_q.pop_entry(&address,&p2,&id);
9657 psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9658 DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u",
9659 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9660 }
9661 }
9662 return OMX_ErrorNone;
9663 }
9664
copy_buffer(OMX_BUFFERHEADERTYPE * pDst,OMX_BUFFERHEADERTYPE * pSrc)9665 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
9666 {
9667 OMX_ERRORTYPE rc = OMX_ErrorNone;
9668 if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
9669 memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
9670 if (pDst->nTimeStamp == LLONG_MAX) {
9671 pDst->nTimeStamp = pSrc->nTimeStamp;
9672 DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp);
9673 }
9674 pDst->nFilledLen += pSrc->nFilledLen;
9675 pSrc->nFilledLen = 0;
9676 } else {
9677 DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
9678 rc = OMX_ErrorBadParameter;
9679 }
9680 return rc;
9681 }
9682
push_input_hevc(OMX_HANDLETYPE hComp)9683 OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp)
9684 {
9685 OMX_U32 partial_frame = 1;
9686 unsigned long address,p2,id;
9687 OMX_BOOL isNewFrame = OMX_FALSE;
9688 OMX_BOOL generate_ebd = OMX_TRUE;
9689 OMX_ERRORTYPE rc = OMX_ErrorNone;
9690 if (h264_scratch.pBuffer == NULL) {
9691 DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
9692 return OMX_ErrorBadParameter;
9693 }
9694
9695 DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \
9696 pdest_frame nFilledLen %u nTimeStamp %lld",
9697 (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9698
9699 if (h264_scratch.nFilledLen && look_ahead_nal) {
9700 look_ahead_nal = false;
9701 rc = copy_buffer(pdest_frame, &h264_scratch);
9702 if (rc != OMX_ErrorNone) {
9703 return rc;
9704 }
9705 }
9706
9707 if (nal_length == 0) {
9708 if (m_frame_parser.parse_sc_frame(psource_frame,
9709 &h264_scratch,&partial_frame) == -1) {
9710 DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9711 return OMX_ErrorBadParameter;
9712 }
9713 } else {
9714 DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
9715 if (m_frame_parser.parse_h264_nallength(psource_frame,
9716 &h264_scratch,&partial_frame) == -1) {
9717 DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9718 return OMX_ErrorBadParameter;
9719 }
9720 }
9721
9722 if (partial_frame == 0) {
9723 if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9724 DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9725 nal_count++;
9726 h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9727 h264_scratch.nFlags = psource_frame->nFlags;
9728 } else {
9729 DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen);
9730 if (h264_scratch.nFilledLen) {
9731 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame);
9732 nal_count++;
9733 }
9734
9735 if (!isNewFrame) {
9736 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \
9737 nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld",
9738 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp,
9739 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9740 rc = copy_buffer(pdest_frame, &h264_scratch);
9741 if (rc != OMX_ErrorNone) {
9742 return rc;
9743 }
9744 } else {
9745 look_ahead_nal = true;
9746 if (pdest_frame->nFilledLen == 0) {
9747 look_ahead_nal = false;
9748 DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
9749 rc = copy_buffer(pdest_frame, &h264_scratch);
9750 if (rc != OMX_ErrorNone) {
9751 return OMX_ErrorBadParameter;
9752 }
9753 } else {
9754 if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9755 pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9756 }
9757 DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \
9758 nTimeStamp %lld, look_ahead_nal in h264_scratch \
9759 nFilledLen %u nTimeStamp %lld",
9760 frame_count++, (unsigned int)pdest_frame->nFilledLen,
9761 pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen,
9762 h264_scratch.nTimeStamp);
9763 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9764 return OMX_ErrorBadParameter;
9765 }
9766 pdest_frame = NULL;
9767 if (m_input_free_q.m_size) {
9768 m_input_free_q.pop_entry(&address, &p2, &id);
9769 pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9770 DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame);
9771 pdest_frame->nFilledLen = 0;
9772 pdest_frame->nFlags = 0;
9773 pdest_frame->nTimeStamp = LLONG_MAX;
9774 }
9775 }
9776 }
9777 }
9778 } else {
9779 DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \
9780 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \
9781 nFilledLen %u nTimeStamp %lld",
9782 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp,
9783 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp,
9784 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
9785
9786 if (h264_scratch.nAllocLen ==
9787 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9788 DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9789 return OMX_ErrorStreamCorrupt;
9790 }
9791 }
9792
9793 if (!psource_frame->nFilledLen) {
9794 DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame);
9795 if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9796 if (pdest_frame) {
9797 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9798 rc = copy_buffer(pdest_frame, &h264_scratch);
9799 if ( rc != OMX_ErrorNone ) {
9800 return rc;
9801 }
9802 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9803 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9804 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld",
9805 frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9806 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9807 return OMX_ErrorBadParameter;
9808 }
9809 frame_count++;
9810 pdest_frame = NULL;
9811 } else {
9812 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9813 pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9814 generate_ebd = OMX_FALSE;
9815 }
9816 }
9817 }
9818
9819 if (generate_ebd && !psource_frame->nFilledLen) {
9820 m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame);
9821 psource_frame = NULL;
9822 if (m_input_pending_q.m_size) {
9823 m_input_pending_q.pop_entry(&address, &p2, &id);
9824 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
9825 DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld",
9826 (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp);
9827 }
9828 }
9829 return OMX_ErrorNone;
9830 }
9831
9832 #ifdef USE_GBM
alloc_map_gbm_memory(OMX_U32 w,OMX_U32 h,int dev_fd,struct vdec_gbm * op_buf_gbm_info,int flag)9833 bool omx_vdec::alloc_map_gbm_memory(OMX_U32 w,OMX_U32 h,int dev_fd,
9834 struct vdec_gbm *op_buf_gbm_info, int flag)
9835 {
9836
9837 uint32 flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
9838 struct gbm_device *gbm = NULL;
9839 struct gbm_bo *bo = NULL;
9840 int bo_fd = -1, meta_fd = -1;
9841 if (!op_buf_gbm_info || dev_fd < 0 ) {
9842 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
9843 return FALSE;
9844 }
9845
9846 gbm = gbm_create_device(dev_fd);
9847 if (gbm == NULL) {
9848 DEBUG_PRINT_ERROR("create gbm device failed");
9849 return FALSE;
9850 } else {
9851 DEBUG_PRINT_LOW( "Successfully created gbm device");
9852 }
9853 if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC)
9854 flags |= GBM_BO_USAGE_UBWC_ALIGNED_QTI;
9855
9856 DEBUG_PRINT_LOW("create NV12 gbm_bo with width=%d, height=%d", w, h);
9857 bo = gbm_bo_create(gbm, w, h,GBM_FORMAT_NV12,
9858 flags);
9859
9860 if (bo == NULL) {
9861 DEBUG_PRINT_ERROR("Create bo failed");
9862 gbm_device_destroy(gbm);
9863 return FALSE;
9864 }
9865
9866 bo_fd = gbm_bo_get_fd(bo);
9867 if (bo_fd < 0) {
9868 DEBUG_PRINT_ERROR("Get bo fd failed");
9869 gbm_bo_destroy(bo);
9870 gbm_device_destroy(gbm);
9871 return FALSE;
9872 }
9873
9874 gbm_perform(GBM_PERFORM_GET_METADATA_ION_FD, bo, &meta_fd);
9875 if (meta_fd < 0) {
9876 DEBUG_PRINT_ERROR("Get bo meta fd failed");
9877 gbm_bo_destroy(bo);
9878 gbm_device_destroy(gbm);
9879 return FALSE;
9880 }
9881 op_buf_gbm_info->gbm = gbm;
9882 op_buf_gbm_info->bo = bo;
9883 op_buf_gbm_info->bo_fd = bo_fd;
9884 op_buf_gbm_info->meta_fd = meta_fd;
9885
9886 DEBUG_PRINT_LOW("allocate gbm bo fd meta fd %p %d %d",bo,bo_fd,meta_fd);
9887 return TRUE;
9888 }
9889
free_gbm_memory(struct vdec_gbm * buf_gbm_info)9890 void omx_vdec::free_gbm_memory(struct vdec_gbm *buf_gbm_info)
9891 {
9892 if(!buf_gbm_info) {
9893 DEBUG_PRINT_ERROR(" GBM: free called with invalid fd/allocdata");
9894 return;
9895 }
9896 DEBUG_PRINT_LOW("free gbm bo fd meta fd %p %d %d",
9897 buf_gbm_info->bo,buf_gbm_info->bo_fd,buf_gbm_info->meta_fd);
9898
9899 if (buf_gbm_info->bo)
9900 gbm_bo_destroy(buf_gbm_info->bo);
9901 buf_gbm_info->bo = NULL;
9902
9903 if (buf_gbm_info->gbm)
9904 gbm_device_destroy(buf_gbm_info->gbm);
9905 buf_gbm_info->gbm = NULL;
9906
9907 buf_gbm_info->bo_fd = -1;
9908 buf_gbm_info->meta_fd = -1;
9909 }
9910 #endif
9911 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)9912 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
9913 OMX_U32 alignment)
9914 {
9915 struct pmem_allocation allocation;
9916 allocation.size = buffer_size;
9917 allocation.align = clip2(alignment);
9918 if (allocation.align < 4096) {
9919 allocation.align = 4096;
9920 }
9921 if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
9922 DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
9923 allocation.align, allocation.size);
9924 return false;
9925 }
9926 return true;
9927 }
9928 #endif
9929 #ifdef USE_ION
alloc_map_ion_memory(OMX_U32 buffer_size,vdec_ion * ion_info,int flag)9930 bool omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size, vdec_ion *ion_info, int flag)
9931
9932 {
9933 int rc = -EINVAL;
9934 int ion_dev_flag;
9935 struct vdec_ion ion_buf_info;
9936
9937 if (!ion_info || buffer_size <= 0) {
9938 DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
9939 return false;
9940 }
9941
9942 ion_info->dev_fd = ion_open();
9943 if (ion_info->dev_fd < 0) {
9944 DEBUG_PRINT_ERROR("opening ion device failed with ion_fd = %d", ion_info->dev_fd);
9945 return false;
9946 }
9947
9948 #ifdef HYPERVISOR
9949 flag &= ~ION_FLAG_CACHED;
9950 #endif
9951 ion_info->alloc_data.flags = flag;
9952 ion_info->alloc_data.len = buffer_size;
9953
9954 ion_info->alloc_data.heap_id_mask = ION_HEAP(ION_SYSTEM_HEAP_ID);
9955 if (secure_mode && (ion_info->alloc_data.flags & ION_FLAG_SECURE)) {
9956 #ifdef HYPERVISOR
9957 ion_info->alloc_data.heap_id_mask = ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
9958 #else
9959 ion_info->alloc_data.heap_id_mask = ION_HEAP(MEM_HEAP_ID);
9960 #endif
9961 }
9962
9963 /* Use secure display cma heap for obvious reasons. */
9964 if (ion_info->alloc_data.flags & ION_FLAG_CP_BITSTREAM) {
9965 ion_info->alloc_data.heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
9966 }
9967
9968 rc = ion_alloc_fd(ion_info->dev_fd, ion_info->alloc_data.len, 0,
9969 ion_info->alloc_data.heap_id_mask, ion_info->alloc_data.flags,
9970 &ion_info->data_fd);
9971
9972 if (rc || ion_info->data_fd < 0) {
9973 DEBUG_PRINT_ERROR("ION ALLOC memory failed");
9974 ion_close(ion_info->dev_fd);
9975 ion_info->data_fd = -1;
9976 ion_info->dev_fd = -1;
9977 return false;
9978 }
9979
9980 DEBUG_PRINT_HIGH("Alloc ion memory: fd (dev:%d data:%d) len %d flags %#x mask %#x",
9981 ion_info->dev_fd, ion_info->data_fd, (unsigned int)ion_info->alloc_data.len,
9982 (unsigned int)ion_info->alloc_data.flags,
9983 (unsigned int)ion_info->alloc_data.heap_id_mask);
9984
9985 return true;
9986 }
9987
free_ion_memory(struct vdec_ion * buf_ion_info)9988 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
9989 {
9990
9991 if (!buf_ion_info) {
9992 DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
9993 return;
9994 }
9995 DEBUG_PRINT_HIGH("Free ion memory: mmap fd %d ion_dev fd %d len %d flags %#x mask %#x",
9996 buf_ion_info->data_fd, buf_ion_info->dev_fd,
9997 (unsigned int)buf_ion_info->alloc_data.len,
9998 (unsigned int)buf_ion_info->alloc_data.flags,
9999 (unsigned int)buf_ion_info->alloc_data.heap_id_mask);
10000
10001 if (buf_ion_info->data_fd >= 0) {
10002 close(buf_ion_info->data_fd);
10003 buf_ion_info->data_fd = -1;
10004 }
10005 if (buf_ion_info->dev_fd >= 0) {
10006 ion_close(buf_ion_info->dev_fd);
10007 buf_ion_info->dev_fd = -1;
10008 }
10009 }
10010
do_cache_operations(int fd)10011 void omx_vdec::do_cache_operations(int fd)
10012 {
10013 if (fd < 0)
10014 return;
10015
10016 struct dma_buf_sync dma_buf_sync_data[2];
10017 dma_buf_sync_data[0].flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
10018 dma_buf_sync_data[1].flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
10019
10020 for(unsigned int i=0; i<2; i++) {
10021 int rc = ioctl(fd, DMA_BUF_IOCTL_SYNC, &dma_buf_sync_data[i]);
10022 if (rc < 0) {
10023 DEBUG_PRINT_ERROR("Failed DMA_BUF_IOCTL_SYNC %s fd : %d", i==0?"start":"end", fd);
10024 return;
10025 }
10026 }
10027 }
10028
10029 #endif
free_output_buffer_header(bool intermediate)10030 void omx_vdec::free_output_buffer_header(bool intermediate)
10031 {
10032 DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
10033 output_use_buffer = false;
10034 ouput_egl_buffers = false;
10035
10036 OMX_BUFFERHEADERTYPE **omx_base_address =
10037 intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
10038 vdec_bufferpayload **omx_ptr_outputbuffer =
10039 intermediate?&drv_ctx.ptr_intermediate_outputbuffer:&drv_ctx.ptr_outputbuffer;
10040 vdec_output_frameinfo **omx_ptr_respbuffer =
10041 intermediate?&drv_ctx.ptr_intermediate_respbuffer:&drv_ctx.ptr_respbuffer;
10042 vdec_ion **omx_op_buf_ion_info =
10043 intermediate?&drv_ctx.op_intermediate_buf_ion_info:&drv_ctx.op_buf_ion_info;
10044 #ifdef USE_GBM
10045 vdec_gbm **omx_op_buf_gbm_info =
10046 intermediate?&drv_ctx.op_intermediate_buf_gbm_info:&drv_ctx.op_buf_gbm_info;
10047 #endif
10048
10049 if (*omx_base_address) {
10050 free (*omx_base_address);
10051 *omx_base_address = NULL;
10052 }
10053
10054 if (m_platform_list) {
10055 free(m_platform_list);
10056 m_platform_list = NULL;
10057 }
10058
10059 if (*omx_ptr_respbuffer) {
10060 free (*omx_ptr_respbuffer);
10061 *omx_ptr_respbuffer = NULL;
10062 }
10063 if (*omx_ptr_outputbuffer) {
10064 free (*omx_ptr_outputbuffer);
10065 *omx_ptr_outputbuffer = NULL;
10066 }
10067 #ifdef USE_GBM
10068 if (*omx_op_buf_gbm_info) {
10069 DEBUG_PRINT_LOW("Free o/p gbm context");
10070 free(*omx_op_buf_gbm_info);
10071 *omx_op_buf_gbm_info = NULL;
10072 }
10073 if (drv_ctx.gbm_device_fd >= 0) {
10074 DEBUG_PRINT_LOW("Close gbm device");
10075 close(drv_ctx.gbm_device_fd);
10076 drv_ctx.gbm_device_fd = -1;
10077 }
10078
10079 #elif defined USE_ION
10080 if (*omx_op_buf_ion_info) {
10081 DEBUG_PRINT_LOW("Free o/p ion context");
10082 free(*omx_op_buf_ion_info);
10083 *omx_op_buf_ion_info = NULL;
10084 }
10085 #endif
10086 if (intermediate == false && client_buffers.is_color_conversion_enabled()) {
10087 free_output_buffer_header(true);
10088 }
10089 }
10090
free_input_buffer_header()10091 void omx_vdec::free_input_buffer_header()
10092 {
10093 input_use_buffer = false;
10094 if (arbitrary_bytes) {
10095 if (m_inp_heap_ptr) {
10096 DEBUG_PRINT_LOW("Free input Heap Pointer");
10097 free (m_inp_heap_ptr);
10098 m_inp_heap_ptr = NULL;
10099 }
10100
10101 if (m_phdr_pmem_ptr) {
10102 DEBUG_PRINT_LOW("Free input pmem header Pointer");
10103 free (m_phdr_pmem_ptr);
10104 m_phdr_pmem_ptr = NULL;
10105 }
10106 }
10107 if (m_inp_mem_ptr) {
10108 DEBUG_PRINT_LOW("Free input pmem Pointer area");
10109 free (m_inp_mem_ptr);
10110 m_inp_mem_ptr = NULL;
10111 }
10112 /* We just freed all the buffer headers, every thing in m_input_free_q,
10113 * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
10114 while (m_input_free_q.m_size) {
10115 unsigned long address, p2, id;
10116 m_input_free_q.pop_entry(&address, &p2, &id);
10117 }
10118 while (m_input_pending_q.m_size) {
10119 unsigned long address, p2, id;
10120 m_input_pending_q.pop_entry(&address, &p2, &id);
10121 }
10122 pdest_frame = NULL;
10123 psource_frame = NULL;
10124 if (drv_ctx.ptr_inputbuffer) {
10125 DEBUG_PRINT_LOW("Free Driver Context pointer");
10126 free (drv_ctx.ptr_inputbuffer);
10127 drv_ctx.ptr_inputbuffer = NULL;
10128 }
10129 #ifdef USE_ION
10130 if (drv_ctx.ip_buf_ion_info) {
10131 DEBUG_PRINT_LOW("Free ion context");
10132 free(drv_ctx.ip_buf_ion_info);
10133 drv_ctx.ip_buf_ion_info = NULL;
10134 }
10135 #endif
10136 }
10137
free_output_extradata_buffer_header()10138 void omx_vdec::free_output_extradata_buffer_header() {
10139 client_extradata = false;
10140 if (m_client_output_extradata_mem_ptr) {
10141 DEBUG_PRINT_LOW("Free extradata pmem Pointer area");
10142 free(m_client_output_extradata_mem_ptr);
10143 m_client_output_extradata_mem_ptr = NULL;
10144 }
10145 }
10146
stream_off(OMX_U32 port)10147 int omx_vdec::stream_off(OMX_U32 port)
10148 {
10149 enum v4l2_buf_type btype;
10150 int rc = 0;
10151 enum v4l2_ports v4l2_port = OUTPUT_PORT;
10152 struct v4l2_requestbuffers bufreq;
10153
10154 if (port == OMX_CORE_INPUT_PORT_INDEX) {
10155 btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10156 v4l2_port = OUTPUT_PORT;
10157 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
10158 btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10159 v4l2_port = CAPTURE_PORT;
10160 } else if (port == OMX_ALL) {
10161 int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
10162 int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
10163
10164 if (!rc_input)
10165 return rc_input;
10166 else
10167 return rc_output;
10168 }
10169
10170 if (!streaming[v4l2_port]) {
10171 // already streamed off, warn and move on
10172 DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
10173 " which is already streamed off", v4l2_port);
10174 return 0;
10175 }
10176
10177 DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
10178
10179 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
10180 if (rc) {
10181 /*TODO: How to handle this case */
10182 DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
10183 } else {
10184 streaming[v4l2_port] = false;
10185 }
10186
10187 if (port == OMX_CORE_INPUT_PORT_INDEX) {
10188 bufreq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10189 } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
10190 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10191 }
10192
10193 bufreq.memory = V4L2_MEMORY_USERPTR;
10194 bufreq.count = 0;
10195 rc = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10196 if (rc) {
10197 DEBUG_PRINT_ERROR("Failed to release buffers on %d Port", v4l2_port);
10198 }
10199 return rc;
10200 }
10201
get_buffer_req(vdec_allocatorproperty * buffer_prop)10202 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
10203 {
10204 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10205 struct v4l2_control control;
10206 unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
10207 unsigned int final_extra_data_size = 0;
10208 struct v4l2_format fmt;
10209 int ret = 0;
10210 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
10211 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10212
10213 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10214 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10215 fmt.fmt.pix_mp.pixelformat = output_capability;
10216 control.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT;
10217 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10218 fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10219 fmt.fmt.pix_mp.pixelformat = capture_capability;
10220 control.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
10221 } else {
10222 eRet = OMX_ErrorBadParameter;
10223 }
10224 if (eRet == OMX_ErrorNone) {
10225 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control);
10226 }
10227 if (ret) {
10228 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
10229 /*TODO: How to handle this case */
10230 eRet = OMX_ErrorInsufficientResources;
10231 return eRet;
10232 }
10233 buffer_prop->actualcount = buffer_prop->mincount = control.value;
10234 DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
10235 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10236
10237 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10238
10239 if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
10240 drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
10241 DEBUG_PRINT_HIGH("Buffer Size = %d, type = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage, fmt.type);
10242
10243 if (ret) {
10244 /*TODO: How to handle this case */
10245 DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
10246 eRet = OMX_ErrorInsufficientResources;
10247 } else {
10248 int extra_idx = 0;
10249
10250 buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
10251 buf_size = buffer_prop->buffer_size;
10252 extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
10253 if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
10254 extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
10255 } else if (extra_idx >= VIDEO_MAX_PLANES) {
10256 DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
10257 return OMX_ErrorBadParameter;
10258 }
10259
10260 default_extra_data_size = VENUS_EXTRADATA_SIZE(
10261 drv_ctx.video_resolution.frame_height,
10262 drv_ctx.video_resolution.frame_width);
10263 final_extra_data_size = extra_data_size > default_extra_data_size ?
10264 extra_data_size : default_extra_data_size;
10265
10266 final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
10267 (~(buffer_prop->alignment - 1));
10268
10269 drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
10270 drv_ctx.extradata_info.count = buffer_prop->actualcount;
10271 drv_ctx.extradata_info.buffer_size = final_extra_data_size;
10272 buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
10273 DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
10274 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
10275 if (extra_data_size)
10276 DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
10277 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
10278
10279 if (in_reconfig) // BufReq will be set to driver when port is disabled
10280 buffer_prop->buffer_size = buf_size;
10281 else if (buf_size != buffer_prop->buffer_size) {
10282 buffer_prop->buffer_size = buf_size;
10283 eRet = set_buffer_req(buffer_prop);
10284 }
10285 }
10286 DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
10287 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10288 return eRet;
10289 }
10290
set_buffer_req(vdec_allocatorproperty * buffer_prop)10291 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
10292 {
10293 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10294 unsigned buf_size = 0;
10295 struct v4l2_format fmt, c_fmt;
10296 struct v4l2_requestbuffers bufreq;
10297 int ret = 0;
10298 DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
10299 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10300 buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
10301 if (buf_size != buffer_prop->buffer_size) {
10302 DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
10303 (unsigned int)buffer_prop->buffer_size, buf_size);
10304 eRet = OMX_ErrorBadParameter;
10305 } else {
10306 memset(&fmt, 0x0, sizeof(struct v4l2_format));
10307 memset(&c_fmt, 0x0, sizeof(struct v4l2_format));
10308 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
10309 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
10310 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
10311
10312 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10313 fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10314 fmt.fmt.pix_mp.pixelformat = output_capability;
10315 DEBUG_PRINT_LOW("S_FMT: type %d wxh %dx%d size %d format %x",
10316 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
10317 fmt.fmt.pix_mp.plane_fmt[0].sizeimage, fmt.fmt.pix_mp.pixelformat);
10318 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10319 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10320 c_fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10321 c_fmt.fmt.pix_mp.pixelformat = capture_capability;
10322 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &c_fmt);
10323 c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
10324 DEBUG_PRINT_LOW("S_FMT: type %d wxh %dx%d size %d format %x",
10325 c_fmt.type, c_fmt.fmt.pix_mp.width, c_fmt.fmt.pix_mp.height,
10326 c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage, c_fmt.fmt.pix_mp.pixelformat);
10327 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &c_fmt);
10328 } else {
10329 eRet = OMX_ErrorBadParameter;
10330 }
10331 if (ret) {
10332 DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
10333 eRet = OMX_ErrorInsufficientResources;
10334 }
10335
10336 bufreq.memory = V4L2_MEMORY_USERPTR;
10337 bufreq.count = buffer_prop->actualcount;
10338 if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10339 bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10340 } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10341 bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10342 } else {
10343 eRet = OMX_ErrorBadParameter;
10344 }
10345
10346 if (eRet == OMX_ErrorNone) {
10347 DEBUG_PRINT_LOW("REQBUFS: type %d count %d", bufreq.type, bufreq.count);
10348 ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10349 }
10350
10351 if (ret) {
10352 DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
10353 /*TODO: How to handle this case */
10354 eRet = OMX_ErrorInsufficientResources;
10355 } else if (bufreq.count < buffer_prop->actualcount) {
10356 DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
10357 " on v4l2 port %d to %d (prefers %d)", bufreq.type,
10358 buffer_prop->actualcount, bufreq.count);
10359 eRet = OMX_ErrorInsufficientResources;
10360 } else {
10361 if (!client_buffers.update_buffer_req()) {
10362 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
10363 eRet = OMX_ErrorInsufficientResources;
10364 }
10365 }
10366 }
10367 return eRet;
10368 }
10369
update_picture_resolution()10370 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
10371 {
10372 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10373 return eRet;
10374 }
10375
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)10376 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
10377 {
10378 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10379 struct v4l2_format fmt;
10380 if (!portDefn) {
10381 DEBUG_PRINT_ERROR("update_portdef: invalid params");
10382 return OMX_ErrorBadParameter;
10383 }
10384 portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
10385 portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
10386 portDefn->eDomain = OMX_PortDomainVideo;
10387 memset(&fmt, 0x0, sizeof(struct v4l2_format));
10388 if (0 == portDefn->nPortIndex) {
10389 int ret = 0;
10390 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10391 fmt.fmt.pix_mp.pixelformat = output_capability;
10392 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10393 if (ret) {
10394 DEBUG_PRINT_ERROR("Get Resolution failed");
10395 return OMX_ErrorHardware;
10396 }
10397 drv_ctx.ip_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
10398 portDefn->eDir = OMX_DirInput;
10399 portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
10400 portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount;
10401 portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size;
10402 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
10403 portDefn->format.video.eCompressionFormat = eCompressionFormat;
10404 //for input port, always report the fps value set by client,
10405 //to distinguish whether client got valid fps from parser.
10406 portDefn->format.video.xFramerate = m_fps_received;
10407 portDefn->bEnabled = m_inp_bEnabled;
10408 portDefn->bPopulated = m_inp_bPopulated;
10409 } else if (1 == portDefn->nPortIndex) {
10410 unsigned int buf_size = 0;
10411 int ret = 0;
10412 if (!is_down_scalar_enabled) {
10413 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10414 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10415 fmt.fmt.pix_mp.pixelformat = capture_capability;
10416 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10417 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10418 }
10419
10420 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10421 fmt.fmt.pix_mp.pixelformat = capture_capability;
10422 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10423 if (ret) {
10424 DEBUG_PRINT_ERROR("Get Resolution failed");
10425 return OMX_ErrorHardware;
10426 }
10427 drv_ctx.op_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
10428 if (!client_buffers.update_buffer_req()) {
10429 DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
10430 return OMX_ErrorHardware;
10431 }
10432
10433 if (!client_buffers.get_buffer_req(buf_size)) {
10434 DEBUG_PRINT_ERROR("update buffer requirements");
10435 return OMX_ErrorHardware;
10436 }
10437 portDefn->nBufferSize = buf_size;
10438 portDefn->eDir = OMX_DirOutput;
10439 portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
10440 portDefn->nBufferCountMin = drv_ctx.op_buf.mincount;
10441 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
10442 if (drv_ctx.frame_rate.fps_denominator > 0)
10443 portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
10444 drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
10445 else {
10446 DEBUG_PRINT_ERROR("Error: Divide by zero");
10447 return OMX_ErrorBadParameter;
10448 }
10449 portDefn->bEnabled = m_out_bEnabled;
10450 portDefn->bPopulated = m_out_bPopulated;
10451 if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
10452 DEBUG_PRINT_ERROR("Error in getting color format");
10453 return OMX_ErrorHardware;
10454 }
10455 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10456 fmt.fmt.pix_mp.pixelformat = capture_capability;
10457 } else if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) {
10458 portDefn->nBufferSize = m_client_out_extradata_info.getSize();
10459 portDefn->nBufferCountMin = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
10460 portDefn->nBufferCountActual = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
10461 portDefn->eDir = OMX_DirOutput;
10462 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height;
10463 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width;
10464 portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
10465 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
10466 portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
10467 portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
10468 DEBUG_PRINT_LOW(" get_parameter: Port idx %d nBufSize %u nBufCnt %u",
10469 (int)portDefn->nPortIndex,
10470 (unsigned int)portDefn->nBufferSize,
10471 (unsigned int)portDefn->nBufferCountActual);
10472 return eRet;
10473 } else {
10474 portDefn->eDir = OMX_DirMax;
10475 DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
10476 (int)portDefn->nPortIndex);
10477 eRet = OMX_ErrorBadPortIndex;
10478 }
10479 if (in_reconfig) {
10480 m_extradata_info.output_crop_rect.nLeft = 0;
10481 m_extradata_info.output_crop_rect.nTop = 0;
10482 m_extradata_info.output_crop_rect.nWidth = fmt.fmt.pix_mp.width;
10483 m_extradata_info.output_crop_rect.nHeight = fmt.fmt.pix_mp.height;
10484 }
10485 update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
10486 fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
10487
10488 portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height;
10489 portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width;
10490 portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
10491 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
10492
10493 if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
10494 (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
10495 portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
10496 portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
10497 }
10498 DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
10499 "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
10500 (unsigned int)portDefn->nPortIndex,
10501 (unsigned int)portDefn->format.video.nFrameWidth,
10502 (unsigned int)portDefn->format.video.nFrameHeight,
10503 (int)portDefn->format.video.nStride,
10504 (unsigned int)portDefn->format.video.nSliceHeight,
10505 (unsigned int)portDefn->format.video.eColorFormat,
10506 (unsigned int)portDefn->nBufferSize,
10507 (unsigned int)portDefn->nBufferCountActual);
10508
10509 return eRet;
10510 }
10511
allocate_output_headers(bool intermediate)10512 OMX_ERRORTYPE omx_vdec::allocate_output_headers(bool intermediate)
10513 {
10514 OMX_ERRORTYPE eRet = OMX_ErrorNone;
10515 OMX_BUFFERHEADERTYPE *bufHdr = NULL;
10516 unsigned i = 0;
10517
10518 OMX_BUFFERHEADERTYPE **omx_base_address =
10519 intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
10520 vdec_bufferpayload **omx_ptr_outputbuffer =
10521 intermediate?&drv_ctx.ptr_intermediate_outputbuffer:&drv_ctx.ptr_outputbuffer;
10522 vdec_output_frameinfo **omx_ptr_respbuffer =
10523 intermediate?&drv_ctx.ptr_intermediate_respbuffer:&drv_ctx.ptr_respbuffer;
10524 vdec_ion **omx_op_buf_ion_info =
10525 intermediate?&drv_ctx.op_intermediate_buf_ion_info:&drv_ctx.op_buf_ion_info;
10526
10527 if (!*omx_base_address) {
10528 DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation, Cnt %d Sz %d",
10529 drv_ctx.op_buf.actualcount, (unsigned int)drv_ctx.op_buf.buffer_size);
10530 int nBufHdrSize = 0;
10531 int nPlatformEntrySize = 0;
10532 int nPlatformListSize = 0;
10533 int nPMEMInfoSize = 0;
10534 OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
10535 OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
10536 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
10537
10538 nBufHdrSize = drv_ctx.op_buf.actualcount *
10539 sizeof(OMX_BUFFERHEADERTYPE);
10540 nPMEMInfoSize = drv_ctx.op_buf.actualcount *
10541 sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
10542 nPlatformListSize = drv_ctx.op_buf.actualcount *
10543 sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
10544 nPlatformEntrySize = drv_ctx.op_buf.actualcount *
10545 sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
10546
10547 *omx_base_address = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
10548 // Alloc mem for platform specific info
10549 char *pPtr=NULL;
10550 pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
10551 nPMEMInfoSize,1);
10552 *omx_ptr_outputbuffer = (struct vdec_bufferpayload *) \
10553 calloc (sizeof(struct vdec_bufferpayload),
10554 drv_ctx.op_buf.actualcount);
10555 *omx_ptr_respbuffer = (struct vdec_output_frameinfo *) \
10556 calloc (sizeof (struct vdec_output_frameinfo),
10557 drv_ctx.op_buf.actualcount);
10558 if (!pPtr || !*omx_ptr_outputbuffer || !*omx_ptr_respbuffer) {
10559 DEBUG_PRINT_ERROR("allocate_output_headers: allocation failed");
10560 free(pPtr); pPtr = NULL;
10561 free(*omx_ptr_outputbuffer); *omx_ptr_outputbuffer = NULL;
10562 free(*omx_ptr_respbuffer); *omx_ptr_respbuffer = NULL;
10563 return OMX_ErrorInsufficientResources;
10564 }
10565
10566 #ifdef USE_ION
10567 *omx_op_buf_ion_info = (struct vdec_ion * ) \
10568 calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
10569 if (!*omx_op_buf_ion_info) {
10570 DEBUG_PRINT_ERROR("Failed to alloc output buffer ion info");
10571 free(pPtr); pPtr = NULL;
10572 free(*omx_ptr_outputbuffer); *omx_ptr_outputbuffer = NULL;
10573 free(*omx_ptr_respbuffer); *omx_ptr_respbuffer = NULL;
10574 return OMX_ErrorInsufficientResources;
10575 }
10576 #endif
10577
10578 if (*omx_base_address && pPtr && *omx_ptr_outputbuffer
10579 && *omx_ptr_respbuffer) {
10580 bufHdr = *omx_base_address;
10581 if (m_platform_list) {
10582 free(m_platform_list);
10583 }
10584 m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
10585 m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
10586 (((char *) m_platform_list) + nPlatformListSize);
10587 m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
10588 (((char *) m_platform_entry) + nPlatformEntrySize);
10589 pPlatformList = m_platform_list;
10590 pPlatformEntry = m_platform_entry;
10591 pPMEMInfo = m_pmem_info;
10592
10593 DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p", *omx_base_address);
10594
10595 // Settting the entire storage nicely
10596 DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
10597 *omx_base_address,pPlatformEntry);
10598 DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
10599 for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
10600 bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
10601 bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
10602 // Set the values when we determine the right HxW param
10603 bufHdr->nAllocLen = 0;
10604 bufHdr->nFilledLen = 0;
10605 bufHdr->pAppPrivate = NULL;
10606 bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
10607 pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
10608 pPlatformEntry->entry = pPMEMInfo;
10609 // Initialize the Platform List
10610 pPlatformList->nEntries = 1;
10611 pPlatformList->entryList = pPlatformEntry;
10612 // Keep pBuffer NULL till vdec is opened
10613 bufHdr->pBuffer = NULL;
10614 pPMEMInfo->offset = 0;
10615 pPMEMInfo->pmem_fd = -1;
10616 bufHdr->pPlatformPrivate = pPlatformList;
10617 (*omx_ptr_outputbuffer)[i].pmem_fd = -1;
10618 #ifdef USE_ION
10619 (*omx_op_buf_ion_info)[i].data_fd = -1;
10620 (*omx_op_buf_ion_info)[i].dev_fd = -1;
10621 #endif
10622 /*Create a mapping between buffers*/
10623 bufHdr->pOutputPortPrivate = &(*omx_ptr_respbuffer)[i];
10624 (*omx_ptr_respbuffer)[i].client_data = (void *) \
10625 &(*omx_ptr_outputbuffer)[i];
10626 // Move the buffer and buffer header pointers
10627 bufHdr++;
10628 pPMEMInfo++;
10629 pPlatformEntry++;
10630 pPlatformList++;
10631 }
10632 } else {
10633 DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
10634 *omx_base_address, pPtr);
10635 if (*omx_base_address) {
10636 free(*omx_base_address);
10637 *omx_base_address = NULL;
10638 }
10639 if (pPtr) {
10640 free(pPtr);
10641 pPtr = NULL;
10642 }
10643 if (*omx_ptr_outputbuffer) {
10644 free(*omx_ptr_outputbuffer);
10645 *omx_ptr_outputbuffer = NULL;
10646 }
10647 if (*omx_ptr_respbuffer) {
10648 free(*omx_ptr_respbuffer);
10649 *omx_ptr_respbuffer = NULL;
10650 }
10651 #ifdef USE_ION
10652 if (*omx_op_buf_ion_info) {
10653 DEBUG_PRINT_LOW("Free o/p ion context");
10654 free(*omx_op_buf_ion_info);
10655 *omx_op_buf_ion_info = NULL;
10656 }
10657 #endif
10658 eRet = OMX_ErrorInsufficientResources;
10659 }
10660 } else {
10661 eRet = OMX_ErrorInsufficientResources;
10662 }
10663
10664 if (intermediate == false &&
10665 eRet == OMX_ErrorNone &&
10666 client_buffers.is_color_conversion_enabled()) {
10667 eRet = allocate_output_headers(true);
10668 }
10669
10670 return eRet;
10671 }
10672
complete_pending_buffer_done_cbs()10673 void omx_vdec::complete_pending_buffer_done_cbs()
10674 {
10675 unsigned long p1, p2, ident;
10676 omx_cmd_queue tmp_q, pending_bd_q;
10677 pthread_mutex_lock(&m_lock);
10678 // pop all pending GENERATE FDB from ftb queue
10679 while (m_ftb_q.m_size) {
10680 m_ftb_q.pop_entry(&p1,&p2,&ident);
10681 if (ident == OMX_COMPONENT_GENERATE_FBD) {
10682 pending_bd_q.insert_entry(p1,p2,ident);
10683 } else {
10684 tmp_q.insert_entry(p1,p2,ident);
10685 }
10686 }
10687 //return all non GENERATE FDB to ftb queue
10688 while (tmp_q.m_size) {
10689 tmp_q.pop_entry(&p1,&p2,&ident);
10690 m_ftb_q.insert_entry(p1,p2,ident);
10691 }
10692 // pop all pending GENERATE EDB from etb queue
10693 while (m_etb_q.m_size) {
10694 m_etb_q.pop_entry(&p1,&p2,&ident);
10695 if (ident == OMX_COMPONENT_GENERATE_EBD) {
10696 pending_bd_q.insert_entry(p1,p2,ident);
10697 } else {
10698 tmp_q.insert_entry(p1,p2,ident);
10699 }
10700 }
10701 //return all non GENERATE FDB to etb queue
10702 while (tmp_q.m_size) {
10703 tmp_q.pop_entry(&p1,&p2,&ident);
10704 m_etb_q.insert_entry(p1,p2,ident);
10705 }
10706 pthread_mutex_unlock(&m_lock);
10707 // process all pending buffer dones
10708 while (pending_bd_q.m_size) {
10709 pending_bd_q.pop_entry(&p1,&p2,&ident);
10710 switch (ident) {
10711 case OMX_COMPONENT_GENERATE_EBD:
10712 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
10713 DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
10714 omx_report_error ();
10715 }
10716 break;
10717
10718 case OMX_COMPONENT_GENERATE_FBD:
10719 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
10720 DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
10721 omx_report_error ();
10722 }
10723 break;
10724 }
10725 }
10726 }
10727
set_frame_rate(OMX_S64 act_timestamp)10728 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
10729 {
10730 OMX_U32 new_frame_interval = 0;
10731 if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
10732 && llabs(act_timestamp - prev_ts) > 2000) {
10733 new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ?
10734 llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual);
10735 if (new_frame_interval != frm_int || frm_int == 0) {
10736 frm_int = new_frame_interval;
10737 if (frm_int) {
10738 drv_ctx.frame_rate.fps_numerator = 1e6;
10739 drv_ctx.frame_rate.fps_denominator = frm_int;
10740 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
10741 (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
10742 (float)drv_ctx.frame_rate.fps_denominator);
10743 /* We need to report the difference between this FBD and the previous FBD
10744 * back to the driver for clock scaling purposes. */
10745 struct v4l2_outputparm oparm;
10746 /*XXX: we're providing timing info as seconds per frame rather than frames
10747 * per second.*/
10748 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
10749 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
10750
10751 struct v4l2_streamparm sparm;
10752 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10753 sparm.parm.output = oparm;
10754 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
10755 DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
10756 performance might be affected");
10757 }
10758
10759 }
10760 }
10761 }
10762 prev_ts = act_timestamp;
10763 }
10764
adjust_timestamp(OMX_S64 & act_timestamp)10765 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
10766 {
10767 if (rst_prev_ts && VALID_TS(act_timestamp)) {
10768 prev_ts = act_timestamp;
10769 prev_ts_actual = act_timestamp;
10770 rst_prev_ts = false;
10771 } else if (VALID_TS(prev_ts)) {
10772 bool codec_cond = (drv_ctx.timestamp_adjust)?
10773 (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) :
10774 (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual);
10775 prev_ts_actual = act_timestamp; //unadjusted previous timestamp
10776 if (frm_int > 0 && codec_cond) {
10777 DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
10778 act_timestamp = prev_ts + frm_int;
10779 DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
10780 prev_ts = act_timestamp;
10781 } else {
10782 if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) {
10783 // ensure that timestamps can never step backwards when in display order
10784 act_timestamp = prev_ts;
10785 }
10786 set_frame_rate(act_timestamp);
10787 }
10788 } else if (frm_int > 0) // In this case the frame rate was set along
10789 { // with the port definition, start ts with 0
10790 act_timestamp = prev_ts = 0; // and correct if a valid ts is received.
10791 rst_prev_ts = true;
10792 }
10793 }
10794
convert_color_space_info(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer,OMX_U32 matrix,ColorAspects * aspects)10795 void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
10796 OMX_U32 transfer, OMX_U32 matrix, ColorAspects *aspects)
10797 {
10798 switch (primaries) {
10799 case MSM_VIDC_BT709_5:
10800 aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
10801 break;
10802 case MSM_VIDC_BT470_6_M:
10803 aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
10804 break;
10805 case MSM_VIDC_BT601_6_625:
10806 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10807 break;
10808 case MSM_VIDC_BT601_6_525:
10809 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
10810 break;
10811 case MSM_VIDC_GENERIC_FILM:
10812 aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
10813 break;
10814 case MSM_VIDC_BT2020:
10815 aspects->mPrimaries = ColorAspects::PrimariesBT2020;
10816 break;
10817 case MSM_VIDC_UNSPECIFIED:
10818 //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default
10819 default:
10820 //aspects->mPrimaries = ColorAspects::PrimariesOther;
10821 aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10822 break;
10823 }
10824
10825 aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
10826
10827 switch (transfer) {
10828 case MSM_VIDC_TRANSFER_BT709_5:
10829 case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
10830 case MSM_VIDC_TRANSFER_BT_2020_10:
10831 case MSM_VIDC_TRANSFER_BT_2020_12:
10832 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10833 break;
10834 case MSM_VIDC_TRANSFER_BT_470_6_M:
10835 aspects->mTransfer = ColorAspects::TransferGamma22;
10836 break;
10837 case MSM_VIDC_TRANSFER_BT_470_6_BG:
10838 aspects->mTransfer = ColorAspects::TransferGamma28;
10839 break;
10840 case MSM_VIDC_TRANSFER_SMPTE_240M:
10841 aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10842 break;
10843 case MSM_VIDC_TRANSFER_LINEAR:
10844 aspects->mTransfer = ColorAspects::TransferLinear;
10845 break;
10846 case MSM_VIDC_TRANSFER_IEC_61966:
10847 aspects->mTransfer = ColorAspects::TransferXvYCC;
10848 break;
10849 case MSM_VIDC_TRANSFER_BT_1361:
10850 aspects->mTransfer = ColorAspects::TransferBT1361;
10851 break;
10852 case MSM_VIDC_TRANSFER_SRGB:
10853 aspects->mTransfer = ColorAspects::TransferSRGB;
10854 break;
10855 case MSM_VIDC_TRANSFER_SMPTE_ST2084:
10856 aspects->mTransfer = ColorAspects::TransferST2084;
10857 break;
10858 case MSM_VIDC_TRANSFER_HLG:
10859 aspects->mTransfer = ColorAspects::TransferHLG;
10860 break;
10861 default:
10862 //aspects->mTransfer = ColorAspects::TransferOther;
10863 aspects->mTransfer = m_client_color_space.sAspects.mTransfer;
10864 break;
10865 }
10866
10867 switch (matrix) {
10868 case MSM_VIDC_MATRIX_BT_709_5:
10869 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10870 break;
10871 case MSM_VIDC_MATRIX_FCC_47:
10872 aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
10873 break;
10874 case MSM_VIDC_MATRIX_601_6_625:
10875 case MSM_VIDC_MATRIX_601_6_525:
10876 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10877 break;
10878 case MSM_VIDC_MATRIX_SMPTE_240M:
10879 aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
10880 break;
10881 case MSM_VIDC_MATRIX_BT_2020:
10882 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10883 break;
10884 case MSM_VIDC_MATRIX_BT_2020_CONST:
10885 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
10886 break;
10887 default:
10888 //aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
10889 aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
10890 break;
10891 }
10892 }
10893
print_debug_color_aspects(ColorAspects * a,const char * prefix)10894 void omx_vdec::print_debug_color_aspects(ColorAspects *a, const char *prefix) {
10895 DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d(%s) Range = %d(%s) Tx = %d(%s) Matrix = %d(%s)",
10896 prefix, a->mPrimaries, asString(a->mPrimaries), a->mRange, asString(a->mRange),
10897 a->mTransfer, asString(a->mTransfer), a->mMatrixCoeffs, asString(a->mMatrixCoeffs));
10898
10899 }
10900
handle_color_space_info(void * data)10901 bool omx_vdec::handle_color_space_info(void *data)
10902 {
10903 ColorAspects tempAspects;
10904 memset(&tempAspects, 0x0, sizeof(ColorAspects));
10905 ColorAspects *aspects = &tempAspects;
10906
10907 switch(output_capability) {
10908 case V4L2_PIX_FMT_MPEG2:
10909 {
10910 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
10911 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
10912
10913 /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
10914 * understand this code */
10915
10916 if (seqdisp_payload && seqdisp_payload->color_descp) {
10917
10918 convert_color_space_info(seqdisp_payload->color_primaries, 0,
10919 seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
10920 aspects);
10921 /* MPEG2 seqdisp payload doesn't give range info. Hence assing the value
10922 * set by client */
10923 aspects->mRange = m_client_color_space.sAspects.mRange;
10924 m_disp_hor_size = seqdisp_payload->disp_width;
10925 m_disp_vert_size = seqdisp_payload->disp_height;
10926 }
10927 }
10928 break;
10929 case V4L2_PIX_FMT_H264:
10930 case V4L2_PIX_FMT_HEVC:
10931 {
10932 struct msm_vidc_vui_display_info_payload *display_info_payload;
10933 display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
10934
10935 /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
10936
10937 if (display_info_payload->video_signal_present_flag &&
10938 display_info_payload->color_description_present_flag) {
10939 convert_color_space_info(display_info_payload->color_primaries,
10940 display_info_payload->video_full_range_flag,
10941 display_info_payload->transfer_characteristics,
10942 display_info_payload->matrix_coefficients,
10943 aspects);
10944 }
10945 }
10946 break;
10947 case V4L2_PIX_FMT_VP8:
10948 {
10949 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10950 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10951 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
10952 * to understand this code */
10953
10954 if (vpx_color_space_payload->color_space == 0) {
10955 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
10956 aspects->mRange = ColorAspects::RangeLimited;
10957 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10958 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10959 } else {
10960 DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
10961 break;
10962 }
10963 }
10964 break;
10965 case V4L2_PIX_FMT_VP9:
10966 {
10967 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10968 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10969 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
10970 * to understand this code */
10971
10972 switch(vpx_color_space_payload->color_space) {
10973 case MSM_VIDC_CS_BT_601:
10974 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10975 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10976 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10977 aspects->mRange = m_client_color_space.sAspects.mRange;
10978 break;
10979 case MSM_VIDC_CS_BT_709:
10980 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10981 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10982 aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
10983 aspects->mRange = m_client_color_space.sAspects.mRange;
10984 break;
10985 case MSM_VIDC_CS_SMPTE_170:
10986 aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10987 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10988 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
10989 aspects->mRange = m_client_color_space.sAspects.mRange;
10990 break;
10991 case MSM_VIDC_CS_SMPTE_240:
10992 aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
10993 aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10994 aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
10995 aspects->mRange = m_client_color_space.sAspects.mRange;
10996 break;
10997 case MSM_VIDC_CS_BT_2020:
10998 aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10999 aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
11000 aspects->mPrimaries = ColorAspects::PrimariesBT2020;
11001 aspects->mRange = m_client_color_space.sAspects.mRange;
11002 break;
11003 case MSM_VIDC_CS_RESERVED:
11004 aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
11005 aspects->mTransfer = ColorAspects::TransferOther;
11006 aspects->mPrimaries = ColorAspects::PrimariesOther;
11007 aspects->mRange = m_client_color_space.sAspects.mRange;
11008 break;
11009 case MSM_VIDC_CS_RGB:
11010 aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
11011 aspects->mTransfer = ColorAspects::TransferSMPTE170M;
11012 aspects->mPrimaries = ColorAspects::PrimariesOther;
11013 aspects->mRange = m_client_color_space.sAspects.mRange;
11014 break;
11015 default:
11016 break;
11017 }
11018 }
11019 break;
11020 default:
11021 break;
11022 }
11023
11024 print_debug_color_aspects(aspects, "Bitstream");
11025
11026 if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
11027 m_internal_color_space.sAspects.mTransfer != aspects->mTransfer ||
11028 m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs ||
11029 m_internal_color_space.sAspects.mRange != aspects->mRange) {
11030 memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
11031
11032 DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to Color Aspects Change");
11033 print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
11034 print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
11035
11036 post_event(OMX_CORE_OUTPUT_PORT_INDEX,
11037 OMX_QTIIndexConfigDescribeColorAspects,
11038 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
11039 return true;
11040 }
11041 return false;
11042 }
11043
print_debug_hdr_color_info(HDRStaticInfo * hdr_info,const char * prefix)11044 void omx_vdec::print_debug_hdr_color_info(HDRStaticInfo *hdr_info, const char *prefix)
11045 {
11046 if (!hdr_info->mID) {
11047 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mR.x = %d mR.y = %d", prefix,
11048 hdr_info->sType1.mR.x, hdr_info->sType1.mR.y);
11049 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mG.x = %d mG.y = %d", prefix,
11050 hdr_info->sType1.mG.x, hdr_info->sType1.mG.y);
11051 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mB.x = %d mB.y = %d", prefix,
11052 hdr_info->sType1.mB.x, hdr_info->sType1.mB.y);
11053 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mW.x = %d mW.y = %d", prefix,
11054 hdr_info->sType1.mW.x, hdr_info->sType1.mW.y);
11055 DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: maxDispLum = %d minDispLum = %d", prefix,
11056 hdr_info->sType1.mMaxDisplayLuminance, hdr_info->sType1.mMinDisplayLuminance);
11057 DEBUG_PRINT_LOW("%s : HDRstaticinfo CLL: CLL = %d FLL = %d", prefix,
11058 hdr_info->sType1.mMaxContentLightLevel, hdr_info->sType1.mMaxFrameAverageLightLevel);
11059 }
11060
11061 }
11062
print_debug_hdr_color_info_mdata(ColorMetaData * color_mdata)11063 void omx_vdec::print_debug_hdr_color_info_mdata(ColorMetaData* color_mdata)
11064 {
11065 DEBUG_PRINT_LOW("setMetaData COLOR_METADATA : color_primaries = %u, range = %u, transfer = %u, matrix = %u",
11066 color_mdata->colorPrimaries, color_mdata->range,
11067 color_mdata->transfer, color_mdata->matrixCoefficients);
11068
11069 for(uint8_t i = 0; i < 3; i++) {
11070 for(uint8_t j = 0; j < 2; j++) {
11071 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : rgbPrimaries[%d][%d] = %d", i, j, color_mdata->masteringDisplayInfo.primaries.rgbPrimaries[i][j]);
11072 }
11073 }
11074
11075 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : whitepoint[0] = %d whitepoint[1] = %d",
11076 color_mdata->masteringDisplayInfo.primaries.whitePoint[0],
11077 color_mdata->masteringDisplayInfo.primaries.whitePoint[1]);
11078
11079 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxDispLum = %d minDispLum = %d",
11080 color_mdata->masteringDisplayInfo.maxDisplayLuminance,
11081 color_mdata->masteringDisplayInfo.minDisplayLuminance);
11082
11083 DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxCLL = %d maxFLL = %d",
11084 color_mdata->contentLightLevel.maxContentLightLevel,
11085 color_mdata->contentLightLevel.minPicAverageLightLevel);
11086
11087
11088 }
11089
handle_content_light_level_info(void * data)11090 bool omx_vdec::handle_content_light_level_info(void* data)
11091 {
11092 struct msm_vidc_content_light_level_sei_payload *light_level_payload =
11093 (msm_vidc_content_light_level_sei_payload*)(data);
11094
11095 if ((m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel != light_level_payload->nMaxContentLight) ||
11096 (m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel != light_level_payload->nMaxPicAverageLight)) {
11097 m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel = light_level_payload->nMaxContentLight;
11098 m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel = light_level_payload->nMaxPicAverageLight;
11099 return true;
11100 }
11101 return false;
11102 }
11103
handle_mastering_display_color_info(void * data)11104 bool omx_vdec::handle_mastering_display_color_info(void* data)
11105 {
11106 struct msm_vidc_mastering_display_colour_sei_payload *mastering_display_payload =
11107 (msm_vidc_mastering_display_colour_sei_payload*)(data);
11108 HDRStaticInfo* hdr_info = &m_internal_hdr_info.sInfo;
11109 bool internal_disp_changed_flag = false;
11110
11111 internal_disp_changed_flag |= (hdr_info->sType1.mG.x != mastering_display_payload->nDisplayPrimariesX[0]) ||
11112 (hdr_info->sType1.mG.y != mastering_display_payload->nDisplayPrimariesY[0]);
11113 internal_disp_changed_flag |= (hdr_info->sType1.mB.x != mastering_display_payload->nDisplayPrimariesX[1]) ||
11114 (hdr_info->sType1.mB.y != mastering_display_payload->nDisplayPrimariesY[1]);
11115 internal_disp_changed_flag |= (hdr_info->sType1.mR.x != mastering_display_payload->nDisplayPrimariesX[2]) ||
11116 (hdr_info->sType1.mR.y != mastering_display_payload->nDisplayPrimariesY[2]);
11117
11118 internal_disp_changed_flag |= (hdr_info->sType1.mW.x != mastering_display_payload->nWhitePointX) ||
11119 (hdr_info->sType1.mW.y != mastering_display_payload->nWhitePointY);
11120
11121 /* Maximum Display Luminance from the bitstream is in 0.0001 cd/m2 while the HDRStaticInfo extension
11122 requires it in cd/m2, so dividing by 10000 and rounding the value after division.
11123 Check if max luminance is at least 100 cd/m^2.This check is required for few bistreams where
11124 max luminance is not in correct scale. Use the default max luminance value if the value from
11125 the bitstream is less than 100 cd/m^2.
11126 */
11127
11128 uint16_t max_display_luminance_cd_m2;
11129 if ((mastering_display_payload->nMaxDisplayMasteringLuminance > 0) &&
11130 ((mastering_display_payload->nMaxDisplayMasteringLuminance / LUMINANCE_DIV_FACTOR) < 100)) {
11131 max_display_luminance_cd_m2 = LUMINANCE_MAXDISPLAY_CDM2;
11132 DEBUG_PRINT_HIGH("Invalid maxLuminance value from SEI [%.4f]. Using default [%u]",
11133 (mastering_display_payload->nMaxDisplayMasteringLuminance / LUMINANCE_DIV_FACTOR),
11134 LUMINANCE_MAXDISPLAY_CDM2);
11135 } else {
11136 max_display_luminance_cd_m2 =
11137 static_cast<int>((mastering_display_payload->nMaxDisplayMasteringLuminance / LUMINANCE_DIV_FACTOR) + 0.5);
11138 }
11139
11140 internal_disp_changed_flag |= (hdr_info->sType1.mMaxDisplayLuminance != max_display_luminance_cd_m2) ||
11141 (hdr_info->sType1.mMinDisplayLuminance != mastering_display_payload->nMinDisplayMasteringLuminance);
11142
11143 if (internal_disp_changed_flag) {
11144 hdr_info->sType1.mG.x = mastering_display_payload->nDisplayPrimariesX[0];
11145 hdr_info->sType1.mG.y = mastering_display_payload->nDisplayPrimariesY[0];
11146 hdr_info->sType1.mB.x = mastering_display_payload->nDisplayPrimariesX[1];
11147 hdr_info->sType1.mB.y = mastering_display_payload->nDisplayPrimariesY[1];
11148 hdr_info->sType1.mR.x = mastering_display_payload->nDisplayPrimariesX[2];
11149 hdr_info->sType1.mR.y = mastering_display_payload->nDisplayPrimariesY[2];
11150 hdr_info->sType1.mW.x = mastering_display_payload->nWhitePointX;
11151 hdr_info->sType1.mW.y = mastering_display_payload->nWhitePointY;
11152
11153 hdr_info->sType1.mMaxDisplayLuminance = max_display_luminance_cd_m2;
11154 hdr_info->sType1.mMinDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance;
11155 }
11156
11157 return internal_disp_changed_flag;
11158 }
11159
set_colormetadata_in_handle(ColorMetaData * color_mdata,unsigned int buf_index)11160 void omx_vdec::set_colormetadata_in_handle(ColorMetaData *color_mdata, unsigned int buf_index)
11161 {
11162 private_handle_t *private_handle = NULL;
11163 if (buf_index < drv_ctx.op_buf.actualcount &&
11164 buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
11165 native_buffer[buf_index].privatehandle) {
11166 private_handle = native_buffer[buf_index].privatehandle;
11167 }
11168 if (private_handle) {
11169 setMetaData(private_handle, COLOR_METADATA, (void*)color_mdata);
11170 }
11171 }
11172
convert_color_aspects_to_metadata(ColorAspects & aspects,ColorMetaData & color_mdata)11173 void omx_vdec::convert_color_aspects_to_metadata(ColorAspects& aspects, ColorMetaData &color_mdata)
11174 {
11175 PrimariesMap::const_iterator primary_it = mPrimariesMap.find(aspects.mPrimaries);
11176 TransferMap::const_iterator transfer_it = mTransferMap.find(aspects.mTransfer);
11177 MatrixCoeffMap::const_iterator matrix_it = mMatrixCoeffMap.find(aspects.mMatrixCoeffs);
11178 RangeMap::const_iterator range_it = mColorRangeMap.find(aspects.mRange);
11179
11180 if (primary_it == mPrimariesMap.end()) {
11181 DEBUG_PRINT_LOW("No mapping for %d in PrimariesMap, defaulting to unspecified", aspects.mPrimaries);
11182 color_mdata.colorPrimaries = (ColorPrimaries)2;
11183 } else {
11184 color_mdata.colorPrimaries = primary_it->second;
11185 }
11186
11187 if (transfer_it == mTransferMap.end()) {
11188 DEBUG_PRINT_LOW("No mapping for %d in TransferMap, defaulting to unspecified", aspects.mTransfer);
11189 color_mdata.transfer = (GammaTransfer)2;
11190 } else {
11191 color_mdata.transfer = transfer_it->second;
11192 }
11193
11194 if (matrix_it == mMatrixCoeffMap.end()) {
11195 DEBUG_PRINT_LOW("No mapping for %d in MatrixCoeffMap, defaulting to unspecified", aspects.mMatrixCoeffs);
11196 color_mdata.matrixCoefficients = (MatrixCoEfficients)2;
11197 } else {
11198 color_mdata.matrixCoefficients = matrix_it->second;
11199 }
11200
11201 if (range_it == mColorRangeMap.end()) {
11202 DEBUG_PRINT_LOW("No mapping for %d in ColorRangeMap, defaulting to limited range", aspects.mRange);
11203 color_mdata.range = Range_Limited;
11204 } else {
11205 color_mdata.range = range_it->second;
11206 }
11207 }
11208
convert_hdr_info_to_metadata(HDRStaticInfo & hdr_info,ColorMetaData & color_mdata)11209 void omx_vdec::convert_hdr_info_to_metadata(HDRStaticInfo& hdr_info, ColorMetaData &color_mdata)
11210 {
11211 HDRStaticInfo::Type1 zero_hdr_info;
11212 MasteringDisplay& mastering_display = color_mdata.masteringDisplayInfo;
11213 ContentLightLevel& content_light = color_mdata.contentLightLevel;
11214 bool hdr_info_enabled = false;
11215 memset(&zero_hdr_info, 0, sizeof(HDRStaticInfo::Type1));
11216 hdr_info_enabled = (memcmp(&hdr_info, &zero_hdr_info, sizeof(HDRStaticInfo::Type1))!= 0);
11217
11218 if (hdr_info_enabled) {
11219 mastering_display.colorVolumeSEIEnabled = true;
11220 mastering_display.primaries.rgbPrimaries[0][0] = hdr_info.sType1.mR.x;
11221 mastering_display.primaries.rgbPrimaries[0][1] = hdr_info.sType1.mR.y;
11222 mastering_display.primaries.rgbPrimaries[1][0] = hdr_info.sType1.mG.x;
11223 mastering_display.primaries.rgbPrimaries[1][1] = hdr_info.sType1.mG.y;
11224 mastering_display.primaries.rgbPrimaries[2][0] = hdr_info.sType1.mB.x;
11225 mastering_display.primaries.rgbPrimaries[2][1] = hdr_info.sType1.mB.y;
11226 mastering_display.primaries.whitePoint[0] = hdr_info.sType1.mW.x;
11227 mastering_display.primaries.whitePoint[1] = hdr_info.sType1.mW.y;
11228 mastering_display.maxDisplayLuminance = hdr_info.sType1.mMaxDisplayLuminance;
11229 mastering_display.minDisplayLuminance = hdr_info.sType1.mMinDisplayLuminance;
11230 content_light.lightLevelSEIEnabled = true;
11231 content_light.maxContentLightLevel = hdr_info.sType1.mMaxContentLightLevel;
11232 content_light.minPicAverageLightLevel = hdr_info.sType1.mMaxFrameAverageLightLevel;
11233 }
11234
11235 }
11236
get_preferred_color_aspects(ColorAspects & preferredColorAspects)11237 void omx_vdec::get_preferred_color_aspects(ColorAspects& preferredColorAspects)
11238 {
11239 OMX_U32 width = drv_ctx.video_resolution.frame_width;
11240 OMX_U32 height = drv_ctx.video_resolution.frame_height;
11241
11242 // For VPX, use client-color if specified.
11243 // For the rest, try to use the stream-color if present
11244 bool preferClientColor = (output_capability == V4L2_PIX_FMT_VP8 ||
11245 output_capability == V4L2_PIX_FMT_VP9);
11246
11247 const ColorAspects &preferredColor = preferClientColor ?
11248 m_client_color_space.sAspects : m_internal_color_space.sAspects;
11249 const ColorAspects &defaultColor = preferClientColor ?
11250 m_internal_color_space.sAspects : m_client_color_space.sAspects;
11251
11252 if ((width >= 3840 || height >= 3840 || width * (int64_t)height >= 3840 * 1634) &&
11253 (m_client_color_space.sAspects.mPrimaries == ColorAspects::PrimariesBT2020) &&
11254 (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8)) {
11255 m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesBT709_5;
11256 m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixBT709_5;
11257 }
11258
11259 preferredColorAspects.mPrimaries = preferredColor.mPrimaries != ColorAspects::PrimariesUnspecified ?
11260 preferredColor.mPrimaries : defaultColor.mPrimaries;
11261 preferredColorAspects.mTransfer = preferredColor.mTransfer != ColorAspects::TransferUnspecified ?
11262 preferredColor.mTransfer : defaultColor.mTransfer;
11263 preferredColorAspects.mMatrixCoeffs = preferredColor.mMatrixCoeffs != ColorAspects::MatrixUnspecified ?
11264 preferredColor.mMatrixCoeffs : defaultColor.mMatrixCoeffs;
11265 preferredColorAspects.mRange = preferredColor.mRange != ColorAspects::RangeUnspecified ?
11266 preferredColor.mRange : defaultColor.mRange;
11267
11268 }
11269
get_preferred_hdr_info(HDRStaticInfo & finalHDRInfo)11270 void omx_vdec::get_preferred_hdr_info(HDRStaticInfo& finalHDRInfo)
11271 {
11272 bool preferClientHDR = (output_capability == V4L2_PIX_FMT_VP9);
11273
11274 const HDRStaticInfo &preferredHDRInfo = preferClientHDR ?
11275 m_client_hdr_info.sInfo : m_internal_hdr_info.sInfo;
11276 const HDRStaticInfo &defaultHDRInfo = preferClientHDR ?
11277 m_internal_hdr_info.sInfo : m_client_hdr_info.sInfo;
11278 finalHDRInfo.sType1.mR = ((preferredHDRInfo.sType1.mR.x != 0) && (preferredHDRInfo.sType1.mR.y != 0)) ?
11279 preferredHDRInfo.sType1.mR : defaultHDRInfo.sType1.mR;
11280 finalHDRInfo.sType1.mG = ((preferredHDRInfo.sType1.mG.x != 0) && (preferredHDRInfo.sType1.mG.y != 0)) ?
11281 preferredHDRInfo.sType1.mG : defaultHDRInfo.sType1.mG;
11282 finalHDRInfo.sType1.mB = ((preferredHDRInfo.sType1.mB.x != 0) && (preferredHDRInfo.sType1.mB.y != 0)) ?
11283 preferredHDRInfo.sType1.mB : defaultHDRInfo.sType1.mB;
11284 finalHDRInfo.sType1.mW = ((preferredHDRInfo.sType1.mW.x != 0) && (preferredHDRInfo.sType1.mW.y != 0)) ?
11285 preferredHDRInfo.sType1.mW : defaultHDRInfo.sType1.mW;
11286 finalHDRInfo.sType1.mMaxDisplayLuminance = (preferredHDRInfo.sType1.mMaxDisplayLuminance != 0) ?
11287 preferredHDRInfo.sType1.mMaxDisplayLuminance : defaultHDRInfo.sType1.mMaxDisplayLuminance;
11288 finalHDRInfo.sType1.mMinDisplayLuminance = (preferredHDRInfo.sType1.mMinDisplayLuminance != 0) ?
11289 preferredHDRInfo.sType1.mMinDisplayLuminance : defaultHDRInfo.sType1.mMinDisplayLuminance;
11290 finalHDRInfo.sType1.mMaxContentLightLevel = (preferredHDRInfo.sType1.mMaxContentLightLevel != 0) ?
11291 preferredHDRInfo.sType1.mMaxContentLightLevel : defaultHDRInfo.sType1.mMaxContentLightLevel;
11292 finalHDRInfo.sType1.mMaxFrameAverageLightLevel = (preferredHDRInfo.sType1.mMaxFrameAverageLightLevel != 0) ?
11293 preferredHDRInfo.sType1.mMaxFrameAverageLightLevel : defaultHDRInfo.sType1.mMaxFrameAverageLightLevel;
11294 }
11295
print_debug_hdr10plus_metadata(ColorMetaData & color_mdata)11296 void omx_vdec::print_debug_hdr10plus_metadata(ColorMetaData& color_mdata) {
11297 DEBUG_PRINT_LOW("HDR10+ valid data length: %d", color_mdata.dynamicMetaDataLen);
11298 for (uint32_t i = 0 ; i < color_mdata.dynamicMetaDataLen && i+3 < HDR_DYNAMIC_META_DATA_SZ; i=i+4) {
11299 DEBUG_PRINT_LOW("HDR10+ mdata: %02X %02X %02X %02X", color_mdata.dynamicMetaDataPayload[i],
11300 color_mdata.dynamicMetaDataPayload[i+1],
11301 color_mdata.dynamicMetaDataPayload[i+2],
11302 color_mdata.dynamicMetaDataPayload[i+3]);
11303 }
11304
11305 }
11306
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)11307 bool omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
11308 {
11309 OMX_OTHER_EXTRADATATYPE *p_sei = NULL, *p_vui = NULL, *p_client_extra = NULL;
11310 OMX_U32 num_conceal_MB = 0;
11311 OMX_TICKS time_stamp = 0;
11312 OMX_U32 frame_rate = 0;
11313 unsigned long consumed_len = 0;
11314 OMX_U32 num_MB_in_frame;
11315 OMX_U32 recovery_sei_flags = 1;
11316 int enable = OMX_InterlaceFrameProgressive;
11317 bool internal_hdr_info_changed_flag = false;
11318 bool reconfig_event_sent = false;
11319 char *p_extradata = NULL;
11320 OMX_OTHER_EXTRADATATYPE *data = NULL;
11321 ColorMetaData color_mdata;
11322
11323 OMX_BUFFERHEADERTYPE *omx_base_address =
11324 client_buffers.is_color_conversion_enabled()?
11325 m_intermediate_out_mem_ptr:m_out_mem_ptr;
11326 vdec_bufferpayload *omx_ptr_outputbuffer =
11327 client_buffers.is_color_conversion_enabled()?
11328 drv_ctx.ptr_intermediate_outputbuffer:drv_ctx.ptr_outputbuffer;
11329 memset(&color_mdata, 0, sizeof(color_mdata));
11330
11331 int buf_index = p_buf_hdr - omx_base_address;
11332 if (buf_index >= drv_ctx.extradata_info.count) {
11333 DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
11334 buf_index, drv_ctx.extradata_info.count);
11335 return reconfig_event_sent;
11336 }
11337 struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
11338
11339 if (omx_ptr_outputbuffer[buf_index].bufferaddr == NULL) {
11340 DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL");
11341 return reconfig_event_sent;
11342 }
11343
11344 if (!drv_ctx.extradata_info.uaddr) {
11345 DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
11346 return reconfig_event_sent;
11347 }
11348
11349 if (m_client_output_extradata_mem_ptr &&
11350 m_client_out_extradata_info.getSize() >= drv_ctx.extradata_info.buffer_size) {
11351 p_client_extra = (OMX_OTHER_EXTRADATATYPE *)((m_client_output_extradata_mem_ptr + buf_index)->pBuffer);
11352 }
11353
11354 p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
11355
11356 m_extradata_info.output_crop_updated = OMX_FALSE;
11357 data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
11358 if (data) {
11359 while ((((consumed_len + sizeof(struct OMX_OTHER_EXTRADATATYPE)) <
11360 drv_ctx.extradata_info.buffer_size) && ((consumed_len + data->nSize) <
11361 drv_ctx.extradata_info.buffer_size))
11362 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
11363 DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
11364 switch ((unsigned long)data->eType) {
11365 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
11366 struct msm_vidc_interlace_payload *payload;
11367 payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
11368 if (payload) {
11369 DEBUG_PRINT_LOW("Interlace format %#x", payload->format);
11370 enable = OMX_InterlaceFrameProgressive;
11371 is_mbaff = payload->format & MSM_VIDC_INTERLACE_FRAME_MBAFF;
11372 switch (payload->format & 0x1F) {
11373 case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
11374 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11375 break;
11376 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
11377 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
11378 enable = OMX_InterlaceInterleaveFrameTopFieldFirst;
11379 break;
11380 case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
11381 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
11382 enable = OMX_InterlaceInterleaveFrameBottomFieldFirst;
11383 break;
11384 case MSM_VIDC_INTERLACE_FRAME_TOPFIELDFIRST:
11385 drv_ctx.interlace = VDEC_InterlaceFrameTopFieldFirst;
11386 enable = OMX_InterlaceFrameTopFieldFirst;
11387 break;
11388 case MSM_VIDC_INTERLACE_FRAME_BOTTOMFIELDFIRST:
11389 drv_ctx.interlace = VDEC_InterlaceFrameBottomFieldFirst;
11390 enable = OMX_InterlaceFrameBottomFieldFirst;
11391 break;
11392 default:
11393 DEBUG_PRINT_LOW("default case - set to progressive");
11394 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11395 }
11396 }
11397
11398 if (m_enable_android_native_buffers) {
11399 DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d enable:%d",
11400 payload->format, enable);
11401
11402 setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
11403 PP_PARAM_INTERLACED, (void*)&enable);
11404
11405 }
11406 if (client_extradata & OMX_INTERLACE_EXTRADATA) {
11407 if (p_client_extra) {
11408 append_interlace_extradata(p_client_extra, (payload->format & 0x1F));
11409 p_client_extra = (OMX_OTHER_EXTRADATATYPE *)
11410 (((OMX_U8 *)p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11411 }
11412 }
11413 break;
11414 case MSM_VIDC_EXTRADATA_FRAME_RATE:
11415 struct msm_vidc_framerate_payload *frame_rate_payload;
11416 frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
11417 frame_rate = frame_rate_payload->frame_rate;
11418 break;
11419 case MSM_VIDC_EXTRADATA_TIMESTAMP:
11420 struct msm_vidc_ts_payload *time_stamp_payload;
11421 time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
11422 time_stamp = time_stamp_payload->timestamp_lo;
11423 time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
11424 p_buf_hdr->nTimeStamp = time_stamp;
11425 break;
11426 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
11427 struct msm_vidc_concealmb_payload *conceal_mb_payload;
11428 conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
11429 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
11430 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
11431 num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
11432 break;
11433 case MSM_VIDC_EXTRADATA_INDEX:
11434 int *etype;
11435 etype = (int *)(void *)data->data;
11436 if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
11437 struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
11438 aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
11439 if (aspect_ratio_payload) {
11440 ((struct vdec_output_frameinfo *)
11441 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
11442 ((struct vdec_output_frameinfo *)
11443 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
11444 }
11445 } else if (etype && *etype == MSM_VIDC_EXTRADATA_OUTPUT_CROP) {
11446 struct msm_vidc_output_crop_payload *output_crop_payload;
11447 output_crop_payload = (struct msm_vidc_output_crop_payload *)(++etype);
11448 if (output_crop_payload) {
11449 m_extradata_info.output_crop_rect.nLeft = output_crop_payload->left;
11450 m_extradata_info.output_crop_rect.nTop = output_crop_payload->top;
11451 m_extradata_info.output_crop_rect.nWidth = output_crop_payload->left + output_crop_payload->display_width;
11452 m_extradata_info.output_crop_rect.nHeight = output_crop_payload->top + output_crop_payload->display_height;
11453 m_extradata_info.output_width = output_crop_payload->width;
11454 m_extradata_info.output_height = output_crop_payload->height;
11455 m_extradata_info.output_crop_updated = OMX_TRUE;
11456 for(unsigned int m=0; m<output_crop_payload->misr_info[0].misr_set; m++) {
11457 DEBUG_PRINT_HIGH("MISR0: %x %x %x %x\n",
11458 output_crop_payload->misr_info[0].misr_dpb_luma[m],
11459 output_crop_payload->misr_info[0].misr_dpb_chroma[m],
11460 output_crop_payload->misr_info[0].misr_opb_luma[m],
11461 output_crop_payload->misr_info[0].misr_opb_chroma[m]);
11462 }
11463 for(unsigned int m=0; m< output_crop_payload->misr_info[1].misr_set; m++) {
11464 DEBUG_PRINT_HIGH("MISR1: %x %x %x %x\n",
11465 output_crop_payload->misr_info[1].misr_dpb_luma[m],
11466 output_crop_payload->misr_info[1].misr_dpb_chroma[m],
11467 output_crop_payload->misr_info[1].misr_opb_luma[m],
11468 output_crop_payload->misr_info[1].misr_opb_chroma[m]);
11469 }
11470 memcpy(m_extradata_info.misr_info, output_crop_payload->misr_info, 2 * sizeof(msm_vidc_misr_info));
11471 if (client_extradata & OMX_OUTPUTCROP_EXTRADATA) {
11472 if (p_client_extra) {
11473 append_outputcrop_extradata(p_client_extra, output_crop_payload);
11474 p_client_extra = (OMX_OTHER_EXTRADATATYPE *)(((OMX_U8 *)p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11475 }
11476 }
11477 }
11478 }
11479 break;
11480 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
11481 struct msm_vidc_recoverysei_payload *recovery_sei_payload;
11482 recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
11483 recovery_sei_flags = recovery_sei_payload->flags;
11484 if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
11485 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
11486 DEBUG_PRINT_HIGH("***************************************************");
11487 DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
11488 DEBUG_PRINT_HIGH("***************************************************");
11489 }
11490 break;
11491 case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
11492 panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
11493 if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
11494 DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
11495 DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
11496 MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
11497 return reconfig_event_sent;
11498 }
11499 break;
11500 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
11501 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
11502 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
11503 reconfig_event_sent |= handle_color_space_info((void *)data->data);
11504 break;
11505 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
11506 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
11507 s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
11508 switch (s3d_frame_packing_payload->fpa_type) {
11509 case MSM_VIDC_FRAMEPACK_SIDE_BY_SIDE:
11510 if (s3d_frame_packing_payload->content_interprtation_type == 1)
11511 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_L_R;
11512 else if (s3d_frame_packing_payload->content_interprtation_type == 2)
11513 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_R_L;
11514 else {
11515 DEBUG_PRINT_ERROR("Unsupported side-by-side framepacking type");
11516 stereo_output_mode = HAL_NO_3D;
11517 }
11518 break;
11519 case MSM_VIDC_FRAMEPACK_TOP_BOTTOM:
11520 stereo_output_mode = HAL_3D_TOP_BOTTOM;
11521 break;
11522 default:
11523 DEBUG_PRINT_ERROR("Unsupported framepacking type");
11524 stereo_output_mode = HAL_NO_3D;
11525 }
11526 DEBUG_PRINT_LOW("setMetaData FRAMEPACKING : fpa_type = %u, content_interprtation_type = %u, stereo_output_mode= %d",
11527 s3d_frame_packing_payload->fpa_type, s3d_frame_packing_payload->content_interprtation_type, stereo_output_mode);
11528 if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
11529 if (p_client_extra) {
11530 append_framepack_extradata(p_client_extra, s3d_frame_packing_payload);
11531 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11532 }
11533 }
11534 break;
11535 case MSM_VIDC_EXTRADATA_FRAME_QP:
11536 struct msm_vidc_frame_qp_payload *qp_payload;
11537 qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
11538 if (client_extradata & OMX_QP_EXTRADATA) {
11539 if (p_client_extra) {
11540 append_qp_extradata(p_client_extra, qp_payload);
11541 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11542 }
11543 }
11544 break;
11545 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
11546 struct msm_vidc_frame_bits_info_payload *bits_info_payload;
11547 bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
11548 if (client_extradata & OMX_BITSINFO_EXTRADATA) {
11549 if (p_client_extra) {
11550 append_bitsinfo_extradata(p_client_extra, bits_info_payload);
11551 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11552 }
11553 }
11554 break;
11555 case MSM_VIDC_EXTRADATA_UBWC_CR_STAT_INFO:
11556 DEBUG_PRINT_LOW("MSM_VIDC_EXTRADATA_UBWC_CR_STAT_INFO not used. Ignoring.");
11557 break;
11558 case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
11559 if(output_capability == V4L2_PIX_FMT_HEVC) {
11560 struct msm_vidc_stream_userdata_payload* userdata_payload = (struct msm_vidc_stream_userdata_payload*)data->data;
11561 // Remove the size of type from msm_vidc_stream_userdata_payload
11562 uint32_t payload_len = data->nDataSize - sizeof(userdata_payload->type);
11563 if ((data->nDataSize < sizeof(userdata_payload->type)) ||
11564 (payload_len > HDR_DYNAMIC_META_DATA_SZ)) {
11565 DEBUG_PRINT_ERROR("Invalid User extradata size %u for HDR10+", data->nDataSize);
11566 } else {
11567 // enable setting metadata via gralloc handle
11568 //#if HDR10_SETMETADATA_ENABLE
11569 color_mdata.dynamicMetaDataValid = true;
11570 color_mdata.dynamicMetaDataLen = payload_len;
11571 memcpy(color_mdata.dynamicMetaDataPayload, userdata_payload->data, payload_len);
11572 DEBUG_PRINT_HIGH("Copied %u bytes of HDR10+ extradata", payload_len);
11573 //#endif
11574 store_hevc_hdr10plusinfo(payload_len, userdata_payload);
11575 }
11576 }
11577 if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
11578 if (p_client_extra) {
11579 append_user_extradata(p_client_extra, data);
11580 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11581 }
11582 }
11583 break;
11584 case MSM_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI:
11585
11586 internal_hdr_info_changed_flag |= handle_content_light_level_info((void*)data->data);
11587 break;
11588 case MSM_VIDC_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI:
11589 internal_hdr_info_changed_flag |= handle_mastering_display_color_info((void*)data->data);
11590 break;
11591 default:
11592 DEBUG_PRINT_LOW("Unrecognized extradata");
11593 goto unrecognized_extradata;
11594 }
11595 consumed_len += data->nSize;
11596 data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
11597 }
11598 if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
11599 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11600 if (p_client_extra) {
11601 append_frame_info_extradata(p_client_extra,
11602 num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
11603 time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
11604 p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
11605 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11606 }
11607 }
11608 if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
11609 if (p_client_extra) {
11610 append_frame_dimension_extradata(p_client_extra);
11611 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11612 }
11613 }
11614
11615 if(internal_hdr_info_changed_flag) {
11616 print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "Internal");
11617 print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "Client");
11618 if(!reconfig_event_sent) {
11619 DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to HDR Info Change");
11620 post_event(OMX_CORE_OUTPUT_PORT_INDEX,
11621 OMX_QTIIndexConfigDescribeHDRColorInfo,
11622 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
11623 reconfig_event_sent = true;
11624 }
11625 }
11626
11627 if (m_enable_android_native_buffers) {
11628 ColorAspects final_color_aspects;
11629 HDRStaticInfo final_hdr_info;
11630 memset(&final_color_aspects, 0, sizeof(final_color_aspects));
11631 memset(&final_hdr_info, 0, sizeof(final_hdr_info));
11632 get_preferred_color_aspects(final_color_aspects);
11633
11634 /* For VP8, always set the metadata on gralloc handle to 601-LR */
11635 if (output_capability == V4L2_PIX_FMT_VP8) {
11636 final_color_aspects.mPrimaries = ColorAspects::PrimariesBT601_6_525;
11637 final_color_aspects.mRange = ColorAspects::RangeLimited;
11638 final_color_aspects.mTransfer = ColorAspects::TransferSMPTE170M;
11639 final_color_aspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
11640 }
11641 get_preferred_hdr_info(final_hdr_info);
11642 // enable setting metadata via gralloc handle
11643 //#if HDR10_SETMETADATA_ENABLE
11644 convert_hdr_info_to_metadata(final_hdr_info, color_mdata);
11645 convert_hdr10plusinfo_to_metadata(p_buf_hdr->pMarkData, color_mdata);
11646 remove_hdr10plusinfo_using_cookie(p_buf_hdr->pMarkData);
11647 convert_color_aspects_to_metadata(final_color_aspects, color_mdata);
11648 print_debug_hdr_color_info_mdata(&color_mdata);
11649 print_debug_hdr10plus_metadata(color_mdata);
11650 set_colormetadata_in_handle(&color_mdata, buf_index);
11651 //#endif
11652 }
11653
11654 }
11655 unrecognized_extradata:
11656 if (client_extradata) {
11657 p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11658 if (p_client_extra) {
11659 append_terminator_extradata(p_client_extra);
11660 }
11661 }
11662 return reconfig_event_sent;
11663 }
11664
enable_extradata(OMX_U64 requested_extradata,bool is_internal,bool enable)11665 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U64 requested_extradata,
11666 bool is_internal, bool enable)
11667 {
11668 OMX_ERRORTYPE ret = OMX_ErrorNone;
11669 struct v4l2_control control;
11670 if (m_state != OMX_StateLoaded) {
11671 DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
11672 return OMX_ErrorIncorrectStateOperation;
11673 }
11674 DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
11675 (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
11676
11677 if (!is_internal) {
11678 if (enable)
11679 client_extradata |= requested_extradata;
11680 else
11681 client_extradata = client_extradata & ~requested_extradata;
11682 }
11683
11684 if (enable) {
11685 if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
11686 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11687 control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
11688 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11689 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
11690 " Quality of interlaced clips might be impacted.");
11691 }
11692 }
11693 if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
11694 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11695 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
11696 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11697 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
11698 }
11699 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11700 control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
11701 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11702 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
11703 }
11704 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11705 control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
11706 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11707 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
11708 }
11709 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11710 control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
11711 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11712 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11713 }
11714 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11715 control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
11716 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11717 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11718 }
11719 if (output_capability == V4L2_PIX_FMT_MPEG2) {
11720 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11721 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
11722 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11723 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11724 }
11725 }
11726 }
11727 if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
11728 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11729 control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
11730 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11731 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
11732 }
11733 }
11734 if (!secure_mode && (requested_extradata & OMX_FRAMEPACK_EXTRADATA)) {
11735 if (output_capability == V4L2_PIX_FMT_H264) {
11736 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
11737 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11738 control.value = V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
11739 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11740 DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
11741 }
11742 } else {
11743 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
11744 }
11745 }
11746 if (requested_extradata & OMX_QP_EXTRADATA) {
11747 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11748 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
11749 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11750 DEBUG_PRINT_HIGH("Failed to set QP extradata");
11751 }
11752 }
11753 if (requested_extradata & OMX_EXTNUSER_EXTRADATA) {
11754 if (!secure_mode || (secure_mode && output_capability == V4L2_PIX_FMT_HEVC)) {
11755 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11756 control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
11757 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11758 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
11759 }
11760 }
11761 }
11762 #if NEED_TO_REVISIT
11763 if (requested_extradata & OMX_QP_EXTRADATA) {
11764 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11765 control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
11766 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11767 DEBUG_PRINT_HIGH("Failed to set QP extradata");
11768 }
11769 }
11770 #endif
11771 if (requested_extradata & OMX_OUTPUTCROP_EXTRADATA) {
11772 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11773 control.value = V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP;
11774 DEBUG_PRINT_LOW("Enable output crop extra data");
11775 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11776 DEBUG_PRINT_HIGH("Failed to set output crop extradata");
11777 }
11778 }
11779 if (requested_extradata & OMX_UBWC_CR_STATS_INFO_EXTRADATA) {
11780 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11781 control.value = V4L2_MPEG_VIDC_EXTRADATA_UBWC_CR_STATS_INFO;
11782 DEBUG_PRINT_LOW("Enable UBWC stats extra data");
11783 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11784 DEBUG_PRINT_HIGH("Failed to set output crop extradata");
11785 }
11786 }
11787 if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) {
11788 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11789 switch(output_capability) {
11790 case V4L2_PIX_FMT_H264:
11791 case V4L2_PIX_FMT_HEVC:
11792 control.value = V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY;
11793 break;
11794 case V4L2_PIX_FMT_VP8:
11795 case V4L2_PIX_FMT_VP9:
11796 control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE;
11797 break;
11798 case V4L2_PIX_FMT_MPEG2:
11799 control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
11800 break;
11801 default:
11802 DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind);
11803 return ret;
11804 }
11805
11806 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11807 DEBUG_PRINT_HIGH("Failed to set Display info extradata");
11808 }
11809 }
11810 if (requested_extradata & OMX_HDR_COLOR_INFO_EXTRADATA) {
11811 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11812 if (output_capability == V4L2_PIX_FMT_HEVC) {
11813 control.value = V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI;
11814 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11815 DEBUG_PRINT_HIGH("Failed to set Display Colour SEI extradata");
11816 }
11817 control.value = V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI;
11818 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11819 DEBUG_PRINT_HIGH("Failed to set Content Light Level SEI extradata");
11820 }
11821 } else {
11822 DEBUG_PRINT_HIGH("OMX_HDR_COLOR_INFO_EXTRADATA supported for HEVC only");
11823 }
11824 }
11825 }
11826 ret = get_buffer_req(&drv_ctx.op_buf);
11827 return ret;
11828 }
11829
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)11830 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11831 {
11832 OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
11833 OMX_U8 *data_ptr = extra->data, data = 0;
11834 while (byte_count < extra->nDataSize) {
11835 data = *data_ptr;
11836 while (data) {
11837 num_MB += (data&0x01);
11838 data >>= 1;
11839 }
11840 data_ptr++;
11841 byte_count++;
11842 }
11843 num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
11844 (drv_ctx.video_resolution.frame_height + 15)) >> 8;
11845 return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
11846 }
11847
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)11848 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11849 {
11850 if (!m_debug_extradata || !extra)
11851 return;
11852
11853
11854 DEBUG_PRINT_HIGH(
11855 "============== Extra Data ==============\n"
11856 " Size: %u\n"
11857 " Version: %u\n"
11858 " PortIndex: %u\n"
11859 " Type: %x\n"
11860 " DataSize: %u",
11861 (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
11862 (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
11863
11864 if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
11865 OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
11866 DEBUG_PRINT_HIGH(
11867 "------ Interlace Format ------\n"
11868 " Size: %u\n"
11869 " Version: %u\n"
11870 " PortIndex: %u\n"
11871 " Is Interlace Format: %d\n"
11872 " Interlace Formats: %u\n"
11873 "=========== End of Interlace ===========",
11874 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
11875 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
11876 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
11877 OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
11878
11879 DEBUG_PRINT_HIGH(
11880 "-------- Frame Format --------\n"
11881 " Picture Type: %d\n"
11882 " Interlace Type: %d\n"
11883 " Pan Scan Total Frame Num: %u\n"
11884 " Concealed Macro Blocks: %u\n"
11885 " Recovery SEI Flag: %u\n"
11886 " frame rate: %u\n"
11887 " Time Stamp: %llu\n"
11888 " Aspect Ratio X: %u\n"
11889 " Aspect Ratio Y: %u",
11890 fminfo->ePicType,
11891 fminfo->interlaceType,
11892 (unsigned int)fminfo->panScan.numWindows,
11893 (unsigned int)fminfo->nConcealedMacroblocks,
11894 (unsigned int)fminfo->nRecoverySeiFlag,
11895 (unsigned int)fminfo->nFrameRate,
11896 fminfo->nTimeStamp,
11897 (unsigned int)fminfo->aspectRatio.aspectRatioX,
11898 (unsigned int)fminfo->aspectRatio.aspectRatioY);
11899
11900 for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
11901 DEBUG_PRINT_HIGH(
11902 "------------------------------"
11903 " Pan Scan Frame Num: %u\n"
11904 " Rectangle x: %d\n"
11905 " Rectangle y: %d\n"
11906 " Rectangle dx: %d\n"
11907 " Rectangle dy: %d",
11908 (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
11909 (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
11910 }
11911
11912 DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
11913 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
11914 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
11915 DEBUG_PRINT_HIGH(
11916 "------------------ Framepack Format ----------\n"
11917 " id: %u \n"
11918 " cancel_flag: %u \n"
11919 " type: %u \n"
11920 " quincunx_sampling_flagFormat: %u \n"
11921 " content_interpretation_type: %u \n"
11922 " spatial_flipping_flag: %u \n"
11923 " frame0_flipped_flag: %u \n"
11924 " field_views_flag: %u \n"
11925 " current_frame_is_frame0_flag: %u \n"
11926 " frame0_self_contained_flag: %u \n"
11927 " frame1_self_contained_flag: %u \n"
11928 " frame0_grid_position_x: %u \n"
11929 " frame0_grid_position_y: %u \n"
11930 " frame1_grid_position_x: %u \n"
11931 " frame1_grid_position_y: %u \n"
11932 " reserved_byte: %u \n"
11933 " repetition_period: %u \n"
11934 " extension_flag: %u \n"
11935 "================== End of Framepack ===========",
11936 (unsigned int)framepack->id,
11937 (unsigned int)framepack->cancel_flag,
11938 (unsigned int)framepack->type,
11939 (unsigned int)framepack->quincunx_sampling_flag,
11940 (unsigned int)framepack->content_interpretation_type,
11941 (unsigned int)framepack->spatial_flipping_flag,
11942 (unsigned int)framepack->frame0_flipped_flag,
11943 (unsigned int)framepack->field_views_flag,
11944 (unsigned int)framepack->current_frame_is_frame0_flag,
11945 (unsigned int)framepack->frame0_self_contained_flag,
11946 (unsigned int)framepack->frame1_self_contained_flag,
11947 (unsigned int)framepack->frame0_grid_position_x,
11948 (unsigned int)framepack->frame0_grid_position_y,
11949 (unsigned int)framepack->frame1_grid_position_x,
11950 (unsigned int)framepack->frame1_grid_position_y,
11951 (unsigned int)framepack->reserved_byte,
11952 (unsigned int)framepack->repetition_period,
11953 (unsigned int)framepack->extension_flag);
11954 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
11955 OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
11956 DEBUG_PRINT_HIGH(
11957 "---- QP (Frame quantization parameter) ----\n"
11958 " Frame QP: %u \n"
11959 " Sum of Frame QP: %u \n"
11960 " Sum of Skipped QP: %u \n"
11961 " Num Skipped Blocks: %u \n"
11962 " Total Blocks: %u \n"
11963 "================ End of QP ================\n",
11964 (unsigned int)qp->nQP,(unsigned int)qp->nQPSum,
11965 (unsigned int)qp->nSkipQPSum,(unsigned int)qp->nSkipNumBlocks,
11966 (unsigned int)qp->nTotalNumBlocks);
11967 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
11968 OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
11969 DEBUG_PRINT_HIGH(
11970 "--------- Input bits information --------\n"
11971 " Header bits: %u \n"
11972 " Frame bits: %u \n"
11973 "===== End of Input bits information =====\n",
11974 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
11975 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
11976 OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
11977 OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
11978 OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
11979 OMX_U32 i = 0;
11980 DEBUG_PRINT_HIGH(
11981 "-------------- Userdata -------------\n"
11982 " Stream userdata type: %u\n"
11983 " userdata size: %u\n"
11984 " STREAM_USERDATA:",
11985 (unsigned int)userdata->type, (unsigned int)userdata_size);
11986 for (i = 0; i < userdata_size; i+=4) {
11987 DEBUG_PRINT_HIGH(" %x %x %x %x",
11988 data_ptr[i], data_ptr[i+1],
11989 data_ptr[i+2], data_ptr[i+3]);
11990 }
11991 DEBUG_PRINT_HIGH(
11992 "=========== End of Userdata ===========");
11993 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) {
11994 OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
11995 DEBUG_PRINT_HIGH(
11996 "-------------- VQZip -------------\n"
11997 " Size: %u\n",
11998 (unsigned int)vq->nSize);
11999 DEBUG_PRINT_HIGH( "=========== End of VQZip ===========");
12000 } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataOutputCropInfo) {
12001 OMX_QCOM_OUTPUT_CROP *outputcrop_info = (OMX_QCOM_OUTPUT_CROP*)(void *)extra->data;
12002 DEBUG_PRINT_HIGH(
12003 "------------------ output crop ----------\n"
12004 " left: %u \n"
12005 " top: %u \n"
12006 " display_width: %u \n"
12007 " display_height: %u \n"
12008 " width: %u \n"
12009 " height: %u \n"
12010 " frame_num: %u \n"
12011 " bit_depth_y: %u \n"
12012 " bit_depth_c: %u \n",
12013 (unsigned int)outputcrop_info->left,
12014 (unsigned int)outputcrop_info->top,
12015 (unsigned int)outputcrop_info->display_width,
12016 (unsigned int)outputcrop_info->display_height,
12017 (unsigned int)outputcrop_info->width,
12018 (unsigned int)outputcrop_info->height,
12019 (unsigned int)outputcrop_info->frame_num,
12020 (unsigned int)outputcrop_info->bit_depth_y,
12021 (unsigned int)outputcrop_info->bit_depth_c);
12022 for(unsigned int m=0; m<outputcrop_info->misr_info[0].misr_set; m++) {
12023 DEBUG_PRINT_HIGH(
12024 " top field: misr_dpb_luma(%d): %u \n"
12025 " top field: misr_dpb_chroma(%d): %u \n"
12026 " top field: misr_opb_luma(%d): %u \n"
12027 " top field: misr_opb_chroma(%d): %u \n",
12028 m, (unsigned int)outputcrop_info->misr_info[0].misr_dpb_luma[m],
12029 m, (unsigned int)outputcrop_info->misr_info[0].misr_dpb_chroma[m],
12030 m, (unsigned int)outputcrop_info->misr_info[0].misr_opb_luma[m],
12031 m, (unsigned int)outputcrop_info->misr_info[0].misr_opb_chroma[m]);
12032 }
12033 for(unsigned int m=0; m<outputcrop_info->misr_info[1].misr_set; m++) {
12034 DEBUG_PRINT_HIGH(
12035 " bottom field: misr_dpb_luma(%d): %u \n"
12036 "bottom field: misr_dpb_chroma(%d): %u \n"
12037 " bottom field: misr_opb_luma(%d): %u \n"
12038 "bottom field: misr_opb_chroma(%d): %u \n",
12039 m, (unsigned int)outputcrop_info->misr_info[1].misr_dpb_luma[m],
12040 m, (unsigned int)outputcrop_info->misr_info[1].misr_dpb_chroma[m],
12041 m, (unsigned int)outputcrop_info->misr_info[1].misr_opb_luma[m],
12042 m, (unsigned int)outputcrop_info->misr_info[1].misr_opb_chroma[m]);
12043 }
12044 DEBUG_PRINT_HIGH("================== End of output crop ===========");
12045 } else if (extra->eType == OMX_ExtraDataNone) {
12046 DEBUG_PRINT_HIGH("========== End of Terminator ===========");
12047 } else {
12048 DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
12049 }
12050 }
12051
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type)12052 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12053 OMX_U32 interlaced_format_type)
12054 {
12055 OMX_STREAMINTERLACEFORMAT *interlace_format;
12056
12057 if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
12058 return;
12059 }
12060 if (!extra) {
12061 DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input");
12062 return;
12063 }
12064 extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
12065 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12066 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12067 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
12068 extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
12069 interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
12070 interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
12071 interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
12072 interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12073
12074 if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) {
12075 interlace_format->bInterlaceFormat = OMX_FALSE;
12076 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
12077 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
12078 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) {
12079 interlace_format->bInterlaceFormat = OMX_TRUE;
12080 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
12081 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
12082 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) {
12083 interlace_format->bInterlaceFormat = OMX_TRUE;
12084 interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
12085 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
12086 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_TOPFIELDFIRST) {
12087 interlace_format->bInterlaceFormat = OMX_TRUE;
12088 interlace_format->nInterlaceFormats = OMX_InterlaceFrameTopFieldFirst;
12089 drv_ctx.interlace = VDEC_InterlaceFrameTopFieldFirst;
12090 } else if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_BOTTOMFIELDFIRST) {
12091 interlace_format->bInterlaceFormat = OMX_TRUE;
12092 interlace_format->nInterlaceFormats = OMX_InterlaceFrameBottomFieldFirst;
12093 drv_ctx.interlace = VDEC_InterlaceFrameBottomFieldFirst;
12094 } else {
12095 //default case - set to progressive
12096 interlace_format->bInterlaceFormat = OMX_FALSE;
12097 interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
12098 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
12099 }
12100 print_debug_extradata(extra);
12101 }
12102
append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE * extra)12103 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12104 {
12105 OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
12106 if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
12107 return;
12108 }
12109 extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
12110 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12111 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12112 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
12113 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
12114 frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
12115 frame_dimension->nDecWidth = rectangle.nLeft;
12116 frame_dimension->nDecHeight = rectangle.nTop;
12117 frame_dimension->nActualWidth = rectangle.nWidth;
12118 frame_dimension->nActualHeight = rectangle.nHeight;
12119 }
12120
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)12121 void omx_vdec::fill_aspect_ratio_info(
12122 struct vdec_aspectratioinfo *aspect_ratio_info,
12123 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
12124 {
12125 m_extradata = frame_info;
12126 m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
12127 m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
12128 DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
12129 (unsigned int)m_extradata->aspectRatio.aspectRatioY);
12130 }
12131
append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 num_conceal_mb,OMX_U32 recovery_sei_flag,OMX_U32 picture_type,OMX_U32 frame_rate,OMX_TICKS time_stamp,struct msm_vidc_panscan_window_payload * panscan_payload,struct vdec_aspectratioinfo * aspect_ratio_info)12132 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12133 OMX_U32 num_conceal_mb, OMX_U32 recovery_sei_flag, OMX_U32 picture_type, OMX_U32 frame_rate,
12134 OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
12135 struct vdec_aspectratioinfo *aspect_ratio_info)
12136 {
12137 OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
12138 struct msm_vidc_panscan_window *panscan_window;
12139 if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
12140 return;
12141 }
12142 extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
12143 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12144 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12145 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
12146 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
12147 frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
12148 switch (picture_type) {
12149 case PICTURE_TYPE_I:
12150 frame_info->ePicType = OMX_VIDEO_PictureTypeI;
12151 break;
12152 case PICTURE_TYPE_P:
12153 frame_info->ePicType = OMX_VIDEO_PictureTypeP;
12154 break;
12155 case PICTURE_TYPE_B:
12156 frame_info->ePicType = OMX_VIDEO_PictureTypeB;
12157 break;
12158 default:
12159 frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
12160 }
12161 if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
12162 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
12163 else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
12164 frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
12165 else if (drv_ctx.interlace == VDEC_InterlaceFrameTopFieldFirst)
12166 frame_info->interlaceType = OMX_QCOM_InterlaceFrameTopFieldFirst;
12167 else if (drv_ctx.interlace == VDEC_InterlaceFrameBottomFieldFirst)
12168 frame_info->interlaceType = OMX_QCOM_InterlaceFrameBottomFieldFirst;
12169 else
12170 frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
12171 memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
12172 frame_info->nConcealedMacroblocks = num_conceal_mb;
12173 frame_info->nRecoverySeiFlag = recovery_sei_flag;
12174 frame_info->nFrameRate = frame_rate;
12175 frame_info->nTimeStamp = time_stamp;
12176 frame_info->panScan.numWindows = 0;
12177 if (output_capability == V4L2_PIX_FMT_MPEG2) {
12178 if (m_disp_hor_size && m_disp_vert_size) {
12179 frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
12180 frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
12181 } else {
12182 frame_info->displayAspectRatio.displayHorizontalSize = 0;
12183 frame_info->displayAspectRatio.displayVerticalSize = 0;
12184 }
12185 }
12186
12187 if (panscan_payload) {
12188 frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
12189 panscan_window = &panscan_payload->wnd[0];
12190 for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
12191 frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
12192 frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
12193 frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
12194 frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
12195 panscan_window++;
12196 }
12197 }
12198 fill_aspect_ratio_info(aspect_ratio_info, frame_info);
12199 print_debug_extradata(extra);
12200 }
12201
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)12202 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12203 {
12204 OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
12205 extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
12206 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12207 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12208 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
12209 extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
12210 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
12211 *portDefn = m_port_def;
12212 DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
12213 "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
12214 (unsigned int)portDefn->format.video.nFrameWidth,
12215 (unsigned int)portDefn->format.video.nStride,
12216 (unsigned int)portDefn->format.video.nSliceHeight);
12217 }
12218
append_outputcrop_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_output_crop_payload * output_crop_payload)12219 void omx_vdec::append_outputcrop_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12220 struct msm_vidc_output_crop_payload *output_crop_payload) {
12221 extra->nSize = OMX_OUTPUTCROP_EXTRADATA_SIZE;
12222 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12223 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12224 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataOutputCropInfo;
12225 extra->nDataSize = sizeof(OMX_QCOM_OUTPUT_CROP);
12226 memcpy(extra->data, output_crop_payload, extra->nDataSize);
12227
12228 print_debug_extradata(extra);
12229 }
12230
append_framepack_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_s3d_frame_packing_payload * s3d_frame_packing_payload)12231 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12232 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
12233 {
12234 OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
12235 if (18 * sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
12236 DEBUG_PRINT_ERROR("frame packing size mismatch");
12237 return;
12238 }
12239 extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
12240 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12241 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12242 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
12243 extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
12244 framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
12245 framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
12246 framepack->nVersion.nVersion = OMX_SPEC_VERSION;
12247 framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12248 memcpy(&framepack->id, s3d_frame_packing_payload,
12249 sizeof(struct msm_vidc_s3d_frame_packing_payload));
12250 memcpy(&m_frame_pack_arrangement, framepack,
12251 sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
12252 print_debug_extradata(extra);
12253 }
12254
append_qp_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_qp_payload * qp_payload)12255 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12256 struct msm_vidc_frame_qp_payload *qp_payload)
12257 {
12258 OMX_QCOM_EXTRADATA_QP * qp = NULL;
12259 if (!qp_payload) {
12260 DEBUG_PRINT_ERROR("QP payload is NULL");
12261 return;
12262 }
12263 extra->nSize = OMX_QP_EXTRADATA_SIZE;
12264 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12265 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12266 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
12267 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
12268 qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
12269 qp->nQP = qp_payload->frame_qp;
12270 qp->nQPSum = qp_payload->qp_sum;
12271 qp->nSkipQPSum = qp_payload->skip_qp_sum;
12272 qp->nSkipNumBlocks = qp_payload->skip_num_blocks;
12273 qp->nTotalNumBlocks = qp_payload->total_num_blocks;
12274 print_debug_extradata(extra);
12275 }
12276
append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_bits_info_payload * bits_payload)12277 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12278 struct msm_vidc_frame_bits_info_payload *bits_payload)
12279 {
12280 OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
12281 if (!bits_payload) {
12282 DEBUG_PRINT_ERROR("bits info payload is NULL");
12283 return;
12284 }
12285 extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
12286 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12287 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12288 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
12289 extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
12290 bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
12291 bits->frame_bits = bits_payload->frame_bits;
12292 bits->header_bits = bits_payload->header_bits;
12293 print_debug_extradata(extra);
12294 }
12295
append_user_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_OTHER_EXTRADATATYPE * p_user)12296 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12297 OMX_OTHER_EXTRADATATYPE *p_user)
12298 {
12299 int userdata_size = 0;
12300 struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
12301 userdata_payload =
12302 (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
12303 userdata_size = p_user->nDataSize;
12304 extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
12305 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12306 extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12307 extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
12308 extra->nDataSize = userdata_size;
12309 if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize))
12310 memcpy(extra->data, p_user->data, extra->nDataSize);
12311 print_debug_extradata(extra);
12312 }
12313
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)12314 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12315 {
12316 if (!client_extradata) {
12317 return;
12318 }
12319 extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
12320 extra->nVersion.nVersion = OMX_SPEC_VERSION;
12321 extra->eType = OMX_ExtraDataNone;
12322 extra->nDataSize = 0;
12323 extra->data[0] = 0;
12324
12325 print_debug_extradata(extra);
12326 }
12327
allocate_desc_buffer(OMX_U32 index)12328 OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index)
12329 {
12330 OMX_ERRORTYPE eRet = OMX_ErrorNone;
12331 if (index >= drv_ctx.ip_buf.actualcount) {
12332 DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
12333 return OMX_ErrorInsufficientResources;
12334 }
12335 if (m_desc_buffer_ptr == NULL) {
12336 m_desc_buffer_ptr = (desc_buffer_hdr*) \
12337 calloc( (sizeof(desc_buffer_hdr)),
12338 drv_ctx.ip_buf.actualcount);
12339 if (m_desc_buffer_ptr == NULL) {
12340 DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
12341 return OMX_ErrorInsufficientResources;
12342 }
12343 }
12344
12345 m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
12346 if (m_desc_buffer_ptr[index].buf_addr == NULL) {
12347 DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
12348 return OMX_ErrorInsufficientResources;
12349 }
12350
12351 return eRet;
12352 }
12353
insert_demux_addr_offset(OMX_U32 address_offset)12354 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
12355 {
12356 DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
12357 if (m_demux_entries < 8192) {
12358 m_demux_offsets[m_demux_entries++] = address_offset;
12359 }
12360 return;
12361 }
12362
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)12363 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
12364 {
12365 OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
12366 OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
12367 OMX_U32 index = 0;
12368
12369 m_demux_entries = 0;
12370
12371 while (index < bytes_to_parse) {
12372 if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
12373 (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
12374 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
12375 (buf[index+2] == 0x01)) ) {
12376 //Found start code, insert address offset
12377 insert_demux_addr_offset(index);
12378 if (buf[index+2] == 0x01) // 3 byte start code
12379 index += 3;
12380 else //4 byte start code
12381 index += 4;
12382 } else
12383 index++;
12384 }
12385 DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
12386 return;
12387 }
12388
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)12389 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
12390 {
12391 //fix this, handle 3 byte start code, vc1 terminator entry
12392 OMX_U8 *p_demux_data = NULL;
12393 OMX_U32 desc_data = 0;
12394 OMX_U32 start_addr = 0;
12395 OMX_U32 nal_size = 0;
12396 OMX_U32 suffix_byte = 0;
12397 OMX_U32 demux_index = 0;
12398 OMX_U32 buffer_index = 0;
12399
12400 if (m_desc_buffer_ptr == NULL) {
12401 DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
12402 return OMX_ErrorBadParameter;
12403 }
12404
12405 buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
12406 if (buffer_index > drv_ctx.ip_buf.actualcount) {
12407 DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
12408 return OMX_ErrorBadParameter;
12409 }
12410
12411 p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
12412
12413 if ( ((OMX_U8*)p_demux_data == NULL) ||
12414 ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
12415 DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
12416 return OMX_ErrorBadParameter;
12417 } else {
12418 for (; demux_index < m_demux_entries; demux_index++) {
12419 desc_data = 0;
12420 start_addr = m_demux_offsets[demux_index];
12421 if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
12422 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
12423 } else {
12424 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
12425 }
12426 if (demux_index < (m_demux_entries - 1)) {
12427 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
12428 } else {
12429 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
12430 }
12431 DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
12432 (unsigned int)start_addr,
12433 (unsigned int)suffix_byte,
12434 (unsigned int)nal_size,
12435 (unsigned int)demux_index);
12436 desc_data = (start_addr >> 3) << 1;
12437 desc_data |= (start_addr & 7) << 21;
12438 desc_data |= suffix_byte << 24;
12439
12440 memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
12441 memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
12442 memset(p_demux_data + 8, 0, sizeof(OMX_U32));
12443 memset(p_demux_data + 12, 0, sizeof(OMX_U32));
12444
12445 p_demux_data += 16;
12446 }
12447 //Add zero word to indicate end of descriptors
12448 memset(p_demux_data, 0, sizeof(OMX_U32));
12449
12450 m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
12451 DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
12452 }
12453 memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
12454 m_demux_entries = 0;
12455 DEBUG_PRINT_LOW("Demux table complete!");
12456 return OMX_ErrorNone;
12457 }
12458
enable_color_conversion(bool enable)12459 void omx_vdec::allocate_color_convert_buf::enable_color_conversion(bool enable) {
12460 if (!omx) {
12461 DEBUG_PRINT_HIGH("Invalid omx_vdec");
12462 return;
12463 }
12464
12465 if (!omx->in_reconfig)
12466 enabled = enable;
12467
12468 omx->c2d_enable_pending = enable;
12469 }
12470
allocate_color_convert_buf()12471 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
12472 {
12473 enabled = false;
12474 client_buffers_disabled = false;
12475 omx = NULL;
12476 init_members();
12477 ColorFormat = OMX_COLOR_FormatMax;
12478 dest_format = YCbCr420P;
12479 m_c2d_width = 0;
12480 m_c2d_height = 0;
12481
12482 mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12][-1] =
12483 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
12484 mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12][VDEC_CODECTYPE_MVC] =
12485 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
12486 mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12_UBWC][-1] =
12487 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
12488 mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12_TP10_UBWC][-1] =
12489 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed;
12490 mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_P010_VENUS][-1] =
12491 QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus;
12492
12493 mMapOutput2Convert.insert( {
12494 {VDEC_YUV_FORMAT_NV12, NV12_128m},
12495 {VDEC_YUV_FORMAT_NV12_UBWC, NV12_UBWC},
12496 {VDEC_YUV_FORMAT_NV12_TP10_UBWC, TP10_UBWC},
12497 {VDEC_YUV_FORMAT_P010_VENUS, YCbCr420_VENUS_P010},
12498 });
12499 }
12500
set_vdec_client(void * client)12501 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
12502 {
12503 omx = reinterpret_cast<omx_vdec*>(client);
12504 }
12505
init_members()12506 void omx_vdec::allocate_color_convert_buf::init_members()
12507 {
12508 allocated_count = 0;
12509 buffer_size_req = 0;
12510 buffer_alignment_req = 0;
12511 m_c2d_width = m_c2d_height = 0;
12512 memset(m_platform_list_client,0,sizeof(m_platform_list_client));
12513 memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
12514 memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
12515 memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
12516 #ifdef USE_ION
12517 memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
12518 #endif
12519 for (int i = 0; i < MAX_COUNT; i++)
12520 pmem_fd[i] = -1;
12521 }
12522
update_buffer_req()12523 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
12524 {
12525 bool status = true;
12526 unsigned int src_size = 0, destination_size = 0;
12527 unsigned int height, width;
12528 struct v4l2_format fmt;
12529 OMX_COLOR_FORMATTYPE drv_color_format;
12530
12531 if (!omx) {
12532 DEBUG_PRINT_ERROR("Invalid client in color convert");
12533 return false;
12534 }
12535 if (!enabled) {
12536 DEBUG_PRINT_HIGH("No color conversion required");
12537 return true;
12538 }
12539 pthread_mutex_lock(&omx->c_lock);
12540
12541 ColorSubMapping::const_iterator
12542 found = mMapOutput2Convert.find(omx->drv_ctx.output_format);
12543 if (found == mMapOutput2Convert.end()) {
12544 DEBUG_PRINT_HIGH("%s: Could not find the color conversion "
12545 "mapping for %#X. Setting to default NV12",
12546 __func__, omx->drv_ctx.output_format);
12547 src_format = NV12_128m;
12548 } else {
12549 src_format = (ColorConvertFormat) found->second;;
12550 }
12551
12552 memset(&fmt, 0x0, sizeof(struct v4l2_format));
12553 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
12554 fmt.fmt.pix_mp.pixelformat = omx->capture_capability;
12555 ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
12556 width = fmt.fmt.pix_mp.width;
12557 height = fmt.fmt.pix_mp.height;
12558
12559 bool resolution_upgrade = (height > m_c2d_height ||
12560 width > m_c2d_width);
12561 bool is_interlaced = omx->m_progressive != MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
12562 if (resolution_upgrade) {
12563 // resolution upgraded ? ensure we are yet to allocate;
12564 // failing which, c2d buffers will never be reallocated and bad things will happen
12565 if (allocated_count > 0) {
12566 DEBUG_PRINT_ERROR("Cannot change C2D buffer requirements with %d active allocations",
12567 allocated_count);
12568 status = false;
12569 }
12570 }
12571
12572 if (status != false) {
12573 if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
12574 (ColorFormat != OMX_COLOR_FormatYUV420Planar &&
12575 ColorFormat != OMX_COLOR_FormatYUV420SemiPlanar &&
12576 ColorFormat != (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m)) {
12577 DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
12578 status = false;
12579 } else {
12580 ColorSubMapping::const_iterator
12581 found = mMapOutput2Convert.find(
12582 omx->drv_ctx.output_format);
12583 if (found == mMapOutput2Convert.end()) {
12584 src_format = NV12_128m;
12585 } else {
12586 src_format = (ColorConvertFormat) found->second;;
12587 }
12588
12589 DEBUG_PRINT_INFO("C2D: Set Resolution, Interlace(%s) Conversion(%#X -> %#X)"
12590 " src(%dX%d) dest(%dX%d)",
12591 (omx->m_progressive != MSM_VIDC_PIC_STRUCT_PROGRESSIVE) ? "true": "false",
12592 src_format, dest_format, width,
12593 omx->m_progressive !=
12594 MSM_VIDC_PIC_STRUCT_PROGRESSIVE?(height+1)/2 : height,
12595 width, height);
12596 status = c2dcc.setResolution(width,
12597 omx->m_progressive !=
12598 MSM_VIDC_PIC_STRUCT_PROGRESSIVE?
12599 (height+1)/2 : height,
12600 width, height,
12601 src_format, dest_format,
12602 0,0);
12603 if (status) {
12604 src_size = c2dcc.getBuffSize(C2D_INPUT);
12605 destination_size = c2dcc.getBuffSize(C2D_OUTPUT);
12606
12607 if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
12608 !destination_size) {
12609 DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
12610 "driver size %u destination size %d",
12611 src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
12612 destination_size);
12613 buffer_size_req = 0;
12614 // TODO: make this fatal. Driver is not supposed to quote size
12615 // smaller than what C2D needs !!
12616 } else {
12617 buffer_size_req = destination_size;
12618 m_c2d_height = height;
12619 m_c2d_width = width;
12620 }
12621 }
12622 }
12623 }
12624 pthread_mutex_unlock(&omx->c_lock);
12625 return status;
12626 }
12627
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)12628 bool omx_vdec::allocate_color_convert_buf::set_color_format(
12629 OMX_COLOR_FORMATTYPE dest_color_format)
12630 {
12631 bool status = true, drv_colorformat_c2d_enable = false;
12632 bool dest_color_format_c2d_enable = false;
12633 OMX_COLOR_FORMATTYPE drv_color_format = OMX_COLOR_FormatUnused;
12634 if (!omx) {
12635 DEBUG_PRINT_ERROR("Invalid client in color convert");
12636 return false;
12637 }
12638 pthread_mutex_lock(&omx->c_lock);
12639 status = get_color_format (drv_color_format);
12640
12641 drv_colorformat_c2d_enable = (drv_color_format != dest_color_format) &&
12642 (drv_color_format != (OMX_COLOR_FORMATTYPE)
12643 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView) &&
12644 (drv_color_format != (OMX_COLOR_FORMATTYPE)
12645 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed) &&
12646 (drv_color_format != (OMX_COLOR_FORMATTYPE)
12647 QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus);
12648
12649 dest_color_format_c2d_enable = (dest_color_format != (OMX_COLOR_FORMATTYPE)
12650 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) &&
12651 (dest_color_format != (OMX_COLOR_FORMATTYPE)
12652 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed);
12653
12654 if (status && drv_colorformat_c2d_enable && dest_color_format_c2d_enable) {
12655 DEBUG_PRINT_LOW("Enabling C2D");
12656 if (dest_color_format == OMX_COLOR_FormatYUV420Planar ||
12657 dest_color_format == OMX_COLOR_FormatYUV420SemiPlanar ||
12658 ((omx->m_progressive != MSM_VIDC_PIC_STRUCT_PROGRESSIVE ||
12659 omx->eCompressionFormat == OMX_VIDEO_CodingMPEG2) &&
12660 dest_color_format == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m)) {
12661 ColorFormat = dest_color_format;
12662 if (dest_color_format == OMX_COLOR_FormatYUV420Planar) {
12663 dest_format = YCbCr420P;
12664 } else if( dest_color_format == OMX_COLOR_FormatYUV420SemiPlanar) {
12665 dest_format = YCbCr420SP;
12666 } else {
12667 dest_format = NV12_128m;
12668 }
12669 enable_color_conversion(true);
12670 } else {
12671 DEBUG_PRINT_ERROR("Unsupported output color format for c2d (%d)",
12672 dest_color_format);
12673 status = false;
12674 enable_color_conversion(false);
12675 }
12676 } else {
12677 enable_color_conversion(false);
12678 }
12679 pthread_mutex_unlock(&omx->c_lock);
12680 return status;
12681 }
12682
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)12683 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
12684 (OMX_BUFFERHEADERTYPE *bufadd)
12685 {
12686 if (!omx) {
12687 DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
12688 return NULL;
12689 }
12690 if (!is_color_conversion_enabled())
12691 return bufadd;
12692
12693 OMX_BUFFERHEADERTYPE *omx_base_address =
12694 is_color_conversion_enabled()?
12695 omx->m_intermediate_out_mem_ptr:omx->m_out_mem_ptr;
12696
12697 unsigned index = 0;
12698 index = bufadd - omx_base_address;
12699 if (index < omx->drv_ctx.op_buf.actualcount) {
12700 m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
12701 m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
12702
12703 omx->m_out_mem_ptr[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
12704 omx->m_out_mem_ptr[index].nTimeStamp = bufadd->nTimeStamp;
12705 bool status = false;
12706 if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
12707 pthread_mutex_lock(&omx->c_lock);
12708 omx->do_cache_operations(omx->drv_ctx.op_intermediate_buf_ion_info[index].data_fd);
12709
12710 DEBUG_PRINT_INFO("C2D: Start color convertion");
12711 status = c2dcc.convertC2D(
12712 omx->drv_ctx.ptr_intermediate_outputbuffer[index].pmem_fd,
12713 bufadd->pBuffer, bufadd->pBuffer,
12714 omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
12715 omx->m_out_mem_ptr[index].pBuffer,
12716 omx->m_out_mem_ptr[index].pBuffer);
12717 omx->do_cache_operations(omx->drv_ctx.op_intermediate_buf_ion_info[index].data_fd);
12718 if (!status) {
12719 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
12720 m_out_mem_ptr_client[index].nFilledLen = 0;
12721 omx->m_out_mem_ptr[index].nFilledLen = 0;
12722 pthread_mutex_unlock(&omx->c_lock);
12723 return &omx->m_out_mem_ptr[index];
12724 } else {
12725 unsigned int filledLen = 0;
12726 c2dcc.getBuffFilledLen(C2D_OUTPUT, filledLen);
12727 if (filledLen > omx->m_out_mem_ptr[index].nAllocLen) {
12728 DEBUG_PRINT_ERROR("Invalid C2D FBD length filledLen = %d alloclen = %d ",filledLen,omx->m_out_mem_ptr[index].nAllocLen);
12729 filledLen = 0;
12730 }
12731 m_out_mem_ptr_client[index].nFilledLen = filledLen;
12732 omx->m_out_mem_ptr[index].nFilledLen = filledLen;
12733 }
12734 pthread_mutex_unlock(&omx->c_lock);
12735 } else {
12736 m_out_mem_ptr_client[index].nFilledLen = 0;
12737 omx->m_out_mem_ptr[index].nFilledLen = 0;
12738 }
12739 return &omx->m_out_mem_ptr[index];
12740 }
12741 DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
12742 return NULL;
12743 }
12744
get_buffer_req(unsigned int & buffer_size)12745 bool omx_vdec::allocate_color_convert_buf::get_buffer_req
12746 (unsigned int &buffer_size)
12747 {
12748 bool status = true;
12749 pthread_mutex_lock(&omx->c_lock);
12750 /* Whenever port mode is set to kPortModeDynamicANWBuffer, Video Frameworks
12751 always uses VideoNativeMetadata and OMX receives buffer type as
12752 grallocsource via storeMetaDataInBuffers_l API. The buffer_size
12753 will be communicated to frameworks via IndexParamPortdefinition. */
12754 if (!enabled)
12755 buffer_size = omx->dynamic_buf_mode ? sizeof(struct VideoNativeMetadata) :
12756 omx->drv_ctx.op_buf.buffer_size;
12757 else {
12758 buffer_size = c2dcc.getBuffSize(C2D_OUTPUT);
12759 }
12760 pthread_mutex_unlock(&omx->c_lock);
12761 return status;
12762 }
12763
set_buffer_req(OMX_U32 buffer_size,OMX_U32 actual_count)12764 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::set_buffer_req(
12765 OMX_U32 buffer_size, OMX_U32 actual_count)
12766 {
12767 OMX_U32 expectedSize = is_color_conversion_enabled() ? buffer_size_req : omx->dynamic_buf_mode ?
12768 sizeof(struct VideoDecoderOutputMetaData) : omx->drv_ctx.op_buf.buffer_size;
12769 if (buffer_size < expectedSize) {
12770 DEBUG_PRINT_ERROR("OP Requirements: Client size(%u) insufficient v/s requested(%u)",
12771 buffer_size, expectedSize);
12772 return OMX_ErrorBadParameter;
12773 }
12774 if (actual_count < omx->drv_ctx.op_buf.mincount) {
12775 DEBUG_PRINT_ERROR("OP Requirements: Client count(%u) insufficient v/s requested(%u)",
12776 actual_count, omx->drv_ctx.op_buf.mincount);
12777 return OMX_ErrorBadParameter;
12778 }
12779
12780 if (enabled) {
12781 // disallow changing buffer size/count while we have active allocated buffers
12782 if (allocated_count > 0) {
12783 DEBUG_PRINT_ERROR("Cannot change C2D buffer size from %u to %u with %d active allocations",
12784 buffer_size_req, buffer_size, allocated_count);
12785 return OMX_ErrorInvalidState;
12786 }
12787
12788 buffer_size_req = buffer_size;
12789 } else {
12790 if (buffer_size > omx->drv_ctx.op_buf.buffer_size) {
12791 omx->drv_ctx.op_buf.buffer_size = buffer_size;
12792 }
12793 }
12794
12795 omx->drv_ctx.op_buf.actualcount = actual_count;
12796 omx->drv_ctx.extradata_info.count = omx->drv_ctx.op_buf.actualcount;
12797 omx->drv_ctx.extradata_info.size = omx->drv_ctx.extradata_info.count *
12798 omx->drv_ctx.extradata_info.buffer_size;
12799 return omx->set_buffer_req(&(omx->drv_ctx.op_buf));
12800 }
12801
is_component_secure()12802 bool omx_vdec::is_component_secure()
12803 {
12804 return secure_mode;
12805 }
12806
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)12807 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
12808 {
12809 bool status = true;
12810 if (!enabled) {
12811 for (auto& x: mMapOutput2DriverColorFormat) {
12812 DecColorMapping::const_iterator
12813 found = mMapOutput2DriverColorFormat.find(omx->drv_ctx.output_format);
12814 if (found == mMapOutput2DriverColorFormat.end()) {
12815 status = false;
12816 } else {
12817 ColorSubMapping::const_iterator
12818 subFound = found->second.find(omx->drv_ctx.decoder_format);
12819 if (subFound == found->second.end()) {
12820 dest_color_format = (OMX_COLOR_FORMATTYPE)
12821 found->second.find(-1)->second;
12822 } else {
12823 dest_color_format = (OMX_COLOR_FORMATTYPE) subFound->second;
12824 }
12825 }
12826 }
12827 } else {
12828 if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
12829 ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
12830 ColorFormat == (OMX_COLOR_FORMATTYPE) QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
12831 dest_color_format = ColorFormat;
12832 } else {
12833 status = false;
12834 }
12835 }
12836 return status;
12837 }
12838
send_codec_config()12839 void omx_vdec::send_codec_config() {
12840 if (codec_config_flag) {
12841 unsigned long p1 = 0, p2 = 0;
12842 unsigned long p3 = 0, p4 = 0;
12843 unsigned long ident = 0, ident2 = 0;
12844 pthread_mutex_lock(&m_lock);
12845 DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
12846 while (m_etb_q.m_size) {
12847 m_etb_q.pop_entry(&p1,&p2,&ident);
12848 if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
12849 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
12850 if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
12851 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
12852 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
12853 omx_report_error();
12854 }
12855 } else {
12856 DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
12857 m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
12858 }
12859 } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
12860 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
12861 while (m_ftb_q.m_size) {
12862 m_ftb_q.pop_entry(&p3,&p4,&ident2);
12863 if (ident2 == OMX_COMPONENT_GENERATE_FTB) {
12864 pthread_mutex_unlock(&m_lock);
12865 if (fill_this_buffer_proxy((OMX_HANDLETYPE)p3,\
12866 (OMX_BUFFERHEADERTYPE *)p4) != OMX_ErrorNone) {
12867 DEBUG_PRINT_ERROR("\n fill_this_buffer_proxy failure");
12868 omx_report_error ();
12869 }
12870 pthread_mutex_lock(&m_lock);
12871 } else if (ident2 == OMX_COMPONENT_GENERATE_FBD) {
12872 fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p3);
12873 }
12874 }
12875 pthread_mutex_unlock(&m_lock);
12876 if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
12877 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
12878 DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
12879 omx_report_error ();
12880 }
12881 } else {
12882 pending_input_buffers++;
12883 VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
12884 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
12885 (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
12886 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
12887 }
12888 } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
12889 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
12890 (OMX_BUFFERHEADERTYPE *)p1);
12891 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
12892 }
12893 }
12894 pthread_mutex_unlock(&m_lock);
12895 }
12896 }
12897
perf_control()12898 omx_vdec::perf_control::perf_control()
12899 {
12900 m_perf_control_enable = 0;
12901 m_perf_lib = NULL;
12902 m_perf_handle = 0;
12903 m_perf_lock_acquire = NULL;
12904 m_perf_lock_release = NULL;
12905 }
12906
~perf_control()12907 omx_vdec::perf_control::~perf_control()
12908 {
12909 if (!m_perf_control_enable)
12910 return;
12911
12912 if (m_perf_handle && m_perf_lock_release) {
12913 m_perf_lock_release(m_perf_handle);
12914 DEBUG_PRINT_LOW("perflock released");
12915 }
12916 if (m_perf_lib) {
12917 dlclose(m_perf_lib);
12918 }
12919 }
12920
perf_lock_acquire()12921 int omx_vdec::perf_control::perf_lock_acquire()
12922 {
12923 int arg[2];
12924 if (!m_perf_control_enable)
12925 return 0;
12926
12927 if (!m_perf_lib) {
12928 DEBUG_PRINT_ERROR("no perf control library");
12929 return -1;
12930 }
12931 if (!m_perf_lock_acquire) {
12932 DEBUG_PRINT_ERROR("NULL perflock acquire");
12933 return -1;
12934 }
12935 if (m_perf_handle) {
12936 DEBUG_PRINT_LOW("perflock already acquired");
12937 return 0;
12938 }
12939 DEBUG_PRINT_HIGH("perflock acquire");
12940 arg[0] = MPCTLV3_VIDEO_DECODE_PB_HINT;
12941 arg[1] = 1;
12942 m_perf_handle = m_perf_lock_acquire(0, 0, arg, sizeof(arg) / sizeof(int));
12943 if (m_perf_handle < 0) {
12944 DEBUG_PRINT_ERROR("perflock acquire failed with error %d", m_perf_handle);
12945 m_perf_handle = 0;
12946 return -1;
12947 }
12948 return 0;
12949 }
12950
perf_lock_release()12951 void omx_vdec::perf_control::perf_lock_release()
12952 {
12953 if (!m_perf_control_enable)
12954 return;
12955
12956 if (!m_perf_lib) {
12957 DEBUG_PRINT_ERROR("no perf control library");
12958 return;
12959 }
12960 if (!m_perf_lock_release) {
12961 DEBUG_PRINT_ERROR("NULL perflock release");
12962 return;
12963 }
12964 if (!m_perf_handle) {
12965 DEBUG_PRINT_LOW("perflock already released");
12966 return;
12967 }
12968 DEBUG_PRINT_HIGH("perflock release");
12969 m_perf_lock_release(m_perf_handle);
12970 m_perf_handle = 0;
12971 }
12972
load_perf_library()12973 bool omx_vdec::perf_control::load_perf_library()
12974 {
12975 char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
12976
12977 if (!m_perf_control_enable) {
12978 DEBUG_PRINT_HIGH("perf control is not enabled");
12979 return false;
12980 }
12981 if (m_perf_lib) {
12982 DEBUG_PRINT_HIGH("perf lib already opened");
12983 return true;
12984 }
12985
12986 if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
12987 DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
12988 goto handle_err;
12989 }
12990
12991 if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
12992 DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
12993 goto handle_err;
12994 } else {
12995 m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
12996 if (m_perf_lock_acquire == NULL) {
12997 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
12998 goto handle_err;
12999 }
13000 m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
13001 if (m_perf_lock_release == NULL) {
13002 DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
13003 goto handle_err;
13004 }
13005 }
13006 return true;
13007
13008 handle_err:
13009 if (m_perf_lib) {
13010 dlclose(m_perf_lib);
13011 }
13012 m_perf_lib = NULL;
13013 m_perf_lock_acquire = NULL;
13014 m_perf_lock_release = NULL;
13015 return false;
13016 }
13017
enable_adaptive_playback(unsigned long nMaxFrameWidth,unsigned long nMaxFrameHeight)13018 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
13019 unsigned long nMaxFrameHeight)
13020 {
13021
13022 OMX_ERRORTYPE eRet = OMX_ErrorNone;
13023 int ret = 0;
13024 unsigned long min_res_buf_count = 0;
13025
13026 eRet = enable_smoothstreaming();
13027 if (eRet != OMX_ErrorNone) {
13028 DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
13029 return eRet;
13030 }
13031
13032 DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
13033 nMaxFrameWidth,
13034 nMaxFrameHeight);
13035 m_smoothstreaming_mode = true;
13036 m_smoothstreaming_width = nMaxFrameWidth;
13037 m_smoothstreaming_height = nMaxFrameHeight;
13038
13039 //Get upper limit buffer count for min supported resolution
13040 struct v4l2_format fmt;
13041 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
13042 fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
13043 fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
13044 fmt.fmt.pix_mp.pixelformat = output_capability;
13045
13046 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
13047 if (ret) {
13048 DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
13049 m_decoder_capability.min_height,
13050 m_decoder_capability.min_width);
13051 return OMX_ErrorUnsupportedSetting;
13052 }
13053
13054 eRet = get_buffer_req(&drv_ctx.op_buf);
13055 if (eRet != OMX_ErrorNone) {
13056 DEBUG_PRINT_ERROR("failed to get_buffer_req");
13057 return eRet;
13058 }
13059
13060 min_res_buf_count = drv_ctx.op_buf.mincount;
13061 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
13062 min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
13063
13064 m_extradata_info.output_crop_rect.nLeft = 0;
13065 m_extradata_info.output_crop_rect.nTop = 0;
13066 m_extradata_info.output_crop_rect.nWidth = m_smoothstreaming_width;
13067 m_extradata_info.output_crop_rect.nHeight = m_smoothstreaming_height;
13068
13069 update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
13070 m_smoothstreaming_width, m_smoothstreaming_height);
13071
13072 //Get upper limit buffer size for max smooth streaming resolution set
13073 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
13074 fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
13075 fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
13076 fmt.fmt.pix_mp.pixelformat = output_capability;
13077 ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
13078 if (ret) {
13079 DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
13080 return OMX_ErrorUnsupportedSetting;
13081 }
13082
13083 eRet = get_buffer_req(&drv_ctx.op_buf);
13084 if (eRet != OMX_ErrorNone) {
13085 DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
13086 return eRet;
13087 }
13088 DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
13089 (unsigned int)drv_ctx.op_buf.buffer_size);
13090
13091 drv_ctx.op_buf.mincount = min_res_buf_count;
13092 drv_ctx.op_buf.actualcount = min_res_buf_count;
13093 drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size;
13094 eRet = set_buffer_req(&drv_ctx.op_buf);
13095 if (eRet != OMX_ErrorNone) {
13096 DEBUG_PRINT_ERROR("failed to set_buffer_req");
13097 return eRet;
13098 }
13099
13100 eRet = get_buffer_req(&drv_ctx.op_buf);
13101 if (eRet != OMX_ErrorNone) {
13102 DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
13103 return eRet;
13104 }
13105 DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
13106 drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
13107 return eRet;
13108 }
13109
13110 //static
describeColorFormat(OMX_PTR pParam)13111 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
13112
13113 #ifndef FLEXYUV_SUPPORTED
13114 return OMX_ErrorUndefined;
13115 #else
13116
13117 if (pParam == NULL) {
13118 DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
13119 return OMX_ErrorBadParameter;
13120 }
13121
13122 DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
13123
13124 MediaImage *img = &(params->sMediaImage);
13125 switch(params->eColorFormat) {
13126 case static_cast <OMX_COLOR_FORMATTYPE> (QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m):
13127 {
13128 img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
13129 img->mNumPlanes = 3;
13130 // mWidth and mHeight represent the W x H of the largest plane
13131 // In our case, this happens to be the Stride x Scanlines of Y plane
13132 img->mWidth = params->nFrameWidth;
13133 img->mHeight = params->nFrameHeight;
13134 size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13135 size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
13136 img->mBitDepth = 8;
13137 //Plane 0 (Y)
13138 img->mPlane[MediaImage::Y].mOffset = 0;
13139 img->mPlane[MediaImage::Y].mColInc = 1;
13140 img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
13141 img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
13142 img->mPlane[MediaImage::Y].mVertSubsampling = 1;
13143 //Plane 1 (U)
13144 img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
13145 img->mPlane[MediaImage::U].mColInc = 2; //interleaved UV
13146 img->mPlane[MediaImage::U].mRowInc =
13147 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13148 img->mPlane[MediaImage::U].mHorizSubsampling = 2;
13149 img->mPlane[MediaImage::U].mVertSubsampling = 2;
13150 //Plane 2 (V)
13151 img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
13152 img->mPlane[MediaImage::V].mColInc = 2; //interleaved UV
13153 img->mPlane[MediaImage::V].mRowInc =
13154 VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
13155 img->mPlane[MediaImage::V].mHorizSubsampling = 2;
13156 img->mPlane[MediaImage::V].mVertSubsampling = 2;
13157 break;
13158 }
13159
13160 case OMX_COLOR_FormatYUV420Planar:
13161 case OMX_COLOR_FormatYUV420SemiPlanar:
13162 // We need not describe the standard OMX linear formats as these are
13163 // understood by client. Fail this deliberately to let client fill-in
13164 return OMX_ErrorUnsupportedSetting;
13165
13166 default:
13167 // Rest all formats which are non-linear cannot be described
13168 DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
13169 img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
13170 return OMX_ErrorNone;
13171 };
13172
13173 DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
13174 DEBUG_PRINT_LOW(" FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
13175 DEBUG_PRINT_LOW(" YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
13176 for (size_t i = 0; i < img->mNumPlanes; ++i) {
13177 DEBUG_PRINT_LOW(" Plane[%zu] : offset=%d / xStep=%d / yStep = %d",
13178 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
13179 }
13180 return OMX_ErrorNone;
13181 #endif //FLEXYUV_SUPPORTED
13182 }
13183
prefetch_buffers(unsigned long prefetch_count,unsigned long prefetch_size,unsigned ioctl_code,unsigned ion_flag)13184 bool omx_vdec::prefetch_buffers(unsigned long prefetch_count,
13185 unsigned long prefetch_size, unsigned ioctl_code, unsigned ion_flag)
13186 {
13187 struct ion_prefetch_data prefetch_data;
13188 struct ion_prefetch_regions regions;
13189 __u64 sizes[prefetch_count];
13190 int rc, ion_fd = ion_open();
13191 if (ion_fd < 0) {
13192 DEBUG_PRINT_ERROR("%s: Ion fd open failed : %d", __func__, ion_fd);
13193 return false;
13194 }
13195
13196 DEBUG_PRINT_HIGH("%s: prefetch_count : %lu, prefetch_size : %lu, ioctl : %u",
13197 __func__, prefetch_count, prefetch_size, ioctl_code);
13198 for (uint32_t i = 0; i < prefetch_count; i++) {
13199 sizes[i] = prefetch_size;
13200 }
13201
13202 regions.nr_sizes = prefetch_count;
13203 #if TARGET_ION_ABI_VERSION >= 2
13204 regions.sizes = (__u64)sizes;
13205 #else
13206 regions.sizes = sizes;
13207 #endif
13208 regions.vmid = ion_flag;
13209
13210 prefetch_data.nr_regions = 1;
13211 #if TARGET_ION_ABI_VERSION >= 2
13212 prefetch_data.regions = (__u64)®ions;
13213 #else
13214 prefetch_data.regions = ®ions;
13215 #endif
13216 prefetch_data.heap_id = ION_HEAP(ION_SECURE_HEAP_ID);
13217
13218 rc = ioctl(ion_fd, ioctl_code, &prefetch_data);
13219 if (rc) {
13220 DEBUG_PRINT_ERROR("%s: Prefetch ioctl failed ioctl : %u, rc : %d, errno : %d",
13221 __func__, ioctl_code, rc, errno);
13222 rc = false;
13223 } else {
13224 rc = true;
13225 }
13226
13227 close(ion_fd);
13228 return rc;
13229 }
13230
store_vp9_hdr10plusinfo(DescribeHDR10PlusInfoParams * hdr10plusdata)13231 bool omx_vdec::store_vp9_hdr10plusinfo(DescribeHDR10PlusInfoParams *hdr10plusdata)
13232 {
13233 struct hdr10plusInfo metadata;
13234
13235 if (!hdr10plusdata) {
13236 DEBUG_PRINT_ERROR("hdr10plus info not present");
13237 return false;
13238 }
13239
13240 if (hdr10plusdata->nParamSize > MAX_HDR10PLUSINFO_SIZE ||
13241 hdr10plusdata->nParamSize < 1) {
13242 DEBUG_PRINT_ERROR("Invalid hdr10plus metadata size %u", hdr10plusdata->nParamSize);
13243 return false;
13244 }
13245
13246 if (output_capability != V4L2_PIX_FMT_VP9) {
13247 DEBUG_PRINT_ERROR("DescribeHDR10PlusInfoParams is not supported for %d codec",
13248 output_capability);
13249 return false;
13250 }
13251
13252 memset(&metadata, 0, sizeof(struct hdr10plusInfo));
13253 metadata.nSize = hdr10plusdata->nSize;
13254 metadata.nVersion = hdr10plusdata->nVersion;
13255 metadata.nPortIndex = hdr10plusdata->nPortIndex;
13256 metadata.nParamSize = hdr10plusdata->nParamSize;
13257 metadata.nParamSizeUsed = hdr10plusdata->nParamSizeUsed;
13258 memcpy(metadata.payload, hdr10plusdata->nValue , hdr10plusdata->nParamSizeUsed);
13259 metadata.is_new = true;
13260
13261 /*
13262 * For the first setconfig, set the timestamp as zero. For
13263 * the remaining, set the timestamp equal to previous
13264 * etb timestamp + 1 to know this hdr10plus data arrived
13265 * after previous etb.
13266 */
13267 if (m_etb_count) {
13268 metadata.timestamp = m_etb_timestamp + 1;
13269 }
13270
13271 pthread_mutex_lock(&m_hdr10pluslock);
13272 DEBUG_PRINT_LOW("add hdr10plus info to the list with timestamp %lld and size %u",
13273 metadata.timestamp, metadata.nParamSizeUsed);
13274 m_hdr10pluslist.push_back(metadata);
13275 pthread_mutex_unlock(&m_hdr10pluslock);
13276
13277 return true;
13278 }
13279
store_hevc_hdr10plusinfo(uint32_t payload_size,msm_vidc_stream_userdata_payload * hdr10plusdata)13280 bool omx_vdec::store_hevc_hdr10plusinfo(uint32_t payload_size,
13281 msm_vidc_stream_userdata_payload *hdr10plusdata)
13282 {
13283 struct hdr10plusInfo metadata;
13284
13285 if (!hdr10plusdata) {
13286 DEBUG_PRINT_ERROR("hdr10plus info not present");
13287 return false;
13288 }
13289
13290 if (payload_size > MAX_HDR10PLUSINFO_SIZE ||
13291 payload_size < 1) {
13292 DEBUG_PRINT_ERROR("Invalid hdr10plus metadata size %u", payload_size);
13293 return false;
13294 }
13295
13296 if (output_capability != V4L2_PIX_FMT_HEVC) {
13297 DEBUG_PRINT_ERROR("msm_vidc_stream_userdata_payload is not supported for %d codec",
13298 output_capability);
13299 return false;
13300 }
13301
13302 memset(&metadata, 0, sizeof(struct hdr10plusInfo));
13303 metadata.nParamSizeUsed = payload_size;
13304 memcpy(metadata.payload, hdr10plusdata->data , payload_size);
13305 metadata.is_new = true;
13306 if (m_etb_count) {
13307 metadata.timestamp = m_etb_timestamp + 1;
13308 }
13309
13310 pthread_mutex_lock(&m_hdr10pluslock);
13311 DEBUG_PRINT_LOW("add hevc hdr10plus info to the list with size %u", payload_size);
13312 m_hdr10pluslist.push_back(metadata);
13313 pthread_mutex_unlock(&m_hdr10pluslock);
13314
13315 return true;
13316 }
13317
update_hdr10plusinfo_cookie_using_timestamp(OMX_PTR markdata,OMX_TICKS timestamp)13318 void omx_vdec::update_hdr10plusinfo_cookie_using_timestamp(OMX_PTR markdata, OMX_TICKS timestamp)
13319 {
13320 std::list<hdr10plusInfo>::reverse_iterator iter;
13321 unsigned int found = 0;
13322 unsigned int cookie = (unsigned int)(unsigned long)markdata;
13323 bool is_list_empty = false;
13324
13325 if (output_capability != V4L2_PIX_FMT_VP9 &&
13326 output_capability != V4L2_PIX_FMT_HEVC)
13327 return;
13328
13329 pthread_mutex_lock(&m_hdr10pluslock);
13330 is_list_empty = m_hdr10pluslist.empty();
13331 pthread_mutex_unlock(&m_hdr10pluslock);
13332
13333 if (is_list_empty) {
13334 DEBUG_PRINT_HIGH("update_hdr10plusinfo_cookie_using_timestamp: hdr10plusinfo list is empty!");
13335 return;
13336 }
13337 /*
13338 * look for the hdr10plus data which has timestamp nearest and
13339 * lower than the etb timestamp, we should not take the
13340 * hdr10plus data which has the timestamp greater than etb timestamp.
13341 */
13342 pthread_mutex_lock(&m_hdr10pluslock);
13343 iter = m_hdr10pluslist.rbegin();
13344 while (iter != m_hdr10pluslist.rend()) {
13345 if (iter->timestamp <= timestamp && iter->is_new) {
13346 found++;
13347 if (found == 1) {
13348 iter->cookie = cookie;
13349 iter->is_new = false;
13350 DEBUG_PRINT_LOW("Cookie value %u stored in hdr10plus list with timestamp %lld, size %u",
13351 iter->cookie, iter->timestamp, iter->nParamSizeUsed);
13352 }
13353 }
13354 iter++;
13355 }
13356 pthread_mutex_unlock(&m_hdr10pluslock);
13357
13358 if(found > 1)
13359 DEBUG_PRINT_HIGH("Multiple hdr10plus data not expected. Continue with the latest");
13360 }
13361
convert_hdr10plusinfo_to_metadata(OMX_PTR markdata,ColorMetaData & colorData)13362 void omx_vdec::convert_hdr10plusinfo_to_metadata(OMX_PTR markdata, ColorMetaData &colorData)
13363 {
13364 std::list<hdr10plusInfo>::iterator iter;
13365 unsigned int cookie = (unsigned int)(unsigned long)markdata;
13366 bool is_list_empty = false;
13367
13368 if (output_capability != V4L2_PIX_FMT_VP9 &&
13369 output_capability != V4L2_PIX_FMT_HEVC)
13370 return;
13371
13372 pthread_mutex_lock(&m_hdr10pluslock);
13373 is_list_empty = m_hdr10pluslist.empty();
13374 pthread_mutex_unlock(&m_hdr10pluslock);
13375
13376 if (is_list_empty) {
13377 DEBUG_PRINT_HIGH("convert_hdr10plusinfo_to_metadata: hdr10plusinfo list is empty!");
13378 return;
13379 }
13380
13381 pthread_mutex_lock(&m_hdr10pluslock);
13382 iter = m_hdr10pluslist.begin();
13383 while (iter != m_hdr10pluslist.end()) {
13384 if (iter->cookie == cookie && !iter->is_new) {
13385 colorData.dynamicMetaDataValid = true;
13386 colorData.dynamicMetaDataLen = iter->nParamSizeUsed;
13387 memcpy(colorData.dynamicMetaDataPayload, iter->payload,
13388 iter->nParamSizeUsed);
13389 DEBUG_PRINT_LOW("found hdr10plus metadata for cookie %u with timestamp %lld, size %u",
13390 cookie, iter->timestamp, colorData.dynamicMetaDataLen);
13391 break;
13392 }
13393 iter++;
13394 }
13395 pthread_mutex_unlock(&m_hdr10pluslock);
13396 }
13397
remove_hdr10plusinfo_using_cookie(OMX_PTR markdata)13398 void omx_vdec::remove_hdr10plusinfo_using_cookie(OMX_PTR markdata)
13399 {
13400 std::list<hdr10plusInfo>::iterator iter;
13401 unsigned int cookie = (unsigned int)(unsigned long)markdata;
13402 bool is_list_empty = false;
13403
13404 if (output_capability != V4L2_PIX_FMT_VP9 &&
13405 output_capability != V4L2_PIX_FMT_HEVC)
13406 return;
13407
13408 pthread_mutex_lock(&m_hdr10pluslock);
13409 is_list_empty = m_hdr10pluslist.empty();
13410 pthread_mutex_unlock(&m_hdr10pluslock);
13411
13412 if (is_list_empty) {
13413 DEBUG_PRINT_HIGH("remove_hdr10plusinfo_using_cookie: hdr10plusinfo list is empty!");
13414 return;
13415 }
13416
13417 pthread_mutex_lock(&m_hdr10pluslock);
13418 iter = m_hdr10pluslist.begin();
13419 while (iter != m_hdr10pluslist.end()) {
13420 if (iter->cookie == cookie && !iter->is_new) {
13421 iter = m_hdr10pluslist.erase(iter);
13422 DEBUG_PRINT_LOW("removed hdr10plusinfo from the list for the cookie %u", cookie);
13423 break;
13424 }
13425 iter++;
13426 }
13427 pthread_mutex_unlock(&m_hdr10pluslock);
13428 }
13429
clear_hdr10plusinfo()13430 void omx_vdec::clear_hdr10plusinfo()
13431 {
13432 bool is_list_empty = false;
13433
13434 if (output_capability != V4L2_PIX_FMT_VP9 &&
13435 output_capability != V4L2_PIX_FMT_HEVC)
13436 return;
13437
13438 pthread_mutex_lock(&m_hdr10pluslock);
13439 is_list_empty = m_hdr10pluslist.empty();
13440 pthread_mutex_unlock(&m_hdr10pluslock);
13441
13442 if (is_list_empty) {
13443 DEBUG_PRINT_HIGH("clear_hdr10plusinfo: hdr10plusinfo list is empty!");
13444 return;
13445 }
13446
13447 pthread_mutex_lock(&m_hdr10pluslock);
13448 m_hdr10pluslist.clear();
13449 pthread_mutex_unlock(&m_hdr10pluslock);
13450 }
13451
get_hdr10plusinfo(DescribeHDR10PlusInfoParams * hdr10plusdata)13452 void omx_vdec::get_hdr10plusinfo(DescribeHDR10PlusInfoParams *hdr10plusdata)
13453 {
13454 std::list<hdr10plusInfo>::iterator iter;
13455 bool is_list_empty = false;
13456
13457 if (output_capability != V4L2_PIX_FMT_VP9 &&
13458 output_capability != V4L2_PIX_FMT_HEVC)
13459 return;
13460
13461 pthread_mutex_lock(&m_hdr10pluslock);
13462 is_list_empty = m_hdr10pluslist.empty();
13463 pthread_mutex_unlock(&m_hdr10pluslock);
13464
13465 if (is_list_empty) {
13466 DEBUG_PRINT_HIGH("get_hdr10plusinfo: hdr10plusinfo list is empty!");
13467 return;
13468 }
13469
13470 pthread_mutex_lock(&m_hdr10pluslock);
13471 iter = m_hdr10pluslist.begin();
13472 while (iter != m_hdr10pluslist.end()) {
13473 if (!iter->is_new) {
13474 hdr10plusdata->nParamSizeUsed = iter->nParamSizeUsed;
13475 memcpy(hdr10plusdata->nValue, iter->payload,
13476 iter->nParamSizeUsed);
13477 DEBUG_PRINT_LOW("found hdr10plus metadata with timestamp %lld, size %u",
13478 iter->timestamp, iter->nParamSizeUsed);
13479 iter = m_hdr10pluslist.erase(iter);
13480 break;
13481 }
13482 iter++;
13483 }
13484 pthread_mutex_unlock(&m_hdr10pluslock);
13485 }
13486
print_hdr10plusinfo(DescribeHDR10PlusInfoParams * hdr10plusdata)13487 void omx_vdec::print_hdr10plusinfo(DescribeHDR10PlusInfoParams *hdr10plusdata)
13488 {
13489 DEBUG_PRINT_LOW("HDR10+ frameworks path valid data length: %d", hdr10plusdata->nParamSizeUsed);
13490 for (uint32_t i = 0 ; i < hdr10plusdata->nParamSizeUsed && i+3 < 1024; i=i+4) {
13491 DEBUG_PRINT_LOW("HDR10+ mdata: %02X %02X %02X %02X", hdr10plusdata->nValue[i],
13492 hdr10plusdata->nValue[i+1],
13493 hdr10plusdata->nValue[i+2],
13494 hdr10plusdata->nValue[i+3]);
13495 }
13496 }
13497
13498 // No code beyond this !
13499
13500 // inline import of vendor-extensions implementation
13501 #include "omx_vdec_extensions.hpp"
13502