1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010 - 2018, 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 #include <media/hardware/HardwareAPI.h>
56 #include <sys/eventfd.h>
57 #include "PlatformConfig.h"
58 #include <linux/dma-buf.h>
59 #include <linux/videodev2.h>
60 
61 #if !defined(_ANDROID_) || defined(SYS_IOCTL)
62 #include <sys/ioctl.h>
63 #include <sys/mman.h>
64 #endif
65 
66 #ifdef _ANDROID_
67 #include <cutils/properties.h>
68 
69 #ifdef _QUERY_DISP_RES_
70 #include "display_config.h"
71 #endif
72 #endif
73 
74 #ifdef _USE_GLIB_
75 #include <glib.h>
76 #define strlcpy g_strlcpy
77 #endif
78 
79 #include <qdMetaData.h>
80 #include <gralloc_priv.h>
81 
82 #ifdef ANDROID_JELLYBEAN_MR2
83 #include "QComOMXMetadata.h"
84 #endif
85 
86 #define BUFFER_LOG_LOC "/data/vendor/media"
87 
88 #ifdef OUTPUT_EXTRADATA_LOG
89 FILE *outputExtradataFile;
90 char output_extradata_filename [] = "/data/vendor/media/extradata";
91 #endif
92 
93 #define DEFAULT_FPS 30
94 #define MAX_SUPPORTED_FPS 240
95 #define DEFAULT_WIDTH_ALIGNMENT 128
96 #define DEFAULT_HEIGHT_ALIGNMENT 32
97 
98 #define POLL_TIMEOUT 0x7fffffff
99 
100 #ifdef _ANDROID_
101 extern "C" {
102 #include<utils/Log.h>
103 }
104 #endif//_ANDROID_
105 
106 #define SZ_4K 0x1000
107 #define SZ_1M 0x100000
108 
109 #define PREFETCH_PIXEL_BUFFER_COUNT 16
110 #define PREFETCH_NON_PIXEL_BUFFER_COUNT 1
111 
112 #define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
113 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }
114 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
115 #undef ALIGN
116 #define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1))
117 
118 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_OUTPUTCROP_EXTRADATA \
119                            | OMX_DISPLAY_INFO_EXTRADATA | OMX_UBWC_CR_STATS_INFO_EXTRADATA)
120 
121 // Y=16(0-9bits), Cb(10-19bits)=Cr(20-29bits)=128, black by default
122 #define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8020010
123 
124 #ifndef ION_FLAG_CP_BITSTREAM
125 #define ION_FLAG_CP_BITSTREAM 0
126 #endif
127 
128 #ifndef ION_FLAG_CP_PIXEL
129 #define ION_FLAG_CP_PIXEL 0
130 #endif
131 
132 #ifdef SLAVE_SIDE_CP
133 #define MEM_HEAP_ID ION_CP_MM_HEAP_ID
134 #define SECURE_ALIGN SZ_1M
135 #define SECURE_FLAGS_INPUT_BUFFER ION_FLAG_SECURE
136 #define SECURE_FLAGS_OUTPUT_BUFFER ION_FLAG_SECURE
137 #else //MASTER_SIDE_CP
138 #define MEM_HEAP_ID ION_SECURE_HEAP_ID
139 #define SECURE_ALIGN SZ_4K
140 #define SECURE_FLAGS_INPUT_BUFFER (ION_FLAG_SECURE | ION_FLAG_CP_BITSTREAM)
141 #define SECURE_FLAGS_OUTPUT_BUFFER (ION_FLAG_SECURE | ION_FLAG_CP_PIXEL)
142 #endif
143 
144 #define LUMINANCE_DIV_FACTOR 10000.0
145 
146 /* defined in mp-ctl.h */
147 #define MPCTLV3_VIDEO_DECODE_PB_HINT 0x41C04000
148 
149 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
150 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
151 
152 using namespace android;
153 
154 static OMX_U32 maxSmoothStreamingWidth = 1920;
155 static OMX_U32 maxSmoothStreamingHeight = 1088;
156 
print_omx_buffer(const char * str,OMX_BUFFERHEADERTYPE * pHeader)157 void print_omx_buffer(const char *str, OMX_BUFFERHEADERTYPE *pHeader)
158 {
159     if (!pHeader)
160         return;
161 
162     DEBUG_PRINT_HIGH("%s: Header %p buffer %p alloclen %d offset %d filledlen %d timestamp %lld flags %#x",
163         str, pHeader, pHeader->pBuffer, pHeader->nAllocLen,
164         pHeader->nOffset, pHeader->nFilledLen,
165         pHeader->nTimeStamp, pHeader->nFlags);
166 }
167 
print_v4l2_buffer(const char * str,struct v4l2_buffer * v4l2)168 void print_v4l2_buffer(const char *str, struct v4l2_buffer *v4l2)
169 {
170     if (!v4l2)
171         return;
172 
173     if (v4l2->length == 1)
174         DEBUG_PRINT_HIGH(
175             "%s: %s: idx %2d userptr %#lx fd %d off %d size %d filled %d flags %#x\n",
176             str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
177             "OUTPUT" : "CAPTURE", v4l2->index,
178             v4l2->m.planes[0].m.userptr, v4l2->m.planes[0].reserved[0],
179             v4l2->m.planes[0].reserved[1], v4l2->m.planes[0].length,
180             v4l2->m.planes[0].bytesused, v4l2->flags);
181     else
182         DEBUG_PRINT_HIGH(
183             "%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",
184             str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
185             "OUTPUT" : "CAPTURE", v4l2->index,
186             v4l2->m.planes[0].m.userptr, v4l2->m.planes[0].reserved[0],
187             v4l2->m.planes[0].reserved[1], v4l2->m.planes[0].length,
188             v4l2->m.planes[0].bytesused, v4l2->m.planes[1].reserved[0],
189             v4l2->flags, v4l2->m.planes[1].reserved[1],
190             v4l2->m.planes[1].length, v4l2->m.planes[1].bytesused);
191 }
192 
async_message_thread(void * input)193 void* async_message_thread (void *input)
194 {
195     OMX_BUFFERHEADERTYPE *buffer;
196     struct v4l2_plane plane[VIDEO_MAX_PLANES];
197     struct pollfd pfds[2];
198     struct v4l2_buffer v4l2_buf;
199     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
200     struct v4l2_event dqevent;
201     omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
202     pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
203     pfds[1].events = POLLIN | POLLERR;
204     pfds[0].fd = omx->drv_ctx.video_driver_fd;
205     pfds[1].fd = omx->m_poll_efd;
206     int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
207     DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
208     prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
209     while (!omx->async_thread_force_stop) {
210         rc = poll(pfds, 2, POLL_TIMEOUT);
211         if (!rc) {
212             DEBUG_PRINT_ERROR("Poll timedout");
213             break;
214         } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
215             DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
216             break;
217         }
218         if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
219             DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited");
220             break;
221         }
222         if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
223             struct vdec_msginfo vdec_msg;
224             memset(&vdec_msg, 0, sizeof(vdec_msg));
225             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
226             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
227             v4l2_buf.length = omx->drv_ctx.num_planes;
228             v4l2_buf.m.planes = plane;
229             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
230                 vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
231                 vdec_msg.status_code=VDEC_S_SUCCESS;
232                 vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
233                 vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
234                 vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
235                 vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
236                     (uint64_t)v4l2_buf.timestamp.tv_usec;
237 
238                 if (omx->async_message_process(input,&vdec_msg) < 0) {
239                     DEBUG_PRINT_HIGH("async_message_thread Exited");
240                     break;
241                 }
242             }
243         }
244         if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
245             struct vdec_msginfo vdec_msg;
246             v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
247             v4l2_buf.memory = V4L2_MEMORY_USERPTR;
248             v4l2_buf.length = 1;
249             v4l2_buf.m.planes = plane;
250             while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
251                 vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
252                 vdec_msg.status_code=VDEC_S_SUCCESS;
253                 vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
254                 if (omx->async_message_process(input,&vdec_msg) < 0) {
255                     DEBUG_PRINT_HIGH("async_message_thread Exited");
256                     break;
257                 }
258             }
259         }
260         if (pfds[0].revents & POLLPRI) {
261             rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
262             if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
263                 struct vdec_msginfo vdec_msg;
264                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
265 
266                 vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
267                 vdec_msg.status_code=VDEC_S_SUCCESS;
268                 vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
269                 vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
270                 vdec_msg.msgdata.output_frame.flags = true; // INSUFFICIENT event
271                 DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient");
272                 omx->dpb_bit_depth = ptr[2];
273                 DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth - %d", ptr[3]);
274                 omx->m_progressive = ptr[3];
275                 DEBUG_PRINT_HIGH("VIDC Port Reconfig PicStruct - %d", ptr[4]);
276                 omx->m_color_space = (ptr[4] == MSM_VIDC_BT2020 ? (omx_vdec::BT2020):
277                                       (omx_vdec:: EXCEPT_BT2020));
278                 DEBUG_PRINT_HIGH("VIDC Port Reconfig ColorSpace - %d", omx->m_color_space);
279                 if (omx->async_message_process(input,&vdec_msg) < 0) {
280                     DEBUG_PRINT_HIGH("async_message_thread Exited");
281                     break;
282                 }
283             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT) {
284 
285                 bool event_fields_changed = false;
286                 bool send_msg = false;
287                 omx_vdec::color_space_type tmp_color_space;
288                 struct vdec_msginfo vdec_msg;
289                 DEBUG_PRINT_HIGH("VIDC Port Reconfig received sufficient");
290                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
291                 int tmp_profile = 0;
292                 int tmp_level = 0;
293                 int codec = omx->get_session_codec_type();
294                 event_fields_changed |= (omx->dpb_bit_depth != (int)ptr[2]);
295                 event_fields_changed |= (omx->m_progressive != (int)ptr[3]);
296                 tmp_color_space = (ptr[4] == MSM_VIDC_BT2020 ? (omx_vdec::BT2020):
297                                    (omx_vdec:: EXCEPT_BT2020));
298                 event_fields_changed |= (omx->m_color_space != tmp_color_space);
299 
300                 /*
301                  * If the resolution is different due to 16\32 pixel alignment,
302                  * let's handle as Sufficient. Ex : 1080 & 1088 or 2160 & 2176.
303                  * When FBD comes, component updates the clients with actual
304                  * resolution through set_buffer_geometry.
305                  */
306 
307                  event_fields_changed |= (omx->drv_ctx.video_resolution.frame_height != ptr[0]);
308                  event_fields_changed |= (omx->drv_ctx.video_resolution.frame_width != ptr[1]);
309 
310                  if ((codec == V4L2_PIX_FMT_H264) ||
311                      (codec  == V4L2_PIX_FMT_HEVC)) {
312                      if (profile_level_converter::convert_v4l2_profile_to_omx(
313                                                          codec, ptr[9], &tmp_profile) &&
314                          profile_level_converter::convert_v4l2_level_to_omx(
315                                                          codec, ptr[10], &tmp_level)) {
316                          event_fields_changed |= (omx->mClientSessionForSufficiency &&
317                                                   ((tmp_profile != (int)omx->mClientSetProfile) ||
318                                                    (tmp_level > (int)omx->mClientSetLevel)));
319                      }
320                  }
321 
322                  if (!omx->is_down_scalar_enabled && omx->m_is_split_mode &&
323                         (omx->drv_ctx.video_resolution.frame_height != ptr[0] ||
324                         omx->drv_ctx.video_resolution.frame_width != ptr[1])) {
325                      event_fields_changed = true;
326                  }
327 
328                  if (event_fields_changed) {
329                     DEBUG_PRINT_HIGH("VIDC Port Reconfig Old Resolution(H,W) = (%d,%d) New Resolution(H,W) = (%d,%d))",
330                                      omx->drv_ctx.video_resolution.frame_height,
331                                      omx->drv_ctx.video_resolution.frame_width,
332                                      ptr[0], ptr[1]);
333                     DEBUG_PRINT_HIGH("VIDC Port Reconfig Old bitdepth = %d New bitdepth = %d",
334                                      omx->dpb_bit_depth, ptr[2]);
335                     DEBUG_PRINT_HIGH("VIDC Port Reconfig Old picstruct = %d New picstruct = %d",
336                                      omx->m_progressive, ptr[3]);
337                     DEBUG_PRINT_HIGH("VIDC Port Reconfig Old colorSpace = %s New colorspace = %s",
338                                      (omx->m_color_space == omx_vdec::BT2020 ? "BT2020": "EXCEPT_BT2020"),
339                                      (tmp_color_space == omx_vdec::BT2020 ? "BT2020": "EXCEPT_BT2020"));
340                     DEBUG_PRINT_HIGH("Client Session for sufficiency feature is %s", omx->mClientSessionForSufficiency ? "enabled": "disabled");
341                     DEBUG_PRINT_HIGH("VIDC Port Reconfig Client (Profile,Level) = (%d,%d) bitstream(Profile,Level) = (%d,%d))",
342                                      omx->mClientSetProfile,
343                                      omx->mClientSetLevel,
344                                      tmp_profile, tmp_level);
345                     omx->dpb_bit_depth = ptr[2];
346                     omx->m_progressive = ptr[3];
347                     omx->m_color_space = (ptr[4] == MSM_VIDC_BT2020 ? (omx_vdec::BT2020):
348                                        (omx_vdec:: EXCEPT_BT2020));
349                     send_msg = true;
350                     vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
351                     vdec_msg.status_code=VDEC_S_SUCCESS;
352                     vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
353                     vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
354                     vdec_msg.msgdata.output_frame.flags = false; // SUFFICIENT event
355                 } else {
356                     struct v4l2_decoder_cmd dec;
357                     memset(&dec, 0, sizeof(dec));
358                     dec.cmd = V4L2_QCOM_CMD_SESSION_CONTINUE;
359                     rc = ioctl(pfds[0].fd, VIDIOC_DECODER_CMD, &dec);
360                     if (rc < 0) {
361                         DEBUG_PRINT_ERROR("Session continue failed");
362                         send_msg = true;
363                         vdec_msg.msgcode=VDEC_MSG_EVT_HW_ERROR;
364                         vdec_msg.status_code=VDEC_S_SUCCESS;
365                     } else {
366                         DEBUG_PRINT_HIGH("Sent Session continue");
367                     }
368                 }
369 
370                 if (send_msg) {
371                     if (omx->async_message_process(input,&vdec_msg) < 0) {
372                         DEBUG_PRINT_HIGH("async_message_thread Exited");
373                         break;
374                     }
375                 }
376 
377             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
378                 struct vdec_msginfo vdec_msg;
379                 uint32_t flush_type = *(uint32_t *)dqevent.u.data;
380                 // Old driver doesn't send flushType information.
381                 // To make this backward compatible fallback to old approach
382                 // if the flush_type is not present.
383                 vdec_msg.status_code=VDEC_S_SUCCESS;
384                 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_OUTPUT)) {
385                     vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
386                     DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
387                     if (omx->async_message_process(input,&vdec_msg) < 0) {
388                         DEBUG_PRINT_HIGH("async_message_thread Exited");
389                         break;
390                     }
391                 }
392 
393                 if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_CAPTURE)) {
394                     vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
395                     DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
396                     if (omx->async_message_process(input,&vdec_msg) < 0) {
397                         DEBUG_PRINT_HIGH("async_message_thread Exited");
398                         break;
399                     }
400                 }
401             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
402                 struct vdec_msginfo vdec_msg;
403                 vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
404                 vdec_msg.status_code=VDEC_S_SUCCESS;
405                 DEBUG_PRINT_ERROR("HW Overload received");
406                 if (omx->async_message_process(input,&vdec_msg) < 0) {
407                     DEBUG_PRINT_HIGH("async_message_thread Exited");
408                     break;
409                 }
410             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
411                 struct vdec_msginfo vdec_msg;
412                 vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
413                 vdec_msg.status_code=VDEC_S_SUCCESS;
414                 DEBUG_PRINT_ERROR("HW Unsupported received");
415                 if (omx->async_message_process(input,&vdec_msg) < 0) {
416                     DEBUG_PRINT_HIGH("async_message_thread Exited");
417                     break;
418                 }
419             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
420                 struct vdec_msginfo vdec_msg;
421                 vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR;
422                 vdec_msg.status_code = VDEC_S_SUCCESS;
423                 DEBUG_PRINT_HIGH("SYS Error Recieved");
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_RELEASE_BUFFER_REFERENCE) {
429                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
430 
431                 DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
432             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
433                 unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
434                 struct vdec_msginfo vdec_msg;
435 
436                 DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
437 
438                 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
439                 v4l2_buf.memory = V4L2_MEMORY_USERPTR;
440                 v4l2_buf.length = omx->drv_ctx.num_planes;
441                 v4l2_buf.m.planes = plane;
442                 v4l2_buf.index = ptr[5];
443                 v4l2_buf.flags = 0;
444 
445                 vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
446                 vdec_msg.status_code = VDEC_S_SUCCESS;
447                 vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
448                 vdec_msg.msgdata.output_frame.len = 0;
449                 vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
450                 vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
451                     (uint64_t)ptr[4];
452                 if (omx->async_message_process(input,&vdec_msg) < 0) {
453                     DEBUG_PRINT_HIGH("async_message_thread Exitedn");
454                     break;
455                 }
456             } else {
457                 DEBUG_PRINT_HIGH("VIDC Some Event recieved");
458                 continue;
459             }
460         }
461     }
462     DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
463     return NULL;
464 }
465 
message_thread_dec(void * input)466 void* message_thread_dec(void *input)
467 {
468     omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
469     int res = 0;
470 
471     DEBUG_PRINT_HIGH("omx_vdec: message thread start");
472     prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
473     while (!omx->message_thread_stop) {
474         res = omx->signal.wait(2 * 1000000000);
475         if (res == ETIMEDOUT || omx->message_thread_stop) {
476             continue;
477         } else if (res) {
478             DEBUG_PRINT_ERROR("omx_vdec: message_thread_dec wait on condition failed, exiting");
479             break;
480         }
481         omx->process_event_cb(omx);
482     }
483     DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
484     return 0;
485 }
486 
post_message(omx_vdec * omx,unsigned char id)487 void post_message(omx_vdec *omx, unsigned char id)
488 {
489     (void)id;
490     omx->signal.signal();
491 }
492 
493 // omx_cmd_queue destructor
~omx_cmd_queue()494 omx_vdec::omx_cmd_queue::~omx_cmd_queue()
495 {
496     // Nothing to do
497 }
498 
499 // omx cmd queue constructor
omx_cmd_queue()500 omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0)
501 {
502     memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE);
503 }
504 
505 // omx cmd queue insert
insert_entry(unsigned long p1,unsigned long p2,unsigned long id)506 bool omx_vdec::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
507 {
508     bool ret = true;
509     if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
510         m_q[m_write].id       = id;
511         m_q[m_write].param1   = p1;
512         m_q[m_write].param2   = p2;
513         m_write++;
514         m_size ++;
515         if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
516             m_write = 0;
517         }
518     } else {
519         ret = false;
520         DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full", __func__);
521     }
522     return ret;
523 }
524 
525 // omx cmd queue pop
pop_entry(unsigned long * p1,unsigned long * p2,unsigned long * id)526 bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
527 {
528     bool ret = true;
529     if (m_size > 0) {
530         *id = m_q[m_read].id;
531         *p1 = m_q[m_read].param1;
532         *p2 = m_q[m_read].param2;
533         // Move the read pointer ahead
534         ++m_read;
535         --m_size;
536         if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
537             m_read = 0;
538         }
539     } else {
540         ret = false;
541     }
542     return ret;
543 }
544 
545 // Retrieve the first mesg type in the queue
get_q_msg_type()546 unsigned omx_vdec::omx_cmd_queue::get_q_msg_type()
547 {
548     return m_q[m_read].id;
549 }
550 
551 #ifdef _ANDROID_
ts_arr_list()552 omx_vdec::ts_arr_list::ts_arr_list()
553 {
554     //initialize timestamps array
555     memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) );
556 }
~ts_arr_list()557 omx_vdec::ts_arr_list::~ts_arr_list()
558 {
559     //free m_ts_arr_list?
560 }
561 
insert_ts(OMX_TICKS ts)562 bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts)
563 {
564     bool ret = true;
565     bool duplicate_ts = false;
566     int idx = 0;
567 
568     //insert at the first available empty location
569     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
570         if (!m_ts_arr_list[idx].valid) {
571             //found invalid or empty entry, save timestamp
572             m_ts_arr_list[idx].valid = true;
573             m_ts_arr_list[idx].timestamp = ts;
574             DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)",
575                     ts, idx);
576             break;
577         }
578     }
579 
580     if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) {
581         DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert");
582         ret = false;
583     }
584     return ret;
585 }
586 
pop_min_ts(OMX_TICKS & ts)587 bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts)
588 {
589     bool ret = true;
590     int min_idx = -1;
591     OMX_TICKS min_ts = 0;
592     int idx = 0;
593 
594     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
595 
596         if (m_ts_arr_list[idx].valid) {
597             //found valid entry, save index
598             if (min_idx < 0) {
599                 //first valid entry
600                 min_ts = m_ts_arr_list[idx].timestamp;
601                 min_idx = idx;
602             } else if (m_ts_arr_list[idx].timestamp < min_ts) {
603                 min_ts = m_ts_arr_list[idx].timestamp;
604                 min_idx = idx;
605             }
606         }
607 
608     }
609 
610     if (min_idx < 0) {
611         //no valid entries found
612         DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop");
613         ts = 0;
614         ret = false;
615     } else {
616         ts = m_ts_arr_list[min_idx].timestamp;
617         m_ts_arr_list[min_idx].valid = false;
618         DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)",
619                 ts, min_idx);
620     }
621 
622     return ret;
623 
624 }
625 
626 
reset_ts_list()627 bool omx_vdec::ts_arr_list::reset_ts_list()
628 {
629     bool ret = true;
630     int idx = 0;
631 
632     DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list");
633     for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) {
634         m_ts_arr_list[idx].valid = false;
635     }
636     return ret;
637 }
638 #endif
639 
640 // factory function executed by the core to create instances
get_omx_component_factory_fn(void)641 void *get_omx_component_factory_fn(void)
642 {
643     return (new omx_vdec);
644 }
645 
is_platform_tp10capture_supported()646 bool is_platform_tp10capture_supported()
647 {
648     DEBUG_PRINT_HIGH("TP10 on capture port is supported");
649     return true;
650 }
651 
get_session_codec_type()652 inline int omx_vdec::get_session_codec_type()
653 {
654     return output_capability;
655 }
656 /* ======================================================================
657    FUNCTION
658    omx_vdec::omx_vdec
659 
660    DESCRIPTION
661    Constructor
662 
663    PARAMETERS
664    None
665 
666    RETURN VALUE
667    None.
668    ========================================================================== */
omx_vdec()669 omx_vdec::omx_vdec(): m_error_propogated(false),
670     m_state(OMX_StateInvalid),
671     m_app_data(NULL),
672     m_inp_mem_ptr(NULL),
673     m_out_mem_ptr(NULL),
674     m_intermediate_out_mem_ptr(NULL),
675     m_client_output_extradata_mem_ptr(NULL),
676     input_flush_progress (false),
677     output_flush_progress (false),
678     input_use_buffer (false),
679     output_use_buffer (false),
680     ouput_egl_buffers(false),
681     m_use_output_pmem(OMX_FALSE),
682     pending_input_buffers(0),
683     pending_output_buffers(0),
684     m_out_bm_count(0),
685     m_inp_bm_count(0),
686     m_out_extradata_bm_count(0),
687     m_inp_bPopulated(OMX_FALSE),
688     m_out_bPopulated(OMX_FALSE),
689     m_flags(0),
690     m_inp_bEnabled(OMX_TRUE),
691     m_out_bEnabled(OMX_TRUE),
692     m_in_alloc_cnt(0),
693     m_platform_list(NULL),
694     m_platform_entry(NULL),
695     m_pmem_info(NULL),
696     h264_parser(NULL),
697     arbitrary_bytes (false),
698     psource_frame (NULL),
699     pdest_frame (NULL),
700     m_inp_heap_ptr (NULL),
701     m_phdr_pmem_ptr(NULL),
702     m_heap_inp_bm_count (0),
703     codec_type_parse ((codec_type)0),
704     first_frame_meta (true),
705     frame_count (0),
706     nal_count (0),
707     nal_length(0),
708     look_ahead_nal (false),
709     first_frame(0),
710     first_buffer(NULL),
711     first_frame_size (0),
712     m_device_file_ptr(NULL),
713     h264_last_au_ts(LLONG_MAX),
714     h264_last_au_flags(0),
715     m_disp_hor_size(0),
716     m_disp_vert_size(0),
717     prev_ts(LLONG_MAX),
718     prev_ts_actual(LLONG_MAX),
719     rst_prev_ts(true),
720     frm_int(0),
721     m_fps_received(0),
722     m_fps_prev(0),
723     m_drc_enable(0),
724     in_reconfig(false),
725     c2d_enable_pending(false),
726     m_display_id(NULL),
727     client_extradata(0),
728 #ifdef _ANDROID_
729     m_enable_android_native_buffers(OMX_FALSE),
730     m_use_android_native_buffers(OMX_FALSE),
731 #endif
732     m_disable_dynamic_buf_mode(0),
733     m_desc_buffer_ptr(NULL),
734     secure_mode(false),
735     allocate_native_handle(false),
736     client_set_fps(false),
737     stereo_output_mode(HAL_NO_3D),
738     m_last_rendered_TS(-1),
739     m_dec_hfr_fps(0),
740     m_dec_secure_prefetch_size_internal(0),
741     m_dec_secure_prefetch_size_output(0),
742     m_arb_mode_override(0),
743     m_queued_codec_config_count(0),
744     secure_scaling_to_non_secure_opb(false),
745     m_force_compressed_for_dpb(true),
746     m_is_display_session(false),
747     m_prefetch_done(0),
748     m_is_split_mode(false),
749     m_buffer_error(false)
750 {
751     m_poll_efd = -1;
752     memset(&drv_ctx, 0, sizeof(drv_ctx));
753     drv_ctx.video_driver_fd = -1;
754     drv_ctx.extradata_info.ion.data_fd = -1;
755     drv_ctx.extradata_info.ion.dev_fd = -1;
756     /* Assumption is that , to begin with , we have all the frames with decoder */
757     DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
758     memset(&m_debug,0,sizeof(m_debug));
759 #ifdef _ANDROID_
760 
761     char property_value[PROPERTY_VALUE_MAX] = {0};
762     property_get("vendor.vidc.debug.level", property_value, "1");
763     debug_level = strtoul(property_value, NULL, 16);
764     property_value[0] = '\0';
765 
766     DEBUG_PRINT_HIGH("In OMX vdec Constructor");
767 
768     // TODO: Support in XML
769     perf_flag = 0;
770     if (perf_flag) {
771         DEBUG_PRINT_HIGH("perf flag is %d", perf_flag);
772         dec_time.start();
773     }
774     proc_frms = latency = 0;
775     prev_n_filled_len = 0;
776 
777     Platform::Config::getInt32(Platform::vidc_dec_log_in,
778             (int32_t *)&m_debug.in_buffer_log, 0);
779     Platform::Config::getInt32(Platform::vidc_dec_log_out,
780             (int32_t *)&m_debug.out_buffer_log, 0);
781 
782     Platform::Config::getInt32(Platform::vidc_dec_hfr_fps,
783             (int32_t *)&m_dec_hfr_fps, 0);
784 
785     DEBUG_PRINT_HIGH("HFR fps value = %d", m_dec_hfr_fps);
786 
787     if (m_dec_hfr_fps) {
788         m_last_rendered_TS = 0;
789     }
790 
791     Platform::Config::getInt32(Platform::vidc_dec_sec_prefetch_size_internal,
792             (int32_t *)&m_dec_secure_prefetch_size_internal, 0);
793     Platform::Config::getInt32(Platform::vidc_dec_sec_prefetch_size_output,
794             (int32_t *)&m_dec_secure_prefetch_size_output, 0);
795 
796     DEBUG_PRINT_HIGH("Prefetch size internal = %d, output = %d",
797             m_dec_secure_prefetch_size_internal, m_dec_secure_prefetch_size_output);
798 
799     Platform::Config::getInt32(Platform::vidc_dec_arb_mode_override,
800             (int32_t *)&m_arb_mode_override, 0);
801 
802     Platform::Config::getInt32(Platform::vidc_perf_control_enable,
803             (int32_t *)&m_perf_control.m_perf_control_enable, 0);
804     if (m_perf_control.m_perf_control_enable) {
805         DEBUG_PRINT_HIGH("perf cotrol enabled");
806         m_perf_control.load_perf_library();
807     }
808 
809     property_value[0] = '\0';
810     property_get("vendor.vidc.dec.log.in", property_value, "0");
811     m_debug.in_buffer_log |= atoi(property_value);
812 
813     DEBUG_PRINT_HIGH("vendor.vidc.dec.log.in value is %d", m_debug.in_buffer_log);
814 
815     property_value[0] = '\0';
816     property_get("vendor.vidc.dec.log.out", property_value, "0");
817     m_debug.out_buffer_log |= atoi(property_value);
818 
819     DEBUG_PRINT_HIGH("vendor.vidc.dec.log.out value is %d", m_debug.out_buffer_log);
820 
821     property_value[0] = '\0';
822     property_get("vendor.vidc.dec.log.cc.out", property_value, "0");
823     m_debug.out_cc_buffer_log |= atoi(property_value);
824 
825     DEBUG_PRINT_HIGH("vendor.vidc.dec.log.cc.out value is %d", m_debug.out_buffer_log);
826 
827     property_value[0] = '\0';
828     property_get("vendor.vidc.dec.meta.log.out", property_value, "0");
829     m_debug.out_meta_buffer_log = atoi(property_value);
830 
831     property_value[0] = '\0';
832     property_get("vendor.vidc.log.loc", property_value, BUFFER_LOG_LOC);
833     if (*property_value)
834         strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
835 
836     struct timeval te;
837     gettimeofday(&te, NULL);
838     m_debug.session_id = te.tv_sec*1000LL + te.tv_usec/1000;
839     m_debug.seq_count = 0;
840 
841 #ifdef _UBWC_
842     property_value[0] = '\0';
843     property_get("vendor.gralloc.disable_ubwc", property_value, "0");
844     m_disable_ubwc_mode = atoi(property_value);
845     DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
846 #else
847     m_disable_ubwc_mode = true;
848 #endif
849 #endif
850     memset(&m_cmp,0,sizeof(m_cmp));
851     memset(&m_cb,0,sizeof(m_cb));
852     memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE));
853     memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
854     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
855     memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
856     memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
857     memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
858     memset(&m_client_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
859     memset(&m_internal_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
860     m_demux_entries = 0;
861     msg_thread_id = 0;
862     async_thread_id = 0;
863     msg_thread_created = false;
864     async_thread_created = false;
865     async_thread_force_stop = false;
866     message_thread_stop = false;
867 #ifdef _ANDROID_ICS_
868     memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
869 #endif
870 
871     /* invalidate m_frame_pack_arrangement */
872     memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
873     m_frame_pack_arrangement.cancel_flag = 1;
874 
875     drv_ctx.timestamp_adjust = false;
876     m_vendor_config.pData = NULL;
877     pthread_mutex_init(&m_lock, NULL);
878     pthread_mutex_init(&c_lock, NULL);
879     pthread_mutex_init(&buf_lock, NULL);
880     sem_init(&m_cmd_lock,0,0);
881     sem_init(&m_safe_flush, 0, 0);
882     streaming[CAPTURE_PORT] =
883         streaming[OUTPUT_PORT] = false;
884 #ifdef _ANDROID_
885     // TODO: Support in XML
886     m_debug_extradata = 0;
887 #endif
888     m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB;
889     client_buffers.set_vdec_client(this);
890     dynamic_buf_mode = false;
891     is_down_scalar_enabled = false;
892     m_downscalar_width = 0;
893     m_downscalar_height = 0;
894     m_force_down_scalar = 0;
895     m_reconfig_height = 0;
896     m_reconfig_width = 0;
897     m_smoothstreaming_mode = false;
898     m_smoothstreaming_width = 0;
899     m_smoothstreaming_height = 0;
900     m_decode_order_mode = false;
901     m_perf_control.perf_lock_acquire();
902     m_client_req_turbo_mode = false;
903     is_q6_platform = false;
904     m_input_pass_buffer_fd = false;
905     memset(&m_extradata_info, 0, sizeof(m_extradata_info));
906     m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
907     m_client_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
908     m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
909     m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
910     m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
911 
912     m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
913     m_internal_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
914     m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
915     m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
916     m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
917     m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams);
918 
919     m_client_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
920     m_internal_hdr_info.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
921 
922     m_dither_config = DITHER_DISABLE;
923 
924     DEBUG_PRINT_HIGH("Dither config is %d", m_dither_config);
925     m_color_space = EXCEPT_BT2020;
926 
927     init_color_aspects_map();
928 
929     profile_level_converter::init();
930     mClientSessionForSufficiency = false;
931     mClientSetProfile = 0;
932     mClientSetLevel = 0;
933 #ifdef USE_GBM
934      drv_ctx.gbm_device_fd = -1;
935 #endif
936 }
937 
938 static const int event_type[] = {
939     V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
940     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
941     V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
942     V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
943     V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
944     V4L2_EVENT_MSM_VIDC_SYS_ERROR,
945     V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
946     V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
947 };
948 
subscribe_to_events(int fd)949 static OMX_ERRORTYPE subscribe_to_events(int fd)
950 {
951     OMX_ERRORTYPE eRet = OMX_ErrorNone;
952     struct v4l2_event_subscription sub;
953     int array_sz = sizeof(event_type)/sizeof(int);
954     int i,rc;
955     if (fd < 0) {
956         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
957         return OMX_ErrorBadParameter;
958     }
959 
960     for (i = 0; i < array_sz; ++i) {
961         memset(&sub, 0, sizeof(sub));
962         sub.type = event_type[i];
963         rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
964         if (rc) {
965             DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
966             break;
967         }
968     }
969     if (i < array_sz) {
970         for (--i; i >=0 ; i--) {
971             memset(&sub, 0, sizeof(sub));
972             sub.type = event_type[i];
973             rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
974             if (rc)
975                 DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
976         }
977         eRet = OMX_ErrorNotImplemented;
978     }
979     return eRet;
980 }
981 
982 
unsubscribe_to_events(int fd)983 static OMX_ERRORTYPE unsubscribe_to_events(int fd)
984 {
985     OMX_ERRORTYPE eRet = OMX_ErrorNone;
986     struct v4l2_event_subscription sub;
987     int array_sz = sizeof(event_type)/sizeof(int);
988     int i,rc;
989     if (fd < 0) {
990         DEBUG_PRINT_ERROR("Invalid input: %d", fd);
991         return OMX_ErrorBadParameter;
992     }
993 
994     for (i = 0; i < array_sz; ++i) {
995         memset(&sub, 0, sizeof(sub));
996         sub.type = event_type[i];
997         rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
998         if (rc) {
999             DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
1000             break;
1001         }
1002     }
1003     return eRet;
1004 }
1005 
1006 /* ======================================================================
1007    FUNCTION
1008    omx_vdec::~omx_vdec
1009 
1010    DESCRIPTION
1011    Destructor
1012 
1013    PARAMETERS
1014    None
1015 
1016    RETURN VALUE
1017    None.
1018    ========================================================================== */
~omx_vdec()1019 omx_vdec::~omx_vdec()
1020 {
1021     m_pmem_info = NULL;
1022     DEBUG_PRINT_HIGH("In OMX vdec Destructor");
1023     if (msg_thread_created) {
1024         DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
1025         message_thread_stop = true;
1026         post_message(this, OMX_COMPONENT_CLOSE_MSG);
1027         DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
1028         pthread_join(msg_thread_id,NULL);
1029     }
1030     DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
1031     if(eventfd_write(m_poll_efd, 1)) {
1032          DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
1033          async_thread_force_stop = true;
1034     }
1035     if (async_thread_created)
1036         pthread_join(async_thread_id,NULL);
1037 
1038     if (m_prefetch_done & 0x1)
1039         prefetch_buffers(PREFETCH_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_output, ION_IOC_DRAIN, ION_FLAG_CP_PIXEL);
1040     if (m_prefetch_done & 0x2)
1041         prefetch_buffers(PREFETCH_NON_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_internal, ION_IOC_DRAIN, ION_FLAG_CP_NON_PIXEL);
1042 
1043     unsubscribe_to_events(drv_ctx.video_driver_fd);
1044     close(m_poll_efd);
1045     close(drv_ctx.video_driver_fd);
1046     pthread_mutex_destroy(&m_lock);
1047     pthread_mutex_destroy(&c_lock);
1048     pthread_mutex_destroy(&buf_lock);
1049     sem_destroy(&m_cmd_lock);
1050     if (perf_flag) {
1051         DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
1052         dec_time.end();
1053     }
1054     DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
1055     m_perf_control.perf_lock_release();
1056 }
1057 
set_dpb(bool is_split_mode)1058 OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode)
1059 {
1060     int rc = 0;
1061     struct v4l2_ext_control ctrl[1];
1062     struct v4l2_ext_controls controls;
1063 
1064     ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
1065     if (is_split_mode) {
1066         ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
1067     } else {
1068         ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY;
1069     }
1070 
1071     controls.count = 1;
1072     controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
1073     controls.controls = ctrl;
1074 
1075     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
1076     if (rc) {
1077         DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc);
1078         return OMX_ErrorUnsupportedSetting;
1079     }
1080     m_is_split_mode = is_split_mode;
1081     return OMX_ErrorNone;
1082 
1083 }
1084 
decide_dpb_buffer_mode()1085 OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode()
1086 {
1087     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1088     struct v4l2_format fmt;
1089     int rc = 0;
1090 
1091     // Default is Combined Mode
1092     bool enable_split = false;
1093     bool is_client_dest_format_non_ubwc = (
1094                      capture_capability != V4L2_PIX_FMT_NV12_UBWC &&
1095                      capture_capability != V4L2_PIX_FMT_NV12_TP10_UBWC);
1096     bool dither_enable = false;
1097     bool capability_changed = false;
1098 
1099     switch (m_dither_config) {
1100     case DITHER_DISABLE:
1101         dither_enable = false;
1102         break;
1103     case DITHER_COLORSPACE_EXCEPTBT2020:
1104         dither_enable = (m_color_space == EXCEPT_BT2020);
1105         break;
1106     case DITHER_ALL_COLORSPACE:
1107         dither_enable = true;
1108         break;
1109     default:
1110         DEBUG_PRINT_ERROR("Unsupported dither configuration:%d", m_dither_config);
1111     }
1112 
1113     // Reset v4l2_foramt struct object
1114     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1115 
1116     if (is_client_dest_format_non_ubwc){
1117         // Assuming all the else blocks are for 8 bit depth
1118         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1119             enable_split = true;
1120             if(is_flexible_format){ // if flexible formats are expected, P010 is set for 10bit cases here
1121                  drv_ctx.output_format = VDEC_YUV_FORMAT_P010_VENUS;
1122                  capture_capability = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS;
1123                  capability_changed = true;
1124             }
1125         } else  if (m_progressive == MSM_VIDC_PIC_STRUCT_PROGRESSIVE) {
1126             enable_split = true;
1127         } else {
1128             // Hardware does not support NV12+interlace clips.
1129             // Request NV12_UBWC and convert it to NV12+interlace using C2D
1130             // in combined mode
1131             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
1132             capture_capability = V4L2_PIX_FMT_NV12_UBWC;
1133             capability_changed = true;
1134         }
1135     } else {
1136         if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
1137             enable_split = dither_enable;
1138 
1139             if (dither_enable) {
1140                 capture_capability = m_disable_ubwc_mode ?
1141                             V4L2_PIX_FMT_NV12 : V4L2_PIX_FMT_NV12_UBWC;
1142                 capability_changed = true;
1143             } else {
1144                 drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_TP10_UBWC;
1145                 capture_capability = V4L2_PIX_FMT_NV12_TP10_UBWC;
1146                 capability_changed = true;
1147             }
1148         }
1149         // 8 bit depth uses the default.
1150         // Combined mode
1151         // V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE
1152     }
1153 
1154     if (capability_changed == true) {
1155         // Get format for CAPTURE port
1156         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1157         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1158         if (rc) {
1159             DEBUG_PRINT_ERROR("%s: Failed get format on capture mplane", __func__);
1160             return OMX_ErrorUnsupportedSetting;
1161         }
1162 
1163         // Set Capability for CAPTURE port if there is a change
1164         fmt.fmt.pix_mp.pixelformat = capture_capability;
1165         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1166         if (rc) {
1167             DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1168             return OMX_ErrorUnsupportedSetting;
1169         }
1170     }
1171     // Check the component for its valid current state
1172     if (!BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_IDLE_PENDING) &&
1173         !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
1174         DEBUG_PRINT_LOW("Invalid state to decide on dpb-opb split");
1175         return OMX_ErrorNone;
1176     }
1177     eRet = set_dpb(enable_split);
1178     if (eRet) {
1179         DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet);
1180     }
1181 
1182     return eRet;
1183 }
1184 
check_supported_flexible_formats(OMX_COLOR_FORMATTYPE required_format)1185 bool omx_vdec::check_supported_flexible_formats(OMX_COLOR_FORMATTYPE required_format)
1186 {
1187     if(required_format == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
1188          required_format == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus) {
1189          //for now, the flexible formats should be NV12 by default for 8bit cases
1190          //it will change to P010 after 10bit port-reconfig accordingly
1191        return TRUE;
1192     }
1193     else {
1194        return FALSE;
1195     }
1196 }
1197 
enable_downscalar()1198 int omx_vdec::enable_downscalar()
1199 {
1200     int rc = 0;
1201     struct v4l2_control control;
1202     struct v4l2_format fmt;
1203 
1204     if (is_down_scalar_enabled) {
1205         DEBUG_PRINT_LOW("%s: already enabled", __func__);
1206         return 0;
1207     }
1208 
1209     DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
1210     rc = decide_dpb_buffer_mode();
1211     if (rc) {
1212         DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
1213         return rc;
1214     }
1215     is_down_scalar_enabled = true;
1216 
1217     return 0;
1218 }
1219 
disable_downscalar()1220 int omx_vdec::disable_downscalar()
1221 {
1222     int rc = 0;
1223     struct v4l2_control control;
1224 
1225     if (!is_down_scalar_enabled) {
1226         DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
1227         return 0;
1228     }
1229     rc = decide_dpb_buffer_mode();
1230     if (rc < 0) {
1231         DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
1232         return rc;
1233     }
1234     is_down_scalar_enabled = false;
1235 
1236     return rc;
1237 }
1238 
decide_downscalar()1239 int omx_vdec::decide_downscalar()
1240 {
1241     int rc = 0;
1242     struct v4l2_format fmt;
1243     enum color_fmts color_format;
1244     OMX_U32 width, height;
1245     OMX_BOOL isPortraitVideo = OMX_FALSE;
1246 
1247     if (capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC) {
1248         rc = disable_downscalar();
1249         if (rc) {
1250             DEBUG_PRINT_ERROR("Disable downscalar failed!");
1251             return rc;
1252         }
1253         return 0;
1254     }
1255 
1256 #ifdef _QUERY_DISP_RES_
1257     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1258     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1259     fmt.fmt.pix_mp.pixelformat = capture_capability;
1260     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1261     if (rc < 0) {
1262        DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1263        return rc;
1264     }
1265     isPortraitVideo = fmt.fmt.pix_mp.width < fmt.fmt.pix_mp.height ? OMX_TRUE : OMX_FALSE;
1266     if (!m_downscalar_width || !m_downscalar_height) {
1267         qdutils::DisplayAttributes dpa = {}, dsa = {}, dva = {};
1268         int prim_config, ext_config, virt_config;
1269 
1270         prim_config = qdutils::getActiveConfig(qdutils::DISPLAY_PRIMARY);
1271         dpa = qdutils::getDisplayAttributes(prim_config, qdutils::DISPLAY_PRIMARY);
1272         DEBUG_PRINT_HIGH("%s: Primary dpa.xres = %d  dpa.yres=%d   dpa.xdpi = %f  dpa.ydpi = %f ",
1273             __func__, dpa.xres, dpa.yres, dpa.xdpi, dpa.ydpi);
1274 
1275         ext_config = qdutils::getActiveConfig(qdutils::DISPLAY_EXTERNAL);
1276         dsa = qdutils::getDisplayAttributes(ext_config, qdutils::DISPLAY_EXTERNAL);
1277         DEBUG_PRINT_HIGH("%s: HDMI dsa.xres = %d  dsa.yres = %d   dsa.xdpi = %f  dsa.ydpi = %f ",
1278             __func__, dsa.xres, dsa.yres, dsa.xdpi, dsa.ydpi);
1279 
1280         virt_config = qdutils::getActiveConfig(qdutils::DISPLAY_VIRTUAL);
1281         dva = qdutils::getDisplayAttributes(virt_config, qdutils::DISPLAY_VIRTUAL);
1282         DEBUG_PRINT_HIGH("%s: Virtual dva.xres = %d  dva.yres = %d   dva.xdpi = %f  dva.ydpi = %f ",
1283             __func__, dva.xres, dva.yres, dva.xdpi, dva.ydpi);
1284 
1285         /* Below logic takes care of following conditions:
1286          *   1. Choose display resolution as maximum resolution of all the connected
1287          *      displays (secondary, primary, virtual), so that we do not downscale
1288          *      unnecessarily which might be supported on one of the display losing quality.
1289          *   2. Displays connected might be in landscape or portrait mode, so the xres might
1290          *      be smaller or greater than the yres. So we first take the max of the two
1291          *      in width and min of two in height and then rotate it if below point is true.
1292          *   3. Video might also be in portrait mode, so invert the downscalar width and
1293          *      height for such cases.
1294          */
1295         if (dsa.xres * dsa.yres > dpa.xres * dpa.yres) {
1296             m_downscalar_width = MAX(dsa.xres, dsa.yres);
1297             m_downscalar_height = MIN(dsa.xres, dsa.yres);
1298         } else if (dva.xres * dva.yres > dpa.xres * dpa.yres) {
1299             m_downscalar_width = MAX(dva.xres, dva.yres);
1300             m_downscalar_height = MIN(dva.xres, dva.yres);
1301 
1302         } else {
1303             m_downscalar_width = MAX(dpa.xres, dpa.yres);
1304             m_downscalar_height = MIN(dpa.xres, dpa.yres);
1305         }
1306         if (isPortraitVideo) {
1307             // Swap width and height
1308             m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
1309             m_downscalar_height = m_downscalar_width ^ m_downscalar_height;
1310             m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
1311         }
1312     }
1313     m_downscalar_width = ALIGN(m_downscalar_width, 128);
1314     m_downscalar_height = ALIGN(m_downscalar_height, 32);
1315 #endif
1316 
1317     if (!m_downscalar_width || !m_downscalar_height) {
1318         DEBUG_PRINT_LOW("%s: Invalid downscalar configuration", __func__);
1319         return 0;
1320     }
1321 
1322     if (m_force_down_scalar) {
1323         DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
1324         return 0;
1325     }
1326 
1327     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1328     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1329     fmt.fmt.pix_mp.pixelformat = capture_capability;
1330     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
1331     if (rc < 0) {
1332        DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
1333        return rc;
1334     }
1335 
1336     height = fmt.fmt.pix_mp.height;
1337     width = fmt.fmt.pix_mp.width;
1338 
1339     DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d m_is_display_session = %d", __func__,
1340         fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height, m_is_display_session);
1341 
1342     if ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) &&
1343          m_is_display_session) {
1344         rc = enable_downscalar();
1345         if (rc < 0) {
1346             DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
1347             return rc;
1348         }
1349 
1350         width = m_downscalar_width > fmt.fmt.pix_mp.width ?
1351                             fmt.fmt.pix_mp.width : m_downscalar_width;
1352         height = m_downscalar_height > fmt.fmt.pix_mp.height ?
1353                             fmt.fmt.pix_mp.height : m_downscalar_height;
1354         switch (capture_capability) {
1355             case V4L2_PIX_FMT_NV12:
1356                 color_format = COLOR_FMT_NV12;
1357                 break;
1358             case V4L2_PIX_FMT_NV12_UBWC:
1359                 color_format = COLOR_FMT_NV12_UBWC;
1360                 break;
1361             case V4L2_PIX_FMT_NV12_TP10_UBWC:
1362                 color_format = COLOR_FMT_NV12_BPP10_UBWC;
1363                 break;
1364             default:
1365                 DEBUG_PRINT_ERROR("Color format not recognized\n");
1366                 rc = OMX_ErrorUndefined;
1367                 return rc;
1368         }
1369     } else {
1370 
1371         rc = disable_downscalar();
1372         if (rc < 0) {
1373             DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
1374             return rc;
1375         }
1376     }
1377 
1378     memset(&fmt, 0x0, sizeof(struct v4l2_format));
1379     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1380     fmt.fmt.pix_mp.height = height;
1381     fmt.fmt.pix_mp.width = width;
1382     fmt.fmt.pix_mp.pixelformat = capture_capability;
1383     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
1384     if (rc) {
1385         DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
1386         return rc;
1387     }
1388 
1389     rc = get_buffer_req(&drv_ctx.op_buf);
1390     if (rc) {
1391         DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__);
1392         return rc;
1393     }
1394 
1395     return rc;
1396 }
1397 
1398 /* ======================================================================
1399    FUNCTION
1400    omx_vdec::OMXCntrlProcessMsgCb
1401 
1402    DESCRIPTION
1403    IL Client callbacks are generated through this routine. The decoder
1404    provides the thread context for this routine.
1405 
1406    PARAMETERS
1407    ctxt -- Context information related to the self.
1408    id   -- Event identifier. This could be any of the following:
1409    1. Command completion event
1410    2. Buffer done callback event
1411    3. Frame done callback event
1412 
1413    RETURN VALUE
1414    None.
1415 
1416    ========================================================================== */
process_event_cb(void * ctxt)1417 void omx_vdec::process_event_cb(void *ctxt)
1418 {
1419     unsigned long p1; // Parameter - 1
1420     unsigned long p2; // Parameter - 2
1421     unsigned long ident;
1422     unsigned qsize=0; // qsize
1423     omx_vdec *pThis = (omx_vdec *) ctxt;
1424 
1425     if (!pThis) {
1426         DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
1427                 __func__);
1428         return;
1429     }
1430 
1431     // Protect the shared queue data structure
1432     do {
1433         /*Read the message id's from the queue*/
1434         pthread_mutex_lock(&pThis->m_lock);
1435         qsize = pThis->m_cmd_q.m_size;
1436         if (qsize) {
1437             pThis->m_cmd_q.pop_entry(&p1, &p2, &ident);
1438         }
1439 
1440         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1441             qsize = pThis->m_ftb_q.m_size;
1442             if (qsize) {
1443                 pThis->m_ftb_q.pop_entry(&p1, &p2, &ident);
1444             }
1445         }
1446 
1447         if (qsize == 0 && pThis->m_state != OMX_StatePause) {
1448             qsize = pThis->m_etb_q.m_size;
1449             if (qsize) {
1450                 pThis->m_etb_q.pop_entry(&p1, &p2, &ident);
1451             }
1452         }
1453         pthread_mutex_unlock(&pThis->m_lock);
1454 
1455         /*process message if we have one*/
1456         if (qsize > 0) {
1457             switch (ident) {
1458                 case OMX_COMPONENT_GENERATE_EVENT:
1459                     if (pThis->m_cb.EventHandler) {
1460                         switch (p1) {
1461                             case OMX_CommandStateSet:
1462                                 pThis->m_state = (OMX_STATETYPE) p2;
1463                                 DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d",
1464                                         pThis->m_state);
1465                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1466                                         OMX_EventCmdComplete, p1, p2, NULL);
1467                                 break;
1468 
1469                             case OMX_EventError:
1470                                 if (p2 == OMX_StateInvalid) {
1471                                     DEBUG_PRINT_ERROR("OMX_EventError: p2 is OMX_StateInvalid");
1472                                     pThis->m_state = (OMX_STATETYPE) p2;
1473                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1474                                             OMX_EventError, OMX_ErrorInvalidState, p2, NULL);
1475                                 } else if (p2 == (unsigned long)OMX_ErrorHardware) {
1476                                     pThis->omx_report_error();
1477                                 } else {
1478                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1479                                             OMX_EventError, p2, (OMX_U32)NULL, NULL );
1480                                 }
1481                                 break;
1482 
1483                             case OMX_CommandPortDisable:
1484                                 DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", p2);
1485                                 if (BITMASK_PRESENT(&pThis->m_flags,
1486                                             OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1487                                     BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1488                                     break;
1489                                 }
1490                                 if (p2 == OMX_CORE_OUTPUT_PORT_INDEX) {
1491                                     OMX_ERRORTYPE eRet = OMX_ErrorNone;
1492                                     pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
1493                                     OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
1494                                     pThis->in_reconfig = false;
1495                                     pThis->client_buffers.enable_color_conversion(pThis->c2d_enable_pending);
1496                                     if (eRet !=  OMX_ErrorNone) {
1497                                         DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
1498                                         pThis->omx_report_error();
1499                                         break;
1500                                     }
1501                                 }
1502                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1503                                         OMX_EventCmdComplete, p1, p2, NULL );
1504                                 break;
1505                             case OMX_CommandPortEnable:
1506                                 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
1507                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
1508                                         OMX_EventCmdComplete, p1, p2, NULL );
1509                                 break;
1510 
1511                             default:
1512                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1513                                         OMX_EventCmdComplete, p1, p2, NULL );
1514                                 break;
1515 
1516                         }
1517                     } else {
1518                         DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1519                     }
1520                     break;
1521                 case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
1522                     if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
1523                                 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1524                         DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
1525                         pThis->omx_report_error ();
1526                     }
1527                     break;
1528                 case OMX_COMPONENT_GENERATE_ETB: {
1529                         OMX_ERRORTYPE iret;
1530                         iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
1531                         if (iret == OMX_ErrorInsufficientResources) {
1532                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
1533                             pThis->omx_report_hw_overload ();
1534                         } else if (iret != OMX_ErrorNone) {
1535                             DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
1536                             pThis->omx_report_error ();
1537                         }
1538                     }
1539                     break;
1540 
1541                 case OMX_COMPONENT_GENERATE_FTB:
1542                     if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
1543                                 (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
1544                         DEBUG_PRINT_ERROR("fill_this_buffer_proxy failure");
1545                         pThis->omx_report_error ();
1546                     }
1547                     break;
1548 
1549                 case OMX_COMPONENT_GENERATE_COMMAND:
1550                     pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
1551                             (OMX_U32)p2,(OMX_PTR)NULL);
1552                     break;
1553 
1554                 case OMX_COMPONENT_GENERATE_EBD:
1555 
1556                     if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) {
1557                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EBD failure");
1558                         pThis->omx_report_error ();
1559                     } else {
1560                         if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
1561                             pThis->time_stamp_dts.remove_time_stamp(
1562                                     ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
1563                                     (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1564                                     ?true:false);
1565                         }
1566 
1567                         if ( pThis->empty_buffer_done(&pThis->m_cmp,
1568                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
1569                             DEBUG_PRINT_ERROR("empty_buffer_done failure");
1570                             pThis->omx_report_error ();
1571                         }
1572                     }
1573                     break;
1574                 case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
1575                                             int64_t *timestamp = (int64_t *)(intptr_t)p1;
1576                                             if (p1) {
1577                                                 pThis->time_stamp_dts.remove_time_stamp(*timestamp,
1578                                                         (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
1579                                                         ?true:false);
1580                                                 free(timestamp);
1581                                             }
1582                                         }
1583                                         break;
1584                 case OMX_COMPONENT_GENERATE_FBD:
1585                                         if (p2 != VDEC_S_SUCCESS) {
1586                                             DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
1587                                             pThis->omx_report_error ();
1588                                         } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
1589                                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
1590                                             DEBUG_PRINT_ERROR("fill_buffer_done failure");
1591                                             pThis->omx_report_error ();
1592                                         }
1593                                         break;
1594 
1595                 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
1596                                         DEBUG_PRINT_HIGH("Driver flush i/p Port complete, flags %#llx",
1597                                                 (unsigned long long)pThis->m_flags);
1598                                         if (!pThis->input_flush_progress) {
1599                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1600                                         } else {
1601                                             pThis->execute_input_flush();
1602                                             if (pThis->m_cb.EventHandler) {
1603                                                 if (p2 != VDEC_S_SUCCESS) {
1604                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure");
1605                                                     pThis->omx_report_error ();
1606                                                 } else {
1607                                                     /*Check if we need generate event for Flush done*/
1608                                                     pThis->notify_flush_done(ctxt);
1609 
1610                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1611                                                                 OMX_COMPONENT_IDLE_PENDING)) {
1612                                                         if (pThis->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
1613                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
1614                                                             pThis->omx_report_error ();
1615                                                         } else {
1616                                                             pThis->streaming[OUTPUT_PORT] = false;
1617                                                         }
1618                                                         if (!pThis->output_flush_progress) {
1619                                                             DEBUG_PRINT_LOW("Input flush done hence issue stop");
1620                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1621                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1622                                                         }
1623                                                     }
1624                                                 }
1625                                             } else {
1626                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1627                                             }
1628                                         }
1629                                         break;
1630 
1631                 case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
1632                                         DEBUG_PRINT_HIGH("Driver flush o/p Port complete, flags %#llx",
1633                                                 (unsigned long long)pThis->m_flags);
1634                                         if (!pThis->output_flush_progress) {
1635                                             DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
1636                                         } else {
1637                                             pThis->execute_output_flush();
1638                                             if (pThis->m_cb.EventHandler) {
1639                                                 if (p2 != VDEC_S_SUCCESS) {
1640                                                     DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed");
1641                                                     pThis->omx_report_error ();
1642                                                 } else {
1643                                                     /*Check if we need generate event for Flush done*/
1644                                                     pThis->notify_flush_done(ctxt);
1645 
1646                                                     if (BITMASK_PRESENT(&pThis->m_flags,
1647                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) {
1648                                                         DEBUG_PRINT_LOW("Internal flush complete");
1649                                                         BITMASK_CLEAR (&pThis->m_flags,
1650                                                                 OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
1651                                                         if (BITMASK_PRESENT(&pThis->m_flags,
1652                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) {
1653                                                             pThis->post_event(OMX_CommandPortDisable,
1654                                                                     OMX_CORE_OUTPUT_PORT_INDEX,
1655                                                                     OMX_COMPONENT_GENERATE_EVENT);
1656                                                             BITMASK_CLEAR (&pThis->m_flags,
1657                                                                     OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED);
1658                                                             BITMASK_CLEAR (&pThis->m_flags,
1659                                                                     OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
1660 
1661                                                         }
1662                                                     }
1663 
1664                                                     if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
1665                                                         if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
1666                                                             DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
1667                                                             pThis->omx_report_error ();
1668                                                             break;
1669                                                         }
1670                                                         pThis->streaming[CAPTURE_PORT] = false;
1671                                                         if (!pThis->input_flush_progress) {
1672                                                             DEBUG_PRINT_LOW("Output flush done hence issue stop");
1673                                                             pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
1674                                                                     OMX_COMPONENT_GENERATE_STOP_DONE);
1675                                                         }
1676                                                     }
1677                                                 }
1678                                             } else {
1679                                                 DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1680                                             }
1681                                         }
1682                                         break;
1683 
1684                 case OMX_COMPONENT_GENERATE_START_DONE:
1685                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE, flags %#llx",
1686                                                 (unsigned long long)pThis->m_flags);
1687                                         if (pThis->m_cb.EventHandler) {
1688                                             if (p2 != VDEC_S_SUCCESS) {
1689                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
1690                                                 pThis->omx_report_error ();
1691                                             } else {
1692                                                 DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
1693                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1694                                                     DEBUG_PRINT_LOW("Move to executing");
1695                                                     // Send the callback now
1696                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1697                                                     pThis->m_state = OMX_StateExecuting;
1698                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1699                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1700                                                             OMX_StateExecuting, NULL);
1701                                                 } else if (BITMASK_PRESENT(&pThis->m_flags,
1702                                                             OMX_COMPONENT_PAUSE_PENDING)) {
1703                                                     if (/*ioctl (pThis->drv_ctx.video_driver_fd,
1704                                                           VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) {
1705                                                         DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_PAUSE failed");
1706                                                         pThis->omx_report_error ();
1707                                                     }
1708                                                 }
1709                                             }
1710                                         } else {
1711                                             DEBUG_PRINT_LOW("Event Handler callback is NULL");
1712                                         }
1713                                         break;
1714 
1715                 case OMX_COMPONENT_GENERATE_PAUSE_DONE:
1716                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE");
1717                                         if (pThis->m_cb.EventHandler) {
1718                                             if (p2 != VDEC_S_SUCCESS) {
1719                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed");
1720                                                 pThis->omx_report_error ();
1721                                             } else {
1722                                                 pThis->complete_pending_buffer_done_cbs();
1723                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
1724                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity");
1725                                                     //Send the callback now
1726                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
1727                                                     pThis->m_state = OMX_StatePause;
1728                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1729                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1730                                                             OMX_StatePause, NULL);
1731                                                 }
1732                                             }
1733                                         } else {
1734                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1735                                         }
1736 
1737                                         break;
1738 
1739                 case OMX_COMPONENT_GENERATE_RESUME_DONE:
1740                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
1741                                         if (pThis->m_cb.EventHandler) {
1742                                             if (p2 != VDEC_S_SUCCESS) {
1743                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
1744                                                 pThis->omx_report_error ();
1745                                             } else {
1746                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
1747                                                     DEBUG_PRINT_LOW("Moving the decoder to execute state");
1748                                                     // Send the callback now
1749                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
1750                                                     pThis->m_state = OMX_StateExecuting;
1751                                                     pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1752                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1753                                                             OMX_StateExecuting,NULL);
1754                                                 }
1755                                             }
1756                                         } else {
1757                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1758                                         }
1759 
1760                                         break;
1761 
1762                 case OMX_COMPONENT_GENERATE_STOP_DONE:
1763                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
1764                                         if (pThis->m_cb.EventHandler) {
1765                                             if (p2 != VDEC_S_SUCCESS) {
1766                                                 DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_STOP_DONE ret failed");
1767                                                 pThis->omx_report_error ();
1768                                             } else {
1769                                                 pThis->complete_pending_buffer_done_cbs();
1770                                                 if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
1771                                                     DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success");
1772                                                     // Send the callback now
1773                                                     BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
1774                                                     pThis->m_state = OMX_StateIdle;
1775                                                     DEBUG_PRINT_LOW("Move to Idle State");
1776                                                     pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data,
1777                                                             OMX_EventCmdComplete,OMX_CommandStateSet,
1778                                                             OMX_StateIdle,NULL);
1779                                                 }
1780                                             }
1781                                         } else {
1782                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1783                                         }
1784 
1785                                         break;
1786 
1787                 case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
1788                                         if (p2 == OMX_IndexParamPortDefinition) {
1789                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
1790                                             pThis->in_reconfig = true;
1791                                             pThis->prev_n_filled_len = 0;
1792                                         }  else if (p2 == OMX_IndexConfigCommonOutputCrop) {
1793                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
1794 
1795                                             /* Check if resolution is changed in smooth streaming mode */
1796                                             if (pThis->m_smoothstreaming_mode &&
1797                                                 (pThis->framesize.nWidth !=
1798                                                     pThis->drv_ctx.video_resolution.frame_width) ||
1799                                                 (pThis->framesize.nHeight !=
1800                                                     pThis->drv_ctx.video_resolution.frame_height)) {
1801 
1802                                                 DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
1803                                                         pThis->framesize.nWidth,
1804                                                         pThis->framesize.nHeight,
1805                                                         pThis->drv_ctx.video_resolution.frame_width,
1806                                                         pThis->drv_ctx.video_resolution.frame_height);
1807 
1808                                                 /* Update new resolution */
1809                                                 pThis->framesize.nWidth =
1810                                                        pThis->drv_ctx.video_resolution.frame_width;
1811                                                 pThis->framesize.nHeight =
1812                                                        pThis->drv_ctx.video_resolution.frame_height;
1813 
1814                                                 /* Update C2D with new resolution */
1815                                                 if (!pThis->client_buffers.update_buffer_req()) {
1816                                                     DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
1817                                                 }
1818                                             }
1819 
1820                                             /* Update new crop information */
1821                                             pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
1822                                             pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
1823                                             pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
1824                                             pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
1825 
1826                                             /* Validate the new crop information */
1827                                             if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
1828                                                 pThis->drv_ctx.video_resolution.frame_width) {
1829 
1830                                                 DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
1831                                                         pThis->rectangle.nLeft, pThis->rectangle.nWidth,
1832                                                         pThis->drv_ctx.video_resolution.frame_width);
1833                                                 pThis->rectangle.nLeft = 0;
1834 
1835                                                 if (pThis->rectangle.nWidth >
1836                                                     pThis->drv_ctx.video_resolution.frame_width) {
1837 
1838                                                     DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
1839                                                             pThis->rectangle.nWidth,
1840                                                             pThis->drv_ctx.video_resolution.frame_width);
1841                                                     pThis->rectangle.nWidth =
1842                                                         pThis->drv_ctx.video_resolution.frame_width;
1843                                                 }
1844                                             }
1845                                             if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
1846                                                 pThis->drv_ctx.video_resolution.frame_height) {
1847 
1848                                                 DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
1849                                                     pThis->rectangle.nTop, pThis->rectangle.nHeight,
1850                                                     pThis->drv_ctx.video_resolution.frame_height);
1851                                                 pThis->rectangle.nTop = 0;
1852 
1853                                                 if (pThis->rectangle.nHeight >
1854                                                     pThis->drv_ctx.video_resolution.frame_height) {
1855 
1856                                                     DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
1857                                                         pThis->rectangle.nHeight,
1858                                                         pThis->drv_ctx.video_resolution.frame_height);
1859                                                     pThis->rectangle.nHeight =
1860                                                         pThis->drv_ctx.video_resolution.frame_height;
1861                                                 }
1862                                             }
1863                                             DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
1864                                                     pThis->rectangle.nLeft, pThis->rectangle.nTop,
1865                                                     pThis->rectangle.nWidth, pThis->rectangle.nHeight);
1866                                         } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
1867                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
1868                                         } else if (p2 == OMX_QTIIndexConfigDescribeHDRColorInfo) {
1869                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeHDRcolorinfo");
1870                                         } else {
1871                                             DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
1872                                             break;
1873                                         }
1874                                         if (pThis->m_debug.outfile) {
1875                                             fclose(pThis->m_debug.outfile);
1876                                             pThis->m_debug.outfile = NULL;
1877                                         }
1878                                         if (pThis->m_debug.ccoutfile) {
1879                                             fclose(pThis->m_debug.ccoutfile);
1880                                             pThis->m_debug.ccoutfile = NULL;
1881                                         }
1882                                         if (pThis->m_debug.out_ymeta_file) {
1883                                             fclose(pThis->m_debug.out_ymeta_file);
1884                                             pThis->m_debug.out_ymeta_file = NULL;
1885                                         }
1886                                         if (pThis->m_debug.out_uvmeta_file) {
1887                                             fclose(pThis->m_debug.out_uvmeta_file);
1888                                             pThis->m_debug.out_uvmeta_file = NULL;
1889                                         }
1890                                         pThis->m_debug.seq_count++;
1891 
1892                                         if (pThis->m_cb.EventHandler) {
1893                                             void *frame_data = NULL;
1894                                             reconfig_client_data port_data;
1895                                             reconfig_client_crop_data crop_data;
1896                                             if (p2 == OMX_IndexConfigCommonOutputCrop) {
1897                                                 crop_data.width = pThis->rectangle.nWidth;
1898                                                 crop_data.height = pThis->rectangle.nHeight;
1899                                                 crop_data.left = pThis->rectangle.nLeft;
1900                                                 crop_data.top = pThis->rectangle.nTop;
1901                                                 crop_data.isPortReconfigInsufficient = pThis->isPortReconfigInsufficient;
1902                                                 frame_data = (void*)&crop_data;
1903                                             } else if (p2 == OMX_IndexParamPortDefinition){
1904                                                 port_data.width = pThis->m_reconfig_width;
1905                                                 port_data.height = pThis->m_reconfig_height;
1906                                                 port_data.dpb_bit_depth = pThis->dpb_bit_depth;
1907                                                 port_data.m_progressive = pThis->m_progressive;
1908                                                 port_data.isPortReconfigInsufficient = pThis->isPortReconfigInsufficient;
1909                                                 frame_data = (void*)&port_data;
1910                                             }
1911                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
1912                                                      OMX_EventPortSettingsChanged, p1, p2, (void*)frame_data);
1913                                         } else {
1914                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1915                                         }
1916                                         break;
1917 
1918                 case OMX_COMPONENT_GENERATE_EOS_DONE:
1919                                         DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE");
1920                                         if (pThis->m_cb.EventHandler) {
1921                                             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag,
1922                                                     OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL );
1923                                         } else {
1924                                             DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
1925                                         }
1926                                         pThis->prev_ts = LLONG_MAX;
1927                                         pThis->rst_prev_ts = true;
1928                                         break;
1929 
1930                 case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
1931                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
1932                                         pThis->omx_report_error();
1933                                         break;
1934 
1935                 case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
1936                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
1937                                         pThis->omx_report_unsupported_setting();
1938                                         break;
1939 
1940                 case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
1941                                         DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
1942                                         pThis->omx_report_hw_overload();
1943                                         break;
1944 
1945                 case OMX_COMPONENT_GENERATE_ION_PREFETCH_PIXEL:
1946                                         DEBUG_PRINT_HIGH("OMX_COMPONENT_GENERATE_ION_PREFETCH_PIXEL");
1947                                         pThis->m_prefetch_done |= pThis->prefetch_buffers(p1, p2, ION_IOC_PREFETCH, ION_FLAG_CP_PIXEL);
1948                                         break;
1949 
1950                 case OMX_COMPONENT_GENERATE_ION_PREFETCH_NON_PIXEL:
1951                                         DEBUG_PRINT_HIGH("OMX_COMPONENT_GENERATE_ION_PREFETCH_NON_PIXEL");
1952                                         pThis->m_prefetch_done |= pThis->prefetch_buffers(p1, p2, ION_IOC_PREFETCH, ION_FLAG_CP_NON_PIXEL) << 1;
1953                                         break;
1954 
1955                 default:
1956                                         break;
1957             }
1958         }
1959         pthread_mutex_lock(&pThis->m_lock);
1960         qsize = pThis->m_cmd_q.m_size;
1961         if (pThis->m_state != OMX_StatePause)
1962             qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size);
1963         pthread_mutex_unlock(&pThis->m_lock);
1964     } while (qsize>0);
1965 
1966 }
1967 
update_resolution(int width,int height,int stride,int scan_lines)1968 int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
1969 {
1970     int format_changed = 0;
1971     if ((height != (int)drv_ctx.video_resolution.frame_height) ||
1972             (width != (int)drv_ctx.video_resolution.frame_width)) {
1973         DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
1974                 width, drv_ctx.video_resolution.frame_width,
1975                 height,drv_ctx.video_resolution.frame_height);
1976         format_changed = 1;
1977     }
1978     drv_ctx.video_resolution.frame_height = height;
1979     drv_ctx.video_resolution.frame_width = width;
1980     drv_ctx.video_resolution.scan_lines = scan_lines;
1981     drv_ctx.video_resolution.stride = stride;
1982 
1983     if (!is_down_scalar_enabled) {
1984         rectangle.nLeft = m_extradata_info.output_crop_rect.nLeft;
1985         rectangle.nTop = m_extradata_info.output_crop_rect.nTop;
1986         rectangle.nWidth = m_extradata_info.output_crop_rect.nWidth;
1987         rectangle.nHeight = m_extradata_info.output_crop_rect.nHeight;
1988     }
1989     return format_changed;
1990 }
1991 
log_input_buffers(const char * buffer_addr,int buffer_len,uint64_t timeStamp,int fd)1992 int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len, uint64_t timeStamp, int fd)
1993 {
1994     if (!m_debug.in_buffer_log)
1995         return 0;
1996 
1997 #ifdef USE_ION
1998     do_cache_operations(fd);
1999 #else
2000     (void)fd;
2001 #endif
2002     if (m_debug.in_buffer_log && !m_debug.infile) {
2003         if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
2004                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p_%" PRId64 ".mpg", m_debug.log_loc,
2005                         drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this, m_debug.session_id);
2006         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
2007                     !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
2008                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
2009                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2010         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
2011                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
2012                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2013         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
2014                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
2015                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2016         } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2017                 snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
2018                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2019         } else {
2020                snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.bin",
2021                         m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2022         }
2023         m_debug.infile = fopen (m_debug.infile_name, "ab");
2024         if (!m_debug.infile) {
2025             DEBUG_PRINT_HIGH("Failed to open input file: %s for logging (%d:%s)",
2026                              m_debug.infile_name, errno, strerror(errno));
2027             m_debug.infile_name[0] = '\0';
2028 #ifdef USE_ION
2029             do_cache_operations(fd);
2030 #endif
2031             return -1;
2032         }
2033         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
2034                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2035             bool isVp9 = drv_ctx.decoder_format == VDEC_CODECTYPE_VP9;
2036             int width = drv_ctx.video_resolution.frame_width;
2037             int height = drv_ctx.video_resolution.frame_height;
2038             int fps = drv_ctx.frame_rate.fps_numerator;
2039             IvfFileHeader ivfHeader(isVp9, width, height, 1, fps, 0);
2040             fwrite((const char *)&ivfHeader,
2041                     sizeof(ivfHeader),1,m_debug.infile);
2042          }
2043     }
2044     if (m_debug.infile && buffer_addr && buffer_len) {
2045         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
2046                 !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
2047             IvfFrameHeader ivfFrameHeader(buffer_len, timeStamp);
2048             fwrite(&ivfFrameHeader, sizeof(ivfFrameHeader), 1, m_debug.infile);
2049         }
2050         fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
2051     }
2052 #ifdef USE_ION
2053     do_cache_operations(fd);
2054 #endif
2055     return 0;
2056 }
2057 
log_cc_output_buffers(OMX_BUFFERHEADERTYPE * buffer)2058 int omx_vdec::log_cc_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
2059     if (client_buffers.client_buffers_invalid() ||
2060         !m_debug.out_cc_buffer_log || !buffer || !buffer->nFilledLen)
2061         return 0;
2062 
2063     if (m_debug.out_cc_buffer_log && !m_debug.ccoutfile) {
2064         snprintf(m_debug.ccoutfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_cc_%d_%d_%p_%" PRId64 "_%d.yuv",
2065                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this,
2066                 m_debug.session_id, m_debug.seq_count);
2067         m_debug.ccoutfile = fopen (m_debug.ccoutfile_name, "ab");
2068         if (!m_debug.ccoutfile) {
2069             DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
2070             m_debug.ccoutfile_name[0] = '\0';
2071             return -1;
2072         }
2073         DEBUG_PRINT_HIGH("Opened CC output file: %s for logging", m_debug.ccoutfile_name);
2074     }
2075 
2076     fwrite(buffer->pBuffer, buffer->nFilledLen, 1, m_debug.ccoutfile);
2077     return 0;
2078 }
2079 
log_output_buffers(OMX_BUFFERHEADERTYPE * buffer)2080 int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
2081     int buf_index = 0;
2082     char *temp = NULL;
2083     char *bufaddr = NULL;
2084 
2085     if (!(m_debug.out_buffer_log || m_debug.out_meta_buffer_log) || !buffer || !buffer->nFilledLen)
2086         return 0;
2087 
2088     if (m_debug.out_buffer_log && !m_debug.outfile) {
2089         snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p_%" PRId64 "_%d.yuv",
2090                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this,
2091                 m_debug.session_id, m_debug.seq_count);
2092         m_debug.outfile = fopen (m_debug.outfile_name, "ab");
2093         if (!m_debug.outfile) {
2094             DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
2095             m_debug.outfile_name[0] = '\0';
2096             return -1;
2097         }
2098         DEBUG_PRINT_HIGH("Opened output file: %s for logging", m_debug.outfile_name);
2099     }
2100 
2101     if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file) {
2102         snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
2103                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2104         snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
2105                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
2106         m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
2107         m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
2108         if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
2109             DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
2110             m_debug.out_ymetafile_name[0] = '\0';
2111             m_debug.out_uvmetafile_name[0] = '\0';
2112             return -1;
2113         }
2114     }
2115 
2116     buf_index = buffer - m_out_mem_ptr;
2117     bufaddr = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
2118     if (dynamic_buf_mode && !secure_mode) {
2119         bufaddr = ion_map(drv_ctx.ptr_outputbuffer[buf_index].pmem_fd,
2120                           drv_ctx.ptr_outputbuffer[buf_index].buffer_len);
2121         //mmap returns (void *)-1 on failure and sets error code in errno.
2122         if (bufaddr == MAP_FAILED) {
2123             DEBUG_PRINT_ERROR("mmap failed - errno: %d", errno);
2124             return -1;
2125         }
2126     }
2127     temp = bufaddr;
2128 
2129     if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC ||
2130             drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
2131         DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
2132             drv_ctx.video_resolution.frame_width,
2133             drv_ctx.video_resolution.frame_height);
2134 
2135         if (m_debug.outfile)
2136             fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
2137 
2138         if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
2139             unsigned int width = 0, height = 0;
2140             unsigned int y_plane, y_meta_plane;
2141             int y_stride = 0, y_sclines = 0;
2142             int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
2143             int color_fmt = (drv_ctx.output_format== VDEC_YUV_FORMAT_NV12_UBWC)? COLOR_FMT_NV12_UBWC: COLOR_FMT_NV12_BPP10_UBWC;
2144             int i;
2145             int bytes_written = 0;
2146 
2147             width = drv_ctx.video_resolution.frame_width;
2148             height = drv_ctx.video_resolution.frame_height;
2149             y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
2150             y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
2151             y_stride = VENUS_Y_STRIDE(color_fmt, width);
2152             y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
2153             uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
2154             uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
2155 
2156             y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
2157             y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
2158 
2159             for (i = 0; i < y_meta_scanlines; i++) {
2160                  bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
2161                  temp += y_meta_stride;
2162             }
2163 
2164             temp = bufaddr + y_meta_plane + y_plane;
2165             for(i = 0; i < uv_meta_scanlines; i++) {
2166                 bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
2167                 temp += uv_meta_stride;
2168             }
2169         }
2170     } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
2171         int stride = drv_ctx.video_resolution.stride;
2172         int scanlines = drv_ctx.video_resolution.scan_lines;
2173         if (m_smoothstreaming_mode) {
2174             stride = drv_ctx.video_resolution.frame_width;
2175             scanlines = drv_ctx.video_resolution.frame_height;
2176             stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
2177             scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
2178         }
2179         unsigned i;
2180         DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
2181             drv_ctx.video_resolution.frame_width,
2182             drv_ctx.video_resolution.frame_height, stride, scanlines);
2183         int bytes_written = 0;
2184         for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
2185              bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2186              temp += stride;
2187         }
2188         temp = bufaddr + stride * scanlines;
2189         int stride_c = stride;
2190         for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
2191             bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
2192             temp += stride_c;
2193         }
2194     } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_P010_VENUS) {
2195         int stride = drv_ctx.video_resolution.stride;
2196         int scanlines = drv_ctx.video_resolution.scan_lines;
2197         if (m_smoothstreaming_mode) {
2198             stride = drv_ctx.video_resolution.frame_width * 2;
2199             scanlines = drv_ctx.video_resolution.frame_height;
2200             stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
2201             scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
2202         }
2203         unsigned i;
2204         DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
2205             drv_ctx.video_resolution.frame_width,
2206             drv_ctx.video_resolution.frame_height, stride, scanlines);
2207         int bytes_written = 0;
2208         for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
2209              bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 2, m_debug.outfile);
2210              temp += stride;
2211         }
2212         temp = bufaddr + stride * scanlines;
2213         int stride_c = stride;
2214         for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
2215             bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 2, m_debug.outfile);
2216             temp += stride_c;
2217         }
2218     }
2219 
2220     if (dynamic_buf_mode && !secure_mode) {
2221         ion_unmap(drv_ctx.ptr_outputbuffer[buf_index].pmem_fd, bufaddr,
2222                   drv_ctx.ptr_outputbuffer[buf_index].buffer_len);
2223     }
2224     return 0;
2225 }
2226 
init_color_aspects_map()2227 void omx_vdec::init_color_aspects_map()
2228 {
2229     mPrimariesMap.insert({
2230             {ColorAspects::PrimariesUnspecified, (ColorPrimaries)(2)},
2231             {ColorAspects::PrimariesBT709_5, ColorPrimaries_BT709_5},
2232             {ColorAspects::PrimariesBT470_6M, ColorPrimaries_BT470_6M},
2233             {ColorAspects::PrimariesBT601_6_625, ColorPrimaries_BT601_6_625},
2234             {ColorAspects::PrimariesBT601_6_525, ColorPrimaries_BT601_6_525},
2235             {ColorAspects::PrimariesGenericFilm, ColorPrimaries_GenericFilm},
2236             {ColorAspects::PrimariesBT2020, ColorPrimaries_BT2020},
2237         });
2238     mTransferMap.insert({
2239             {ColorAspects::TransferUnspecified, (GammaTransfer)(2)},
2240             {ColorAspects::TransferLinear, Transfer_Linear},
2241             {ColorAspects::TransferSRGB, Transfer_sRGB},
2242             {ColorAspects::TransferSMPTE170M, Transfer_SMPTE_170M},
2243             {ColorAspects::TransferGamma22, Transfer_Gamma2_2},
2244             {ColorAspects::TransferGamma28, Transfer_Gamma2_8},
2245             {ColorAspects::TransferST2084, Transfer_SMPTE_ST2084},
2246             {ColorAspects::TransferHLG, Transfer_HLG},
2247             {ColorAspects::TransferSMPTE240M, Transfer_SMPTE_240M},
2248             {ColorAspects::TransferXvYCC, Transfer_XvYCC},
2249             {ColorAspects::TransferBT1361, Transfer_BT1361},
2250             {ColorAspects::TransferST428, Transfer_ST_428},
2251         });
2252     mMatrixCoeffMap.insert({
2253             {ColorAspects::MatrixUnspecified, (MatrixCoEfficients)(2)},
2254             {ColorAspects::MatrixBT709_5, MatrixCoEff_BT709_5},
2255             {ColorAspects::MatrixBT470_6M, MatrixCoeff_FCC_73_682},
2256             {ColorAspects::MatrixBT601_6, MatrixCoEff_BT601_6_625},
2257             {ColorAspects::MatrixSMPTE240M, MatrixCoEff_SMPTE240M},
2258             {ColorAspects::MatrixBT2020, MatrixCoEff_BT2020},
2259             {ColorAspects::MatrixBT2020Constant, MatrixCoEff_BT2020Constant},
2260         });
2261     mColorRangeMap.insert({
2262             {ColorAspects::RangeUnspecified, (ColorRange)(2)},
2263             {ColorAspects::RangeFull, Range_Full},
2264             {ColorAspects::RangeLimited, Range_Limited},
2265         });
2266 }
2267 /* ======================================================================
2268    FUNCTION
2269    omx_vdec::ComponentInit
2270 
2271    DESCRIPTION
2272    Initialize the component.
2273 
2274    PARAMETERS
2275    ctxt -- Context information related to the self.
2276    id   -- Event identifier. This could be any of the following:
2277    1. Command completion event
2278    2. Buffer done callback event
2279    3. Frame done callback event
2280 
2281    RETURN VALUE
2282    None.
2283 
2284    ========================================================================== */
component_init(OMX_STRING role)2285 OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role)
2286 {
2287 
2288     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2289     struct v4l2_fmtdesc fdesc;
2290     struct v4l2_format fmt;
2291     struct v4l2_requestbuffers bufreq;
2292     struct v4l2_control control;
2293     struct v4l2_frmsizeenum frmsize;
2294     struct v4l2_queryctrl query;
2295     unsigned int   alignment = 0,buffer_size = 0;
2296     int fds[2];
2297     int r,ret=0;
2298     bool codec_ambiguous = false;
2299     OMX_STRING device_name = (OMX_STRING)"/dev/video32";
2300     char property_value[PROPERTY_VALUE_MAX] = {0};
2301     FILE *soc_file = NULL;
2302     char buffer[10];
2303     struct v4l2_ext_control ctrl[2];
2304     struct v4l2_ext_controls controls;
2305     int conceal_color_8bit = 0, conceal_color_10bit = 0;
2306 
2307 #ifdef _ANDROID_
2308     char platform_name[PROPERTY_VALUE_MAX];
2309     property_get("ro.board.platform", platform_name, "0");
2310     if (!strncmp(platform_name, "msm8610", 7)) {
2311         device_name = (OMX_STRING)"/dev/video/q6_dec";
2312         is_q6_platform = true;
2313         maxSmoothStreamingWidth = 1280;
2314         maxSmoothStreamingHeight = 720;
2315     }
2316 #endif
2317 
2318     if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
2319                 OMX_MAX_STRINGNAME_SIZE)) {
2320         secure_mode = true;
2321         role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
2322     } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
2323                 OMX_MAX_STRINGNAME_SIZE)) {
2324         secure_mode = true;
2325         role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
2326     } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
2327                 OMX_MAX_STRINGNAME_SIZE)) {
2328         secure_mode = true;
2329         role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
2330     } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
2331                 OMX_MAX_STRINGNAME_SIZE)) {
2332         secure_mode = true;
2333         role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
2334     }
2335 
2336     drv_ctx.video_driver_fd = open(device_name, O_RDWR);
2337 
2338     DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
2339 
2340     if (drv_ctx.video_driver_fd < 0) {
2341         DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
2342         return OMX_ErrorInsufficientResources;
2343     }
2344     drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
2345     drv_ctx.frame_rate.fps_denominator = 1;
2346     operating_frame_rate = DEFAULT_FPS;
2347     m_poll_efd = eventfd(0, 0);
2348     if (m_poll_efd < 0) {
2349         DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
2350         return OMX_ErrorInsufficientResources;
2351     }
2352     ret = subscribe_to_events(drv_ctx.video_driver_fd);
2353     if (!ret) {
2354         async_thread_created = true;
2355         ret = pthread_create(&async_thread_id,0,async_message_thread,this);
2356     }
2357     if (ret) {
2358         DEBUG_PRINT_ERROR("Failed to create async_message_thread");
2359         async_thread_created = false;
2360         return OMX_ErrorInsufficientResources;
2361     }
2362 
2363 #ifdef OUTPUT_EXTRADATA_LOG
2364     outputExtradataFile = fopen (output_extradata_filename, "ab");
2365 #endif
2366 
2367     // Copy the role information which provides the decoder kind
2368     strlcpy(drv_ctx.kind,role,128);
2369 
2370 
2371     if (!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\
2372                 OMX_MAX_STRINGNAME_SIZE)) {
2373         strlcpy((char *)m_cRole, "video_decoder.mpeg2",\
2374                 OMX_MAX_STRINGNAME_SIZE);
2375         drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2;
2376         output_capability = V4L2_PIX_FMT_MPEG2;
2377         eCompressionFormat = OMX_VIDEO_CodingMPEG2;
2378         /*Initialize Start Code for MPEG2*/
2379         codec_type_parse = CODEC_TYPE_MPEG2;
2380         m_frame_parser.init_start_codes(codec_type_parse);
2381     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\
2382                 OMX_MAX_STRINGNAME_SIZE)) {
2383         strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
2384         drv_ctx.decoder_format = VDEC_CODECTYPE_H264;
2385         output_capability=V4L2_PIX_FMT_H264;
2386         eCompressionFormat = OMX_VIDEO_CodingAVC;
2387         codec_type_parse = CODEC_TYPE_H264;
2388         m_frame_parser.init_start_codes(codec_type_parse);
2389         m_frame_parser.init_nal_length(nal_length);
2390     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
2391                 OMX_MAX_STRINGNAME_SIZE)) {
2392         strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
2393         drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
2394         output_capability = V4L2_PIX_FMT_H264_MVC;
2395         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
2396         codec_type_parse = CODEC_TYPE_H264;
2397         m_frame_parser.init_start_codes(codec_type_parse);
2398         m_frame_parser.init_nal_length(nal_length);
2399     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
2400                 OMX_MAX_STRINGNAME_SIZE)) {
2401         strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
2402         drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
2403         output_capability = V4L2_PIX_FMT_HEVC;
2404         eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
2405         codec_type_parse = CODEC_TYPE_HEVC;
2406         m_frame_parser.init_start_codes(codec_type_parse);
2407         m_frame_parser.init_nal_length(nal_length);
2408     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",    \
2409                 OMX_MAX_STRINGNAME_SIZE)) {
2410         strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
2411         drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
2412         output_capability = V4L2_PIX_FMT_VP8;
2413         eCompressionFormat = OMX_VIDEO_CodingVP8;
2414         codec_type_parse = CODEC_TYPE_VP8;
2415     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",    \
2416                 OMX_MAX_STRINGNAME_SIZE)) {
2417         strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
2418         drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
2419         output_capability = V4L2_PIX_FMT_VP9;
2420         eCompressionFormat = OMX_VIDEO_CodingVP9;
2421         codec_type_parse = CODEC_TYPE_VP9;
2422     } else {
2423         DEBUG_PRINT_ERROR("ERROR:Unknown Component");
2424         eRet = OMX_ErrorInvalidComponentName;
2425     }
2426 
2427     m_progressive = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
2428 
2429     if (eRet == OMX_ErrorNone) {
2430         OMX_COLOR_FORMATTYPE dest_color_format;
2431         if (m_disable_ubwc_mode) {
2432             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
2433         } else {
2434             drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
2435         }
2436         if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
2437             dest_color_format = (OMX_COLOR_FORMATTYPE)
2438                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
2439         else
2440             dest_color_format = (OMX_COLOR_FORMATTYPE)
2441                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
2442         if (!client_buffers.set_color_format(dest_color_format)) {
2443             DEBUG_PRINT_ERROR("Setting color format failed");
2444             eRet = OMX_ErrorInsufficientResources;
2445         }
2446 
2447         dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
2448         is_flexible_format = FALSE;
2449         is_mbaff = FALSE;
2450 
2451         if (m_disable_ubwc_mode) {
2452             capture_capability = V4L2_PIX_FMT_NV12;
2453         } else {
2454             capture_capability = V4L2_PIX_FMT_NV12_UBWC;
2455         }
2456 
2457         struct v4l2_capability cap;
2458         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
2459         if (ret) {
2460             DEBUG_PRINT_ERROR("Failed to query capabilities");
2461             /*TODO: How to handle this case */
2462         } else {
2463             DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
2464                 " version = %d, capabilities = %x", cap.driver, cap.card,
2465                 cap.bus_info, cap.version, cap.capabilities);
2466         }
2467         ret=0;
2468         fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2469         fdesc.index=0;
2470         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2471             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2472                     fdesc.pixelformat, fdesc.flags);
2473             fdesc.index++;
2474         }
2475         fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2476         fdesc.index=0;
2477         while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
2478 
2479             DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
2480                     fdesc.pixelformat, fdesc.flags);
2481             fdesc.index++;
2482         }
2483         m_extradata_info.output_crop_rect.nLeft = 0;
2484         m_extradata_info.output_crop_rect.nTop = 0;
2485         m_extradata_info.output_crop_rect.nWidth = 320;
2486         m_extradata_info.output_crop_rect.nHeight = 240;
2487         update_resolution(320, 240, 320, 240);
2488 
2489         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2490         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2491         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2492         fmt.fmt.pix_mp.pixelformat = output_capability;
2493         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2494         if (ret) {
2495             /*TODO: How to handle this case */
2496             DEBUG_PRINT_ERROR("Failed to set format on output port");
2497             return OMX_ErrorInsufficientResources;
2498         }
2499         DEBUG_PRINT_HIGH("Set Format was successful");
2500 
2501         /*
2502          * refer macro DEFAULT_CONCEAL_COLOR to set conceal color values
2503          */
2504         Platform::Config::getInt32(Platform::vidc_dec_conceal_color_8bit, &conceal_color_8bit, DEFAULT_VIDEO_CONCEAL_COLOR_BLACK);
2505         Platform::Config::getInt32(Platform::vidc_dec_conceal_color_10bit, &conceal_color_10bit, DEFAULT_VIDEO_CONCEAL_COLOR_BLACK);
2506         memset(&controls, 0, sizeof(controls));
2507         memset(ctrl, 0, sizeof(ctrl));
2508         ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_8BIT;
2509         ctrl[0].value = conceal_color_8bit;
2510         ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR_10BIT;
2511         ctrl[1].value = conceal_color_10bit;
2512 
2513         controls.count = 2;
2514         controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
2515         controls.controls = ctrl;
2516         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
2517         if (ret) {
2518             DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
2519         }
2520 
2521         //Get the hardware capabilities
2522         memset((void *)&frmsize,0,sizeof(frmsize));
2523         frmsize.index = 0;
2524         frmsize.pixel_format = output_capability;
2525         ret = ioctl(drv_ctx.video_driver_fd,
2526                 VIDIOC_ENUM_FRAMESIZES, &frmsize);
2527         if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
2528             DEBUG_PRINT_ERROR("Failed to get framesizes");
2529             return OMX_ErrorHardware;
2530         }
2531 
2532         if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
2533             m_decoder_capability.min_width = frmsize.stepwise.min_width;
2534             m_decoder_capability.max_width = frmsize.stepwise.max_width;
2535             m_decoder_capability.min_height = frmsize.stepwise.min_height;
2536             m_decoder_capability.max_height = frmsize.stepwise.max_height;
2537         }
2538 
2539         /* Based on UBWC enable, decide split mode to driver before calling S_FMT */
2540         eRet = set_dpb(m_disable_ubwc_mode);
2541 
2542         memset(&fmt, 0x0, sizeof(struct v4l2_format));
2543         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2544         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
2545         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
2546         fmt.fmt.pix_mp.pixelformat = capture_capability;
2547         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
2548         if (ret) {
2549             /*TODO: How to handle this case */
2550             DEBUG_PRINT_ERROR("Failed to set format on capture port");
2551         }
2552         memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
2553         framesize.nWidth = drv_ctx.video_resolution.frame_width;
2554         framesize.nHeight = drv_ctx.video_resolution.frame_height;
2555 
2556         memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
2557         rectangle.nWidth = drv_ctx.video_resolution.frame_width;
2558         rectangle.nHeight = drv_ctx.video_resolution.frame_height;
2559 
2560         DEBUG_PRINT_HIGH("Set Format was successful");
2561         if (secure_mode) {
2562             control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
2563             control.value = 1;
2564             DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
2565             ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
2566             if (ret) {
2567                 DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
2568                 return OMX_ErrorInsufficientResources;
2569             }
2570         }
2571 
2572         /*Get the Buffer requirements for input and output ports*/
2573         drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT;
2574         drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
2575 
2576         if (secure_mode) {
2577             drv_ctx.op_buf.alignment = SECURE_ALIGN;
2578             drv_ctx.ip_buf.alignment = SECURE_ALIGN;
2579         } else {
2580             drv_ctx.op_buf.alignment = SZ_4K;
2581             drv_ctx.ip_buf.alignment = SZ_4K;
2582         }
2583 
2584         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
2585         drv_ctx.extradata = 0;
2586         drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
2587         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
2588         control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
2589         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
2590         drv_ctx.idr_only_decoding = 0;
2591 
2592 #ifdef _ANDROID_
2593         if (m_dec_hfr_fps) {
2594             memset(&query, 0, sizeof(struct v4l2_queryctrl));
2595 
2596             query.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE;
2597             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCTRL, &query);
2598             if (!ret)
2599                 m_dec_hfr_fps = MIN(query.maximum, m_dec_hfr_fps);
2600 
2601             DEBUG_PRINT_HIGH("Updated HFR fps value = %d", m_dec_hfr_fps);
2602         }
2603 
2604 #endif
2605         m_state = OMX_StateLoaded;
2606 
2607         unsigned long long extradata_mask = DEFAULT_EXTRADATA;
2608         if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc) {
2609             extradata_mask |= OMX_HDR_COLOR_INFO_EXTRADATA | OMX_EXTNUSER_EXTRADATA;
2610         }
2611         enable_extradata(extradata_mask, true, true);
2612 
2613         eRet = get_buffer_req(&drv_ctx.ip_buf);
2614         DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
2615         get_buffer_req(&drv_ctx.op_buf);
2616         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2617                 drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC ||
2618                 drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2619                     h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size;
2620                     h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size);
2621                     h264_scratch.nFilledLen = 0;
2622                     h264_scratch.nOffset = 0;
2623 
2624                     if (h264_scratch.pBuffer == NULL) {
2625                         DEBUG_PRINT_ERROR("h264_scratch.pBuffer Allocation failed ");
2626                         return OMX_ErrorInsufficientResources;
2627                     }
2628         }
2629         if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
2630             drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
2631             if (m_frame_parser.mutils == NULL) {
2632                 m_frame_parser.mutils = new H264_Utils();
2633                 if (m_frame_parser.mutils == NULL) {
2634                     DEBUG_PRINT_ERROR("parser utils Allocation failed ");
2635                     eRet = OMX_ErrorInsufficientResources;
2636                 } else {
2637                     m_frame_parser.mutils->initialize_frame_checking_environment();
2638                     m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size);
2639                 }
2640             }
2641 
2642             h264_parser = new h264_stream_parser();
2643             if (!h264_parser) {
2644                 DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!");
2645                 eRet = OMX_ErrorInsufficientResources;
2646             }
2647         }
2648         msg_thread_created = true;
2649         r = pthread_create(&msg_thread_id,0,message_thread_dec,this);
2650 
2651         if (r < 0) {
2652             DEBUG_PRINT_ERROR("component_init(): message_thread_dec creation failed");
2653             msg_thread_created = false;
2654             eRet = OMX_ErrorInsufficientResources;
2655         } else if (secure_mode) {
2656             this->post_event(PREFETCH_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_output, OMX_COMPONENT_GENERATE_ION_PREFETCH_PIXEL);
2657             this->post_event(PREFETCH_NON_PIXEL_BUFFER_COUNT, m_dec_secure_prefetch_size_internal, OMX_COMPONENT_GENERATE_ION_PREFETCH_NON_PIXEL);
2658         }
2659     }
2660 
2661     {
2662         VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore);
2663         init_vendor_extensions(*extStore);
2664         mVendorExtensionStore.dumpExtensions((const char *)role);
2665     }
2666 
2667     if (eRet != OMX_ErrorNone) {
2668         DEBUG_PRINT_ERROR("Component Init Failed");
2669     } else {
2670         DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
2671                 drv_ctx.video_driver_fd);
2672     }
2673     //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
2674 
2675     OMX_INIT_STRUCT(&m_sParamLowLatency, QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE);
2676     m_sParamLowLatency.nNumFrames = 0;
2677     m_sParamLowLatency.bEnableLowLatencyMode = OMX_FALSE;
2678 
2679     return eRet;
2680 }
2681 
2682 /* ======================================================================
2683    FUNCTION
2684    omx_vdec::GetComponentVersion
2685 
2686    DESCRIPTION
2687    Returns the component version.
2688 
2689    PARAMETERS
2690    TBD.
2691 
2692    RETURN VALUE
2693    OMX_ErrorNone.
2694 
2695    ========================================================================== */
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)2696 OMX_ERRORTYPE  omx_vdec::get_component_version
2697 (
2698  OMX_IN OMX_HANDLETYPE hComp,
2699  OMX_OUT OMX_STRING componentName,
2700  OMX_OUT OMX_VERSIONTYPE* componentVersion,
2701  OMX_OUT OMX_VERSIONTYPE* specVersion,
2702  OMX_OUT OMX_UUIDTYPE* componentUUID
2703  )
2704 {
2705     (void) hComp;
2706     (void) componentName;
2707     (void) componentVersion;
2708     (void) componentUUID;
2709     if (m_state == OMX_StateInvalid) {
2710         DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
2711         return OMX_ErrorInvalidState;
2712     }
2713     /* TBD -- Return the proper version */
2714     if (specVersion) {
2715         specVersion->nVersion = OMX_SPEC_VERSION;
2716     }
2717     return OMX_ErrorNone;
2718 }
2719 /* ======================================================================
2720    FUNCTION
2721    omx_vdec::SendCommand
2722 
2723    DESCRIPTION
2724    Returns zero if all the buffers released..
2725 
2726    PARAMETERS
2727    None.
2728 
2729    RETURN VALUE
2730    true/false
2731 
2732    ========================================================================== */
send_command(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2733 OMX_ERRORTYPE  omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp,
2734         OMX_IN OMX_COMMANDTYPE cmd,
2735         OMX_IN OMX_U32 param1,
2736         OMX_IN OMX_PTR cmdData
2737         )
2738 {
2739     (void) hComp;
2740     (void) cmdData;
2741     DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
2742     if (m_state == OMX_StateInvalid) {
2743         DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
2744         return OMX_ErrorInvalidState;
2745     }
2746     if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX
2747             && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) {
2748         DEBUG_PRINT_ERROR("send_command(): ERROR OMX_CommandFlush "
2749                 "to invalid port: %u", (unsigned int)param1);
2750         return OMX_ErrorBadPortIndex;
2751     }
2752 
2753     post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
2754     sem_wait(&m_cmd_lock);
2755     DEBUG_PRINT_LOW("send_command: Command Processed");
2756     return OMX_ErrorNone;
2757 }
2758 
2759 /* ======================================================================
2760    FUNCTION
2761    omx_vdec::SendCommand
2762 
2763    DESCRIPTION
2764    Returns zero if all the buffers released..
2765 
2766    PARAMETERS
2767    None.
2768 
2769    RETURN VALUE
2770    true/false
2771 
2772    ========================================================================== */
send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_COMMANDTYPE cmd,OMX_IN OMX_U32 param1,OMX_IN OMX_PTR cmdData)2773 OMX_ERRORTYPE  omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
2774         OMX_IN OMX_COMMANDTYPE cmd,
2775         OMX_IN OMX_U32 param1,
2776         OMX_IN OMX_PTR cmdData
2777         )
2778 {
2779     (void) hComp;
2780     (void) cmdData;
2781     OMX_ERRORTYPE eRet = OMX_ErrorNone;
2782     OMX_STATETYPE eState = (OMX_STATETYPE) param1;
2783     int bFlag = 1,sem_posted = 0,ret=0;
2784 
2785     DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
2786     DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
2787             m_state, eState);
2788 
2789     if (cmd == OMX_CommandStateSet) {
2790         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
2791         DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState);
2792         /***************************/
2793         /* Current State is Loaded */
2794         /***************************/
2795         if (m_state == OMX_StateLoaded) {
2796             if (eState == OMX_StateIdle) {
2797                 //if all buffers are allocated or all ports disabled
2798                 if (allocate_done() ||
2799                         (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) {
2800                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle");
2801                 } else {
2802                     DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
2803                     BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
2804                     // Skip the event notification
2805                     bFlag = 0;
2806                 }
2807             }
2808             /* Requesting transition from Loaded to Loaded */
2809             else if (eState == OMX_StateLoaded) {
2810                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded");
2811                 post_event(OMX_EventError,OMX_ErrorSameState,\
2812                         OMX_COMPONENT_GENERATE_EVENT);
2813                 eRet = OMX_ErrorSameState;
2814             }
2815             /* Requesting transition from Loaded to WaitForResources */
2816             else if (eState == OMX_StateWaitForResources) {
2817                 /* Since error is None , we will post an event
2818                    at the end of this function definition */
2819                 DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources");
2820             }
2821             /* Requesting transition from Loaded to Executing */
2822             else if (eState == OMX_StateExecuting) {
2823                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
2824                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2825                         OMX_COMPONENT_GENERATE_EVENT);
2826                 eRet = OMX_ErrorIncorrectStateTransition;
2827             }
2828             /* Requesting transition from Loaded to Pause */
2829             else if (eState == OMX_StatePause) {
2830                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause");
2831                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2832                         OMX_COMPONENT_GENERATE_EVENT);
2833                 eRet = OMX_ErrorIncorrectStateTransition;
2834             }
2835             /* Requesting transition from Loaded to Invalid */
2836             else if (eState == OMX_StateInvalid) {
2837                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid");
2838                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2839                 eRet = OMX_ErrorInvalidState;
2840             } else {
2841                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)",\
2842                         eState);
2843                 eRet = OMX_ErrorBadParameter;
2844             }
2845         }
2846 
2847         /***************************/
2848         /* Current State is IDLE */
2849         /***************************/
2850         else if (m_state == OMX_StateIdle) {
2851             if (eState == OMX_StateLoaded) {
2852                 if (release_done()) {
2853                     /*
2854                      * Since error is None , we will post an event at the end
2855                      * of this function definition
2856                      * Reset buffer requirements here to ensure setting buffer requirement
2857                      * when component move to executing state from loaded state via Idle.
2858                      */
2859                     drv_ctx.op_buf.buffer_size = 0;
2860                     drv_ctx.op_buf.actualcount = 0;
2861                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
2862                 } else {
2863                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
2864                     BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
2865                     // Skip the event notification
2866                     bFlag = 0;
2867                 }
2868             }
2869             /* Requesting transition from Idle to Executing */
2870             else if (eState == OMX_StateExecuting) {
2871                 bFlag = 1;
2872                 DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
2873                 m_state=OMX_StateExecuting;
2874             }
2875             /* Requesting transition from Idle to Idle */
2876             else if (eState == OMX_StateIdle) {
2877                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
2878                 post_event(OMX_EventError,OMX_ErrorSameState,\
2879                         OMX_COMPONENT_GENERATE_EVENT);
2880                 eRet = OMX_ErrorSameState;
2881             }
2882             /* Requesting transition from Idle to WaitForResources */
2883             else if (eState == OMX_StateWaitForResources) {
2884                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources");
2885                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2886                         OMX_COMPONENT_GENERATE_EVENT);
2887                 eRet = OMX_ErrorIncorrectStateTransition;
2888             }
2889             /* Requesting transition from Idle to Pause */
2890             else if (eState == OMX_StatePause) {
2891                 /*To pause the Video core we need to start the driver*/
2892                 if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START,
2893                       NULL) < */0) {
2894                     DEBUG_PRINT_ERROR("VDEC_IOCTL_CMD_START FAILED");
2895                     omx_report_error ();
2896                     eRet = OMX_ErrorHardware;
2897                 } else {
2898                     BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
2899                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause");
2900                     bFlag = 0;
2901                 }
2902             }
2903             /* Requesting transition from Idle to Invalid */
2904             else if (eState == OMX_StateInvalid) {
2905                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
2906                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2907                 eRet = OMX_ErrorInvalidState;
2908             } else {
2909                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
2910                 eRet = OMX_ErrorBadParameter;
2911             }
2912         }
2913 
2914         /******************************/
2915         /* Current State is Executing */
2916         /******************************/
2917         else if (m_state == OMX_StateExecuting) {
2918             DEBUG_PRINT_LOW("Command Recieved in OMX_StateExecuting");
2919             /* Requesting transition from Executing to Idle */
2920             if (eState == OMX_StateIdle) {
2921                 /* Since error is None , we will post an event
2922                    at the end of this function definition
2923                  */
2924                 DEBUG_PRINT_LOW("send_command_proxy(): Executing --> Idle");
2925                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2926                 if (!sem_posted) {
2927                     sem_posted = 1;
2928                     sem_post (&m_cmd_lock);
2929                     execute_omx_flush(OMX_ALL);
2930                 }
2931                 bFlag = 0;
2932             }
2933             /* Requesting transition from Executing to Paused */
2934             else if (eState == OMX_StatePause) {
2935                 DEBUG_PRINT_LOW("PAUSE Command Issued");
2936                 m_state = OMX_StatePause;
2937                 bFlag = 1;
2938             }
2939             /* Requesting transition from Executing to Loaded */
2940             else if (eState == OMX_StateLoaded) {
2941                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
2942                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2943                         OMX_COMPONENT_GENERATE_EVENT);
2944                 eRet = OMX_ErrorIncorrectStateTransition;
2945             }
2946             /* Requesting transition from Executing to WaitForResources */
2947             else if (eState == OMX_StateWaitForResources) {
2948                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> WaitForResources");
2949                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2950                         OMX_COMPONENT_GENERATE_EVENT);
2951                 eRet = OMX_ErrorIncorrectStateTransition;
2952             }
2953             /* Requesting transition from Executing to Executing */
2954             else if (eState == OMX_StateExecuting) {
2955                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Executing");
2956                 post_event(OMX_EventError,OMX_ErrorSameState,\
2957                         OMX_COMPONENT_GENERATE_EVENT);
2958                 eRet = OMX_ErrorSameState;
2959             }
2960             /* Requesting transition from Executing to Invalid */
2961             else if (eState == OMX_StateInvalid) {
2962                 DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Invalid");
2963                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
2964                 eRet = OMX_ErrorInvalidState;
2965             } else {
2966                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",eState);
2967                 eRet = OMX_ErrorBadParameter;
2968             }
2969         }
2970         /***************************/
2971         /* Current State is Pause  */
2972         /***************************/
2973         else if (m_state == OMX_StatePause) {
2974             /* Requesting transition from Pause to Executing */
2975             if (eState == OMX_StateExecuting) {
2976                 DEBUG_PRINT_LOW("Pause --> Executing");
2977                 m_state = OMX_StateExecuting;
2978                 bFlag = 1;
2979             }
2980             /* Requesting transition from Pause to Idle */
2981             else if (eState == OMX_StateIdle) {
2982                 /* Since error is None , we will post an event
2983                    at the end of this function definition */
2984                 DEBUG_PRINT_LOW("Pause --> Idle");
2985                 BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
2986                 if (!sem_posted) {
2987                     sem_posted = 1;
2988                     sem_post (&m_cmd_lock);
2989                     execute_omx_flush(OMX_ALL);
2990                 }
2991                 bFlag = 0;
2992             }
2993             /* Requesting transition from Pause to loaded */
2994             else if (eState == OMX_StateLoaded) {
2995                 DEBUG_PRINT_ERROR("Pause --> loaded");
2996                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
2997                         OMX_COMPONENT_GENERATE_EVENT);
2998                 eRet = OMX_ErrorIncorrectStateTransition;
2999             }
3000             /* Requesting transition from Pause to WaitForResources */
3001             else if (eState == OMX_StateWaitForResources) {
3002                 DEBUG_PRINT_ERROR("Pause --> WaitForResources");
3003                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3004                         OMX_COMPONENT_GENERATE_EVENT);
3005                 eRet = OMX_ErrorIncorrectStateTransition;
3006             }
3007             /* Requesting transition from Pause to Pause */
3008             else if (eState == OMX_StatePause) {
3009                 DEBUG_PRINT_ERROR("Pause --> Pause");
3010                 post_event(OMX_EventError,OMX_ErrorSameState,\
3011                         OMX_COMPONENT_GENERATE_EVENT);
3012                 eRet = OMX_ErrorSameState;
3013             }
3014             /* Requesting transition from Pause to Invalid */
3015             else if (eState == OMX_StateInvalid) {
3016                 DEBUG_PRINT_ERROR("Pause --> Invalid");
3017                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3018                 eRet = OMX_ErrorInvalidState;
3019             } else {
3020                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",eState);
3021                 eRet = OMX_ErrorBadParameter;
3022             }
3023         }
3024         /***************************/
3025         /* Current State is WaitForResources  */
3026         /***************************/
3027         else if (m_state == OMX_StateWaitForResources) {
3028             /* Requesting transition from WaitForResources to Loaded */
3029             if (eState == OMX_StateLoaded) {
3030                 /* Since error is None , we will post an event
3031                    at the end of this function definition */
3032                 DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded");
3033             }
3034             /* Requesting transition from WaitForResources to WaitForResources */
3035             else if (eState == OMX_StateWaitForResources) {
3036                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
3037                 post_event(OMX_EventError,OMX_ErrorSameState,
3038                         OMX_COMPONENT_GENERATE_EVENT);
3039                 eRet = OMX_ErrorSameState;
3040             }
3041             /* Requesting transition from WaitForResources to Executing */
3042             else if (eState == OMX_StateExecuting) {
3043                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing");
3044                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3045                         OMX_COMPONENT_GENERATE_EVENT);
3046                 eRet = OMX_ErrorIncorrectStateTransition;
3047             }
3048             /* Requesting transition from WaitForResources to Pause */
3049             else if (eState == OMX_StatePause) {
3050                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause");
3051                 post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
3052                         OMX_COMPONENT_GENERATE_EVENT);
3053                 eRet = OMX_ErrorIncorrectStateTransition;
3054             }
3055             /* Requesting transition from WaitForResources to Invalid */
3056             else if (eState == OMX_StateInvalid) {
3057                 DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid");
3058                 post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
3059                 eRet = OMX_ErrorInvalidState;
3060             }
3061             /* Requesting transition from WaitForResources to Loaded -
3062                is NOT tested by Khronos TS */
3063 
3064         } else {
3065             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)",m_state,eState);
3066             eRet = OMX_ErrorBadParameter;
3067         }
3068     }
3069     /********************************/
3070     /* Current State is Invalid */
3071     /*******************************/
3072     else if (m_state == OMX_StateInvalid) {
3073         /* State Transition from Inavlid to any state */
3074         if ((eState ==  OMX_StateLoaded) ||
3075             (eState == OMX_StateWaitForResources) ||
3076             (eState == OMX_StateIdle) ||
3077             (eState == OMX_StateExecuting) ||
3078             (eState == OMX_StatePause) ||
3079             (eState == OMX_StateInvalid)
3080         ) {
3081             DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded");
3082             post_event(OMX_EventError,OMX_ErrorInvalidState,\
3083                     OMX_COMPONENT_GENERATE_EVENT);
3084             eRet = OMX_ErrorInvalidState;
3085         }
3086     } else if (cmd == OMX_CommandFlush) {
3087         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
3088                 "with param1: %u", (unsigned int)param1);
3089         send_codec_config();
3090         if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
3091                     param1 == OMX_ALL)) {
3092             if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
3093                struct timespec ts;
3094 
3095                clock_gettime(CLOCK_REALTIME, &ts);
3096                ts.tv_sec += 2;
3097                DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
3098                        m_queued_codec_config_count);
3099                BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
3100                if (sem_timedwait(&m_safe_flush, &ts)) {
3101                    DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
3102                }
3103                BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
3104             }
3105         }
3106 
3107         if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3108             BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
3109         }
3110         if (OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) {
3111             BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3112         }
3113         if (!sem_posted) {
3114             sem_posted = 1;
3115             DEBUG_PRINT_LOW("Set the Semaphore");
3116             sem_post (&m_cmd_lock);
3117             execute_omx_flush(param1);
3118         }
3119         bFlag = 0;
3120     } else if ( cmd == OMX_CommandPortEnable) {
3121         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
3122                 "with param1: %u", (unsigned int)param1);
3123         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3124             m_inp_bEnabled = OMX_TRUE;
3125 
3126             if ( (m_state == OMX_StateLoaded &&
3127                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3128                     || allocate_input_done()) {
3129                 post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX,
3130                         OMX_COMPONENT_GENERATE_EVENT);
3131             } else {
3132                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3133                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
3134                 // Skip the event notification
3135                 bFlag = 0;
3136             }
3137         }
3138         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3139             DEBUG_PRINT_LOW("Enable output Port command recieved");
3140             m_out_bEnabled = OMX_TRUE;
3141 
3142             if ( (m_state == OMX_StateLoaded &&
3143                         !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
3144                     || (allocate_output_done())) {
3145                 post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX,
3146                         OMX_COMPONENT_GENERATE_EVENT);
3147 
3148             } else {
3149                 DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending");
3150                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
3151                 // Skip the event notification
3152                 bFlag = 0;
3153                 /* enable/disable downscaling if required */
3154                 ret = decide_downscalar();
3155                 if (ret) {
3156                     DEBUG_PRINT_LOW("decide_downscalar failed\n");
3157                 }
3158             }
3159         }
3160     } else if (cmd == OMX_CommandPortDisable) {
3161         DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
3162                 "with param1: %u", (unsigned int)param1);
3163         if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
3164             codec_config_flag = false;
3165             m_inp_bEnabled = OMX_FALSE;
3166             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3167                     && release_input_done()) {
3168                 post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX,
3169                         OMX_COMPONENT_GENERATE_EVENT);
3170             } else {
3171                 DEBUG_PRINT_HIGH("Set input port disable pending");
3172                 BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING);
3173                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3174                     if (!sem_posted) {
3175                         sem_posted = 1;
3176                         sem_post (&m_cmd_lock);
3177                     }
3178                     execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX);
3179                 }
3180 
3181                 // Skip the event notification
3182                 bFlag = 0;
3183             }
3184         }
3185         if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
3186             m_out_bEnabled = OMX_FALSE;
3187             DEBUG_PRINT_LOW("Disable output Port command recieved");
3188             if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
3189                     && release_output_done()) {
3190                 post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\
3191                         OMX_COMPONENT_GENERATE_EVENT);
3192             } else {
3193                 DEBUG_PRINT_HIGH("Set output port disable pending");
3194                 BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
3195                 if (m_state == OMX_StatePause ||m_state == OMX_StateExecuting) {
3196                     if (!sem_posted) {
3197                         sem_posted = 1;
3198                         sem_post (&m_cmd_lock);
3199                     }
3200                     DEBUG_PRINT_HIGH("Set output port flush in disable pending");
3201                     BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING);
3202                     execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX);
3203                 }
3204                 // Skip the event notification
3205                 bFlag = 0;
3206 
3207             }
3208         }
3209     } else {
3210         DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)",cmd);
3211         eRet = OMX_ErrorNotImplemented;
3212     }
3213     if (eRet == OMX_ErrorNone && bFlag) {
3214         post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
3215     }
3216     if (!sem_posted) {
3217         sem_post(&m_cmd_lock);
3218     }
3219 
3220     return eRet;
3221 }
3222 
3223 /* ======================================================================
3224    FUNCTION
3225    omx_vdec::ExecuteOmxFlush
3226 
3227    DESCRIPTION
3228    Executes the OMX flush.
3229 
3230    PARAMETERS
3231    flushtype - input flush(1)/output flush(0)/ both.
3232 
3233    RETURN VALUE
3234    true/false
3235 
3236    ========================================================================== */
execute_omx_flush(OMX_U32 flushType)3237 bool omx_vdec::execute_omx_flush(OMX_U32 flushType)
3238 {
3239     bool bRet = false;
3240     struct v4l2_plane plane;
3241     struct v4l2_buffer v4l2_buf;
3242     struct v4l2_decoder_cmd dec;
3243     DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
3244     memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
3245     dec.cmd = V4L2_QCOM_CMD_FLUSH;
3246 
3247     DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
3248 
3249     if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
3250         output_flush_progress = true;
3251         dec.flags = V4L2_QCOM_CMD_FLUSH_CAPTURE;
3252     } else {
3253         /* XXX: The driver/hardware does not support flushing of individual ports
3254          * in all states. So we pretty much need to flush both ports internally,
3255          * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
3256          * requested.  Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
3257          * we automatically omit sending the FLUSH done for the "opposite" port. */
3258         input_flush_progress = true;
3259         output_flush_progress = true;
3260         dec.flags = V4L2_QCOM_CMD_FLUSH_OUTPUT | V4L2_QCOM_CMD_FLUSH_CAPTURE;
3261     }
3262 
3263     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
3264         DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
3265         bRet = false;
3266     }
3267 
3268     return bRet;
3269 }
3270 /*=========================================================================
3271 FUNCTION : execute_output_flush
3272 
3273 DESCRIPTION
3274 Executes the OMX flush at OUTPUT PORT.
3275 
3276 PARAMETERS
3277 None.
3278 
3279 RETURN VALUE
3280 true/false
3281 ==========================================================================*/
execute_output_flush()3282 bool omx_vdec::execute_output_flush()
3283 {
3284     unsigned long p1 = 0; // Parameter - 1
3285     unsigned long p2 = 0; // Parameter - 2
3286     unsigned long ident = 0;
3287     bool bRet = true;
3288 
3289     /*Generate FBD for all Buffers in the FTBq*/
3290     pthread_mutex_lock(&m_lock);
3291     DEBUG_PRINT_LOW("Initiate Output Flush");
3292 
3293     //reset last render TS
3294     if(m_last_rendered_TS > 0) {
3295         m_last_rendered_TS = 0;
3296     }
3297 
3298     while (m_ftb_q.m_size) {
3299         m_ftb_q.pop_entry(&p1,&p2,&ident);
3300         if (ident == m_fill_output_msg ) {
3301             print_omx_buffer("Flush FBD", (OMX_BUFFERHEADERTYPE *)p2);
3302             m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
3303         } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
3304             fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
3305         }
3306     }
3307     pthread_mutex_unlock(&m_lock);
3308     output_flush_progress = false;
3309 
3310     if (arbitrary_bytes) {
3311         prev_ts = LLONG_MAX;
3312         rst_prev_ts = true;
3313     }
3314     DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers);
3315     return bRet;
3316 }
3317 /*=========================================================================
3318 FUNCTION : execute_input_flush
3319 
3320 DESCRIPTION
3321 Executes the OMX flush at INPUT PORT.
3322 
3323 PARAMETERS
3324 None.
3325 
3326 RETURN VALUE
3327 true/false
3328 ==========================================================================*/
execute_input_flush()3329 bool omx_vdec::execute_input_flush()
3330 {
3331     unsigned       i =0;
3332     unsigned long p1 = 0; // Parameter - 1
3333     unsigned long p2 = 0; // Parameter - 2
3334     unsigned long ident = 0;
3335     bool bRet = true;
3336 
3337     /*Generate EBD for all Buffers in the ETBq*/
3338     DEBUG_PRINT_LOW("Initiate Input Flush");
3339 
3340     pthread_mutex_lock(&m_lock);
3341     DEBUG_PRINT_LOW("Check if the Queue is empty");
3342     while (m_etb_q.m_size) {
3343         m_etb_q.pop_entry(&p1,&p2,&ident);
3344 
3345         if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
3346             print_omx_buffer("Flush ETB_ARBITRARY", (OMX_BUFFERHEADERTYPE *)p2);
3347             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
3348         } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
3349             pending_input_buffers++;
3350             VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
3351             print_omx_buffer("Flush ETB", (OMX_BUFFERHEADERTYPE *)p2);
3352             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
3353         } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
3354             print_omx_buffer("Flush EBD", (OMX_BUFFERHEADERTYPE *)p1);
3355             empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
3356         }
3357     }
3358     time_stamp_dts.flush_timestamp();
3359     /*Check if Heap Buffers are to be flushed*/
3360     if (arbitrary_bytes && !(codec_config_flag)) {
3361         DEBUG_PRINT_LOW("Reset all the variables before flusing");
3362         h264_scratch.nFilledLen = 0;
3363         nal_count = 0;
3364         look_ahead_nal = false;
3365         frame_count = 0;
3366         h264_last_au_ts = LLONG_MAX;
3367         h264_last_au_flags = 0;
3368         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
3369         m_demux_entries = 0;
3370         DEBUG_PRINT_LOW("Initialize parser");
3371         if (m_frame_parser.mutils) {
3372             m_frame_parser.mutils->initialize_frame_checking_environment();
3373         }
3374 
3375         while (m_input_pending_q.m_size) {
3376             m_input_pending_q.pop_entry(&p1,&p2,&ident);
3377             m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1);
3378         }
3379 
3380         if (psource_frame) {
3381             m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame);
3382             psource_frame = NULL;
3383         }
3384 
3385         if (pdest_frame) {
3386             pdest_frame->nFilledLen = 0;
3387             m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned int)NULL,
3388                     (unsigned int)NULL);
3389             pdest_frame = NULL;
3390         }
3391         m_frame_parser.flush();
3392     } else if (codec_config_flag) {
3393         DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer "
3394                 "is not sent to the driver yet");
3395     }
3396     pthread_mutex_unlock(&m_lock);
3397     input_flush_progress = false;
3398     if (!arbitrary_bytes) {
3399         prev_ts = LLONG_MAX;
3400         rst_prev_ts = true;
3401     }
3402 
3403     DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers);
3404     return bRet;
3405 }
3406 
3407 /*=========================================================================
3408 FUNCTION : notify_flush_done
3409 
3410 DESCRIPTION
3411 Notifies flush done to the OMX Client.
3412 
3413 PARAMETERS
3414 ctxt -- Context information related to the self..
3415 
3416 RETURN VALUE
3417 NONE
3418 ==========================================================================*/
notify_flush_done(void * ctxt)3419 void omx_vdec::notify_flush_done(void *ctxt) {
3420 
3421     omx_vdec *pThis = (omx_vdec *) ctxt;
3422 
3423     if (!pThis->input_flush_progress && !pThis->output_flush_progress) {
3424         if (BITMASK_PRESENT(&pThis->m_flags,
3425                 OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
3426             DEBUG_PRINT_LOW("Notify Output Flush done");
3427             BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
3428             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3429                 OMX_EventCmdComplete,OMX_CommandFlush,
3430                 OMX_CORE_OUTPUT_PORT_INDEX,NULL );
3431         }
3432 
3433         if (BITMASK_PRESENT(&pThis->m_flags,
3434                 OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
3435             BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
3436             DEBUG_PRINT_LOW("Input Flush completed - Notify Client");
3437             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
3438                     OMX_EventCmdComplete,OMX_CommandFlush,
3439                     OMX_CORE_INPUT_PORT_INDEX,NULL );
3440         }
3441     }
3442 }
3443 
3444 /* ======================================================================
3445    FUNCTION
3446    omx_vdec::SendCommandEvent
3447 
3448    DESCRIPTION
3449    Send the event to decoder pipe.  This is needed to generate the callbacks
3450    in decoder thread context.
3451 
3452    PARAMETERS
3453    None.
3454 
3455    RETURN VALUE
3456    true/false
3457 
3458    ========================================================================== */
post_event(unsigned long p1,unsigned long p2,unsigned long id)3459 bool omx_vdec::post_event(unsigned long p1,
3460         unsigned long p2,
3461         unsigned long id)
3462 {
3463     bool bRet = false;
3464 
3465     /* Just drop messages typically generated by hardware (w/o client request),
3466      * if we've reported an error to client. */
3467     if (m_error_propogated) {
3468         switch (id) {
3469             case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
3470             case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
3471                 DEBUG_PRINT_ERROR("Dropping message %lx "
3472                         "since client expected to be in error state", id);
3473                 return false;
3474             default:
3475                 /* whatever */
3476                 break;
3477         }
3478     }
3479 
3480     pthread_mutex_lock(&m_lock);
3481 
3482     if (id == m_fill_output_msg ||
3483             id == OMX_COMPONENT_GENERATE_FBD ||
3484             id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
3485             id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
3486         m_ftb_q.insert_entry(p1,p2,id);
3487     } else if (id == OMX_COMPONENT_GENERATE_ETB ||
3488             id == OMX_COMPONENT_GENERATE_EBD ||
3489             id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY ||
3490             id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
3491         m_etb_q.insert_entry(p1,p2,id);
3492     } else {
3493         DEBUG_PRINT_HIGH("post_event(%ld, %ld, %ld)", p1, p2, id);
3494         m_cmd_q.insert_entry(p1,p2,id);
3495     }
3496 
3497     bRet = true;
3498     post_message(this, id);
3499 
3500     pthread_mutex_unlock(&m_lock);
3501 
3502     return bRet;
3503 }
3504 
vdec_query_cap(struct v4l2_queryctrl & cap)3505 bool inline omx_vdec::vdec_query_cap(struct v4l2_queryctrl &cap) {
3506 
3507     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCTRL, &cap)) {
3508         DEBUG_PRINT_ERROR("Query caps for id = %u failed\n", cap.id);
3509         return false;
3510     }
3511     return true;
3512 }
3513 
get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE * profileLevelType)3514 OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType)
3515 {
3516     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3517     struct v4l2_queryctrl profile_cap, level_cap;
3518     int v4l2_profile;
3519     int avc_profiles[5] = { QOMX_VIDEO_AVCProfileConstrainedBaseline,
3520                             QOMX_VIDEO_AVCProfileBaseline,
3521                             QOMX_VIDEO_AVCProfileMain,
3522                             QOMX_VIDEO_AVCProfileConstrainedHigh,
3523                             QOMX_VIDEO_AVCProfileHigh };
3524     int hevc_profiles[3] = { OMX_VIDEO_HEVCProfileMain,
3525                              OMX_VIDEO_HEVCProfileMain10,
3526                              OMX_VIDEO_HEVCProfileMain10HDR10 };
3527     int mpeg2_profiles[2] = { OMX_VIDEO_MPEG2ProfileSimple,
3528                               OMX_VIDEO_MPEG2ProfileMain};
3529     int vp9_profiles[3] = { OMX_VIDEO_VP9Profile0,
3530                             OMX_VIDEO_VP9Profile2,
3531                             OMX_VIDEO_VP9Profile2HDR};
3532 
3533     if (!profileLevelType)
3534         return OMX_ErrorBadParameter;
3535 
3536     memset(&level_cap, 0, sizeof(struct v4l2_queryctrl));
3537     memset(&profile_cap, 0, sizeof(struct v4l2_queryctrl));
3538 
3539     if (output_capability == V4L2_PIX_FMT_H264) {
3540         level_cap.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3541         profile_cap.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3542     } else if (output_capability == V4L2_PIX_FMT_VP8) {
3543         level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL;
3544     } else if (output_capability == V4L2_PIX_FMT_VP9) {
3545         level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP9_LEVEL;
3546         profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP9_PROFILE;
3547     } else if (output_capability == V4L2_PIX_FMT_HEVC) {
3548         level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL;
3549         profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE;
3550     } else if (output_capability == V4L2_PIX_FMT_MPEG2) {
3551         level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL;
3552         profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE;
3553     } else {
3554         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported Invalid codec");
3555         return OMX_ErrorInvalidComponent;
3556     }
3557 
3558     if (profile_cap.id) {
3559         if(!vdec_query_cap(profile_cap)) {
3560             DEBUG_PRINT_ERROR("Getting capabilities for profile failed");
3561             return OMX_ErrorHardware;
3562         }
3563     }
3564 
3565     if (level_cap.id) {
3566         if(!vdec_query_cap(level_cap)) {
3567             DEBUG_PRINT_ERROR("Getting capabilities for level failed");
3568             return OMX_ErrorHardware;
3569         }
3570     }
3571 
3572     /* Get the corresponding omx level from v4l2 level */
3573     if (!profile_level_converter::convert_v4l2_level_to_omx(output_capability, level_cap.maximum, (int *)&profileLevelType->eLevel)) {
3574         DEBUG_PRINT_ERROR("Invalid level, cannot find corresponding v4l2 level : %d ", level_cap.maximum);
3575         return OMX_ErrorHardware;
3576     }
3577 
3578     /* For given profile index get corresponding profile that needs to be supported */
3579     if (profileLevelType->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
3580         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on Input port only %u", (unsigned int)profileLevelType->nPortIndex);
3581         return OMX_ErrorBadPortIndex;
3582     }
3583 
3584     if (output_capability == V4L2_PIX_FMT_H264) {
3585         if (profileLevelType->nProfileIndex < (sizeof(avc_profiles)/sizeof(int))) {
3586             profileLevelType->eProfile = avc_profiles[profileLevelType->nProfileIndex];
3587         } else {
3588             DEBUG_PRINT_LOW("AVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3589                                           (unsigned int)profileLevelType->nProfileIndex);
3590             return OMX_ErrorNoMore;
3591         }
3592     } else if (output_capability == V4L2_PIX_FMT_VP8) {
3593         if (profileLevelType->nProfileIndex == 0) {
3594             profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain;
3595         } else {
3596             DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3597                                           (unsigned int)profileLevelType->nProfileIndex);
3598             return OMX_ErrorNoMore;
3599         }
3600         /* Driver has no notion of VP8 profile. Only one profile is supported.  Return this */
3601         return OMX_ErrorNone;
3602     } else if (output_capability == V4L2_PIX_FMT_VP9) {
3603         if (profileLevelType->nProfileIndex < (sizeof(vp9_profiles)/sizeof(int))) {
3604             profileLevelType->eProfile = vp9_profiles[profileLevelType->nProfileIndex];
3605         } else {
3606             DEBUG_PRINT_LOW("VP9: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3607                                           (unsigned int)profileLevelType->nProfileIndex);
3608             return OMX_ErrorNoMore;
3609         }
3610     } else if (output_capability == V4L2_PIX_FMT_HEVC) {
3611         if (profileLevelType->nProfileIndex < (sizeof(hevc_profiles)/sizeof(int))) {
3612             profileLevelType->eProfile =  hevc_profiles[profileLevelType->nProfileIndex];
3613         } else {
3614             DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3615                                          (unsigned int)profileLevelType->nProfileIndex);
3616             return OMX_ErrorNoMore;
3617         }
3618     } else if (output_capability == V4L2_PIX_FMT_MPEG2) {
3619         if (profileLevelType->nProfileIndex < (sizeof(mpeg2_profiles)/sizeof(int))) {
3620             profileLevelType->eProfile = mpeg2_profiles[profileLevelType->nProfileIndex];
3621         } else {
3622             DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
3623                                          (unsigned int)profileLevelType->nProfileIndex);
3624             return OMX_ErrorNoMore;
3625         }
3626     }
3627 
3628     /* Check if the profile is supported by driver or not  */
3629     /* During query caps of profile driver sends a mask of */
3630     /* of all v4l2 profiles supported(in the flags field)  */
3631     if((output_capability != V4L2_PIX_FMT_HEVC) &&
3632          (output_capability != V4L2_PIX_FMT_VP9)) {
3633         if (!profile_level_converter::convert_omx_profile_to_v4l2(output_capability, profileLevelType->eProfile, &v4l2_profile)) {
3634             DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
3635             return OMX_ErrorHardware;
3636         }
3637     }else if(output_capability == V4L2_PIX_FMT_HEVC) { //convert omx profile to v4l2 profile for HEVC Main10 and Main10HDR10 profiles,seperately
3638         switch (profileLevelType->eProfile) {
3639             case OMX_VIDEO_HEVCProfileMain:
3640                 v4l2_profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN;
3641                 break;
3642             case OMX_VIDEO_HEVCProfileMain10:
3643             case OMX_VIDEO_HEVCProfileMain10HDR10:
3644                 v4l2_profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10;
3645                 break;
3646             default:
3647                 DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
3648                 return OMX_ErrorHardware;
3649         }
3650     }else { //convert omx profile to v4l2 profile for VP9 Profile2 and VP9 Profile2HDR profiles,seperately
3651         switch (profileLevelType->eProfile) {
3652             case OMX_VIDEO_VP9Profile0:
3653                 v4l2_profile = V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_P0;
3654                 break;
3655             case OMX_VIDEO_VP9Profile2:
3656             case OMX_VIDEO_VP9Profile2HDR:
3657                 v4l2_profile = V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_P2_10;
3658                 break;
3659             default:
3660                 DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile");
3661                 return OMX_ErrorHardware;
3662         }
3663     }
3664     if(!((profile_cap.flags >> v4l2_profile) & 0x1)) {
3665         DEBUG_PRINT_ERROR("%s: Invalid index corresponding profile not supported : %d ",__FUNCTION__, profileLevelType->eProfile);
3666         eRet = OMX_ErrorNoMore;
3667     }
3668 
3669     DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u",
3670             (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel);
3671     return eRet;
3672 }
3673 
3674 /* ======================================================================
3675    FUNCTION
3676    omx_vdec::GetParameter
3677 
3678    DESCRIPTION
3679    OMX Get Parameter method implementation
3680 
3681    PARAMETERS
3682    <TBD>.
3683 
3684    RETURN VALUE
3685    Error None if successful.
3686 
3687    ========================================================================== */
get_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_INOUT OMX_PTR paramData)3688 OMX_ERRORTYPE  omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE     hComp,
3689         OMX_IN OMX_INDEXTYPE paramIndex,
3690         OMX_INOUT OMX_PTR     paramData)
3691 {
3692     (void) hComp;
3693     OMX_ERRORTYPE eRet = OMX_ErrorNone;
3694 
3695     DEBUG_PRINT_LOW("get_parameter:");
3696     if (m_state == OMX_StateInvalid) {
3697         DEBUG_PRINT_ERROR("Get Param in Invalid State");
3698         return OMX_ErrorInvalidState;
3699     }
3700     if (paramData == NULL) {
3701         DEBUG_PRINT_LOW("Get Param in Invalid paramData");
3702         return OMX_ErrorBadParameter;
3703     }
3704     switch ((unsigned long)paramIndex) {
3705         case OMX_IndexParamPortDefinition: {
3706                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
3707                                OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
3708                                    (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
3709                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
3710 
3711                                OMX_COLOR_FORMATTYPE drv_color_format;
3712                                bool status = false;
3713 
3714                                if (!client_buffers.is_color_conversion_enabled()) {
3715                                    status = client_buffers.get_color_format(drv_color_format);
3716                                }
3717 
3718                                if (decide_dpb_buffer_mode()) {
3719                                    DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed", __func__);
3720                                    return OMX_ErrorBadParameter;
3721                                }
3722 
3723                               if (status) {
3724                                  if (!client_buffers.is_color_conversion_enabled()) {
3725                                          client_buffers.set_client_buffers_disabled(true);
3726                                          client_buffers.set_color_format(drv_color_format);
3727                                  }
3728                               }
3729 
3730                                eRet = update_portdef(portDefn);
3731                                if (eRet == OMX_ErrorNone)
3732                                    m_port_def = *portDefn;
3733                                break;
3734                            }
3735         case OMX_IndexParamVideoInit: {
3736                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3737                               OMX_PORT_PARAM_TYPE *portParamType =
3738                                   (OMX_PORT_PARAM_TYPE *) paramData;
3739                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
3740 
3741                               portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3742                               portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3743                               portParamType->nPorts           = 2;
3744                               portParamType->nStartPortNumber = 0;
3745                               break;
3746                           }
3747         case OMX_IndexParamVideoPortFormat: {
3748                                 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
3749                                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
3750                                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
3751                                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
3752 
3753                                 portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
3754                                 portFmt->nSize             = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
3755 
3756                                 if (0 == portFmt->nPortIndex) {
3757                                     if (0 == portFmt->nIndex) {
3758                                         portFmt->eColorFormat =  OMX_COLOR_FormatUnused;
3759                                         portFmt->eCompressionFormat = eCompressionFormat;
3760                                     } else {
3761                                         DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\
3762                                                 " NoMore compression formats");
3763                                         eRet =  OMX_ErrorNoMore;
3764                                     }
3765                                 } else if (1 == portFmt->nPortIndex) {
3766                                     portFmt->eCompressionFormat =  OMX_VIDEO_CodingUnused;
3767 
3768                                     // Distinguish non-surface mode from normal playback use-case based on
3769                                     // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
3770                                     // For non-android, use the default list
3771                                     // Also use default format-list if FLEXIBLE YUV is supported,
3772                                     // as the client negotiates the standard color-format if it needs to
3773                                     bool useNonSurfaceMode = false;
3774 #if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED) && !defined(USE_GBM)
3775                                     useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
3776 #endif
3777                                     portFmt->eColorFormat = useNonSurfaceMode ?
3778                                         getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
3779                                         getPreferredColorFormatDefaultMode(portFmt->nIndex);
3780 
3781                                     if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
3782                                         eRet = OMX_ErrorNoMore;
3783                                         DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
3784                                                 " NoMore Color formats");
3785                                     }
3786                                     DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
3787                                 } else {
3788                                     DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
3789                                             (int)portFmt->nPortIndex);
3790                                     eRet = OMX_ErrorBadPortIndex;
3791                                 }
3792                                 break;
3793                             }
3794                             /*Component should support this port definition*/
3795         case OMX_IndexParamAudioInit: {
3796                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3797                               OMX_PORT_PARAM_TYPE *audioPortParamType =
3798                                   (OMX_PORT_PARAM_TYPE *) paramData;
3799                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
3800                               audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3801                               audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3802                               audioPortParamType->nPorts           = 0;
3803                               audioPortParamType->nStartPortNumber = 0;
3804                               break;
3805                           }
3806                           /*Component should support this port definition*/
3807         case OMX_IndexParamImageInit: {
3808                               VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
3809                               OMX_PORT_PARAM_TYPE *imagePortParamType =
3810                                   (OMX_PORT_PARAM_TYPE *) paramData;
3811                               DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
3812                               imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
3813                               imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
3814                               imagePortParamType->nPorts           = 0;
3815                               imagePortParamType->nStartPortNumber = 0;
3816                               break;
3817 
3818                           }
3819                           /*Component should support this port definition*/
3820         case OMX_IndexParamOtherInit: {
3821                               DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
3822                                       paramIndex);
3823                               eRet =OMX_ErrorUnsupportedIndex;
3824                               break;
3825                           }
3826         case OMX_IndexParamStandardComponentRole: {
3827                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
3828                                   OMX_PARAM_COMPONENTROLETYPE *comp_role;
3829                                   comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
3830                                   comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
3831                                   comp_role->nSize = sizeof(*comp_role);
3832 
3833                                   DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",
3834                                           paramIndex);
3835                                   strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
3836                                           OMX_MAX_STRINGNAME_SIZE);
3837                                   break;
3838                               }
3839                               /* Added for parameter test */
3840         case OMX_IndexParamPriorityMgmt: {
3841                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
3842                              OMX_PRIORITYMGMTTYPE *priorityMgmType =
3843                                  (OMX_PRIORITYMGMTTYPE *) paramData;
3844                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
3845                              priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
3846                              priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
3847 
3848                              break;
3849                          }
3850                          /* Added for parameter test */
3851         case OMX_IndexParamCompBufferSupplier: {
3852                                    VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
3853                                    OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
3854                                        (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
3855                                    DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
3856 
3857                                    bufferSupplierType->nSize = sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE);
3858                                    bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION;
3859                                    if (0 == bufferSupplierType->nPortIndex)
3860                                        bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3861                                    else if (1 == bufferSupplierType->nPortIndex)
3862                                        bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified;
3863                                    else
3864                                        eRet = OMX_ErrorBadPortIndex;
3865 
3866 
3867                                    break;
3868                                }
3869         case OMX_IndexParamVideoAvc: {
3870                              DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x",
3871                                      paramIndex);
3872                              break;
3873                          }
3874         case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
3875                              DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
3876                                      paramIndex);
3877                              break;
3878                          }
3879         case OMX_IndexParamVideoMpeg2: {
3880                                DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
3881                                        paramIndex);
3882                                break;
3883                            }
3884         case OMX_IndexParamVideoProfileLevelQuerySupported: {
3885                                         VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3886                                         DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
3887                                         OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
3888                                             (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
3889                                         eRet = get_supported_profile_level(profileLevelType);
3890                                         break;
3891                                     }
3892 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
3893         case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
3894                                         VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
3895                                         DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
3896                                         GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
3897                                         if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
3898 
3899                                             if (secure_mode && !secure_scaling_to_non_secure_opb) {
3900                                                 nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
3901                                                         GRALLOC_USAGE_PRIVATE_UNCACHED);
3902                                             } else {
3903                                                 nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED;
3904                                             }
3905                                         } else {
3906                                             DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
3907                                             eRet = OMX_ErrorBadParameter;
3908                                         }
3909                                     }
3910                                     break;
3911 #endif
3912 
3913 #ifdef FLEXYUV_SUPPORTED
3914         case OMX_QcomIndexFlexibleYUVDescription: {
3915                 DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
3916                 VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
3917                 eRet = describeColorFormat(paramData);
3918                 if (eRet == OMX_ErrorUnsupportedSetting) {
3919                     DEBUG_PRINT_LOW("The standard OMX linear formats are understood by client. Please ignore this  Unsupported Setting (0x80001019).");
3920                 }
3921                 break;
3922             }
3923 #endif
3924         case OMX_IndexParamVideoProfileLevelCurrent: {
3925              VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
3926              OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
3927              struct v4l2_control profile_control, level_control;
3928 
3929              switch (drv_ctx.decoder_format) {
3930                  case VDEC_CODECTYPE_H264:
3931                      profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
3932                      level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
3933                      break;
3934                  default:
3935                      DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264");
3936                      eRet = OMX_ErrorNotImplemented;
3937                      break;
3938              }
3939 
3940              if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) {
3941                 switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) {
3942                     case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
3943                         pParam->eProfile = OMX_VIDEO_AVCProfileBaseline;
3944                         break;
3945                     case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
3946                         pParam->eProfile = OMX_VIDEO_AVCProfileConstrainedBaseline;
3947                         break;
3948                     case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
3949                         pParam->eProfile = OMX_VIDEO_AVCProfileConstrainedHigh;
3950                         break;
3951                     case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
3952                         pParam->eProfile = OMX_VIDEO_AVCProfileMain;
3953                         break;
3954                     case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
3955                         pParam->eProfile = OMX_VIDEO_AVCProfileExtended;
3956                         break;
3957                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
3958                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh;
3959                         break;
3960                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
3961                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh10;
3962                         break;
3963                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
3964                         pParam->eProfile = OMX_VIDEO_AVCProfileHigh422;
3965                         break;
3966                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
3967                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
3968                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
3969                     case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
3970                     case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
3971                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
3972                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
3973                     case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
3974                     case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
3975                     case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
3976                         eRet = OMX_ErrorUnsupportedIndex;
3977                         break;
3978                 }
3979              } else {
3980                  eRet = OMX_ErrorUnsupportedIndex;
3981              }
3982 
3983 
3984              if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) {
3985                 switch ((enum v4l2_mpeg_video_h264_level)level_control.value) {
3986                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
3987                         pParam->eLevel = OMX_VIDEO_AVCLevel1;
3988                         break;
3989                     case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
3990                         pParam->eLevel = OMX_VIDEO_AVCLevel1b;
3991                         break;
3992                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
3993                         pParam->eLevel = OMX_VIDEO_AVCLevel11;
3994                         break;
3995                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
3996                         pParam->eLevel = OMX_VIDEO_AVCLevel12;
3997                         break;
3998                     case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
3999                         pParam->eLevel = OMX_VIDEO_AVCLevel13;
4000                         break;
4001                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
4002                         pParam->eLevel = OMX_VIDEO_AVCLevel2;
4003                         break;
4004                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
4005                         pParam->eLevel = OMX_VIDEO_AVCLevel21;
4006                         break;
4007                     case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
4008                         pParam->eLevel = OMX_VIDEO_AVCLevel22;
4009                         break;
4010                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
4011                         pParam->eLevel = OMX_VIDEO_AVCLevel3;
4012                         break;
4013                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
4014                         pParam->eLevel = OMX_VIDEO_AVCLevel31;
4015                         break;
4016                     case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
4017                         pParam->eLevel = OMX_VIDEO_AVCLevel32;
4018                         break;
4019                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
4020                         pParam->eLevel = OMX_VIDEO_AVCLevel4;
4021                         break;
4022                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
4023                         pParam->eLevel = OMX_VIDEO_AVCLevel41;
4024                         break;
4025                     case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
4026                         pParam->eLevel = OMX_VIDEO_AVCLevel42;
4027                         break;
4028                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
4029                         pParam->eLevel = OMX_VIDEO_AVCLevel5;
4030                         break;
4031                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
4032                         pParam->eLevel = OMX_VIDEO_AVCLevel51;
4033                         break;
4034                     case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
4035                         pParam->eLevel = OMX_VIDEO_AVCLevel52;
4036                         break;
4037                     case V4L2_MPEG_VIDEO_H264_LEVEL_6_0:
4038                         pParam->eLevel = OMX_VIDEO_AVCLevel6;
4039                         break;
4040                     case V4L2_MPEG_VIDEO_H264_LEVEL_6_1:
4041                         pParam->eLevel = OMX_VIDEO_AVCLevel61;
4042                         break;
4043                     case V4L2_MPEG_VIDEO_H264_LEVEL_6_2:
4044                         pParam->eLevel = OMX_VIDEO_AVCLevel62;
4045                         break;
4046                     default:
4047                         eRet = OMX_ErrorUnsupportedIndex;
4048                         break;
4049                 }
4050              } else {
4051                  eRet = OMX_ErrorUnsupportedIndex;
4052              }
4053 
4054              break;
4055 
4056          }
4057         case OMX_QTIIndexParamVideoClientExtradata:
4058         {
4059             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
4060             DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVideoClientExtradata");
4061             QOMX_EXTRADATA_ENABLE *pParam =
4062                 (QOMX_EXTRADATA_ENABLE *)paramData;
4063             if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
4064                 pParam->bEnable = client_extradata ? OMX_TRUE : OMX_FALSE;
4065                 eRet = OMX_ErrorNone;
4066             } else {
4067                 eRet = OMX_ErrorUnsupportedIndex;
4068             }
4069             break;
4070         }
4071         case OMX_QTIIndexParamDitherControl:
4072         {
4073             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
4074             DEBUG_PRINT_LOW("get_parameter: QOMX_VIDEO_DITHER_CONTROL");
4075             QOMX_VIDEO_DITHER_CONTROL *pParam =
4076                 (QOMX_VIDEO_DITHER_CONTROL *) paramData;
4077             pParam->eDitherType = (QOMX_VIDEO_DITHERTYPE) m_dither_config;
4078             eRet = OMX_ErrorNone;
4079             break;
4080         }
4081         case OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency:
4082         {
4083             VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
4084             DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency");
4085             OMX_VIDEO_PARAM_PROFILELEVELTYPE *pParam =
4086                 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) paramData;
4087             pParam->eProfile = mClientSetProfile;
4088             pParam->eLevel = mClientSetLevel;
4089             eRet = OMX_ErrorNone;
4090             break;
4091         }
4092         default: {
4093                  DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
4094                  eRet =OMX_ErrorUnsupportedIndex;
4095              }
4096 
4097     }
4098 
4099     DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
4100             drv_ctx.video_resolution.frame_width,
4101             drv_ctx.video_resolution.frame_height,
4102             drv_ctx.video_resolution.stride,
4103             drv_ctx.video_resolution.scan_lines);
4104 
4105     return eRet;
4106 }
4107 
4108 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_PTR data)4109 OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
4110 {
4111     DEBUG_PRINT_LOW("Inside use_android_native_buffer");
4112     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4113     UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
4114 
4115     if ((params == NULL) ||
4116             (params->nativeBuffer == NULL) ||
4117             (params->nativeBuffer->handle == NULL) ||
4118             !m_enable_android_native_buffers)
4119         return OMX_ErrorBadParameter;
4120     m_use_android_native_buffers = OMX_TRUE;
4121     sp<android_native_buffer_t> nBuf = params->nativeBuffer;
4122     private_handle_t *handle = (private_handle_t *)nBuf->handle;
4123     if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
4124         OMX_U8 *buffer = NULL;
4125         if (!secure_mode) {
4126             buffer = (OMX_U8*)mmap(0, handle->size,
4127                     PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
4128             if (buffer == MAP_FAILED) {
4129                 DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
4130                 return OMX_ErrorInsufficientResources;
4131             }
4132         }
4133         eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
4134     } else {
4135         eRet = OMX_ErrorBadParameter;
4136     }
4137     return eRet;
4138 }
4139 #endif
4140 
enable_smoothstreaming()4141 OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
4142     struct v4l2_control control;
4143     struct v4l2_format fmt;
4144     /*control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
4145     control.value = 1;
4146     int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
4147     if (rc < 0) {
4148         DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
4149         return OMX_ErrorHardware;
4150     }*/
4151     m_smoothstreaming_mode = true;
4152     return OMX_ErrorNone;
4153 }
4154 
4155 /* ======================================================================
4156    FUNCTION
4157    omx_vdec::Setparameter
4158 
4159    DESCRIPTION
4160    OMX Set Parameter method implementation.
4161 
4162    PARAMETERS
4163    <TBD>.
4164 
4165    RETURN VALUE
4166    OMX Error None if successful.
4167 
4168    ========================================================================== */
set_parameter(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE paramIndex,OMX_IN OMX_PTR paramData)4169 OMX_ERRORTYPE  omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE     hComp,
4170         OMX_IN OMX_INDEXTYPE paramIndex,
4171         OMX_IN OMX_PTR        paramData)
4172 {
4173     OMX_ERRORTYPE eRet = OMX_ErrorNone;
4174     int ret=0;
4175     struct v4l2_format fmt;
4176 #ifdef _ANDROID_
4177     char property_value[PROPERTY_VALUE_MAX] = {0};
4178 #endif
4179     if (m_state == OMX_StateInvalid) {
4180         DEBUG_PRINT_ERROR("Set Param in Invalid State");
4181         return OMX_ErrorInvalidState;
4182     }
4183     if (paramData == NULL) {
4184         DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
4185         return OMX_ErrorBadParameter;
4186     }
4187     if ((m_state != OMX_StateLoaded) &&
4188             BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
4189             (m_out_bEnabled == OMX_TRUE) &&
4190             BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
4191             (m_inp_bEnabled == OMX_TRUE)) {
4192         DEBUG_PRINT_ERROR("Set Param in Invalid State");
4193         return OMX_ErrorIncorrectStateOperation;
4194     }
4195     switch ((unsigned long)paramIndex) {
4196         case OMX_IndexParamPortDefinition: {
4197                                VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
4198                                OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
4199                                portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
4200                                //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
4201                                //been called.
4202                                DEBUG_PRINT_LOW(
4203                                        "set_parameter: OMX_IndexParamPortDefinition: dir %d port %d wxh %dx%d count: min %d actual %d size %d",
4204                                        (int)portDefn->eDir, (int)portDefn->nPortIndex,
4205                                        (int)portDefn->format.video.nFrameWidth,
4206                                        (int)portDefn->format.video.nFrameHeight,
4207                                        (int)portDefn->nBufferCountMin,
4208                                        (int)portDefn->nBufferCountActual,
4209                                        (int)portDefn->nBufferSize);
4210 
4211                                if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4212                                    DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
4213                                                           portDefn->nBufferCountActual);
4214                                    eRet = OMX_ErrorBadParameter;
4215                                    break;
4216                                }
4217                                if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) {
4218                                    if (portDefn->nBufferCountActual < MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS ||
4219                                         portDefn->nBufferSize != m_client_out_extradata_info.getSize()) {
4220                                         DEBUG_PRINT_ERROR("ERROR: Bad parameeters request for extradata limit %d size - %d",
4221                                                           portDefn->nBufferCountActual, portDefn->nBufferSize);
4222                                         eRet = OMX_ErrorBadParameter;
4223                                         break;
4224                                    }
4225                                     m_client_out_extradata_info.set_extradata_info(portDefn->nBufferSize,
4226                                             portDefn->nBufferCountActual);
4227                                     break;
4228                                }
4229 
4230                                if (OMX_DirOutput == portDefn->eDir) {
4231                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
4232                                    bool port_format_changed = false;
4233                                    m_display_id = portDefn->format.video.pNativeWindow;
4234                                    unsigned int buffer_size;
4235                                    /* update output port resolution with client supplied dimensions
4236                                       in case scaling is enabled, else it follows input resolution set
4237                                    */
4238                                    if (decide_dpb_buffer_mode()) {
4239                                        DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed", __func__);
4240                                        return OMX_ErrorBadParameter;
4241                                    }
4242                                    if (is_down_scalar_enabled) {
4243                                        DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
4244                                                (unsigned int)portDefn->format.video.nFrameWidth,
4245                                                (unsigned int)portDefn->format.video.nFrameHeight);
4246                                        if (portDefn->format.video.nFrameHeight != 0x0 &&
4247                                                portDefn->format.video.nFrameWidth != 0x0) {
4248                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
4249                                            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4250                                            fmt.fmt.pix_mp.pixelformat = capture_capability;
4251                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4252                                            if (ret) {
4253                                                DEBUG_PRINT_ERROR("Get Resolution failed");
4254                                                eRet = OMX_ErrorHardware;
4255                                                break;
4256                                            }
4257                                            if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
4258                                                (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
4259                                                    port_format_changed = true;
4260                                            }
4261 
4262                                            /* set crop info */
4263                                            rectangle.nLeft = 0;
4264                                            rectangle.nTop = 0;
4265                                            rectangle.nWidth = portDefn->format.video.nFrameWidth;
4266                                            rectangle.nHeight = portDefn->format.video.nFrameHeight;
4267 
4268                                            m_extradata_info.output_crop_rect.nLeft = 0;
4269                                            m_extradata_info.output_crop_rect.nTop = 0;
4270                                            m_extradata_info.output_crop_rect.nWidth = rectangle.nWidth;
4271                                            m_extradata_info.output_crop_rect.nHeight = rectangle.nHeight;
4272 
4273                                            memset(&fmt, 0x0, sizeof(struct v4l2_format));
4274                                            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4275                                            fmt.fmt.pix_mp.height = (unsigned int)portDefn->format.video.nFrameHeight;
4276                                            fmt.fmt.pix_mp.width = (unsigned int)portDefn->format.video.nFrameWidth;
4277                                            fmt.fmt.pix_mp.pixelformat = capture_capability;
4278                                            DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
4279                                                fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
4280                                            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4281                                            if (ret) {
4282                                                DEBUG_PRINT_ERROR("Set Resolution failed");
4283                                                eRet = OMX_ErrorUnsupportedSetting;
4284                                            } else
4285                                                eRet = get_buffer_req(&drv_ctx.op_buf);
4286                                        }
4287 
4288                                        if (eRet) {
4289                                            break;
4290                                        }
4291                                    }
4292 
4293                                    if (eRet) {
4294                                        break;
4295                                    }
4296 
4297                                    if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4298                                        DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
4299                                                portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4300                                        eRet = OMX_ErrorBadParameter;
4301                                    } else if (!client_buffers.get_buffer_req(buffer_size)) {
4302                                        DEBUG_PRINT_ERROR("Error in getting buffer requirements");
4303                                        eRet = OMX_ErrorBadParameter;
4304                                    } else if (!port_format_changed) {
4305 
4306                                        // Buffer count can change only when port is unallocated
4307                                        if (m_out_mem_ptr &&
4308                                                 (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount ||
4309                                                 portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) {
4310 
4311                                            DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
4312                                            eRet = OMX_ErrorInvalidState;
4313                                            break;
4314                                        }
4315 
4316                                        // route updating of buffer requirements via c2d proxy.
4317                                        // Based on whether c2d is enabled, requirements will be handed
4318                                        // to the vidc driver appropriately
4319                                        eRet = client_buffers.set_buffer_req(portDefn->nBufferSize,
4320                                                 portDefn->nBufferCountActual);
4321                                        if (eRet == OMX_ErrorNone) {
4322                                            m_port_def = *portDefn;
4323                                        } else {
4324                                            DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
4325                                                    drv_ctx.op_buf.mincount, (unsigned int)buffer_size,
4326                                                    (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4327                                            eRet = OMX_ErrorBadParameter;
4328                                        }
4329                                    }
4330                                } else if (OMX_DirInput == portDefn->eDir) {
4331                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
4332                                    bool port_format_changed = false;
4333                                    if ((portDefn->format.video.xFramerate >> 16) > 0 &&
4334                                            (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
4335                                        // Frame rate only should be set if this is a "known value" or to
4336                                        // activate ts prediction logic (arbitrary mode only) sending input
4337                                        // timestamps with max value (LLONG_MAX).
4338                                        m_fps_received = portDefn->format.video.xFramerate;
4339                                        DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
4340                                                (unsigned int)portDefn->format.video.xFramerate >> 16);
4341                                        Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
4342                                                drv_ctx.frame_rate.fps_denominator);
4343                                        if (!drv_ctx.frame_rate.fps_numerator) {
4344                                            DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
4345                                            drv_ctx.frame_rate.fps_numerator = 30;
4346                                        }
4347                                        if (drv_ctx.frame_rate.fps_denominator)
4348                                            drv_ctx.frame_rate.fps_numerator = (int)
4349                                                drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
4350                                        drv_ctx.frame_rate.fps_denominator = 1;
4351                                        frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
4352                                            drv_ctx.frame_rate.fps_numerator;
4353                                        DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
4354                                                (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
4355                                                (float)drv_ctx.frame_rate.fps_denominator);
4356 
4357                                        struct v4l2_outputparm oparm;
4358                                        /*XXX: we're providing timing info as seconds per frame rather than frames
4359                                         * per second.*/
4360                                        oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
4361                                        oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
4362 
4363                                        struct v4l2_streamparm sparm;
4364                                        sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4365                                        sparm.parm.output = oparm;
4366                                        if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
4367                                            DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
4368                                            eRet = OMX_ErrorHardware;
4369                                            break;
4370                                        }
4371                                    }
4372 
4373                                    if (drv_ctx.video_resolution.frame_height !=
4374                                            portDefn->format.video.nFrameHeight ||
4375                                            drv_ctx.video_resolution.frame_width  !=
4376                                            portDefn->format.video.nFrameWidth) {
4377                                        DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
4378                                                (unsigned int)portDefn->format.video.nFrameWidth,
4379                                                (unsigned int)portDefn->format.video.nFrameHeight);
4380                                        port_format_changed = true;
4381                                        OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
4382                                        OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
4383                                        if (frameHeight != 0x0 && frameWidth != 0x0) {
4384                                            if (m_smoothstreaming_mode &&
4385                                                    ((frameWidth * frameHeight) <
4386                                                    (m_smoothstreaming_width * m_smoothstreaming_height))) {
4387                                                frameWidth = m_smoothstreaming_width;
4388                                                frameHeight = m_smoothstreaming_height;
4389                                                DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
4390                                                        "for adaptive-playback/smooth-streaming",
4391                                                        (unsigned int)frameWidth, (unsigned int)frameHeight);
4392                                            }
4393 
4394                                            m_extradata_info.output_crop_rect.nLeft = 0;
4395                                            m_extradata_info.output_crop_rect.nTop = 0;
4396                                            m_extradata_info.output_crop_rect.nWidth = frameWidth;
4397                                            m_extradata_info.output_crop_rect.nHeight = frameHeight;
4398 
4399                                            update_resolution(frameWidth, frameHeight,
4400                                                    frameWidth, frameHeight);
4401                                            if (is_down_scalar_enabled) {
4402                                                memset(&fmt, 0x0, sizeof(struct v4l2_format));
4403                                                fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4404                                                fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4405                                                fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4406                                                fmt.fmt.pix_mp.pixelformat = output_capability;
4407                                                DEBUG_PRINT_LOW("DS Enabled : height = %d , width = %d",
4408                                                    fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4409                                                ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4410                                            } else {
4411                                                memset(&fmt, 0x0, sizeof(struct v4l2_format));
4412                                                fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
4413                                                fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
4414                                                fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
4415                                                fmt.fmt.pix_mp.pixelformat = output_capability;
4416                                                DEBUG_PRINT_LOW("DS Disabled : height = %d , width = %d",
4417                                                    fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
4418                                                ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4419                                                fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4420                                                fmt.fmt.pix_mp.pixelformat = capture_capability;
4421                                                ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4422                                            }
4423                                            if (ret) {
4424                                                DEBUG_PRINT_ERROR("Set Resolution failed");
4425                                                eRet = OMX_ErrorUnsupportedSetting;
4426                                            } else {
4427                                                if (!is_down_scalar_enabled)
4428                                                    eRet = get_buffer_req(&drv_ctx.op_buf);
4429                                            }
4430                                            if (eRet)
4431                                                break;
4432                                        }
4433                                    }
4434                                    if (m_custom_buffersize.input_buffersize
4435                                         && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
4436                                        DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
4437                                                m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
4438                                        eRet = OMX_ErrorBadParameter;
4439                                        break;
4440                                    }
4441                                    if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
4442                                        DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
4443                                                portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
4444                                        eRet = OMX_ErrorBadParameter;
4445                                        break;
4446                                    }
4447                                    // Buffer count can change only when port is unallocated
4448                                    if (m_inp_mem_ptr &&
4449                                             (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount ||
4450                                             portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) {
4451                                        DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
4452                                        eRet = OMX_ErrorInvalidState;
4453                                        break;
4454                                    }
4455 
4456                                    if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
4457                                            || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
4458                                        port_format_changed = true;
4459                                        vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
4460                                        drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
4461                                        drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
4462                                            (~(buffer_prop->alignment - 1));
4463                                        eRet = set_buffer_req(buffer_prop);
4464                                    }
4465                                    if (false == port_format_changed) {
4466                                        DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
4467                                                drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
4468                                                (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
4469                                        eRet = OMX_ErrorBadParameter;
4470                                    }
4471                                } else if (portDefn->eDir ==  OMX_DirMax) {
4472                                    DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
4473                                            (int)portDefn->nPortIndex);
4474                                    eRet = OMX_ErrorBadPortIndex;
4475                                }
4476                            }
4477                            break;
4478         case OMX_IndexParamVideoPortFormat: {
4479                                 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
4480                                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
4481                                     (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
4482                                 int ret=0;
4483                                 struct v4l2_format fmt;
4484                                 DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
4485                                         portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
4486 
4487                                 memset(&fmt, 0x0, sizeof(struct v4l2_format));
4488                                 if (1 == portFmt->nPortIndex) {
4489                                     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
4490                                     ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
4491                                     if (ret < 0) {
4492                                         DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
4493                                         return OMX_ErrorBadParameter;
4494                                     }
4495                                     enum vdec_output_format op_format;
4496                                     if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4497                                                      QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
4498                                         portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
4499                                         op_format = (enum vdec_output_format)VDEC_YUV_FORMAT_NV12;
4500                                         fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12;
4501                                         //check if the required color format is a supported flexible format
4502                                         is_flexible_format = check_supported_flexible_formats(portFmt->eColorFormat);
4503                                     } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
4504                                                    QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed ||
4505                                                portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar) {
4506                                         op_format = (enum vdec_output_format)VDEC_YUV_FORMAT_NV12_UBWC;
4507                                         fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC;
4508                                         //check if the required color format is a supported flexible format
4509                                         is_flexible_format = check_supported_flexible_formats(portFmt->eColorFormat);
4510                                     } else {
4511                                         eRet = OMX_ErrorBadParameter;
4512                                     }
4513 
4514                                     if (eRet == OMX_ErrorNone) {
4515                                         drv_ctx.output_format = op_format;
4516                                         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
4517                                         if (ret) {
4518                                             DEBUG_PRINT_ERROR("Set output format failed");
4519                                             eRet = OMX_ErrorUnsupportedSetting;
4520                                             /*TODO: How to handle this case */
4521                                         } else {
4522                                             eRet = get_buffer_req(&drv_ctx.op_buf);
4523                                         }
4524                                     }
4525                                     if (eRet == OMX_ErrorNone) {
4526                                         if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
4527                                             DEBUG_PRINT_ERROR("Set color format failed");
4528                                             eRet = OMX_ErrorBadParameter;
4529                                         }
4530                                     }
4531                                 }
4532                             }
4533                             break;
4534         case OMX_QcomIndexPortDefn: {
4535                             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
4536                             OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
4537                                 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
4538                             DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u",
4539                                     (unsigned int)portFmt->nFramePackingFormat);
4540 
4541                             /* Input port */
4542                             if (portFmt->nPortIndex == 0) {
4543                                 // arbitrary_bytes mode cannot be changed arbitrarily since this controls how:
4544                                 //   - headers are allocated and
4545                                 //   - headers-indices are derived
4546                                 // Avoid changing arbitrary_bytes when the port is already allocated
4547                                 if (m_inp_mem_ptr) {
4548                                     DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!");
4549                                     return OMX_ErrorUnsupportedSetting;
4550                                 }
4551                                 if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
4552                                     if (secure_mode || m_input_pass_buffer_fd) {
4553                                         arbitrary_bytes = false;
4554                                         DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode");
4555                                         eRet = OMX_ErrorUnsupportedSetting;
4556                                     } else {
4557                                         arbitrary_bytes = true;
4558                                     }
4559                                 } else if (portFmt->nFramePackingFormat ==
4560                                         OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
4561                                     arbitrary_bytes = false;
4562                                 } else {
4563                                     DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u",
4564                                             (unsigned int)portFmt->nFramePackingFormat);
4565                                     eRet = OMX_ErrorUnsupportedSetting;
4566                                 }
4567                                 //Explicitly disable arb mode for unsupported codecs
4568                                 bool is_arb_supported = false;
4569                                 if (arbitrary_bytes) {
4570                                    switch (drv_ctx.decoder_format) {
4571                                    case VDEC_CODECTYPE_H264:
4572                                       is_arb_supported = m_arb_mode_override & VDEC_ARB_CODEC_H264;
4573                                       break;
4574                                    case VDEC_CODECTYPE_HEVC:
4575                                       is_arb_supported = m_arb_mode_override & VDEC_ARB_CODEC_HEVC;
4576                                       break;
4577                                    case VDEC_CODECTYPE_MPEG2:
4578                                       is_arb_supported = m_arb_mode_override & VDEC_ARB_CODEC_MPEG2;
4579                                       break;
4580                                    default:
4581                                       DEBUG_PRINT_HIGH("Arbitrary bytes mode not enabled for this Codec");
4582                                       break;
4583                                    }
4584 
4585                                    if (!is_arb_supported) {
4586                                        DEBUG_PRINT_ERROR("Setparameter: Disabling arbitrary bytes mode explicitly");
4587                                        arbitrary_bytes = false;
4588                                        eRet = OMX_ErrorUnsupportedSetting;
4589                                    }
4590                                 }
4591                             } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4592                                 DEBUG_PRINT_ERROR("Unsupported at O/P port");
4593                                 eRet = OMX_ErrorUnsupportedSetting;
4594                             }
4595                             break;
4596                         }
4597         case OMX_QTIIndexParamVideoClientExtradata: {
4598                                   VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
4599                                   DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoClientExtradata");
4600                                   QOMX_EXTRADATA_ENABLE *pParam =
4601                                       (QOMX_EXTRADATA_ENABLE *)paramData;
4602 
4603                                   if (m_state != OMX_StateLoaded) {
4604                                       DEBUG_PRINT_ERROR("Set Parameter called in Invalid state");
4605                                       return OMX_ErrorIncorrectStateOperation;
4606                                   }
4607 
4608                                   if (pParam->nPortIndex == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
4609                                       m_client_out_extradata_info.enable_client_extradata(pParam->bEnable);
4610                                   } else {
4611                                       DEBUG_PRINT_ERROR("Incorrect portIndex - %d", pParam->nPortIndex);
4612                                       eRet = OMX_ErrorUnsupportedIndex;
4613                                   }
4614                                   break;
4615                               }
4616         case OMX_IndexParamStandardComponentRole: {
4617                                   VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
4618                                   OMX_PARAM_COMPONENTROLETYPE *comp_role;
4619                                   comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
4620                                   DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
4621                                           comp_role->cRole);
4622 
4623                                   if ((m_state == OMX_StateLoaded)&&
4624                                           !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) {
4625                                       DEBUG_PRINT_LOW("Set Parameter called in valid state");
4626                                   } else {
4627                                       DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4628                                       return OMX_ErrorIncorrectStateOperation;
4629                                   }
4630 
4631                                   if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4632                                       if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
4633                                           strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
4634                                       } else {
4635                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4636                                           eRet =OMX_ErrorUnsupportedSetting;
4637                                       }
4638                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4639                                       if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
4640                                           strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
4641                                       } else {
4642                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4643                                           eRet = OMX_ErrorUnsupportedSetting;
4644                                       }
4645                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4646                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
4647                                           strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE);
4648                                       } else {
4649                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4650                                           eRet = OMX_ErrorUnsupportedSetting;
4651                                       }
4652                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
4653                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
4654                                               !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4655                                           strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE);
4656                                       } else {
4657                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4658                                           eRet = OMX_ErrorUnsupportedSetting;
4659                                       }
4660                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
4661                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) ||
4662                                               !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
4663                                           strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE);
4664                                       } else {
4665                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4666                                           eRet = OMX_ErrorUnsupportedSetting;
4667                                       }
4668                                   } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4669                                       if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
4670                                           strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
4671                                       } else {
4672                                           DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
4673                                           eRet = OMX_ErrorUnsupportedSetting;
4674                                       }
4675                                   } else {
4676                                       DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
4677                                       eRet = OMX_ErrorInvalidComponentName;
4678                                   }
4679                                   break;
4680                               }
4681 
4682         case OMX_IndexParamPriorityMgmt: {
4683                              VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
4684                              if (m_state != OMX_StateLoaded) {
4685                                  DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
4686                                  return OMX_ErrorIncorrectStateOperation;
4687                              }
4688                              OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
4689                              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
4690                                      (unsigned int)priorityMgmtype->nGroupID);
4691 
4692                              DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
4693                                      (unsigned int)priorityMgmtype->nGroupPriority);
4694 
4695                              m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
4696                              m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
4697 
4698                              break;
4699                          }
4700 
4701         case OMX_IndexParamCompBufferSupplier: {
4702                                    VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
4703                                    OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
4704                                    DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
4705                                            bufferSupplierType->eBufferSupplier);
4706                                    if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
4707                                        m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
4708 
4709                                    else
4710 
4711                                        eRet = OMX_ErrorBadPortIndex;
4712 
4713                                    break;
4714 
4715                                }
4716         case OMX_IndexParamVideoAvc: {
4717                              DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
4718                                      paramIndex);
4719                              break;
4720                          }
4721         case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
4722                             DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
4723                                      paramIndex);
4724                              break;
4725                         }
4726         case OMX_IndexParamVideoMpeg2: {
4727                                DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
4728                                        paramIndex);
4729                                break;
4730                            }
4731         case OMX_QTIIndexParamLowLatencyMode: {
4732                                struct v4l2_control control;
4733                                int rc = 0;
4734                                QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE* pParam =
4735                                    (QOMX_EXTNINDEX_VIDEO_LOW_LATENCY_MODE*)paramData;
4736                                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE;
4737                                 if (pParam->bEnableLowLatencyMode)
4738                                     control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
4739                                 else
4740                                     control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
4741 
4742                                 rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4743                                 if (rc) {
4744                                     DEBUG_PRINT_ERROR("Set low latency failed");
4745                                     eRet = OMX_ErrorUnsupportedSetting;
4746                                 } else {
4747                                     m_sParamLowLatency.bEnableLowLatencyMode = pParam->bEnableLowLatencyMode;
4748                                 }
4749                                break;
4750                            }
4751         case OMX_QcomIndexParamVideoDecoderPictureOrder: {
4752                                      VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
4753                                      QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
4754                                          (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
4755                                      struct v4l2_control control;
4756                                      int pic_order,rc=0;
4757                                      DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
4758                                              pictureOrder->eOutputPictureOrder);
4759                                      if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
4760                                          pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
4761                                      } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
4762                                          pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4763                                          time_stamp_dts.set_timestamp_reorder_mode(false);
4764                                      } else
4765                                          eRet = OMX_ErrorBadParameter;
4766                                      if (eRet == OMX_ErrorNone) {
4767                                          control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4768                                          control.value = pic_order;
4769                                          rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4770                                          if (rc) {
4771                                              DEBUG_PRINT_ERROR("Set picture order failed");
4772                                              eRet = OMX_ErrorUnsupportedSetting;
4773                                          }
4774                                      }
4775                                      m_decode_order_mode =
4776                                             pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER;
4777                                      break;
4778                                  }
4779         case OMX_QcomIndexParamConcealMBMapExtraData:
4780                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4781                                eRet = enable_extradata(OMX_MB_ERROR_MAP_EXTRADATA, false,
4782                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4783                                break;
4784         case OMX_QcomIndexParamFrameInfoExtraData:
4785                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4786                                eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
4787                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4788                                break;
4789         case OMX_ExtraDataFrameDimension:
4790                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4791                                eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
4792                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4793                                break;
4794         case OMX_QcomIndexParamInterlaceExtraData:
4795                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4796                                eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
4797                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4798                                break;
4799         case OMX_QcomIndexParamOutputCropExtraData:
4800                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4801                                eRet = enable_extradata(OMX_OUTPUTCROP_EXTRADATA, false,
4802                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4803                                break;
4804         case OMX_QcomIndexParamH264TimeInfo:
4805                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4806                                eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
4807                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4808                                break;
4809         case OMX_QcomIndexParamVideoFramePackingExtradata:
4810                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4811                                eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
4812                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4813                                break;
4814         case OMX_QcomIndexParamVideoQPExtraData:
4815                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4816                                eRet = enable_extradata(OMX_QP_EXTRADATA, false,
4817                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4818                                break;
4819         case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
4820                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4821                                eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
4822                                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
4823                                break;
4824         case OMX_QcomIndexEnableExtnUserData:
4825                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4826                                 eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
4827                                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4828                                 break;
4829         case OMX_QTIIndexParamVQZipSEIExtraData:
4830                                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
4831                                 eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
4832                                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
4833                                 break;
4834         case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
4835                                        DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
4836                                        DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
4837                                        struct v4l2_control control;
4838                                        int rc;
4839                                        drv_ctx.idr_only_decoding = 1;
4840                                        control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
4841                                        control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
4842                                        rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4843                                        if (rc) {
4844                                            DEBUG_PRINT_ERROR("Set picture order failed");
4845                                            eRet = OMX_ErrorUnsupportedSetting;
4846                                        } else {
4847                                            control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
4848                                            control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
4849                                            rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
4850                                            if (rc) {
4851                                                DEBUG_PRINT_ERROR("Sync frame setting failed");
4852                                                eRet = OMX_ErrorUnsupportedSetting;
4853                                            }
4854                                            /*Setting sync frame decoding on driver might change buffer
4855                                             * requirements so update them here*/
4856                                            if (get_buffer_req(&drv_ctx.ip_buf)) {
4857                                                DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
4858                                                eRet = OMX_ErrorUnsupportedSetting;
4859                                            }
4860                                            if (get_buffer_req(&drv_ctx.op_buf)) {
4861                                                DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
4862                                                eRet = OMX_ErrorUnsupportedSetting;
4863                                            }
4864                                        }
4865                                    }
4866                                    break;
4867 
4868         case OMX_QcomIndexParamIndexExtraDataType: {
4869                                     VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
4870                                     QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
4871                                     if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
4872                                             (extradataIndexType->bEnabled == OMX_TRUE) &&
4873                                             (extradataIndexType->nPortIndex == 1)) {
4874                                         DEBUG_PRINT_HIGH("set_parameter:  OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
4875                                         eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
4876                                     } else if ((extradataIndexType->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataOutputCropInfo) &&
4877                                             (extradataIndexType->bEnabled == OMX_TRUE) &&
4878                                             (extradataIndexType->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX)) {
4879                                         eRet = enable_extradata(OMX_OUTPUTCROP_EXTRADATA, false,
4880                                             ((QOMX_ENABLETYPE *)paramData)->bEnable);
4881                                     }
4882                                 }
4883                                 break;
4884         case OMX_QcomIndexParamEnableSmoothStreaming: {
4885 #ifndef SMOOTH_STREAMING_DISABLED
4886                                       eRet = enable_smoothstreaming();
4887 #else
4888                                       eRet = OMX_ErrorUnsupportedSetting;
4889 #endif
4890                                   }
4891                                   break;
4892 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
4893                                   /* Need to allow following two set_parameters even in Idle
4894                                    * state. This is ANDROID architecture which is not in sync
4895                                    * with openmax standard. */
4896         case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
4897                                            VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
4898                                            EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
4899                                            if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
4900                                                 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!");
4901                                                 eRet = OMX_ErrorUnsupportedSetting;
4902                                                 break;
4903                                            } else if (m_out_mem_ptr) {
4904                                                 DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !");
4905                                                 eRet = OMX_ErrorInvalidState;
4906                                                 break;
4907                                            }
4908                                            if (enableNativeBuffers) {
4909                                                m_enable_android_native_buffers = enableNativeBuffers->enable;
4910                                            }
4911 #if !defined(FLEXYUV_SUPPORTED)
4912                                            if (m_enable_android_native_buffers) {
4913                                                // Use the most-preferred-native-color-format as surface-mode is hinted here
4914                                                if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
4915                                                    DEBUG_PRINT_ERROR("Failed to set native color format!");
4916                                                    eRet = OMX_ErrorUnsupportedSetting;
4917                                                }
4918                                            }
4919 #endif
4920                                        }
4921                                        break;
4922         case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
4923                                        VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
4924                                        eRet = use_android_native_buffer(hComp, paramData);
4925                                    }
4926                                    break;
4927 #if ALLOCATE_OUTPUT_NATIVEHANDLE
4928         case OMX_GoogleAndroidIndexAllocateNativeHandle: {
4929 
4930                 AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
4931                 VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams);
4932 
4933                 if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
4934                     DEBUG_PRINT_LOW("Enable/Disable allocate-native-handle allowed only on input port!. Please ignore this Unsupported Setting (0x80001019).");
4935                     eRet = OMX_ErrorUnsupportedSetting;
4936                     break;
4937                 } else if (m_inp_mem_ptr) {
4938                     DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !");
4939                     eRet = OMX_ErrorInvalidState;
4940                     break;
4941                 }
4942 
4943                 if (allocateNativeHandleParams != NULL) {
4944                     allocate_native_handle = allocateNativeHandleParams->enable;
4945                 }
4946             }
4947             break;
4948 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE
4949 #endif
4950         case OMX_QcomIndexParamEnableTimeStampReorder: {
4951                                        VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
4952                                        QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
4953                                        if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
4954                                            if (reorder->bEnable == OMX_TRUE) {
4955                                                frm_int =0;
4956                                                time_stamp_dts.set_timestamp_reorder_mode(true);
4957                                            } else
4958                                                time_stamp_dts.set_timestamp_reorder_mode(false);
4959                                        } else {
4960                                            time_stamp_dts.set_timestamp_reorder_mode(false);
4961                                            if (reorder->bEnable == OMX_TRUE) {
4962                                                eRet = OMX_ErrorUnsupportedSetting;
4963                                            }
4964                                        }
4965                                    }
4966                                    break;
4967         case OMX_IndexParamVideoProfileLevelCurrent: {
4968                                      VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
4969                                      OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
4970                                          (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
4971                                      if (pParam) {
4972                                          m_profile_lvl.eProfile = pParam->eProfile;
4973                                          m_profile_lvl.eLevel = pParam->eLevel;
4974                                      }
4975                                      break;
4976 
4977                                  }
4978         case OMX_QcomIndexParamVideoMetaBufferMode:
4979         {
4980             VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
4981             StoreMetaDataInBuffersParams *metabuffer =
4982                 (StoreMetaDataInBuffersParams *)paramData;
4983             if (!metabuffer) {
4984                 DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
4985                 eRet = OMX_ErrorBadParameter;
4986                 break;
4987             }
4988             if (m_disable_dynamic_buf_mode) {
4989                 DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled");
4990                 eRet = OMX_ErrorUnsupportedSetting;
4991                 break;
4992             }
4993             if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
4994 
4995                 if (m_out_mem_ptr) {
4996                     DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !");
4997                     eRet = OMX_ErrorInvalidState;
4998                     break;
4999                 }
5000 
5001                 dynamic_buf_mode = metabuffer->bStoreMetaData;
5002                 DEBUG_PRINT_HIGH("%s buffer mode",
5003                     (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
5004 
5005             } else {
5006                 DEBUG_PRINT_ERROR(
5007                    "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
5008                    (unsigned int)metabuffer->nPortIndex);
5009                 eRet = OMX_ErrorUnsupportedSetting;
5010             }
5011             break;
5012         }
5013         case OMX_QcomIndexParamVideoDownScalar:
5014         {
5015             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
5016             QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
5017             struct v4l2_control control;
5018             int rc;
5019             DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
5020 
5021             if (pParam && pParam->bEnable) {
5022                 rc = enable_downscalar();
5023                 if (rc < 0) {
5024                     DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
5025                     return OMX_ErrorUnsupportedSetting;
5026                 }
5027                 m_force_down_scalar = pParam->bEnable;
5028             } else {
5029                 rc = disable_downscalar();
5030                 if (rc < 0) {
5031                     DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
5032                     return OMX_ErrorUnsupportedSetting;
5033                 }
5034                 m_force_down_scalar = pParam->bEnable;
5035             }
5036             break;
5037         }
5038 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5039         case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
5040         {
5041             VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
5042             DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
5043             PrepareForAdaptivePlaybackParams* pParams =
5044                     (PrepareForAdaptivePlaybackParams *) paramData;
5045             if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
5046                 if (!pParams->bEnable) {
5047                     return OMX_ErrorNone;
5048                 }
5049                 if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
5050                         || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
5051                     DEBUG_PRINT_ERROR(
5052                             "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
5053                              (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
5054                              (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
5055                     eRet = OMX_ErrorBadParameter;
5056                 } else {
5057                     eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
5058                 }
5059             } else {
5060                 DEBUG_PRINT_ERROR(
5061                         "Prepare for adaptive playback supported only on output port");
5062                 eRet = OMX_ErrorBadParameter;
5063             }
5064             break;
5065         }
5066 
5067         case OMX_QTIIndexParamVideoPreferAdaptivePlayback:
5068         {
5069             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
5070             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback");
5071             m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable;
5072             if (m_disable_dynamic_buf_mode) {
5073                 DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set");
5074             }
5075             break;
5076         }
5077 #endif
5078         case OMX_QcomIndexParamVideoCustomBufferSize:
5079         {
5080             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
5081             DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
5082             QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
5083             if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5084                 struct v4l2_control control;
5085                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
5086                 control.value = pParam->nBufferSize;
5087                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5088                     DEBUG_PRINT_ERROR("Failed to set input buffer size");
5089                     eRet = OMX_ErrorUnsupportedSetting;
5090                 } else {
5091                     eRet = get_buffer_req(&drv_ctx.ip_buf);
5092                     if (eRet == OMX_ErrorNone) {
5093                         m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
5094                         DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
5095                             m_custom_buffersize.input_buffersize);
5096                     } else {
5097                         DEBUG_PRINT_ERROR("Failed to get buffer requirement");
5098                     }
5099                 }
5100             } else {
5101                 DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
5102                 eRet = OMX_ErrorBadParameter;
5103             }
5104             break;
5105         }
5106         case OMX_QTIIndexParamVQZIPSEIType:
5107         {
5108             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE);
5109             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType");
5110             OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
5111                 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
5112                 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
5113 
5114             eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
5115                 ((QOMX_ENABLETYPE *)paramData)->bEnable);
5116             if (eRet != OMX_ErrorNone) {
5117                 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
5118                 eRet = OMX_ErrorBadParameter;
5119                 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5120                 break;
5121             }
5122             eRet = enable_extradata(OMX_QP_EXTRADATA, false,
5123                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
5124             if (eRet != OMX_ErrorNone) {
5125                 DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
5126                 eRet = OMX_ErrorBadParameter;
5127                 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5128                 client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
5129                 break;
5130             }
5131             eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
5132                         ((QOMX_ENABLETYPE *)paramData)->bEnable);
5133             if (eRet != OMX_ErrorNone) {
5134                 DEBUG_PRINT_ERROR("ERROR: Failed to set FrameInfo Extradata");
5135                 eRet = OMX_ErrorBadParameter;
5136                 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
5137                 client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
5138                 client_extradata = client_extradata & ~OMX_FRAMEINFO_EXTRADATA;
5139             }
5140             break;
5141         }
5142         case OMX_QTIIndexParamPassInputBufferFd:
5143         {
5144             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
5145             if (arbitrary_bytes) {
5146                 DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode");
5147                 eRet = OMX_ErrorUnsupportedSetting;
5148                 break;
5149             }
5150 
5151             m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable;
5152             if (m_input_pass_buffer_fd)
5153                 DEBUG_PRINT_LOW("Enable passing input buffer FD");
5154             break;
5155         }
5156         case OMX_QTIIndexParamForceCompressedForDPB:
5157         {
5158             VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE);
5159             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB");
5160             OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam =
5161                 (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData;
5162             if (m_disable_ubwc_mode) {
5163                 DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled");
5164                 eRet = OMX_ErrorUnsupportedSetting;
5165                 break;
5166             }
5167             if (!paramData) {
5168                DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL");
5169                eRet = OMX_ErrorBadParameter;
5170                break;
5171             }
5172 
5173             m_force_compressed_for_dpb = pParam->bEnable;
5174             break;
5175         }
5176         case OMX_QTIIndexParamForceUnCompressedForOPB:
5177         {
5178             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB");
5179             OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam =
5180                 (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData;
5181             if (!paramData) {
5182                 DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL");
5183                 eRet = OMX_ErrorBadParameter;
5184                 break;
5185             }
5186             m_disable_ubwc_mode = pParam->bEnable;
5187             DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled");
5188             break;
5189         }
5190         case OMX_QTIIndexParamDitherControl:
5191         {
5192             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DITHER_CONTROL);
5193             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamDitherControl");
5194             QOMX_VIDEO_DITHER_CONTROL *pParam = (QOMX_VIDEO_DITHER_CONTROL *)paramData;
5195             DEBUG_PRINT_LOW("set_parameter: Dither Config from client is: %d", pParam->eDitherType);
5196             if (( pParam->eDitherType < QOMX_DITHER_DISABLE ) ||
5197                 ( pParam->eDitherType > QOMX_DITHER_ALL_COLORSPACE)) {
5198                 DEBUG_PRINT_ERROR("set_parameter: DitherType outside the range");
5199                 eRet = OMX_ErrorBadParameter;
5200                 break;
5201             }
5202             m_dither_config = is_platform_tp10capture_supported() ? (dither_type)pParam->eDitherType : DITHER_ALL_COLORSPACE;
5203             DEBUG_PRINT_LOW("set_parameter: Final Dither Config is: %d", m_dither_config);
5204             break;
5205         }
5206         case OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency:
5207         {
5208             VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
5209             DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency");
5210             OMX_VIDEO_PARAM_PROFILELEVELTYPE *pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
5211 
5212             if ((output_capability != V4L2_PIX_FMT_H264) ||
5213                 (output_capability != V4L2_PIX_FMT_HEVC)) {
5214                 DEBUG_PRINT_ERROR("set_parameter: Unsupported codec for client configured profile and level");
5215                 eRet = OMX_ErrorBadParameter;
5216             }
5217 
5218             DEBUG_PRINT_LOW("set_parameter: Client set profile is: %d", pParam->eProfile);
5219             DEBUG_PRINT_LOW("set_parameter: Client set level is: %d", pParam->eLevel);
5220             mClientSessionForSufficiency = true;
5221             mClientSetProfile = pParam->eProfile;
5222             mClientSetLevel = pParam->eLevel;
5223             break;
5224         }
5225         default: {
5226                  DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
5227                  eRet = OMX_ErrorUnsupportedIndex;
5228              }
5229     }
5230     if (eRet != OMX_ErrorNone)
5231         DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
5232     return eRet;
5233 }
5234 
5235 /* ======================================================================
5236    FUNCTION
5237    omx_vdec::GetConfig
5238 
5239    DESCRIPTION
5240    OMX Get Config Method implementation.
5241 
5242    PARAMETERS
5243    <TBD>.
5244 
5245    RETURN VALUE
5246    OMX Error None if successful.
5247 
5248    ========================================================================== */
get_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_INOUT OMX_PTR configData)5249 OMX_ERRORTYPE  omx_vdec::get_config(OMX_IN OMX_HANDLETYPE      hComp,
5250         OMX_IN OMX_INDEXTYPE configIndex,
5251         OMX_INOUT OMX_PTR     configData)
5252 {
5253     (void) hComp;
5254     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5255 
5256     if (m_state == OMX_StateInvalid) {
5257         DEBUG_PRINT_ERROR("Get Config in Invalid State");
5258         return OMX_ErrorInvalidState;
5259     }
5260 
5261     switch ((unsigned long)configIndex) {
5262         case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
5263                                      VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
5264                                      QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
5265                                          (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
5266                                      decoderinstances->nNumOfInstances = 16;
5267                                      /*TODO: How to handle this case */
5268                                      break;
5269                                  }
5270         case OMX_QcomIndexConfigVideoFramePackingArrangement: {
5271                                           if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
5272                                               VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
5273                                               OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
5274                                                   (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
5275                                               memcpy(configFmt, &m_frame_pack_arrangement,
5276                                                   sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
5277                                           } else {
5278                                               DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
5279                                           }
5280                                           break;
5281                                       }
5282         case OMX_IndexConfigCommonOutputCrop: {
5283                                   VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
5284                                   OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
5285                                   memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
5286                                   DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
5287                                         rectangle.nLeft, rectangle.nTop,
5288                                         rectangle.nWidth, rectangle.nHeight);
5289                                   break;
5290                               }
5291         case OMX_QcomIndexConfigH264EntropyCodingCabac: {
5292             VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE);
5293             QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
5294             struct v4l2_control control;
5295 
5296             if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
5297                 DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
5298                 eRet = OMX_ErrorNotImplemented;
5299                 break;
5300             }
5301 
5302             control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
5303             if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
5304                 coding->bCabac = (OMX_BOOL)
5305                     (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
5306                 /* We can't query driver at the moment for the cabac mode, so
5307                  * just use 0xff...f as a place holder for future improvement */
5308                 coding->nCabacInitIdc = ~0;
5309             } else {
5310                 eRet = OMX_ErrorUnsupportedIndex;
5311             }
5312 
5313             break;
5314         }
5315         case OMX_QTIIndexConfigDescribeColorAspects:
5316         {
5317             VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5318             DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5319 
5320             if (params->bRequestingDataSpace) {
5321                 DEBUG_PRINT_LOW("Does not handle dataspace request. Please ignore this Unsupported Setting (0x80001019).");
5322                 return OMX_ErrorUnsupportedSetting;
5323             }
5324 
5325             print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client");
5326             print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal");
5327             get_preferred_color_aspects(params->sAspects);
5328             print_debug_color_aspects(&(params->sAspects), "GetConfig");
5329 
5330             break;
5331         }
5332         case OMX_QTIIndexConfigDescribeHDRColorInfo:
5333         {
5334             VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5335             DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5336             print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "GetConfig Client HDR");
5337             print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "GetConfig Internal HDR");
5338             get_preferred_hdr_info(params->sInfo);
5339             print_debug_hdr_color_info(&(params->sInfo), "GetConfig HDR");
5340 
5341             break;
5342         }
5343         case OMX_IndexConfigAndroidVendorExtension:
5344         {
5345             VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5346 
5347             OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5348                 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5349             VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5350             return get_vendor_extension_config(ext);
5351         }
5352         default:
5353         {
5354             DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
5355             eRet = OMX_ErrorBadParameter;
5356         }
5357 
5358     }
5359 
5360     return eRet;
5361 }
5362 
5363 /* ======================================================================
5364    FUNCTION
5365    omx_vdec::SetConfig
5366 
5367    DESCRIPTION
5368    OMX Set Config method implementation
5369 
5370    PARAMETERS
5371    <TBD>.
5372 
5373    RETURN VALUE
5374    OMX Error None if successful.
5375    ========================================================================== */
set_config(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_INDEXTYPE configIndex,OMX_IN OMX_PTR configData)5376 OMX_ERRORTYPE  omx_vdec::set_config(OMX_IN OMX_HANDLETYPE      hComp,
5377         OMX_IN OMX_INDEXTYPE configIndex,
5378         OMX_IN OMX_PTR        configData)
5379 {
5380     (void) hComp;
5381     if (m_state == OMX_StateInvalid) {
5382         DEBUG_PRINT_ERROR("Get Config in Invalid State");
5383         return OMX_ErrorInvalidState;
5384     }
5385 
5386     OMX_ERRORTYPE ret = OMX_ErrorNone;
5387     OMX_VIDEO_CONFIG_NALSIZE *pNal;
5388 
5389     DEBUG_PRINT_LOW("Set Config Called");
5390 
5391 
5392     if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
5393         OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
5394         DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
5395 
5396         if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
5397             if (config->bEnabled) {
5398                 if ((config->nFps >> 16) > 0 &&
5399                         (config->nFps >> 16) <= MAX_SUPPORTED_FPS) {
5400                     m_fps_received = config->nFps;
5401                     DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
5402                             (unsigned int)config->nFps >> 16);
5403                     Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
5404                             drv_ctx.frame_rate.fps_denominator);
5405 
5406                     if (!drv_ctx.frame_rate.fps_numerator) {
5407                         DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
5408                         drv_ctx.frame_rate.fps_numerator = 30;
5409                     }
5410 
5411                     if (drv_ctx.frame_rate.fps_denominator) {
5412                         drv_ctx.frame_rate.fps_numerator = (int)
5413                             drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
5414                     }
5415 
5416                     drv_ctx.frame_rate.fps_denominator = 1;
5417                     frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
5418                         drv_ctx.frame_rate.fps_numerator;
5419 
5420                     struct v4l2_outputparm oparm;
5421                     /*XXX: we're providing timing info as seconds per frame rather than frames
5422                      * per second.*/
5423                     oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
5424                     oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
5425 
5426                     struct v4l2_streamparm sparm;
5427                     sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
5428                     sparm.parm.output = oparm;
5429                     if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
5430                         DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
5431                                 performance might be affected");
5432                         ret = OMX_ErrorHardware;
5433                     }
5434                     client_set_fps = true;
5435                 } else {
5436                     DEBUG_PRINT_ERROR("Frame rate not supported.");
5437                     ret = OMX_ErrorUnsupportedSetting;
5438                 }
5439             } else {
5440                 DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
5441                 client_set_fps = false;
5442             }
5443         } else {
5444             DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
5445                     (int)config->nPortIndex);
5446             ret = OMX_ErrorBadPortIndex;
5447         }
5448 
5449         return ret;
5450     } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) {
5451         OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config =
5452             (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData;
5453         struct v4l2_control control;
5454         DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType);
5455         control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE;
5456 
5457         switch (config->eDecodeType) {
5458             case OMX_QCOM_PictypeDecode_I:
5459                 control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_I;
5460                 break;
5461             case OMX_QCOM_PictypeDecode_IPB:
5462             default:
5463                 control.value = (V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_I|
5464                                   V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_P|
5465                                   V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_B);
5466                 break;
5467         }
5468 
5469         ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
5470                 OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
5471         if (ret)
5472             DEBUG_PRINT_ERROR("Failed to set picture type decode");
5473 
5474         return ret;
5475     } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
5476         OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
5477         DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
5478 
5479         struct v4l2_control control;
5480 
5481         control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
5482         if (priority->nU32 == 0)
5483             control.value = V4L2_MPEG_MSM_VIDC_ENABLE;
5484         else
5485             control.value = V4L2_MPEG_MSM_VIDC_DISABLE;
5486 
5487         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5488             DEBUG_PRINT_ERROR("Failed to set Priority");
5489             ret = OMX_ErrorUnsupportedSetting;
5490         }
5491         return ret;
5492     } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
5493         OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
5494         DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
5495 
5496         struct v4l2_control control;
5497 
5498         control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
5499         control.value = rate->nU32;
5500 
5501         if (rate->nU32 == QOMX_VIDEO_HIGH_PERF_OPERATING_MODE) {
5502             DEBUG_PRINT_LOW("Turbo mode requested");
5503             m_client_req_turbo_mode = true;
5504         } else {
5505             operating_frame_rate = rate->nU32 >> 16;
5506             m_client_req_turbo_mode = false;
5507             DEBUG_PRINT_LOW("Operating Rate Set = %d fps",  operating_frame_rate);
5508         }
5509 
5510         if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
5511             ret = errno == -EBUSY ? OMX_ErrorInsufficientResources :
5512                     OMX_ErrorUnsupportedSetting;
5513             DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
5514                     rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
5515         }
5516         return ret;
5517 
5518     } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
5519         VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
5520         DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
5521         if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) {
5522             enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, false, true);
5523         }
5524 
5525         print_debug_color_aspects(&(params->sAspects), "Set Config");
5526         memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
5527         return ret;
5528     } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeHDRColorInfo) {
5529         VALIDATE_OMX_PARAM_DATA(configData, DescribeHDRStaticInfoParams);
5530         DescribeHDRStaticInfoParams *params = (DescribeHDRStaticInfoParams *)configData;
5531         ret = enable_extradata(OMX_HDR_COLOR_INFO_EXTRADATA, false, true);
5532         if (ret != OMX_ErrorNone) {
5533             DEBUG_PRINT_ERROR("Failed to enable OMX_HDR_COLOR_INFO_EXTRADATA");
5534             return ret;
5535         }
5536 
5537         print_debug_hdr_color_info(&(params->sInfo), "Set Config HDR");
5538         memcpy(&m_client_hdr_info, params, sizeof(DescribeHDRStaticInfoParams));
5539         return ret;
5540 
5541     } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) {
5542         VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
5543 
5544         OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
5545                 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
5546         VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
5547 
5548         return set_vendor_extension_config(ext);
5549     }
5550 
5551     return OMX_ErrorNotImplemented;
5552 }
5553 
5554 #define extn_equals(param, extn) (!strcmp(param, extn))
5555 
5556 /* ======================================================================
5557    FUNCTION
5558    omx_vdec::GetExtensionIndex
5559 
5560    DESCRIPTION
5561    OMX GetExtensionIndex method implementaion.  <TBD>
5562 
5563    PARAMETERS
5564    <TBD>.
5565 
5566    RETURN VALUE
5567    OMX Error None if everything successful.
5568 
5569    ========================================================================== */
get_extension_index(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_STRING paramName,OMX_OUT OMX_INDEXTYPE * indexType)5570 OMX_ERRORTYPE  omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE      hComp,
5571         OMX_IN OMX_STRING      paramName,
5572         OMX_OUT OMX_INDEXTYPE* indexType)
5573 {
5574     (void) hComp;
5575     if (m_state == OMX_StateInvalid) {
5576         DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
5577         return OMX_ErrorInvalidState;
5578     } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
5579         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
5580     } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
5581         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
5582     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
5583         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
5584     } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
5585         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
5586     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
5587         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
5588     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
5589         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
5590     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
5591         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
5592     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNOUTPUTCROP_EXTRADATA)) {
5593         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamOutputCropExtraData;
5594     }
5595 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
5596     else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
5597         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
5598     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
5599         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
5600     } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
5601         DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
5602         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
5603     } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
5604         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
5605     }
5606 #if ALLOCATE_OUTPUT_NATIVEHANDLE
5607     else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
5608         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
5609     }
5610 #endif //ALLOCATE_OUTPUT_NATIVEHANDLE
5611 #endif
5612     else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
5613         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
5614     }
5615 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
5616     else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
5617         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
5618     } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
5619         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
5620     }
5621 #endif
5622 #ifdef FLEXYUV_SUPPORTED
5623     else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
5624         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
5625     }
5626 #endif
5627     else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
5628         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
5629     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
5630         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
5631     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
5632         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
5633     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.LowLatency")) {
5634         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode;
5635     } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) {
5636         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata;
5637     } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
5638         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
5639     } else if (extn_equals(paramName, "OMX.google.android.index.describeHDRStaticInfo")) {
5640         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDRColorInfo;
5641     } else if (extn_equals(paramName, "OMX.QTI.index.param.ClientConfiguredProfileLevel")) {
5642         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency;
5643     }else {
5644         DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
5645         return OMX_ErrorNotImplemented;
5646     }
5647     return OMX_ErrorNone;
5648 }
5649 
5650 /* ======================================================================
5651    FUNCTION
5652    omx_vdec::GetState
5653 
5654    DESCRIPTION
5655    Returns the state information back to the caller.<TBD>
5656 
5657    PARAMETERS
5658    <TBD>.
5659 
5660    RETURN VALUE
5661    Error None if everything is successful.
5662    ========================================================================== */
get_state(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_STATETYPE * state)5663 OMX_ERRORTYPE  omx_vdec::get_state(OMX_IN OMX_HANDLETYPE  hComp,
5664         OMX_OUT OMX_STATETYPE* state)
5665 {
5666     (void) hComp;
5667     *state = m_state;
5668     DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
5669     return OMX_ErrorNone;
5670 }
5671 
5672 /* ======================================================================
5673    FUNCTION
5674    omx_vdec::ComponentTunnelRequest
5675 
5676    DESCRIPTION
5677    OMX Component Tunnel Request method implementation. <TBD>
5678 
5679    PARAMETERS
5680    None.
5681 
5682    RETURN VALUE
5683    OMX Error None if everything successful.
5684 
5685    ========================================================================== */
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)5686 OMX_ERRORTYPE  omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE  hComp,
5687         OMX_IN OMX_U32                        port,
5688         OMX_IN OMX_HANDLETYPE        peerComponent,
5689         OMX_IN OMX_U32                    peerPort,
5690         OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
5691 {
5692     (void) hComp;
5693     (void) port;
5694     (void) peerComponent;
5695     (void) peerPort;
5696     (void) tunnelSetup;
5697     DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
5698     return OMX_ErrorNotImplemented;
5699 }
5700 
5701 
5702 
5703 /* ======================================================================
5704    FUNCTION
5705    omx_vdec::ion_map
5706 
5707    DESCRIPTION
5708    Map the memory and run the ioctl SYNC operations
5709    on ION fd with DMA_BUF_IOCTL_SYNC
5710 
5711    PARAMETERS
5712    fd    : ION fd
5713    len   : Lenth of the memory
5714 
5715    RETURN VALUE
5716    ERROR: mapped memory pointer
5717 
5718    ========================================================================== */
ion_map(int fd,int len)5719 char *omx_vdec::ion_map(int fd, int len)
5720 {
5721     char *bufaddr = (char*)mmap(NULL, len, PROT_READ|PROT_WRITE,
5722                                 MAP_SHARED, fd, 0);
5723     if (bufaddr != MAP_FAILED) {
5724 #ifdef USE_ION
5725     do_cache_operations(fd);
5726 #endif
5727     }
5728     return bufaddr;
5729 }
5730 
5731 /* ======================================================================
5732    FUNCTION
5733    omx_vdec::ion_unmap
5734 
5735    DESCRIPTION
5736    Unmap the memory
5737 
5738    PARAMETERS
5739    fd      : ION fd
5740    bufaddr : buffer address
5741    len     : Lenth of the memory
5742 
5743    RETURN VALUE
5744    OMX_Error*
5745 
5746    ========================================================================== */
ion_unmap(int fd,void * bufaddr,int len)5747 OMX_ERRORTYPE omx_vdec::ion_unmap(int fd, void *bufaddr, int len)
5748 {
5749 #ifdef USE_ION
5750     do_cache_operations(fd);
5751 #else
5752     (void)fd;
5753 #endif
5754     if (-1 == munmap(bufaddr, len)) {
5755         DEBUG_PRINT_ERROR("munmap failed.");
5756         return OMX_ErrorInsufficientResources;
5757     }
5758     return OMX_ErrorNone;
5759 }
5760 
5761 /* ======================================================================
5762    FUNCTION
5763    omx_vdec::UseOutputBuffer
5764 
5765    DESCRIPTION
5766    Helper function for Use buffer in the input pin
5767 
5768    PARAMETERS
5769    None.
5770 
5771    RETURN VALUE
5772    true/false
5773 
5774    ========================================================================== */
allocate_extradata()5775 OMX_ERRORTYPE omx_vdec::allocate_extradata()
5776 {
5777 #ifdef USE_ION
5778     if (drv_ctx.extradata_info.buffer_size) {
5779         if (drv_ctx.extradata_info.ion.data_fd >= 0) {
5780             free_extradata();
5781         }
5782 
5783         drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
5784         // Decoder extradata is always uncached as buffer sizes are very small
5785         bool status = alloc_map_ion_memory(
5786                 drv_ctx.extradata_info.size, &drv_ctx.extradata_info.ion, 0);
5787         if (status == false) {
5788             DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
5789             return OMX_ErrorInsufficientResources;
5790         }
5791         DEBUG_PRINT_HIGH("Allocated extradata size : %d fd: %d",
5792             drv_ctx.extradata_info.size, drv_ctx.extradata_info.ion.data_fd);
5793         drv_ctx.extradata_info.uaddr = ion_map(drv_ctx.extradata_info.ion.data_fd,
5794                                                drv_ctx.extradata_info.size);
5795         if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
5796             DEBUG_PRINT_ERROR("Failed to map extradata memory");
5797             free_ion_memory(&drv_ctx.extradata_info.ion);
5798             return OMX_ErrorInsufficientResources;
5799         }
5800     }
5801 #endif
5802     return OMX_ErrorNone;
5803 }
5804 
free_extradata()5805 void omx_vdec::free_extradata()
5806 {
5807 #ifdef USE_ION
5808     if (drv_ctx.extradata_info.uaddr) {
5809         ion_unmap(drv_ctx.extradata_info.ion.data_fd,
5810                   (void *)drv_ctx.extradata_info.uaddr,
5811                   drv_ctx.extradata_info.ion.alloc_data.len);
5812         free_ion_memory(&drv_ctx.extradata_info.ion);
5813         drv_ctx.extradata_info.uaddr = NULL;
5814         drv_ctx.extradata_info.ion.data_fd = -1;
5815     }
5816 #endif
5817 }
5818 
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)5819 OMX_ERRORTYPE  omx_vdec::use_output_buffer(
5820         OMX_IN OMX_HANDLETYPE            hComp,
5821         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
5822         OMX_IN OMX_U32                   port,
5823         OMX_IN OMX_PTR                   appData,
5824         OMX_IN OMX_U32                   bytes,
5825         OMX_IN OMX_U8*                   buffer)
5826 {
5827     OMX_ERRORTYPE eRet = OMX_ErrorNone;
5828     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
5829     unsigned                         i= 0; // Temporary counter
5830     OMX_PTR privateAppData = NULL;
5831     private_handle_t *handle = NULL;
5832     OMX_U8 *buff = buffer;
5833     bool intermediate = client_buffers.is_color_conversion_enabled();
5834     (void) hComp;
5835     (void) port;
5836 
5837     if (!m_out_mem_ptr) {
5838         DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers C2D(%d)",
5839                          client_buffers.is_color_conversion_enabled());
5840         eRet = allocate_output_headers();
5841         if (eRet == OMX_ErrorNone)
5842             eRet = allocate_extradata();
5843         output_use_buffer = true;
5844     }
5845 
5846     OMX_BUFFERHEADERTYPE  **omx_base_address =
5847         intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
5848 
5849     if (eRet == OMX_ErrorNone) {
5850         for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
5851             if (BITMASK_ABSENT(&m_out_bm_count,i)) {
5852                 break;
5853             }
5854         }
5855     }
5856 
5857     if (i >= drv_ctx.op_buf.actualcount) {
5858         DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
5859         return OMX_ErrorInsufficientResources;
5860     }
5861 
5862     if (intermediate) {
5863         DEBUG_PRINT_HIGH("Use_op_buf:Allocating intermediate output. %d", i);
5864         OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
5865         eRet = allocate_output_buffer(hComp, &temp_bufferHdr,
5866                                       port, appData,
5867                                       drv_ctx.op_buf.buffer_size,
5868                                       true, i);
5869     }
5870 
5871     if (eRet == OMX_ErrorNone && dynamic_buf_mode) {
5872         *bufferHdr = (m_out_mem_ptr + i );
5873         (*bufferHdr)->pBuffer = NULL;
5874         if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
5875             enum v4l2_buf_type buf_type;
5876             int rr = 0;
5877             DEBUG_PRINT_LOW("USE intermediate bufferSTREAMON(CAPTURE_MPLANE)");
5878             set_buffer_req(&drv_ctx.op_buf);
5879             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
5880             if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
5881                 DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
5882                 return OMX_ErrorInsufficientResources;
5883             } else {
5884                 streaming[CAPTURE_PORT] = true;
5885                 DEBUG_PRINT_LOW("STREAMON Successful");
5886             }
5887         }
5888         BITMASK_SET(&m_out_bm_count,i);
5889         (*bufferHdr)->pAppPrivate = appData;
5890         (*bufferHdr)->pBuffer = buffer;
5891         (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
5892         return eRet;
5893     }
5894 
5895     if (eRet == OMX_ErrorNone) {
5896 #if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
5897         if (m_enable_android_native_buffers) {
5898             if (m_use_android_native_buffers) {
5899                 UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
5900                 sp<android_native_buffer_t> nBuf = params->nativeBuffer;
5901                 handle = (private_handle_t *)nBuf->handle;
5902                 privateAppData = params->pAppPrivate;
5903             } else {
5904                 handle = (private_handle_t *)buff;
5905                 privateAppData = appData;
5906             }
5907             if (!handle) {
5908                 DEBUG_PRINT_ERROR("handle is invalid");
5909                 return OMX_ErrorBadParameter;
5910             }
5911 
5912             if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
5913                 if (secure_mode && secure_scaling_to_non_secure_opb) {
5914                     DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
5915                         (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5916                 } else {
5917                     DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
5918                             " expected %u, got %u",
5919                             (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
5920                     return OMX_ErrorBadParameter;
5921                 }
5922             }
5923 
5924             drv_ctx.op_buf.buffer_size = handle->size;
5925 
5926             if (!m_use_android_native_buffers) {
5927                 if (!secure_mode) {
5928                     buff = (OMX_U8*)ion_map(handle->fd, handle->size);
5929                     if (buff == MAP_FAILED) {
5930                         DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
5931                         return OMX_ErrorInsufficientResources;
5932                     }
5933                 }
5934             }
5935 #if defined(_ANDROID_ICS_)
5936             native_buffer[i].nativehandle = handle;
5937             native_buffer[i].privatehandle = handle;
5938 #endif
5939             if (!handle) {
5940                 DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
5941                 return OMX_ErrorBadParameter;
5942             }
5943             drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
5944             drv_ctx.ptr_outputbuffer[i].offset = 0;
5945             drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
5946             drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
5947             drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
5948         } else
5949 #endif
5950             if (!ouput_egl_buffers && !m_use_output_pmem) {
5951 #ifdef USE_GBM
5952                bool status = alloc_map_gbm_memory(
5953                        drv_ctx.video_resolution.frame_width,
5954                        drv_ctx.video_resolution.frame_height,
5955                        drv_ctx.gbm_device_fd,
5956                        &drv_ctx.op_buf_gbm_info[i],
5957                        secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
5958                 if (status == false) {
5959                     DEBUG_PRINT_ERROR("ION device fd is bad %d",
5960                                       (int) drv_ctx.op_buf_ion_info[i].data_fd);
5961                     return OMX_ErrorInsufficientResources;
5962                 }
5963                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5964                                      drv_ctx.op_buf_gbm_info[i].bo_fd;
5965                 if (intermediate)
5966                    m_pmem_info[i].pmeta_fd = drv_ctx.op_buf_gbm_info[i].meta_fd;
5967 #elif defined USE_ION
5968                 bool status = alloc_map_ion_memory(
5969                         drv_ctx.op_buf.buffer_size, &drv_ctx.op_buf_ion_info[i],
5970                         secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
5971                 if (status == false) {
5972                     DEBUG_PRINT_ERROR("ION device fd is bad %d",
5973                                       (int) drv_ctx.op_buf_ion_info[i].data_fd);
5974                     return OMX_ErrorInsufficientResources;
5975                 }
5976                 drv_ctx.ptr_outputbuffer[i].pmem_fd = \
5977                                      drv_ctx.op_buf_ion_info[i].data_fd;
5978 #endif
5979                 if (!secure_mode) {
5980                     drv_ctx.ptr_outputbuffer[i].bufferaddr =
5981                         (unsigned char *)ion_map(drv_ctx.ptr_outputbuffer[i].pmem_fd,
5982                                                  drv_ctx.op_buf.buffer_size);
5983                     if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
5984 #ifdef USE_GBM
5985                         free_gbm_memory(&drv_ctx.op_buf_gbm_info[i]);
5986 #elif defined USE_ION
5987                         free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
5988 #endif
5989                         DEBUG_PRINT_ERROR("Unable to mmap output buffer");
5990                         return OMX_ErrorInsufficientResources;
5991                     }
5992                 }
5993                 drv_ctx.ptr_outputbuffer[i].offset = 0;
5994                 privateAppData = appData;
5995             } else {
5996                 DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
5997                 if (!appData || !bytes ) {
5998                     if (!secure_mode && !buffer) {
5999                         DEBUG_PRINT_ERROR("Bad parameters for use buffer");
6000                         return OMX_ErrorBadParameter;
6001                     }
6002                 }
6003 
6004                 OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
6005                 OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
6006                 pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
6007                 if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
6008                         !pmem_list->nEntries ||
6009                         pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
6010                     DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
6011                     return OMX_ErrorBadParameter;
6012                 }
6013                 pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6014                     pmem_list->entryList->entry;
6015                 DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
6016                         pmem_info->pmem_fd);
6017                 drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
6018 #ifdef USE_GBM
6019                 if (intermediate)
6020                    m_pmem_info[i].pmeta_fd = pmem_info->pmeta_fd;
6021 #endif
6022                 drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
6023                 drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
6024                 drv_ctx.ptr_outputbuffer[i].mmaped_size =
6025                     drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
6026                 privateAppData = appData;
6027             }
6028         if (intermediate) {
6029             m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
6030             m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
6031             m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
6032             m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
6033             m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
6034         }
6035         *bufferHdr = (m_out_mem_ptr + i );
6036 
6037         if (secure_mode)
6038             drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
6039 
6040         if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
6041             enum v4l2_buf_type buf_type;
6042             buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6043             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
6044                 return OMX_ErrorInsufficientResources;
6045             } else {
6046                 streaming[CAPTURE_PORT] = true;
6047                 DEBUG_PRINT_LOW("STREAMON Successful");
6048             }
6049         }
6050 
6051         (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
6052         if (m_enable_android_native_buffers) {
6053             DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
6054             (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
6055         } else {
6056             (*bufferHdr)->pBuffer = buff;
6057         }
6058         (*bufferHdr)->pAppPrivate = privateAppData;
6059         BITMASK_SET(&m_out_bm_count,i);
6060     }
6061     return eRet;
6062 }
6063 
allocate_client_output_extradata_headers()6064 OMX_ERRORTYPE omx_vdec::allocate_client_output_extradata_headers() {
6065     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6066     OMX_BUFFERHEADERTYPE *bufHdr = NULL;
6067     int i = 0;
6068 
6069     if (!m_client_output_extradata_mem_ptr) {
6070         int nBufferCount       = 0;
6071 
6072         nBufferCount = m_client_out_extradata_info.getBufferCount();
6073         DEBUG_PRINT_HIGH("allocate_client_output_extradata_headers buffer_count - %d", nBufferCount);
6074 
6075         m_client_output_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE));
6076 
6077         if (m_client_output_extradata_mem_ptr) {
6078             bufHdr          =  m_client_output_extradata_mem_ptr;
6079             for (i=0; i < nBufferCount; i++) {
6080                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
6081                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
6082                 // Set the values when we determine the right HxW param
6083                 bufHdr->nAllocLen          = 0;
6084                 bufHdr->nFilledLen         = 0;
6085                 bufHdr->pAppPrivate        = NULL;
6086                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_EXTRADATA_INDEX;
6087                 bufHdr->pBuffer            = NULL;
6088                 bufHdr->pOutputPortPrivate = NULL;
6089                 bufHdr++;
6090             }
6091         } else {
6092              DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\
6093                     m_client_output_extradata_mem_ptr);
6094               eRet =  OMX_ErrorInsufficientResources;
6095         }
6096     }
6097     return eRet;
6098 }
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)6099 OMX_ERRORTYPE  omx_vdec::use_client_output_extradata_buffer(
6100         OMX_IN OMX_HANDLETYPE            hComp,
6101         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6102         OMX_IN OMX_U32                   port,
6103         OMX_IN OMX_PTR                   appData,
6104         OMX_IN OMX_U32                   bytes,
6105         OMX_IN OMX_U8*                   buffer)
6106 {
6107     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6108     unsigned i = 0; // Temporary counter
6109     unsigned buffer_count = m_client_out_extradata_info.getBufferCount();;
6110     OMX_U32 buffer_size = m_client_out_extradata_info.getSize();
6111     (void) hComp;
6112 
6113     if (port != OMX_CORE_OUTPUT_EXTRADATA_INDEX ||
6114             !client_extradata || bytes != buffer_size|| bufferHdr == NULL) {
6115         DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d,"
6116             "client_extradata - %d, bytes = %d expected is %d bufferHdr - %p", port,
6117             OMX_CORE_OUTPUT_EXTRADATA_INDEX, client_extradata, bytes, buffer_size, bufferHdr);
6118         eRet = OMX_ErrorBadParameter;
6119         return eRet;
6120     }
6121 
6122     if (!m_client_output_extradata_mem_ptr) {
6123         eRet = allocate_client_output_extradata_headers();
6124     }
6125 
6126     if (eRet == OMX_ErrorNone) {
6127         for (i = 0; i < buffer_count; i++) {
6128             if (BITMASK_ABSENT(&m_out_extradata_bm_count,i)) {
6129                 break;
6130             }
6131         }
6132     }
6133 
6134     if (i >= buffer_count) {
6135         DEBUG_PRINT_ERROR("Already using %d Extradata o/p buffers", buffer_count);
6136         eRet = OMX_ErrorInsufficientResources;
6137     }
6138 
6139     if (eRet == OMX_ErrorNone) {
6140         BITMASK_SET(&m_out_extradata_bm_count,i);
6141         *bufferHdr = (m_client_output_extradata_mem_ptr + i );
6142         (*bufferHdr)->pAppPrivate = appData;
6143         (*bufferHdr)->pBuffer = buffer;
6144         (*bufferHdr)->nAllocLen = bytes;
6145     }
6146 
6147     return eRet;
6148 }
6149 /* ======================================================================
6150    FUNCTION
6151    omx_vdec::use_input_heap_buffers
6152 
6153    DESCRIPTION
6154    OMX Use Buffer Heap allocation method implementation.
6155 
6156    PARAMETERS
6157    <TBD>.
6158 
6159    RETURN VALUE
6160    OMX Error None , if everything successful.
6161 
6162    ========================================================================== */
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)6163 OMX_ERRORTYPE  omx_vdec::use_input_heap_buffers(
6164         OMX_IN OMX_HANDLETYPE            hComp,
6165         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6166         OMX_IN OMX_U32                   port,
6167         OMX_IN OMX_PTR                   appData,
6168         OMX_IN OMX_U32                   bytes,
6169         OMX_IN OMX_U8*                   buffer)
6170 {
6171     DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
6172     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6173 
6174     if (secure_mode) {
6175         DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode");
6176         return OMX_ErrorUndefined;
6177     }
6178 
6179     if (!m_inp_heap_ptr)
6180         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
6181             calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6182                     drv_ctx.ip_buf.actualcount);
6183     if (!m_phdr_pmem_ptr)
6184         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
6185             calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6186                     drv_ctx.ip_buf.actualcount);
6187     if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
6188         DEBUG_PRINT_ERROR("Insufficent memory");
6189         eRet = OMX_ErrorInsufficientResources;
6190     } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
6191         input_use_buffer = true;
6192         memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
6193         m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
6194         m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
6195         m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
6196         m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
6197         m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
6198         *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
6199         eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
6200         DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
6201         if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
6202                     (unsigned)NULL, (unsigned)NULL)) {
6203             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6204             return OMX_ErrorInsufficientResources;
6205         }
6206         m_in_alloc_cnt++;
6207     } else {
6208         DEBUG_PRINT_ERROR("All i/p buffers have been set!");
6209         eRet = OMX_ErrorInsufficientResources;
6210     }
6211     return eRet;
6212 }
6213 
6214 /* ======================================================================
6215    FUNCTION
6216    omx_vdec::UseBuffer
6217 
6218    DESCRIPTION
6219    OMX Use Buffer method implementation.
6220 
6221    PARAMETERS
6222    <TBD>.
6223 
6224    RETURN VALUE
6225    OMX Error None , if everything successful.
6226 
6227    ========================================================================== */
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)6228 OMX_ERRORTYPE  omx_vdec::use_buffer(
6229         OMX_IN OMX_HANDLETYPE            hComp,
6230         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6231         OMX_IN OMX_U32                   port,
6232         OMX_IN OMX_PTR                   appData,
6233         OMX_IN OMX_U32                   bytes,
6234         OMX_IN OMX_U8*                   buffer)
6235 {
6236     OMX_ERRORTYPE error = OMX_ErrorNone;
6237 
6238     if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
6239             DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
6240             return OMX_ErrorBadParameter;
6241     }
6242     if (m_state == OMX_StateInvalid) {
6243         DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
6244         return OMX_ErrorInvalidState;
6245     }
6246     if (port == OMX_CORE_INPUT_PORT_INDEX) {
6247         // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
6248         // ensure that use-buffer was called for previous allocation.
6249         // Mix-and-match of useBuffer and allocateBuffer is not allowed
6250         if (m_inp_mem_ptr && !input_use_buffer) {
6251             DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !");
6252             return OMX_ErrorUndefined;
6253         }
6254         error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
6255     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
6256         error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
6257     } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
6258         error = use_client_output_extradata_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
6259     } else {
6260         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
6261         error = OMX_ErrorBadPortIndex;
6262     }
6263     DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
6264     if (error == OMX_ErrorNone) {
6265         if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
6266             // Send the callback now
6267             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
6268             post_event(OMX_CommandStateSet,OMX_StateIdle,
6269                     OMX_COMPONENT_GENERATE_EVENT);
6270         }
6271         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
6272                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
6273             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
6274             post_event(OMX_CommandPortEnable,
6275                     OMX_CORE_INPUT_PORT_INDEX,
6276                     OMX_COMPONENT_GENERATE_EVENT);
6277         } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
6278                 BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
6279             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
6280             post_event(OMX_CommandPortEnable,
6281                     OMX_CORE_OUTPUT_PORT_INDEX,
6282                     OMX_COMPONENT_GENERATE_EVENT);
6283         }
6284     }
6285     return error;
6286 }
6287 
free_input_buffer(unsigned int bufferindex,OMX_BUFFERHEADERTYPE * pmem_bufferHdr)6288 OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
6289         OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
6290 {
6291     if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
6292         if (m_inp_heap_ptr[bufferindex].pBuffer)
6293             free(m_inp_heap_ptr[bufferindex].pBuffer);
6294         m_inp_heap_ptr[bufferindex].pBuffer = NULL;
6295     }
6296     if (pmem_bufferHdr)
6297         free_input_buffer(pmem_bufferHdr);
6298     return OMX_ErrorNone;
6299 }
6300 
free_input_buffer(OMX_BUFFERHEADERTYPE * bufferHdr)6301 OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
6302 {
6303     unsigned int index = 0;
6304     if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
6305         return OMX_ErrorBadParameter;
6306     }
6307     print_omx_buffer("free_input_buffer", bufferHdr);
6308 
6309     index = bufferHdr - m_inp_mem_ptr;
6310     DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
6311 
6312     bufferHdr->pInputPortPrivate = NULL;
6313 
6314     if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
6315         if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
6316             if (!secure_mode) {
6317                 ion_unmap(drv_ctx.ptr_inputbuffer[index].pmem_fd,
6318                           drv_ctx.ptr_inputbuffer[index].bufferaddr,
6319                           drv_ctx.ptr_inputbuffer[index].mmaped_size);
6320             }
6321 
6322             if (allocate_native_handle){
6323                 native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
6324                 native_handle_close(nh);
6325                 native_handle_delete(nh);
6326             } else {
6327 #ifndef USE_ION
6328                 // Close fd for non-secure and secure non-native-handle case
6329                 close(drv_ctx.ptr_inputbuffer[index].pmem_fd);
6330 #endif
6331             }
6332             drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
6333 
6334             if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
6335                 free(m_desc_buffer_ptr[index].buf_addr);
6336                 m_desc_buffer_ptr[index].buf_addr = NULL;
6337                 m_desc_buffer_ptr[index].desc_data_size = 0;
6338             }
6339 #ifdef USE_ION
6340             free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
6341 #endif
6342             m_in_alloc_cnt--;
6343         } else {
6344             DEBUG_PRINT_ERROR("Invalid input buffer fd %d", drv_ctx.ptr_inputbuffer[index].pmem_fd);
6345         }
6346     } else {
6347         DEBUG_PRINT_ERROR("Invalid input buffer index %d, drv_ctx.ptr_inputbuffer %p",
6348             index, drv_ctx.ptr_inputbuffer);
6349     }
6350 
6351     return OMX_ErrorNone;
6352 }
6353 
free_output_buffer(OMX_BUFFERHEADERTYPE * bufferHdr,bool intermediate)6354 OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr,
6355                                            bool                 intermediate)
6356 {
6357     unsigned int index = 0;
6358 
6359     OMX_BUFFERHEADERTYPE  *omx_base_address =
6360              intermediate?m_intermediate_out_mem_ptr:m_out_mem_ptr;
6361     vdec_bufferpayload *omx_ptr_outputbuffer =
6362          intermediate?drv_ctx.ptr_intermediate_outputbuffer:drv_ctx.ptr_outputbuffer;
6363     vdec_ion *omx_op_buf_ion_info =
6364         intermediate?drv_ctx.op_intermediate_buf_ion_info:drv_ctx.op_buf_ion_info;
6365 #ifdef USE_GBM
6366     vdec_gbm *omx_op_buf_gbm_info =
6367         intermediate?drv_ctx.op_intermediate_buf_gbm_info:drv_ctx.op_buf_gbm_info;
6368 #endif
6369     if (bufferHdr == NULL || omx_base_address == NULL) {
6370         return OMX_ErrorBadParameter;
6371     }
6372     print_omx_buffer("free_output_buffer", bufferHdr);
6373 
6374     index = bufferHdr - omx_base_address;
6375 
6376     if (index < drv_ctx.op_buf.actualcount
6377         && omx_ptr_outputbuffer) {
6378         DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
6379                         omx_ptr_outputbuffer[index].bufferaddr);
6380 
6381         if (!dynamic_buf_mode) {
6382             if (streaming[CAPTURE_PORT] &&
6383                 !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
6384                 if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
6385                     DEBUG_PRINT_ERROR("STREAMOFF(CAPTURE_MPLANE) Failed");
6386                 } else {
6387                     DEBUG_PRINT_LOW("STREAMOFF(CAPTURE_MPLANE) Successful");
6388                 }
6389             }
6390 #ifdef _ANDROID_
6391             if (m_enable_android_native_buffers) {
6392                 if (!secure_mode) {
6393                     if (omx_ptr_outputbuffer[index].pmem_fd > 0) {
6394                         ion_unmap(omx_ptr_outputbuffer[index].pmem_fd,
6395                                   omx_ptr_outputbuffer[index].bufferaddr,
6396                                   omx_ptr_outputbuffer[index].mmaped_size);
6397                     }
6398                 }
6399             } else {
6400 #endif
6401                 if (omx_ptr_outputbuffer[index].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
6402                     if (!secure_mode) {
6403                         ion_unmap(omx_ptr_outputbuffer[index].pmem_fd,
6404                                   omx_ptr_outputbuffer[index].bufferaddr,
6405                                   omx_ptr_outputbuffer[index].mmaped_size);
6406                         omx_ptr_outputbuffer[index].bufferaddr = NULL;
6407                         omx_ptr_outputbuffer[index].mmaped_size = 0;
6408                     }
6409 #ifdef USE_GBM
6410                     free_gbm_memory(&omx_op_buf_gbm_info[index]);
6411 #elif defined USE_ION
6412                     free_ion_memory(&omx_op_buf_ion_info[index]);
6413 #endif
6414 
6415                     omx_ptr_outputbuffer[index].pmem_fd = -1;
6416                 }
6417 #ifdef _ANDROID_
6418             }
6419 #endif
6420         } //!dynamic_buf_mode
6421         if (intermediate == false) {
6422             OMX_BUFFERHEADERTYPE *tempBufHdr = m_intermediate_out_mem_ptr + index;
6423             if (client_buffers.is_color_conversion_enabled() &&
6424                 free_output_buffer(tempBufHdr, true) != OMX_ErrorNone) {
6425                 return OMX_ErrorBadParameter;
6426             }
6427 
6428             if (release_output_done()) {
6429             DEBUG_PRINT_HIGH("All output buffers released, free extradata");
6430             free_extradata();
6431             }
6432         }
6433     }
6434 
6435     return OMX_ErrorNone;
6436 }
6437 
allocate_input_heap_buffer(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE ** bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)6438 OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE       hComp,
6439         OMX_BUFFERHEADERTYPE **bufferHdr,
6440         OMX_U32              port,
6441         OMX_PTR              appData,
6442         OMX_U32              bytes)
6443 {
6444     OMX_BUFFERHEADERTYPE *input = NULL;
6445     unsigned char *buf_addr = NULL;
6446     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6447     unsigned   i = 0;
6448 
6449     /* Sanity Check*/
6450     if (bufferHdr == NULL) {
6451         return OMX_ErrorBadParameter;
6452     }
6453 
6454     if (m_inp_heap_ptr == NULL) {
6455         m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
6456                  calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
6457                          drv_ctx.ip_buf.actualcount);
6458         m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
6459                   calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
6460                           drv_ctx.ip_buf.actualcount);
6461 
6462         if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) {
6463             DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed ");
6464             return OMX_ErrorInsufficientResources;
6465         }
6466     }
6467 
6468     /*Find a Free index*/
6469     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6470         if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
6471             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6472             break;
6473         }
6474     }
6475 
6476     if (i < drv_ctx.ip_buf.actualcount) {
6477         buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
6478 
6479         if (buf_addr == NULL) {
6480             return OMX_ErrorInsufficientResources;
6481         }
6482 
6483         *bufferHdr = (m_inp_heap_ptr + i);
6484         input = *bufferHdr;
6485         BITMASK_SET(&m_heap_inp_bm_count,i);
6486 
6487         input->pBuffer           = (OMX_U8 *)buf_addr;
6488         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
6489         input->nVersion.nVersion = OMX_SPEC_VERSION;
6490         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
6491         input->pAppPrivate       = appData;
6492         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
6493         DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
6494         eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
6495         DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
6496         /*Add the Buffers to freeq*/
6497         if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i],
6498                     (unsigned)NULL, (unsigned)NULL)) {
6499             DEBUG_PRINT_ERROR("ERROR:Free_q is full");
6500             return OMX_ErrorInsufficientResources;
6501         }
6502     } else {
6503         return OMX_ErrorBadParameter;
6504     }
6505 
6506     return eRet;
6507 }
6508 
6509 
6510 /* ======================================================================
6511    FUNCTION
6512    omx_vdec::AllocateInputBuffer
6513 
6514    DESCRIPTION
6515    Helper function for allocate buffer in the input pin
6516 
6517    PARAMETERS
6518    None.
6519 
6520    RETURN VALUE
6521    true/false
6522 
6523    ========================================================================== */
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)6524 OMX_ERRORTYPE  omx_vdec::allocate_input_buffer(
6525         OMX_IN OMX_HANDLETYPE            hComp,
6526         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6527         OMX_IN OMX_U32                   port,
6528         OMX_IN OMX_PTR                   appData,
6529         OMX_IN OMX_U32                   bytes)
6530 {
6531     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6532     OMX_BUFFERHEADERTYPE *input = NULL;
6533     unsigned   i = 0;
6534     unsigned char *buf_addr = NULL;
6535     int pmem_fd = -1, ret = 0;
6536     unsigned int align_size = 0;
6537 
6538     (void) hComp;
6539     (void) port;
6540 
6541 
6542     if (bytes != drv_ctx.ip_buf.buffer_size) {
6543         DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
6544                 (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
6545         return OMX_ErrorBadParameter;
6546     }
6547 
6548     if (!m_inp_mem_ptr) {
6549         /* Currently buffer reqs is being set only in set port defn                          */
6550         /* Client need not do set port definition if he sees enough buffers in get port defn */
6551         /* In such cases we need to do a set buffer reqs to driver. Doing it here            */
6552         struct v4l2_requestbuffers bufreq;
6553 
6554         DEBUG_PRINT_HIGH("Calling REQBUFS in %s ",__FUNCTION__);
6555         bufreq.memory = V4L2_MEMORY_USERPTR;
6556         bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
6557         bufreq.count = drv_ctx.ip_buf.actualcount;
6558         ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
6559         if (ret) {
6560             DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
6561             /*TODO: How to handle this case */
6562             eRet = OMX_ErrorInsufficientResources;
6563         } else if (bufreq.count != drv_ctx.ip_buf.actualcount) {
6564             DEBUG_PRINT_ERROR("%s Count(%d) is not expected to change to %d",
6565                 __FUNCTION__, drv_ctx.ip_buf.actualcount, bufreq.count);
6566             eRet = OMX_ErrorInsufficientResources;
6567         }
6568 
6569         DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
6570                 drv_ctx.ip_buf.actualcount,
6571                 (unsigned int)drv_ctx.ip_buf.buffer_size);
6572 
6573         m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
6574                 calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
6575 
6576         if (m_inp_mem_ptr == NULL) {
6577             return OMX_ErrorInsufficientResources;
6578         }
6579 
6580         drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
6581                       calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
6582 
6583         if (drv_ctx.ptr_inputbuffer == NULL) {
6584             return OMX_ErrorInsufficientResources;
6585         }
6586 #ifdef USE_ION
6587         drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
6588                       calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
6589 
6590         if (drv_ctx.ip_buf_ion_info == NULL) {
6591             return OMX_ErrorInsufficientResources;
6592         }
6593 #endif
6594 
6595         for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
6596             drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
6597 #ifdef USE_ION
6598             drv_ctx.ip_buf_ion_info[i].data_fd = -1;
6599             drv_ctx.ip_buf_ion_info[i].dev_fd = -1;
6600 #endif
6601         }
6602     }
6603 
6604     for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
6605         if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
6606             DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
6607             break;
6608         }
6609     }
6610 
6611     if (i < drv_ctx.ip_buf.actualcount) {
6612         int rc;
6613         DEBUG_PRINT_LOW("Allocate input Buffer");
6614 #ifdef USE_ION
6615         align_size = drv_ctx.ip_buf.buffer_size + 512;
6616         align_size = (align_size + drv_ctx.ip_buf.alignment - 1)&(~(drv_ctx.ip_buf.alignment - 1));
6617         // Input buffers are cached to make parsing faster
6618         bool status = alloc_map_ion_memory(
6619                 align_size, &drv_ctx.ip_buf_ion_info[i],
6620                 secure_mode ? SECURE_FLAGS_INPUT_BUFFER : ION_FLAG_CACHED);
6621         if (status == false) {
6622             return OMX_ErrorInsufficientResources;
6623         }
6624         pmem_fd = drv_ctx.ip_buf_ion_info[i].data_fd;
6625 #endif
6626         if (!secure_mode) {
6627             buf_addr = (unsigned char *)ion_map(pmem_fd, drv_ctx.ip_buf.buffer_size);
6628             if (buf_addr == MAP_FAILED) {
6629 #ifdef USE_ION
6630                 free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
6631 #endif
6632                 DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
6633                 return OMX_ErrorInsufficientResources;
6634             }
6635         }
6636         *bufferHdr = (m_inp_mem_ptr + i);
6637         if (secure_mode)
6638             drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
6639         else
6640             drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
6641         drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
6642         drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
6643         drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
6644         drv_ctx.ptr_inputbuffer [i].offset = 0;
6645 
6646         input = *bufferHdr;
6647         BITMASK_SET(&m_inp_bm_count,i);
6648         if (allocate_native_handle) {
6649             native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
6650             if (!nh) {
6651                 DEBUG_PRINT_ERROR("Native handle create failed");
6652                 return OMX_ErrorInsufficientResources;
6653             }
6654             nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
6655             input->pBuffer = (OMX_U8 *)nh;
6656         } else if (secure_mode || m_input_pass_buffer_fd) {
6657             /*Legacy method, pass ion fd stashed directly in pBuffer*/
6658             input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
6659         } else {
6660             input->pBuffer           = (OMX_U8 *)buf_addr;
6661         }
6662         input->nSize             = sizeof(OMX_BUFFERHEADERTYPE);
6663         input->nVersion.nVersion = OMX_SPEC_VERSION;
6664         input->nAllocLen         = drv_ctx.ip_buf.buffer_size;
6665         input->pAppPrivate       = appData;
6666         input->nInputPortIndex   = OMX_CORE_INPUT_PORT_INDEX;
6667         input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
6668 
6669         if (drv_ctx.disable_dmx) {
6670             eRet = allocate_desc_buffer(i);
6671         }
6672     } else {
6673         DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
6674         eRet = OMX_ErrorInsufficientResources;
6675     }
6676 
6677     if (eRet == OMX_ErrorNone)
6678         DEBUG_PRINT_HIGH("Allocate_input_buffer(%d): Header %p buffer %p allocLen %d offset %d fd = %d",
6679             i, input, input->pBuffer, input->nAllocLen,
6680             input->nOffset, drv_ctx.ptr_inputbuffer[i].pmem_fd);
6681 
6682     return eRet;
6683 }
6684 
6685 
6686 /* ======================================================================
6687    FUNCTION
6688    omx_vdec::AllocateOutputBuffer
6689 
6690    DESCRIPTION
6691    Helper fn for AllocateBuffer in the output pin
6692 
6693    PARAMETERS
6694    <TBD>.
6695 
6696    RETURN VALUE
6697    OMX Error None if everything went well.
6698 
6699    ========================================================================== */
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)6700 OMX_ERRORTYPE  omx_vdec::allocate_output_buffer(
6701         OMX_IN OMX_HANDLETYPE            hComp,
6702         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
6703         OMX_IN OMX_U32                   port,
6704         OMX_IN OMX_PTR                   appData,
6705         OMX_IN OMX_U32                   bytes,
6706         OMX_IN bool                      intermediate,
6707         OMX_IN int                       index)
6708 {
6709     (void)hComp;
6710     (void)port;
6711 
6712     OMX_ERRORTYPE eRet = OMX_ErrorNone;
6713     OMX_BUFFERHEADERTYPE       *bufHdr= NULL; // buffer header
6714     unsigned                         i= 0; // Temporary counter
6715 #ifdef USE_ION
6716     struct ion_allocation_data ion_alloc_data;
6717 #endif
6718     OMX_BUFFERHEADERTYPE  **omx_base_address =
6719         intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
6720 
6721     vdec_bufferpayload **omx_ptr_outputbuffer =
6722         intermediate?&drv_ctx.ptr_intermediate_outputbuffer:&drv_ctx.ptr_outputbuffer;
6723     vdec_output_frameinfo **omx_ptr_respbuffer =
6724         intermediate?&drv_ctx.ptr_intermediate_respbuffer:&drv_ctx.ptr_respbuffer;
6725     vdec_ion **omx_op_buf_ion_info =
6726         intermediate?&drv_ctx.op_intermediate_buf_ion_info:&drv_ctx.op_buf_ion_info;
6727 #ifdef USE_GBM
6728     vdec_gbm **omx_op_buf_gbm_info =
6729         intermediate?&drv_ctx.op_intermediate_buf_gbm_info:&drv_ctx.op_buf_gbm_info;
6730 #endif
6731 
6732     if (!*omx_base_address) {
6733         DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
6734                 drv_ctx.op_buf.actualcount,
6735                 (unsigned int)drv_ctx.op_buf.buffer_size);
6736         int nBufHdrSize        = 0;
6737         int nPlatformEntrySize = 0;
6738         int nPlatformListSize  = 0;
6739         int nPMEMInfoSize = 0;
6740 
6741         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
6742         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
6743         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
6744 
6745         nBufHdrSize        = drv_ctx.op_buf.actualcount *
6746             sizeof(OMX_BUFFERHEADERTYPE);
6747         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
6748             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
6749         nPlatformListSize  = drv_ctx.op_buf.actualcount *
6750             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
6751         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
6752             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
6753 
6754         *omx_base_address = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
6755         // Alloc mem for platform specific info
6756         char *pPtr=NULL;
6757         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
6758                 nPMEMInfoSize,1);
6759         *omx_ptr_outputbuffer = (struct vdec_bufferpayload *)    \
6760                        calloc (sizeof(struct vdec_bufferpayload),
6761                                drv_ctx.op_buf.actualcount);
6762         *omx_ptr_respbuffer = (struct vdec_output_frameinfo  *)\
6763                      calloc (sizeof (struct vdec_output_frameinfo),
6764                              drv_ctx.op_buf.actualcount);
6765         if (!*omx_ptr_outputbuffer || !*omx_ptr_respbuffer) {
6766             DEBUG_PRINT_ERROR("Failed to alloc outputbuffer or respbuffer ");
6767             free(pPtr);
6768             return OMX_ErrorInsufficientResources;
6769         }
6770 
6771 #ifdef USE_GBM
6772         *omx_op_buf_gbm_info = (struct vdec_gbm *)\
6773                       calloc (sizeof(struct vdec_gbm),
6774                       drv_ctx.op_buf.actualcount);
6775         if (!*omx_op_buf_gbm_info) {
6776                  DEBUG_PRINT_ERROR("Failed to alloc op_buf_gbm_info");
6777             return OMX_ErrorInsufficientResources;
6778         }
6779         drv_ctx.gbm_device_fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC);
6780         if (drv_ctx.gbm_device_fd < 0) {
6781            DEBUG_PRINT_ERROR("opening dri device for gbm failed with fd = %d", drv_ctx.gbm_device_fd);
6782            return OMX_ErrorInsufficientResources;
6783         }
6784 #elif defined USE_ION
6785         *omx_op_buf_ion_info = (struct vdec_ion *)\
6786                       calloc (sizeof(struct vdec_ion),
6787                               drv_ctx.op_buf.actualcount);
6788         if (!*omx_op_buf_ion_info) {
6789             DEBUG_PRINT_ERROR("Failed to alloc op_buf_ion_info");
6790             return OMX_ErrorInsufficientResources;
6791         }
6792 #endif
6793 
6794         if (*omx_base_address && pPtr && *omx_ptr_outputbuffer
6795             && *omx_ptr_respbuffer) {
6796             bufHdr          =  *omx_base_address;
6797             if (m_platform_list) {
6798                 free(m_platform_list);
6799             }
6800             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
6801             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
6802                 (((char *) m_platform_list)  + nPlatformListSize);
6803             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
6804                 (((char *) m_platform_entry) + nPlatformEntrySize);
6805             pPlatformList   = m_platform_list;
6806             pPlatformEntry  = m_platform_entry;
6807             pPMEMInfo       = m_pmem_info;
6808 
6809             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p", *omx_base_address);
6810 
6811             // Settting the entire storage nicely
6812             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
6813                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
6814                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
6815                 // Set the values when we determine the right HxW param
6816                 bufHdr->nAllocLen          = bytes;
6817                 bufHdr->nFilledLen         = 0;
6818                 bufHdr->pAppPrivate        = appData;
6819                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
6820                 // Platform specific PMEM Information
6821                 // Initialize the Platform Entry
6822                 //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
6823                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
6824                 pPlatformEntry->entry      = pPMEMInfo;
6825                 // Initialize the Platform List
6826                 pPlatformList->nEntries    = 1;
6827                 pPlatformList->entryList   = pPlatformEntry;
6828                 // Keep pBuffer NULL till vdec is opened
6829                 bufHdr->pBuffer            = NULL;
6830                 bufHdr->nOffset            = 0;
6831                 pPMEMInfo->offset = 0;
6832                 pPMEMInfo->pmem_fd = -1;
6833                 bufHdr->pPlatformPrivate = pPlatformList;
6834                 /*Create a mapping between buffers*/
6835                 bufHdr->pOutputPortPrivate = &(*omx_ptr_respbuffer)[i];
6836                 (*omx_ptr_respbuffer)[i].client_data = (void *) \
6837                     &(*omx_ptr_outputbuffer)[i];
6838                 // Move the buffer and buffer header pointers
6839                 bufHdr++;
6840                 pPMEMInfo++;
6841                 pPlatformEntry++;
6842                 pPlatformList++;
6843             }
6844         } else {
6845             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
6846                               *omx_base_address, pPtr);
6847             if (*omx_base_address) {
6848                 free(*omx_base_address);
6849                 *omx_base_address = NULL;
6850             }
6851             if (pPtr) {
6852                 free(pPtr);
6853                 pPtr = NULL;
6854             }
6855             if (*omx_ptr_outputbuffer) {
6856                 free(*omx_ptr_outputbuffer);
6857                 *omx_ptr_outputbuffer = NULL;
6858             }
6859             if (*omx_ptr_respbuffer) {
6860                 free(*omx_ptr_respbuffer);
6861                 *omx_ptr_respbuffer = NULL;
6862             }
6863 #ifdef USE_GBM
6864       if(drv_ctx.gbm_device_fd >= 0) {
6865        DEBUG_PRINT_LOW("Close gbm device");
6866        close(drv_ctx.gbm_device_fd);
6867        drv_ctx.gbm_device_fd = -1;
6868     }
6869             if (*omx_op_buf_gbm_info) {
6870                 DEBUG_PRINT_LOW("Free o/p gbm context");
6871                 free(*omx_op_buf_gbm_info);
6872                 *omx_op_buf_gbm_info = NULL;
6873             }
6874 #elif defined USE_ION
6875             if (*omx_op_buf_ion_info) {
6876                 DEBUG_PRINT_LOW("Free o/p ion context");
6877                 free(*omx_op_buf_ion_info);
6878                 *omx_op_buf_ion_info = NULL;
6879             }
6880 #endif
6881             eRet =  OMX_ErrorInsufficientResources;
6882         }
6883         if (eRet == OMX_ErrorNone)
6884             eRet = allocate_extradata();
6885     }
6886 
6887     if (intermediate == true && index != -1) {
6888         i = index;
6889     } else {
6890         for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
6891             if (BITMASK_ABSENT(&m_out_bm_count,i)) {
6892                 break;
6893             }
6894         }
6895     }
6896 
6897     if (eRet == OMX_ErrorNone) {
6898         if (i < drv_ctx.op_buf.actualcount) {
6899             int rc;
6900             int pmem_fd = -1;
6901             int fd = -1;
6902             unsigned char *pmem_baseaddress = NULL;
6903 #ifdef USE_GBM
6904             int pmeta_fd = -1;
6905             // Allocate output buffers as cached to improve performance of software-reading
6906             // of the YUVs. Output buffers are cache-invalidated in driver.
6907             // If color-conversion is involved, Only the C2D output buffers are cached, no
6908             // need to cache the decoder's output buffers
6909             int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
6910             bool status = alloc_map_gbm_memory(
6911                                drv_ctx.video_resolution.frame_width,
6912                                drv_ctx.video_resolution.frame_height,
6913                                drv_ctx.gbm_device_fd,
6914                                &(*omx_op_buf_gbm_info)[i],
6915                                (secure_mode && !secure_scaling_to_non_secure_opb) ?
6916                                       SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
6917             if (status == false) {
6918                 return OMX_ErrorInsufficientResources;
6919             }
6920             pmem_fd = (*omx_op_buf_gbm_info)[i].bo_fd;
6921             pmeta_fd = (*omx_op_buf_gbm_info)[i].meta_fd;
6922 #elif defined USE_ION
6923             // Allocate output buffers as cached to improve performance of software-reading
6924             // of the YUVs. Output buffers are cache-invalidated in driver.
6925             // If color-conversion is involved, Only the C2D output buffers are cached, no
6926             // need to cache the decoder's output buffers
6927             int cache_flag = ION_FLAG_CACHED;
6928             if (intermediate == true && client_buffers.is_color_conversion_enabled()) {
6929                 cache_flag = 0;
6930             }
6931             bool status = alloc_map_ion_memory(drv_ctx.op_buf.buffer_size,
6932                                                &(*omx_op_buf_ion_info)[i],
6933                     (secure_mode && !secure_scaling_to_non_secure_opb) ?
6934                     SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
6935             if (status == false) {
6936                 return OMX_ErrorInsufficientResources;
6937             }
6938             pmem_fd = (*omx_op_buf_ion_info)[i].data_fd;
6939 #endif
6940             if (!secure_mode) {
6941                 pmem_baseaddress = (unsigned char *)ion_map(pmem_fd, drv_ctx.op_buf.buffer_size);
6942                 if (pmem_baseaddress == MAP_FAILED) {
6943                     DEBUG_PRINT_ERROR("MMAP failed for Size %u",
6944                             (unsigned int)drv_ctx.op_buf.buffer_size);
6945 #ifdef USE_GBM
6946                     free_gbm_memory(&(*omx_op_buf_gbm_info)[i]);
6947 #elif defined USE_ION
6948                     free_ion_memory(&(*omx_op_buf_ion_info)[i]);
6949 #endif
6950                     return OMX_ErrorInsufficientResources;
6951                 }
6952             }
6953             (*omx_ptr_outputbuffer)[i].pmem_fd = pmem_fd;
6954 #ifdef USE_GBM
6955             m_pmem_info[i].pmeta_fd = pmeta_fd;
6956 #endif
6957             (*omx_ptr_outputbuffer)[i].offset = 0;
6958             (*omx_ptr_outputbuffer)[i].bufferaddr = pmem_baseaddress;
6959             (*omx_ptr_outputbuffer)[i].mmaped_size = drv_ctx.op_buf.buffer_size;
6960             (*omx_ptr_outputbuffer)[i].buffer_len = drv_ctx.op_buf.buffer_size;
6961             m_pmem_info[i].pmem_fd = pmem_fd;
6962             m_pmem_info[i].size = (*omx_ptr_outputbuffer)[i].buffer_len;
6963             m_pmem_info[i].mapped_size = (*omx_ptr_outputbuffer)[i].mmaped_size;
6964             m_pmem_info[i].buffer = (*omx_ptr_outputbuffer)[i].bufferaddr;
6965             m_pmem_info[i].offset = (*omx_ptr_outputbuffer)[i].offset;
6966 
6967             *bufferHdr = (*omx_base_address + i );
6968             if (secure_mode) {
6969 #ifdef USE_GBM
6970                 (*omx_ptr_outputbuffer)[i].bufferaddr =
6971                     (OMX_U8 *)(intptr_t)(*omx_op_buf_gbm_info)[i].bo_fd;
6972 #elif defined USE_ION
6973                 (*omx_ptr_outputbuffer)[i].bufferaddr =
6974                     (OMX_U8 *)(intptr_t)(*omx_op_buf_ion_info)[i].data_fd;
6975 #endif
6976             }
6977             if (intermediate == false &&
6978                 client_buffers.is_color_conversion_enabled()) {
6979                 OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
6980                 eRet = allocate_output_buffer(hComp, &temp_bufferHdr,
6981                                               port, appData,
6982                                               drv_ctx.op_buf.buffer_size,
6983                                               true, i);
6984             }
6985             if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
6986                 enum v4l2_buf_type buf_type;
6987 
6988                 set_buffer_req(&drv_ctx.op_buf);
6989                 buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
6990                 if (!client_buffers.is_color_conversion_enabled() ||
6991                     (client_buffers.is_color_conversion_enabled() && intermediate == true)) {
6992                     rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
6993                     if (rc) {
6994                         DEBUG_PRINT_ERROR("STREAMON(CAPTURE_MPLANE) Failed");
6995                         return OMX_ErrorInsufficientResources;
6996                     } else {
6997                         streaming[CAPTURE_PORT] = true;
6998                         DEBUG_PRINT_LOW("STREAMON(CAPTURE_MPLANE) Successful");
6999                     }
7000                 }
7001             }
7002 
7003             (*bufferHdr)->pBuffer = (OMX_U8*)(*omx_ptr_outputbuffer)[i].bufferaddr;
7004             (*bufferHdr)->pAppPrivate = appData;
7005             BITMASK_SET(&m_out_bm_count,i);
7006         } else {
7007             DEBUG_PRINT_ERROR("Faile to allocate output buffer (%d) maxcount %d",
7008                 i, drv_ctx.op_buf.actualcount);
7009             eRet = OMX_ErrorInsufficientResources;
7010         }
7011     }
7012 
7013     if (eRet == OMX_ErrorNone)
7014         DEBUG_PRINT_HIGH("Allocate_output_buffer(%d): Header %p buffer %p allocLen %d offset %d fd = %d intermediate %d",
7015                          i, (*bufferHdr), (*bufferHdr)->pBuffer, (*bufferHdr)->nAllocLen,
7016                          (*bufferHdr)->nOffset, (*omx_ptr_outputbuffer)[i].pmem_fd,
7017                          intermediate);
7018     return eRet;
7019 }
7020 
7021 
7022 // AllocateBuffer  -- API Call
7023 /* ======================================================================
7024    FUNCTION
7025    omx_vdec::AllocateBuffer
7026 
7027    DESCRIPTION
7028    Returns zero if all the buffers released..
7029 
7030    PARAMETERS
7031    None.
7032 
7033    RETURN VALUE
7034    true/false
7035 
7036    ========================================================================== */
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)7037 OMX_ERRORTYPE  omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE                hComp,
7038         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
7039         OMX_IN OMX_U32                        port,
7040         OMX_IN OMX_PTR                     appData,
7041         OMX_IN OMX_U32                       bytes)
7042 {
7043     unsigned i = 0;
7044     OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
7045 
7046     DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
7047     if (m_state == OMX_StateInvalid) {
7048         DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
7049         return OMX_ErrorInvalidState;
7050     }
7051 
7052     if (port == OMX_CORE_INPUT_PORT_INDEX) {
7053         // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
7054         // ensure that use-buffer was never called.
7055         // Mix-and-match of useBuffer and allocateBuffer is not allowed
7056         if (m_inp_mem_ptr && input_use_buffer) {
7057             DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !");
7058             return OMX_ErrorUndefined;
7059         }
7060         if (arbitrary_bytes) {
7061             eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
7062         } else {
7063             eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
7064         }
7065     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7066         if (output_use_buffer) {
7067             DEBUG_PRINT_ERROR("Allocate output buffer not allowed after use buffer");
7068             return OMX_ErrorBadParameter;
7069         }
7070         eRet = allocate_output_buffer(hComp, bufferHdr, port, appData, bytes);
7071     } else {
7072         DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
7073         eRet = OMX_ErrorBadPortIndex;
7074     }
7075     if (eRet == OMX_ErrorNone) {
7076         if (allocate_done()) {
7077             DEBUG_PRINT_HIGH("Allocated all buffers on port %d", port);
7078             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
7079                 // Send the callback now
7080                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
7081                 post_event(OMX_CommandStateSet,OMX_StateIdle,
7082                         OMX_COMPONENT_GENERATE_EVENT);
7083             }
7084         }
7085         if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
7086             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
7087                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
7088                 post_event(OMX_CommandPortEnable,
7089                         OMX_CORE_INPUT_PORT_INDEX,
7090                         OMX_COMPONENT_GENERATE_EVENT);
7091             }
7092         }
7093         if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
7094             if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
7095                 BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
7096                 post_event(OMX_CommandPortEnable,
7097                         OMX_CORE_OUTPUT_PORT_INDEX,
7098                         OMX_COMPONENT_GENERATE_EVENT);
7099             }
7100         }
7101     }
7102     return eRet;
7103 }
7104 
7105 // Free Buffer - API call
7106 /* ======================================================================
7107    FUNCTION
7108    omx_vdec::FreeBuffer
7109 
7110    DESCRIPTION
7111 
7112    PARAMETERS
7113    None.
7114 
7115    RETURN VALUE
7116    true/false
7117 
7118    ========================================================================== */
free_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_U32 port,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7119 OMX_ERRORTYPE  omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE         hComp,
7120         OMX_IN OMX_U32                 port,
7121         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7122 {
7123     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7124     unsigned int nPortIndex;
7125     (void) hComp;
7126 
7127     auto_lock l(buf_lock);
7128     if (m_state == OMX_StateIdle &&
7129             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
7130         DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
7131     } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
7132             (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
7133         DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
7134     } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
7135                 BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
7136             (port == OMX_CORE_OUTPUT_PORT_INDEX &&
7137              BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
7138         DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
7139     } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
7140         DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
7141         post_event(OMX_EventError,
7142                 OMX_ErrorPortUnpopulated,
7143                 OMX_COMPONENT_GENERATE_EVENT);
7144         m_buffer_error = true;
7145         return OMX_ErrorIncorrectStateOperation;
7146     } else if (m_state != OMX_StateInvalid) {
7147         DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
7148         post_event(OMX_EventError,
7149                 OMX_ErrorPortUnpopulated,
7150                 OMX_COMPONENT_GENERATE_EVENT);
7151     }
7152 
7153     if (port == OMX_CORE_INPUT_PORT_INDEX) {
7154         /*Check if arbitrary bytes*/
7155         if (!arbitrary_bytes && !input_use_buffer)
7156             nPortIndex = buffer - m_inp_mem_ptr;
7157         else
7158             nPortIndex = buffer - m_inp_heap_ptr;
7159 
7160         DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
7161         if (nPortIndex < drv_ctx.ip_buf.actualcount &&
7162                 BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
7163             // Clear the bit associated with it.
7164             BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
7165             BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
7166             if (input_use_buffer == true) {
7167 
7168                 DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
7169                 if (m_phdr_pmem_ptr)
7170                     free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
7171             } else {
7172                 if (arbitrary_bytes) {
7173                     if (m_phdr_pmem_ptr)
7174                         free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
7175                     else
7176                         free_input_buffer(nPortIndex,NULL);
7177                 } else
7178                     free_input_buffer(buffer);
7179             }
7180             m_inp_bPopulated = OMX_FALSE;
7181             /*Free the Buffer Header*/
7182             if (release_input_done()) {
7183                 DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
7184                 free_input_buffer_header();
7185             }
7186         } else {
7187             DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
7188             eRet = OMX_ErrorBadPortIndex;
7189         }
7190 
7191         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
7192                 && release_input_done()) {
7193             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
7194             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
7195             post_event(OMX_CommandPortDisable,
7196                     OMX_CORE_INPUT_PORT_INDEX,
7197                     OMX_COMPONENT_GENERATE_EVENT);
7198         }
7199     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
7200         // check if the buffer is valid
7201         OMX_BUFFERHEADERTYPE  *omx_base_address =
7202             client_buffers.is_color_conversion_enabled()?
7203             m_intermediate_out_mem_ptr:m_out_mem_ptr;
7204         nPortIndex = buffer - m_out_mem_ptr;
7205         if (nPortIndex < drv_ctx.op_buf.actualcount &&
7206                 BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
7207             DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
7208             // Clear the bit associated with it.
7209             BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
7210             m_out_bPopulated = OMX_FALSE;
7211             free_output_buffer (buffer);
7212 
7213             if (release_output_done()) {
7214                 DEBUG_PRINT_HIGH("All output buffers released.");
7215                 free_output_buffer_header();
7216             }
7217         } else {
7218             DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
7219             eRet = OMX_ErrorBadPortIndex;
7220         }
7221         if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
7222                 && release_output_done()) {
7223             DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
7224             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
7225 #ifdef _ANDROID_ICS_
7226             if (m_enable_android_native_buffers) {
7227                 DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
7228                 memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
7229             }
7230 #endif
7231 
7232             post_event(OMX_CommandPortDisable,
7233                     OMX_CORE_OUTPUT_PORT_INDEX,
7234                     OMX_COMPONENT_GENERATE_EVENT);
7235         }
7236     } else if (port == OMX_CORE_OUTPUT_EXTRADATA_INDEX) {
7237         nPortIndex = buffer - m_client_output_extradata_mem_ptr;
7238         DEBUG_PRINT_LOW("free_buffer on extradata output port - Port idx %d", nPortIndex);
7239 
7240         BITMASK_CLEAR(&m_out_extradata_bm_count,nPortIndex);
7241 
7242         if (release_output_extradata_done()) {
7243             free_output_extradata_buffer_header();
7244         }
7245     } else {
7246         eRet = OMX_ErrorBadPortIndex;
7247     }
7248     if ((eRet == OMX_ErrorNone) &&
7249             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
7250         if (release_done()) {
7251             /*
7252              * Reset buffer requirements here to ensure setting buffer requirement
7253              * when component move to executing state from loaded state via idle.
7254              */
7255             drv_ctx.op_buf.buffer_size = 0;
7256             drv_ctx.op_buf.actualcount = 0;
7257 
7258             // Send the callback now
7259             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
7260             post_event(OMX_CommandStateSet, OMX_StateLoaded,
7261                     OMX_COMPONENT_GENERATE_EVENT);
7262             m_buffer_error = false;
7263         }
7264     }
7265     return eRet;
7266 }
7267 
7268 
7269 /* ======================================================================
7270    FUNCTION
7271    omx_vdec::EmptyThisBuffer
7272 
7273    DESCRIPTION
7274    This routine is used to push the encoded video frames to
7275    the video decoder.
7276 
7277    PARAMETERS
7278    None.
7279 
7280    RETURN VALUE
7281    OMX Error None if everything went successful.
7282 
7283    ========================================================================== */
empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7284 OMX_ERRORTYPE  omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE         hComp,
7285         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7286 {
7287     OMX_ERRORTYPE ret1 = OMX_ErrorNone;
7288     unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
7289 
7290     if (m_state != OMX_StateExecuting &&
7291             m_state != OMX_StatePause &&
7292             m_state != OMX_StateIdle) {
7293         DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
7294         return OMX_ErrorInvalidState;
7295     }
7296 
7297     if (m_error_propogated) {
7298         DEBUG_PRINT_ERROR("Empty this buffer not allowed after error");
7299         return OMX_ErrorHardware;
7300     }
7301 
7302     if (buffer == NULL) {
7303         DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
7304         return OMX_ErrorBadParameter;
7305     }
7306     print_omx_buffer("EmptyThisBuffer", buffer);
7307 
7308     if (!m_inp_bEnabled) {
7309         DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
7310         return OMX_ErrorIncorrectStateOperation;
7311     }
7312 
7313     if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
7314         DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
7315         return OMX_ErrorBadPortIndex;
7316     }
7317 
7318     if (perf_flag) {
7319         if (!latency) {
7320             dec_time.stop();
7321             latency = dec_time.processing_time_us();
7322             dec_time.start();
7323         }
7324     }
7325 
7326     if (arbitrary_bytes) {
7327         nBufferIndex = buffer - m_inp_heap_ptr;
7328     } else {
7329         if (input_use_buffer == true) {
7330             nBufferIndex = buffer - m_inp_heap_ptr;
7331             if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7332                 DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode");
7333                 return OMX_ErrorBadParameter;
7334             }
7335             m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
7336             m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
7337             m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
7338             buffer = &m_inp_mem_ptr[nBufferIndex];
7339             DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
7340                     &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
7341         } else {
7342             nBufferIndex = buffer - m_inp_mem_ptr;
7343         }
7344     }
7345 
7346     if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
7347         DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
7348         return OMX_ErrorBadParameter;
7349     }
7350 
7351     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7352         codec_config_flag = true;
7353         DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
7354     }
7355 
7356     /* The client should not set this when codec is in arbitrary bytes mode */
7357     if (m_input_pass_buffer_fd) {
7358         buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
7359     }
7360 
7361     DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
7362             buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
7363     if (arbitrary_bytes) {
7364         post_event ((unsigned long)hComp,(unsigned long)buffer,
7365                 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
7366     } else {
7367         post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
7368     }
7369     time_stamp_dts.insert_timestamp(buffer);
7370     return OMX_ErrorNone;
7371 }
7372 
7373 /* ======================================================================
7374    FUNCTION
7375    omx_vdec::empty_this_buffer_proxy
7376 
7377    DESCRIPTION
7378    This routine is used to push the encoded video frames to
7379    the video decoder.
7380 
7381    PARAMETERS
7382    None.
7383 
7384    RETURN VALUE
7385    OMX Error None if everything went successful.
7386 
7387    ========================================================================== */
empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7388 OMX_ERRORTYPE  omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE  hComp,
7389         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7390 {
7391     VIDC_TRACE_NAME_HIGH("ETB");
7392     (void) hComp;
7393     int push_cnt = 0,i=0;
7394     unsigned nPortIndex = 0;
7395     OMX_ERRORTYPE ret = OMX_ErrorNone;
7396     struct vdec_bufferpayload *temp_buffer;
7397     bool port_setting_changed = true;
7398 
7399     /*Should we generate a Aync error event*/
7400     if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
7401         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
7402         return OMX_ErrorBadParameter;
7403     }
7404 
7405     nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
7406 
7407     if (nPortIndex >= drv_ctx.ip_buf.actualcount) {
7408         DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
7409                 nPortIndex);
7410         return OMX_ErrorBadParameter;
7411     }
7412 
7413     pending_input_buffers++;
7414     VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
7415 
7416     /* return zero length and not an EOS buffer */
7417     if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
7418             ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
7419         DEBUG_PRINT_HIGH("return zero legth buffer");
7420         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7421                 OMX_COMPONENT_GENERATE_EBD);
7422         return OMX_ErrorNone;
7423     }
7424 
7425     if (input_flush_progress == true) {
7426         DEBUG_PRINT_LOW("Flush in progress return buffer ");
7427         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7428                 OMX_COMPONENT_GENERATE_EBD);
7429         return OMX_ErrorNone;
7430     }
7431 
7432     if (m_error_propogated == true) {
7433         DEBUG_PRINT_LOW("Return buffer in error state");
7434         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
7435                 OMX_COMPONENT_GENERATE_EBD);
7436         return OMX_ErrorNone;
7437     }
7438 
7439     auto_lock l(buf_lock);
7440     temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
7441 
7442     if (!temp_buffer || (temp_buffer -  drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
7443         return OMX_ErrorBadParameter;
7444     }
7445 
7446     if (BITMASK_ABSENT(&m_inp_bm_count, nPortIndex) || m_buffer_error) {
7447         DEBUG_PRINT_ERROR("ETBProxy: ERROR: invalid buffer, nPortIndex %u", nPortIndex);
7448         return OMX_ErrorBadParameter;
7449     }
7450 
7451     VIDC_TRACE_INT_LOW("ETB-TS", buffer->nTimeStamp / 1000);
7452     VIDC_TRACE_INT_LOW("ETB-size", buffer->nFilledLen);
7453     /*for use buffer we need to memcpy the data*/
7454     temp_buffer->buffer_len = buffer->nFilledLen;
7455 
7456     if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) {
7457         if (buffer->nFilledLen <= temp_buffer->buffer_len) {
7458             if (arbitrary_bytes) {
7459                 memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
7460             } else {
7461                 memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
7462                         buffer->nFilledLen);
7463             }
7464         } else {
7465             return OMX_ErrorBadParameter;
7466         }
7467 
7468     }
7469 
7470     if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
7471         DEBUG_PRINT_LOW("ETB: dmx enabled");
7472         if (m_demux_entries == 0) {
7473             extract_demux_addr_offsets(buffer);
7474         }
7475 
7476         DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
7477         handle_demux_data(buffer);
7478     }
7479 
7480     log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len, buffer->nTimeStamp, temp_buffer->pmem_fd);
7481 
7482     if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
7483         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
7484     }
7485 
7486     if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7487         DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
7488         h264_scratch.nFilledLen = 0;
7489         nal_count = 0;
7490         look_ahead_nal = false;
7491         frame_count = 0;
7492         if (m_frame_parser.mutils)
7493             m_frame_parser.mutils->initialize_frame_checking_environment();
7494         m_frame_parser.flush();
7495         h264_last_au_ts = LLONG_MAX;
7496         h264_last_au_flags = 0;
7497         memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
7498         m_demux_entries = 0;
7499     }
7500     struct v4l2_buffer buf;
7501     struct v4l2_plane plane;
7502     memset( (void *)&buf, 0, sizeof(buf));
7503     memset( (void *)&plane, 0, sizeof(plane));
7504     int rc;
7505     unsigned long  print_count;
7506     if (temp_buffer->buffer_len == 0 && (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
7507         struct v4l2_decoder_cmd dec;
7508 
7509         if (!streaming[OUTPUT_PORT]) {
7510             enum v4l2_buf_type buf_type;
7511             int ret = 0;
7512 
7513             buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7514             DEBUG_PRINT_HIGH("Calling streamon before issuing stop command for EOS");
7515             ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7516             if (!ret) {
7517                 DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7518                 streaming[OUTPUT_PORT] = true;
7519             } else {
7520                 DEBUG_PRINT_ERROR("Streamon failed before sending stop command");
7521                 return OMX_ErrorHardware;
7522             }
7523         }
7524 
7525         DEBUG_PRINT_HIGH("Input EOS reached. Converted to STOP command") ;
7526         memset(&dec, 0, sizeof(dec));
7527         dec.cmd = V4L2_DEC_CMD_STOP;
7528         rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec);
7529         post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7530             OMX_COMPONENT_GENERATE_EBD);
7531         if (rc < 0) {
7532             DEBUG_PRINT_ERROR("Decoder CMD failed");
7533             return OMX_ErrorHardware;
7534         }
7535         return OMX_ErrorNone;
7536     }
7537 
7538     if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
7539         DEBUG_PRINT_HIGH("Input EOS reached") ;
7540         buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
7541     }
7542 
7543 
7544     OMX_ERRORTYPE eRet = OMX_ErrorNone;
7545     buf.index = nPortIndex;
7546     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7547     buf.memory = V4L2_MEMORY_USERPTR;
7548     plane.bytesused = temp_buffer->buffer_len;
7549     plane.length = drv_ctx.ip_buf.buffer_size;
7550     plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
7551         (unsigned long)temp_buffer->offset;
7552     plane.reserved[0] = temp_buffer->pmem_fd;
7553     plane.reserved[1] = temp_buffer->offset;
7554     plane.reserved[3] = (unsigned long)buffer->pMarkData;
7555     plane.reserved[4] = (unsigned long)buffer->hMarkTargetComponent;
7556     plane.data_offset = 0;
7557     buf.m.planes = &plane;
7558     buf.length = 1;
7559     //assumption is that timestamp is in milliseconds
7560     buf.timestamp.tv_sec = buffer->nTimeStamp / 1000000;
7561     buf.timestamp.tv_usec = (buffer->nTimeStamp % 1000000);
7562     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
7563 #if NEED_TO_REVISIT
7564     buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
7565 #endif
7566 
7567     if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
7568         DEBUG_PRINT_LOW("Increment codec_config buffer counter");
7569         android_atomic_inc(&m_queued_codec_config_count);
7570     }
7571 
7572     print_v4l2_buffer("QBUF-ETB", &buf);
7573     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7574     if (rc) {
7575         DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver, send ETB back to client");
7576         print_v4l2_buffer("QBUF failed", &buf);
7577         print_omx_buffer("EBD on qbuf failed", buffer);
7578         m_cb.EmptyBufferDone(hComp, m_app_data, buffer);
7579         return OMX_ErrorHardware;
7580     }
7581 
7582     if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
7583         codec_config_flag = false;
7584     }
7585     if (!streaming[OUTPUT_PORT]) {
7586         enum v4l2_buf_type buf_type;
7587         int ret,r;
7588 
7589         buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
7590         DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
7591         ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
7592         if (!ret) {
7593             DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
7594             streaming[OUTPUT_PORT] = true;
7595         } else if (errno == EBUSY) {
7596             DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
7597             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7598                     OMX_COMPONENT_GENERATE_EBD);
7599             return OMX_ErrorInsufficientResources;
7600         } else {
7601             DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
7602             DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
7603             post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
7604                     OMX_COMPONENT_GENERATE_EBD);
7605             return OMX_ErrorBadParameter;
7606         }
7607     }
7608 
7609     return ret;
7610 }
7611 
7612 /* ======================================================================
7613    FUNCTION
7614    omx_vdec::FillThisBuffer
7615 
7616    DESCRIPTION
7617    IL client uses this method to release the frame buffer
7618    after displaying them.
7619 
7620    PARAMETERS
7621    None.
7622 
7623    RETURN VALUE
7624    true/false
7625 
7626    ========================================================================== */
fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * buffer)7627 OMX_ERRORTYPE  omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE  hComp,
7628         OMX_IN OMX_BUFFERHEADERTYPE* buffer)
7629 {
7630     if (m_state != OMX_StateExecuting &&
7631             m_state != OMX_StatePause &&
7632             m_state != OMX_StateIdle) {
7633         DEBUG_PRINT_ERROR("FTB in Invalid State");
7634         return OMX_ErrorInvalidState;
7635     }
7636 
7637     if (buffer == NULL || buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
7638         DEBUG_PRINT_ERROR("ERROR:FTB invalid buffer %p or PortIndex - %d",
7639              buffer, buffer ? (int)buffer->nOutputPortIndex : -1);
7640         return OMX_ErrorBadPortIndex;
7641     }
7642     print_omx_buffer("FillThisBuffer", buffer);
7643 
7644     if (m_error_propogated) {
7645         DEBUG_PRINT_ERROR("Fill this buffer not allowed after error");
7646         return OMX_ErrorHardware;
7647     }
7648 
7649     if (!m_out_bEnabled) {
7650         DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
7651         return OMX_ErrorIncorrectStateOperation;
7652     }
7653 
7654     unsigned nPortIndex = buffer - m_out_mem_ptr;
7655     if (dynamic_buf_mode) {
7656         private_handle_t *handle = NULL;
7657         struct VideoDecoderOutputMetaData *meta = NULL;
7658 
7659         if (!buffer || !buffer->pBuffer) {
7660             DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
7661             return OMX_ErrorBadParameter;
7662         }
7663 
7664         meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
7665         handle = (private_handle_t *)meta->pHandle;
7666 
7667         //get the buffer type and fd info
7668         DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ",
7669                         meta, meta->eType, meta->pHandle);
7670 
7671         if (!handle) {
7672             DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
7673             return OMX_ErrorBadParameter;
7674         }
7675 
7676         //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
7677         if (nPortIndex < drv_ctx.op_buf.actualcount &&
7678             nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
7679             drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
7680             drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
7681 
7682             //Store private handle from GraphicBuffer
7683             native_buffer[nPortIndex].privatehandle = handle;
7684             native_buffer[nPortIndex].nativehandle = handle;
7685         } else {
7686             DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
7687             return OMX_ErrorBadParameter;
7688         }
7689 
7690         if (handle->flags & private_handle_t::PRIV_FLAGS_DISP_CONSUMER) {
7691             m_is_display_session = true;
7692         } else {
7693             m_is_display_session = false;
7694         }
7695         buffer->nAllocLen = handle->size;
7696         DEBUG_PRINT_LOW("%s: buffer size = d-%d:b-%d",
7697                         __func__, (int)drv_ctx.op_buf.buffer_size, (int)handle->size);
7698 
7699         if (!client_buffers.is_color_conversion_enabled()) {
7700             drv_ctx.op_buf.buffer_size = handle->size;
7701         }
7702 
7703         DEBUG_PRINT_LOW("%s: m_is_display_session = %d", __func__, m_is_display_session);
7704     }
7705 
7706     if (client_buffers.is_color_conversion_enabled()) {
7707         buffer = m_intermediate_out_mem_ptr + nPortIndex;
7708         buffer->nAllocLen = drv_ctx.op_buf.buffer_size;
7709     }
7710 
7711     //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
7712     //this with a more sane size so that we don't compensate in rest of code
7713     //We'll restore this size later on, so that it's transparent to client
7714     buffer->nFilledLen = 0;
7715 
7716     post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
7717     return OMX_ErrorNone;
7718 }
7719 
7720 /* ======================================================================
7721    FUNCTION
7722    omx_vdec::fill_this_buffer_proxy
7723 
7724    DESCRIPTION
7725    IL client uses this method to release the frame buffer
7726    after displaying them.
7727 
7728    PARAMETERS
7729    None.
7730 
7731    RETURN VALUE
7732    true/false
7733 
7734    ========================================================================== */
fill_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_BUFFERHEADERTYPE * bufferAdd)7735 OMX_ERRORTYPE  omx_vdec::fill_this_buffer_proxy(
7736         OMX_IN OMX_HANDLETYPE        hComp,
7737         OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
7738 {
7739     VIDC_TRACE_NAME_HIGH("FTB");
7740     OMX_ERRORTYPE nRet = OMX_ErrorNone;
7741     OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
7742     unsigned bufIndex = 0;
7743     struct vdec_bufferpayload     *ptr_outputbuffer = NULL;
7744     struct vdec_output_frameinfo  *ptr_respbuffer = NULL;
7745 
7746     auto_lock l(buf_lock);
7747     OMX_BUFFERHEADERTYPE  *omx_base_address =
7748         client_buffers.is_color_conversion_enabled()?
7749                            m_intermediate_out_mem_ptr:m_out_mem_ptr;
7750     vdec_bufferpayload *omx_ptr_outputbuffer =
7751         client_buffers.is_color_conversion_enabled()?
7752                     drv_ctx.ptr_intermediate_outputbuffer:drv_ctx.ptr_outputbuffer;
7753     bufIndex = buffer-omx_base_address;
7754 
7755     if (bufferAdd == NULL || bufIndex >= drv_ctx.op_buf.actualcount) {
7756         DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, bufIndex %u bufCount %u",
7757             bufIndex, drv_ctx.op_buf.actualcount);
7758         return OMX_ErrorBadParameter;
7759     }
7760 
7761     if (BITMASK_ABSENT(&m_out_bm_count, bufIndex) || m_buffer_error) {
7762         DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer, bufIndex %u", bufIndex);
7763         return OMX_ErrorBadParameter;
7764     }
7765 
7766     /*Return back the output buffer to client*/
7767     if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true || in_reconfig) {
7768         DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
7769         buffer->nFilledLen = 0;
7770         print_omx_buffer("FBD in FTBProxy", &m_out_mem_ptr[bufIndex]);
7771         m_cb.FillBufferDone (hComp,m_app_data,&m_out_mem_ptr[bufIndex]);
7772         return OMX_ErrorNone;
7773     }
7774     if (m_error_propogated == true) {
7775         DEBUG_PRINT_LOW("Return buffers in error state");
7776         buffer->nFilledLen = 0;
7777         print_omx_buffer("FBD in FTBProxy", &m_out_mem_ptr[bufIndex]);
7778         m_cb.FillBufferDone (hComp,m_app_data,&m_out_mem_ptr[bufIndex]);
7779         return OMX_ErrorNone;
7780     }
7781 
7782     if (dynamic_buf_mode) {
7783         omx_ptr_outputbuffer[bufIndex].offset = 0;
7784         omx_ptr_outputbuffer[bufIndex].buffer_len = buffer->nAllocLen;
7785         omx_ptr_outputbuffer[bufIndex].mmaped_size = buffer->nAllocLen;
7786     }
7787 
7788     pending_output_buffers++;
7789     VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
7790     ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
7791     if (ptr_respbuffer) {
7792         ptr_outputbuffer =  (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
7793     }
7794 
7795     if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
7796         DEBUG_PRINT_ERROR("Invalid ptr_respbuffer %p, ptr_outputbuffer %p",
7797             ptr_respbuffer, ptr_outputbuffer);
7798         buffer->nFilledLen = 0;
7799         print_omx_buffer("FBD in error", &m_out_mem_ptr[bufIndex]);
7800         m_cb.FillBufferDone (hComp,m_app_data,&m_out_mem_ptr[bufIndex]);
7801         pending_output_buffers--;
7802         VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
7803         return OMX_ErrorBadParameter;
7804     }
7805 
7806     int rc = 0;
7807     struct v4l2_buffer buf;
7808     struct v4l2_plane plane[VIDEO_MAX_PLANES];
7809     memset( (void *)&buf, 0, sizeof(buf));
7810     memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
7811     unsigned int extra_idx = 0;
7812 
7813     buf.index = bufIndex;
7814     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
7815     buf.memory = V4L2_MEMORY_USERPTR;
7816     plane[0].bytesused = buffer->nFilledLen;
7817     plane[0].length = buffer->nAllocLen;
7818     plane[0].m.userptr =
7819         (unsigned long)omx_ptr_outputbuffer[bufIndex].bufferaddr -
7820         (unsigned long)omx_ptr_outputbuffer[bufIndex].offset;
7821     plane[0].reserved[0] = omx_ptr_outputbuffer[bufIndex].pmem_fd;
7822     plane[0].reserved[1] = omx_ptr_outputbuffer[bufIndex].offset;
7823     plane[0].data_offset = 0;
7824     extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
7825     if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
7826         plane[extra_idx].bytesused = 0;
7827         plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
7828         plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + bufIndex * drv_ctx.extradata_info.buffer_size);
7829 #ifdef USE_ION
7830         plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.data_fd;
7831 #endif
7832         plane[extra_idx].reserved[1] = bufIndex * drv_ctx.extradata_info.buffer_size;
7833         plane[extra_idx].data_offset = 0;
7834     } else if (extra_idx >= VIDEO_MAX_PLANES) {
7835         DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
7836         return OMX_ErrorBadParameter;
7837     }
7838     buf.m.planes = plane;
7839     buf.length = drv_ctx.num_planes;
7840     print_v4l2_buffer("QBUF-FTB", &buf);
7841     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
7842     if (rc) {
7843         buffer->nFilledLen = 0;
7844         DEBUG_PRINT_ERROR("Failed to qbuf to driver, error %s", strerror(errno));
7845         print_omx_buffer("FBD in error", &m_out_mem_ptr[bufIndex]);
7846         m_cb.FillBufferDone(hComp, m_app_data, &m_out_mem_ptr[bufIndex]);
7847         return OMX_ErrorHardware;
7848     }
7849 
7850     return OMX_ErrorNone;
7851 }
7852 
7853 /* ======================================================================
7854    FUNCTION
7855    omx_vdec::SetCallbacks
7856 
7857    DESCRIPTION
7858    Set the callbacks.
7859 
7860    PARAMETERS
7861    None.
7862 
7863    RETURN VALUE
7864    OMX Error None if everything successful.
7865 
7866    ========================================================================== */
set_callbacks(OMX_IN OMX_HANDLETYPE hComp,OMX_IN OMX_CALLBACKTYPE * callbacks,OMX_IN OMX_PTR appData)7867 OMX_ERRORTYPE  omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE        hComp,
7868         OMX_IN OMX_CALLBACKTYPE* callbacks,
7869         OMX_IN OMX_PTR             appData)
7870 {
7871     (void) hComp;
7872 
7873     if (!callbacks)
7874         return OMX_ErrorBadParameter;
7875 
7876     m_cb       = *callbacks;
7877     DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
7878             m_cb.EventHandler,m_cb.FillBufferDone);
7879     m_app_data =    appData;
7880     return OMX_ErrorNone;
7881 }
7882 
7883 /* ======================================================================
7884    FUNCTION
7885    omx_vdec::ComponentDeInit
7886 
7887    DESCRIPTION
7888    Destroys the component and release memory allocated to the heap.
7889 
7890    PARAMETERS
7891    <TBD>.
7892 
7893    RETURN VALUE
7894    OMX Error None if everything successful.
7895 
7896    ========================================================================== */
component_deinit(OMX_IN OMX_HANDLETYPE hComp)7897 OMX_ERRORTYPE  omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
7898 {
7899    (void) hComp;
7900    OMX_ERRORTYPE nRet = OMX_ErrorNone;
7901    OMX_BUFFERHEADERTYPE *buffer;
7902 
7903     unsigned i = 0;
7904     if (OMX_StateLoaded != m_state) {
7905         DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
7906                 m_state);
7907         DEBUG_PRINT_ERROR("Playback Ended - FAILED");
7908     } else {
7909         DEBUG_PRINT_HIGH("Playback Ended - PASSED");
7910     }
7911 
7912     /*Check if the output buffers have to be cleaned up*/
7913     buffer = m_out_mem_ptr;
7914     if (buffer) {
7915         DEBUG_PRINT_LOW("Freeing the Output Memory");
7916         for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
7917             if (BITMASK_PRESENT(&m_out_bm_count, i)) {
7918                 BITMASK_CLEAR(&m_out_bm_count, i);
7919                     nRet = free_output_buffer (buffer+i);
7920                     if (OMX_ErrorNone != nRet)
7921                         break;
7922             }
7923             if (release_output_done()) {
7924                 DEBUG_PRINT_HIGH("All output buffers are released");
7925                 break;
7926             }
7927         }
7928 #ifdef _ANDROID_ICS_
7929         memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
7930 #endif
7931     }
7932 
7933     /*Check if the input buffers have to be cleaned up*/
7934     if (m_inp_mem_ptr || m_inp_heap_ptr) {
7935         DEBUG_PRINT_LOW("Freeing the Input Memory");
7936         for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
7937 
7938             if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
7939                 BITMASK_CLEAR(&m_inp_bm_count, i);
7940                 if (m_inp_mem_ptr)
7941                     free_input_buffer (i,&m_inp_mem_ptr[i]);
7942                 else
7943                     free_input_buffer (i,NULL);
7944             }
7945 
7946             if (release_input_done()) {
7947                 DEBUG_PRINT_HIGH("All input buffers released");
7948                 break;
7949             }
7950        }
7951     }
7952     free_input_buffer_header();
7953     free_output_buffer_header();
7954     if (h264_scratch.pBuffer) {
7955         free(h264_scratch.pBuffer);
7956         h264_scratch.pBuffer = NULL;
7957     }
7958 
7959     if (h264_parser) {
7960         delete h264_parser;
7961         h264_parser = NULL;
7962     }
7963 
7964     if (m_frame_parser.mutils) {
7965         DEBUG_PRINT_LOW("Free utils parser");
7966         delete (m_frame_parser.mutils);
7967         m_frame_parser.mutils = NULL;
7968     }
7969 
7970     if (m_platform_list) {
7971         free(m_platform_list);
7972         m_platform_list = NULL;
7973     }
7974     if (m_vendor_config.pData) {
7975         free(m_vendor_config.pData);
7976         m_vendor_config.pData = NULL;
7977     }
7978 
7979     // Reset counters in mesg queues
7980     m_ftb_q.m_size=0;
7981     m_cmd_q.m_size=0;
7982     m_etb_q.m_size=0;
7983     m_ftb_q.m_read = m_ftb_q.m_write =0;
7984     m_cmd_q.m_read = m_cmd_q.m_write =0;
7985     m_etb_q.m_read = m_etb_q.m_write =0;
7986 
7987     DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
7988     //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
7989     // NULL);
7990     DEBUG_PRINT_HIGH("Close the driver instance");
7991 
7992     if (m_debug.infile) {
7993         fclose(m_debug.infile);
7994         m_debug.infile = NULL;
7995     }
7996     if (m_debug.outfile) {
7997         fclose(m_debug.outfile);
7998         m_debug.outfile = NULL;
7999     }
8000     if (m_debug.ccoutfile) {
8001         fclose(m_debug.ccoutfile);
8002         m_debug.ccoutfile = NULL;
8003     }
8004     if (m_debug.out_ymeta_file) {
8005         fclose(m_debug.out_ymeta_file);
8006         m_debug.out_ymeta_file = NULL;
8007     }
8008     if (m_debug.out_uvmeta_file) {
8009         fclose(m_debug.out_uvmeta_file);
8010         m_debug.out_uvmeta_file = NULL;
8011     }
8012 #ifdef OUTPUT_EXTRADATA_LOG
8013     if (outputExtradataFile)
8014         fclose (outputExtradataFile);
8015 #endif
8016     DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
8017     return OMX_ErrorNone;
8018 }
8019 
8020 /* ======================================================================
8021    FUNCTION
8022    omx_vdec::UseEGLImage
8023 
8024    DESCRIPTION
8025    OMX Use EGL Image method implementation <TBD>.
8026 
8027    PARAMETERS
8028    <TBD>.
8029 
8030    RETURN VALUE
8031    Not Implemented error.
8032 
8033    ========================================================================== */
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)8034 OMX_ERRORTYPE  omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE     hComp,
8035         OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
8036         OMX_IN OMX_U32                        port,
8037         OMX_IN OMX_PTR                     appData,
8038         OMX_IN void*                      eglImage)
8039 {
8040     (void) appData;
8041     OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
8042     OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
8043     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
8044 
8045 #ifdef USE_EGL_IMAGE_GPU
8046     PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
8047     EGLint fd = -1, offset = 0,pmemPtr = 0;
8048 #else
8049     int fd = -1, offset = 0;
8050 #endif
8051     DEBUG_PRINT_HIGH("use EGL image support for decoder");
8052     if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
8053         DEBUG_PRINT_ERROR("Invalid EGL image");
8054     }
8055 #ifdef USE_EGL_IMAGE_GPU
8056     if (m_display_id == NULL) {
8057         DEBUG_PRINT_ERROR("Display ID is not set by IL client");
8058         return OMX_ErrorInsufficientResources;
8059     }
8060     egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
8061         eglGetProcAddress("eglQueryImageKHR");
8062     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
8063     egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
8064     egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
8065 #else //with OMX test app
8066     struct temp_egl {
8067         int pmem_fd;
8068         int offset;
8069     };
8070     struct temp_egl *temp_egl_id = NULL;
8071     void * pmemPtr = (void *) eglImage;
8072     temp_egl_id = (struct temp_egl *)eglImage;
8073     if (temp_egl_id != NULL) {
8074         fd = temp_egl_id->pmem_fd;
8075         offset = temp_egl_id->offset;
8076     }
8077 #endif
8078     if (fd < 0) {
8079         DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
8080         return OMX_ErrorInsufficientResources;
8081     }
8082     pmem_info.pmem_fd = (OMX_U32) fd;
8083     pmem_info.offset = (OMX_U32) offset;
8084     pmem_entry.entry = (void *) &pmem_info;
8085     pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
8086     pmem_list.entryList = &pmem_entry;
8087     pmem_list.nEntries = 1;
8088     ouput_egl_buffers = true;
8089     if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
8090                 (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
8091                 (OMX_U8 *)pmemPtr)) {
8092         DEBUG_PRINT_ERROR("use buffer call failed for egl image");
8093         return OMX_ErrorInsufficientResources;
8094     }
8095     return OMX_ErrorNone;
8096 }
8097 
8098 /* ======================================================================
8099    FUNCTION
8100    omx_vdec::ComponentRoleEnum
8101 
8102    DESCRIPTION
8103    OMX Component Role Enum method implementation.
8104 
8105    PARAMETERS
8106    <TBD>.
8107 
8108    RETURN VALUE
8109    OMX Error None if everything is successful.
8110    ========================================================================== */
component_role_enum(OMX_IN OMX_HANDLETYPE hComp,OMX_OUT OMX_U8 * role,OMX_IN OMX_U32 index)8111 OMX_ERRORTYPE  omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
8112         OMX_OUT OMX_U8*        role,
8113         OMX_IN OMX_U32        index)
8114 {
8115     (void) hComp;
8116     OMX_ERRORTYPE eRet = OMX_ErrorNone;
8117 
8118     if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
8119         if ((0 == index) && role) {
8120             strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
8121             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8122         } else {
8123             eRet = OMX_ErrorNoMore;
8124         }
8125     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
8126         if ((0 == index) && role) {
8127             strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
8128             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8129         } else {
8130             DEBUG_PRINT_LOW("No more roles");
8131             eRet = OMX_ErrorNoMore;
8132         }
8133     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
8134         if ((0 == index) && role) {
8135             strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
8136             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8137         } else {
8138             DEBUG_PRINT_LOW("No more roles");
8139             eRet = OMX_ErrorNoMore;
8140         }
8141     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
8142         if ((0 == index) && role) {
8143             strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
8144             DEBUG_PRINT_LOW("component_role_enum: role %s", role);
8145         } else {
8146             DEBUG_PRINT_LOW("No more roles");
8147             eRet = OMX_ErrorNoMore;
8148         }
8149     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
8150         if ((0 == index) && role) {
8151             strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
8152             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8153         } else {
8154             DEBUG_PRINT_LOW("No more roles");
8155             eRet = OMX_ErrorNoMore;
8156         }
8157     } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
8158         if ((0 == index) && role) {
8159             strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
8160             DEBUG_PRINT_LOW("component_role_enum: role %s",role);
8161         } else {
8162             DEBUG_PRINT_LOW("No more roles");
8163             eRet = OMX_ErrorNoMore;
8164         }
8165     } else {
8166         DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
8167         eRet = OMX_ErrorInvalidComponentName;
8168     }
8169     return eRet;
8170 }
8171 
8172 
8173 
8174 
8175 /* ======================================================================
8176    FUNCTION
8177    omx_vdec::AllocateDone
8178 
8179    DESCRIPTION
8180    Checks if entire buffer pool is allocated by IL Client or not.
8181    Need this to move to IDLE state.
8182 
8183    PARAMETERS
8184    None.
8185 
8186    RETURN VALUE
8187    true/false.
8188 
8189    ========================================================================== */
allocate_done(void)8190 bool omx_vdec::allocate_done(void)
8191 {
8192     bool bRet = false;
8193     bool bRet_In = false;
8194     bool bRet_Out = false;
8195     bool bRet_Out_Extra = false;
8196 
8197     bRet_In = allocate_input_done();
8198     bRet_Out = allocate_output_done();
8199     bRet_Out_Extra = allocate_output_extradata_done();
8200 
8201     if (bRet_In && bRet_Out && bRet_Out_Extra) {
8202         DEBUG_PRINT_HIGH("All ports buffers are allocated");
8203         bRet = true;
8204     }
8205 
8206     return bRet;
8207 }
8208 /* ======================================================================
8209    FUNCTION
8210    omx_vdec::AllocateInputDone
8211 
8212    DESCRIPTION
8213    Checks if I/P buffer pool is allocated by IL Client or not.
8214 
8215    PARAMETERS
8216    None.
8217 
8218    RETURN VALUE
8219    true/false.
8220 
8221    ========================================================================== */
allocate_input_done(void)8222 bool omx_vdec::allocate_input_done(void)
8223 {
8224     bool bRet = false;
8225     unsigned i=0;
8226 
8227     if (m_inp_mem_ptr == NULL) {
8228         return bRet;
8229     }
8230     if (m_inp_mem_ptr ) {
8231         for (; i<drv_ctx.ip_buf.actualcount; i++) {
8232             if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
8233                 break;
8234             }
8235         }
8236     }
8237     if (i == drv_ctx.ip_buf.actualcount) {
8238         bRet = true;
8239     }
8240     if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
8241         m_inp_bPopulated = OMX_TRUE;
8242     }
8243     return bRet;
8244 }
8245 /* ======================================================================
8246    FUNCTION
8247    omx_vdec::AllocateOutputDone
8248 
8249    DESCRIPTION
8250    Checks if entire O/P buffer pool is allocated by IL Client or not.
8251 
8252    PARAMETERS
8253    None.
8254 
8255    RETURN VALUE
8256    true/false.
8257 
8258    ========================================================================== */
allocate_output_done(void)8259 bool omx_vdec::allocate_output_done(void)
8260 {
8261     bool bRet = false;
8262     unsigned j=0;
8263 
8264     if (m_out_mem_ptr == NULL) {
8265         return bRet;
8266     }
8267 
8268     if (m_out_mem_ptr) {
8269         for (; j < drv_ctx.op_buf.actualcount; j++) {
8270             if (BITMASK_ABSENT(&m_out_bm_count,j)) {
8271                 break;
8272             }
8273         }
8274     }
8275 
8276     if (j == drv_ctx.op_buf.actualcount) {
8277         bRet = true;
8278         if (m_out_bEnabled)
8279             m_out_bPopulated = OMX_TRUE;
8280     }
8281 
8282     return bRet;
8283 }
8284 
allocate_output_extradata_done(void)8285 bool omx_vdec::allocate_output_extradata_done(void) {
8286     bool bRet = false;
8287     unsigned j=0;
8288     unsigned nBufferCount = 0;
8289 
8290     nBufferCount = m_client_out_extradata_info.getBufferCount();
8291 
8292     if (!m_client_out_extradata_info.is_client_extradata_enabled()) {
8293         return true;
8294     }
8295 
8296     if (m_client_output_extradata_mem_ptr) {
8297         for (; j < nBufferCount; j++) {
8298             if (BITMASK_ABSENT(&m_out_extradata_bm_count,j)) {
8299                 break;
8300             }
8301         }
8302 
8303         if (j == nBufferCount) {
8304             bRet = true;
8305             DEBUG_PRINT_HIGH("Allocate done for all extradata o/p buffers");
8306         }
8307     }
8308 
8309     return bRet;
8310 }
8311 /* ======================================================================
8312    FUNCTION
8313    omx_vdec::ReleaseDone
8314 
8315    DESCRIPTION
8316    Checks if IL client has released all the buffers.
8317 
8318    PARAMETERS
8319    None.
8320 
8321    RETURN VALUE
8322    true/false
8323 
8324    ========================================================================== */
release_done(void)8325 bool omx_vdec::release_done(void)
8326 {
8327     bool bRet = false;
8328 
8329     if (release_input_done()) {
8330         if (release_output_done()) {
8331             if (release_output_extradata_done()) {
8332                 DEBUG_PRINT_HIGH("All ports buffers are released");
8333                 bRet = true;
8334             }
8335         }
8336     }
8337     return bRet;
8338 }
8339 
8340 
8341 /* ======================================================================
8342    FUNCTION
8343    omx_vdec::ReleaseOutputDone
8344 
8345    DESCRIPTION
8346    Checks if IL client has released all the buffers.
8347 
8348    PARAMETERS
8349    None.
8350 
8351    RETURN VALUE
8352    true/false
8353 
8354    ========================================================================== */
release_output_done(void)8355 bool omx_vdec::release_output_done(void)
8356 {
8357     bool bRet = false;
8358     unsigned i=0,j=0;
8359 
8360     if (m_out_mem_ptr) {
8361         for (; j < drv_ctx.op_buf.actualcount ; j++) {
8362             if (BITMASK_PRESENT(&m_out_bm_count,j)) {
8363                 break;
8364             }
8365         }
8366         if (j == drv_ctx.op_buf.actualcount) {
8367             m_out_bm_count = 0;
8368             bRet = true;
8369         }
8370     } else {
8371         m_out_bm_count = 0;
8372         bRet = true;
8373     }
8374     return bRet;
8375 }
8376 /* ======================================================================
8377    FUNCTION
8378    omx_vdec::ReleaseInputDone
8379 
8380    DESCRIPTION
8381    Checks if IL client has released all the buffers.
8382 
8383    PARAMETERS
8384    None.
8385 
8386    RETURN VALUE
8387    true/false
8388 
8389    ========================================================================== */
release_input_done(void)8390 bool omx_vdec::release_input_done(void)
8391 {
8392     bool bRet = false;
8393     unsigned i=0,j=0;
8394 
8395     if (m_inp_mem_ptr) {
8396         for (; j<drv_ctx.ip_buf.actualcount; j++) {
8397             if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
8398                 break;
8399             }
8400         }
8401         if (j==drv_ctx.ip_buf.actualcount) {
8402             bRet = true;
8403         }
8404     } else {
8405         bRet = true;
8406     }
8407     return bRet;
8408 }
8409 
release_output_extradata_done(void)8410 bool omx_vdec::release_output_extradata_done(void) {
8411     bool bRet = false;
8412     unsigned i=0,j=0, buffer_count=0;
8413 
8414     buffer_count = m_client_out_extradata_info.getBufferCount();
8415     DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d",
8416             m_client_output_extradata_mem_ptr, buffer_count);
8417 
8418     if (m_client_output_extradata_mem_ptr) {
8419         for (; j<buffer_count; j++) {
8420             if ( BITMASK_PRESENT(&m_out_extradata_bm_count,j)) {
8421                 break;
8422             }
8423         }
8424         if (j == buffer_count) {
8425             bRet = true;
8426         }
8427     } else {
8428         bRet = true;
8429     }
8430     return bRet;
8431 }
8432 
fill_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8433 OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
8434         OMX_BUFFERHEADERTYPE * buffer)
8435 {
8436     VIDC_TRACE_NAME_HIGH("FBD");
8437     OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
8438     OMX_BUFFERHEADERTYPE  *omx_base_address =
8439         client_buffers.is_color_conversion_enabled()?
8440                               m_intermediate_out_mem_ptr:m_out_mem_ptr;
8441     vdec_bufferpayload *omx_ptr_outputbuffer =
8442         client_buffers.is_color_conversion_enabled()?
8443                     drv_ctx.ptr_intermediate_outputbuffer:drv_ctx.ptr_outputbuffer;
8444 
8445     if (!buffer || (buffer - omx_base_address) >= (int)drv_ctx.op_buf.actualcount) {
8446         DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
8447         return OMX_ErrorBadParameter;
8448     } else if (output_flush_progress) {
8449         DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
8450         buffer->nFilledLen = 0;
8451         buffer->nTimeStamp = 0;
8452         buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
8453         buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
8454         buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
8455     }
8456 
8457     if (m_debug_extradata) {
8458         if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
8459             DEBUG_PRINT_HIGH("***************************************************");
8460             DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
8461             DEBUG_PRINT_HIGH("***************************************************");
8462         }
8463 
8464         if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
8465             DEBUG_PRINT_HIGH("***************************************************");
8466             DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
8467             DEBUG_PRINT_HIGH("***************************************************");
8468         }
8469     }
8470 
8471     pending_output_buffers --;
8472     VIDC_TRACE_INT_LOW("FTB-pending", pending_output_buffers);
8473 
8474     if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8475         DEBUG_PRINT_HIGH("Output EOS has been reached");
8476         if (!output_flush_progress)
8477             post_event((unsigned)NULL, (unsigned)NULL,
8478                     OMX_COMPONENT_GENERATE_EOS_DONE);
8479 
8480         if (psource_frame) {
8481             print_omx_buffer("EBD in FBD", psource_frame);
8482             m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame);
8483             psource_frame = NULL;
8484         }
8485         if (pdest_frame) {
8486             pdest_frame->nFilledLen = 0;
8487             m_input_free_q.insert_entry((unsigned long) pdest_frame,(unsigned)NULL,
8488                     (unsigned)NULL);
8489             pdest_frame = NULL;
8490         }
8491     }
8492 
8493 #ifdef OUTPUT_EXTRADATA_LOG
8494     if (outputExtradataFile) {
8495         int buf_index = buffer - omx_base_address;
8496         OMX_U8 *pBuffer = (OMX_U8 *)(omx_ptr_outputbuffer[buf_index].bufferaddr);
8497 
8498         OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
8499         p_extra = (OMX_OTHER_EXTRADATATYPE *)
8500             ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
8501 
8502         while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
8503             DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
8504                                     p_extra->nSize, p_extra->eType);
8505             fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
8506 
8507             if (p_extra->eType == OMX_ExtraDataNone) {
8508                 break;
8509             }
8510             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
8511         }
8512     }
8513 #endif
8514 
8515     /* For use buffer we need to copy the data */
8516     if (!output_flush_progress) {
8517         /* This is the error check for non-recoverable errros */
8518         bool is_duplicate_ts_valid = true;
8519         bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
8520 
8521         if (output_capability == V4L2_PIX_FMT_MPEG4 ||
8522                 output_capability == V4L2_PIX_FMT_MPEG2)
8523             is_duplicate_ts_valid = false;
8524 
8525         if (buffer->nFilledLen > 0) {
8526             time_stamp_dts.get_next_timestamp(buffer,
8527                     is_interlaced && is_duplicate_ts_valid && !is_mbaff);
8528         }
8529     }
8530     VIDC_TRACE_INT_LOW("FBD-TS", buffer->nTimeStamp / 1000);
8531 
8532     if (m_cb.FillBufferDone) {
8533         if (buffer->nFilledLen > 0) {
8534             if (arbitrary_bytes)
8535                 adjust_timestamp(buffer->nTimeStamp);
8536             else
8537                 set_frame_rate(buffer->nTimeStamp);
8538 
8539             proc_frms++;
8540             if (perf_flag) {
8541                 if (1 == proc_frms) {
8542                     dec_time.stop();
8543                     latency = dec_time.processing_time_us() - latency;
8544                     DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
8545                     dec_time.start();
8546                     fps_metrics.start();
8547                 }
8548                 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8549                     OMX_U64 proc_time = 0;
8550                     fps_metrics.stop();
8551                     proc_time = fps_metrics.processing_time_us();
8552                     DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
8553                             (unsigned int)proc_frms, (float)proc_time / 1e6,
8554                             (float)(1e6 * proc_frms) / proc_time);
8555                 }
8556             }
8557         }
8558         if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
8559             prev_ts = LLONG_MAX;
8560             rst_prev_ts = true;
8561             proc_frms = 0;
8562         }
8563 
8564         pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
8565             ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
8566              buffer->pPlatformPrivate)->entryList->entry;
8567         OMX_BUFFERHEADERTYPE *il_buffer;
8568         il_buffer = client_buffers.get_il_buf_hdr(buffer);
8569         OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
8570 
8571         if (il_buffer && m_last_rendered_TS >= 0) {
8572             OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
8573             // Convert fps into ms value. 1 sec = 1000000 ms.
8574             OMX_U64 target_ts_delta = m_dec_hfr_fps ? 1000000 / m_dec_hfr_fps : ts_delta;
8575 
8576             // Current frame can be send for rendering if
8577             // (a) current FPS is <=  60
8578             // (b) is the next frame after the frame with TS 0
8579             // (c) is the first frame after seek
8580             // (d) the delta TS b\w two consecutive frames is > 16 ms
8581             // (e) its TS is equal to previous frame TS
8582             // (f) if marked EOS
8583 
8584             if(current_framerate <= (OMX_U32)m_dec_hfr_fps || m_last_rendered_TS == 0 ||
8585                il_buffer->nTimeStamp == 0 || ts_delta >= (OMX_TICKS)target_ts_delta||
8586                ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
8587                m_last_rendered_TS = il_buffer->nTimeStamp;
8588             } else {
8589                //mark for droping
8590                buffer->nFilledLen = 0;
8591             }
8592 
8593             DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
8594                               buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
8595                               il_buffer->nTimeStamp,ts_delta);
8596 
8597             //above code makes sure that delta b\w two consecutive frames is not
8598             //greater than 16ms, slow-mo feature, so cap fps to max 60
8599             if (current_framerate > (OMX_U32)m_dec_hfr_fps ) {
8600                 current_framerate = m_dec_hfr_fps;
8601             }
8602         }
8603 
8604         // add current framerate to gralloc meta data
8605         if ((buffer->nFilledLen > 0) && m_enable_android_native_buffers && omx_base_address) {
8606             // If valid fps was received, directly send it to display for the 1st fbd.
8607             // Otherwise, calculate fps using fbd timestamps
8608             float refresh_rate = m_fps_prev;
8609             if (m_fps_received) {
8610                 if (1 == proc_frms) {
8611                     refresh_rate = m_fps_received / (float)(1<<16);
8612                 }
8613             } else {
8614                 // calculate and set refresh rate for every frame from second frame onwards
8615                 // display will assume the default refresh rate for first frame (which is 60 fps)
8616                 if (m_fps_prev) {
8617                     if (drv_ctx.frame_rate.fps_denominator) {
8618                         refresh_rate = drv_ctx.frame_rate.fps_numerator /
8619                             (float) drv_ctx.frame_rate.fps_denominator;
8620                     }
8621                 }
8622             }
8623             OMX_U32 fps_limit = m_dec_hfr_fps ? (OMX_U32)m_dec_hfr_fps : 60;
8624             if (refresh_rate > fps_limit) {
8625                 refresh_rate = fps_limit;
8626             }
8627             DEBUG_PRINT_LOW("frc set refresh_rate %f, frame %d", refresh_rate, proc_frms);
8628             OMX_U32 buf_index = buffer - omx_base_address;
8629             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8630                          UPDATE_REFRESH_RATE, (void*)&refresh_rate);
8631             m_fps_prev = refresh_rate;
8632         }
8633 
8634         if (buffer->nFilledLen && m_enable_android_native_buffers && omx_base_address) {
8635             OMX_U32 buf_index = buffer - omx_base_address;
8636             DEBUG_PRINT_LOW("stereo_output_mode = %d",stereo_output_mode);
8637             setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
8638                                S3D_FORMAT, (void*)&stereo_output_mode);
8639         }
8640 
8641         if (il_buffer) {
8642             log_output_buffers(buffer);
8643             log_cc_output_buffers(il_buffer);
8644             if (dynamic_buf_mode) {
8645                 unsigned int nPortIndex = 0;
8646                 nPortIndex = buffer-omx_base_address;
8647 
8648                 // Since we're passing around handles, adjust nFilledLen and nAllocLen
8649                 // to size of the handle. Do it _after_ log_output_buffers which
8650                 // requires the respective sizes to be accurate.
8651 
8652                 buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
8653                 buffer->nFilledLen = buffer->nFilledLen ?
8654                         sizeof(struct VideoDecoderOutputMetaData) : 0;
8655 
8656                 //Clear graphic buffer handles in dynamic mode
8657                 if (nPortIndex < drv_ctx.op_buf.actualcount &&
8658                     nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
8659                     native_buffer[nPortIndex].privatehandle = NULL;
8660                     native_buffer[nPortIndex].nativehandle = NULL;
8661                 } else {
8662                     DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
8663                     return OMX_ErrorBadParameter;
8664                 }
8665             }
8666             print_omx_buffer("FillBufferDone", buffer);
8667             m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
8668         } else {
8669             DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
8670             return OMX_ErrorBadParameter;
8671         }
8672     } else {
8673         DEBUG_PRINT_ERROR("NULL m_cb.FillBufferDone");
8674         return OMX_ErrorBadParameter;
8675     }
8676 
8677 #ifdef ADAPTIVE_PLAYBACK_SUPPORTED
8678     if (m_smoothstreaming_mode && omx_base_address) {
8679         OMX_U32 buf_index = buffer - omx_base_address;
8680         BufferDim_t dim;
8681         private_handle_t *private_handle = NULL;
8682         dim.sliceWidth = framesize.nWidth;
8683         dim.sliceHeight = framesize.nHeight;
8684         if (buf_index < drv_ctx.op_buf.actualcount &&
8685             buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
8686             native_buffer[buf_index].privatehandle)
8687             private_handle = native_buffer[buf_index].privatehandle;
8688         if (private_handle) {
8689             DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
8690                 dim.sliceWidth, dim.sliceHeight);
8691             setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
8692         }
8693     }
8694 #endif
8695 
8696     return OMX_ErrorNone;
8697 }
8698 
empty_buffer_done(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)8699 OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE         hComp,
8700         OMX_BUFFERHEADERTYPE* buffer)
8701 {
8702     VIDC_TRACE_NAME_HIGH("EBD");
8703     int nBufferIndex = buffer - m_inp_mem_ptr;
8704 
8705     if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) {
8706         DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
8707         return OMX_ErrorBadParameter;
8708     }
8709 
8710     pending_input_buffers--;
8711     VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
8712 
8713     if (arbitrary_bytes) {
8714         if (pdest_frame == NULL && input_flush_progress == false) {
8715             DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
8716             pdest_frame = buffer;
8717             buffer->nFilledLen = 0;
8718             buffer->nTimeStamp = LLONG_MAX;
8719             push_input_buffer (hComp);
8720         } else {
8721             DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
8722             buffer->nFilledLen = 0;
8723             if (!m_input_free_q.insert_entry((unsigned long)buffer,
8724                         (unsigned)NULL, (unsigned)NULL)) {
8725                 DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
8726             }
8727         }
8728     } else if (m_cb.EmptyBufferDone) {
8729         buffer->nFilledLen = 0;
8730         if (input_use_buffer == true) {
8731             buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
8732         }
8733 
8734         /* Restore the FD that we over-wrote in ETB */
8735         if (m_input_pass_buffer_fd) {
8736             buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
8737         }
8738 
8739         print_omx_buffer("EmptyBufferDone", buffer);
8740         m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
8741     }
8742     return OMX_ErrorNone;
8743 }
8744 
async_message_process(void * context,void * message)8745 int omx_vdec::async_message_process (void *context, void* message)
8746 {
8747     omx_vdec* omx = NULL;
8748     struct vdec_msginfo *vdec_msg = NULL;
8749     OMX_BUFFERHEADERTYPE* omxhdr = NULL;
8750     struct v4l2_buffer *v4l2_buf_ptr = NULL;
8751     struct v4l2_plane *plane = NULL;
8752     struct vdec_output_frameinfo *output_respbuf = NULL;
8753     int rc=1;
8754     bool reconfig_event_sent = false;
8755     if (context == NULL || message == NULL) {
8756         DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
8757         return -1;
8758     }
8759     vdec_msg = (struct vdec_msginfo *)message;
8760 
8761     omx = reinterpret_cast<omx_vdec*>(context);
8762 
8763     switch (vdec_msg->msgcode) {
8764 
8765         case VDEC_MSG_EVT_HW_ERROR:
8766             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8767                     OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8768             break;
8769 
8770         case VDEC_MSG_EVT_HW_OVERLOAD:
8771             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8772                     OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
8773             break;
8774 
8775         case VDEC_MSG_EVT_HW_UNSUPPORTED:
8776             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8777                     OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
8778             break;
8779 
8780         case VDEC_MSG_RESP_START_DONE:
8781             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8782                     OMX_COMPONENT_GENERATE_START_DONE);
8783             break;
8784 
8785         case VDEC_MSG_RESP_STOP_DONE:
8786             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8787                     OMX_COMPONENT_GENERATE_STOP_DONE);
8788             break;
8789 
8790         case VDEC_MSG_RESP_RESUME_DONE:
8791             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8792                     OMX_COMPONENT_GENERATE_RESUME_DONE);
8793             break;
8794 
8795         case VDEC_MSG_RESP_PAUSE_DONE:
8796             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8797                     OMX_COMPONENT_GENERATE_PAUSE_DONE);
8798             break;
8799 
8800         case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
8801             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8802                     OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
8803             break;
8804         case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
8805             omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8806                     OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
8807             break;
8808         case VDEC_MSG_RESP_INPUT_FLUSHED:
8809         case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
8810 
8811             /* omxhdr = (OMX_BUFFERHEADERTYPE* )
8812                vdec_msg->msgdata.input_frame_clientdata; */
8813 
8814             v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
8815             if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
8816                 v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
8817                 omxhdr = NULL;
8818                 vdec_msg->status_code = VDEC_S_EFATAL;
8819                 break;
8820 
8821             }
8822             omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
8823 
8824             if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
8825                 DEBUG_PRINT_HIGH("Unsupported input");
8826                 omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
8827                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
8828             }
8829             if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_DATA_CORRUPT) {
8830                 omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8831                 vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
8832             }
8833             if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
8834 
8835                 DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
8836                 android_atomic_dec(&omx->m_queued_codec_config_count);
8837                 if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
8838                     BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
8839                     DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
8840                     sem_post(&omx->m_safe_flush);
8841                 }
8842             }
8843             if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
8844                 omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8845             }
8846             omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
8847                     OMX_COMPONENT_GENERATE_EBD);
8848             break;
8849         case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
8850             int64_t *timestamp;
8851             timestamp = (int64_t *) malloc(sizeof(int64_t));
8852             if (timestamp) {
8853                 *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
8854                 omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
8855                         OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
8856                 DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
8857                         (long long)vdec_msg->msgdata.output_frame.time_stamp);
8858             }
8859             break;
8860         case VDEC_MSG_RESP_OUTPUT_FLUSHED:
8861         case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: {
8862            v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
8863 
8864            OMX_BUFFERHEADERTYPE  *omx_base_address = omx->m_out_mem_ptr;
8865            vdec_bufferpayload *omx_ptr_outputbuffer = omx->drv_ctx.ptr_outputbuffer;
8866            vdec_output_frameinfo *omx_ptr_respbuffer = omx->drv_ctx.ptr_respbuffer;
8867 
8868            if (omx->client_buffers.is_color_conversion_enabled()) {
8869                omx_base_address = omx->m_intermediate_out_mem_ptr;
8870                omx_ptr_outputbuffer = omx->drv_ctx.ptr_intermediate_outputbuffer;
8871                omx_ptr_respbuffer = omx->drv_ctx.ptr_intermediate_respbuffer;
8872            }
8873 
8874            if (v4l2_buf_ptr == NULL || omx_base_address == NULL ||
8875                v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
8876                omxhdr = NULL;
8877                vdec_msg->status_code = VDEC_S_EFATAL;
8878                break;
8879            }
8880            plane = v4l2_buf_ptr->m.planes;
8881            omxhdr = omx_base_address + v4l2_buf_ptr->index;
8882 
8883            if (omxhdr && omxhdr->pOutputPortPrivate &&
8884                ((omxhdr - omx_base_address) < (int)omx->drv_ctx.op_buf.actualcount) &&
8885                    (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
8886                      - omx_ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
8887 
8888                omxhdr->pMarkData = (OMX_PTR)(unsigned long)plane[0].reserved[3];
8889                omxhdr->hMarkTargetComponent = (OMX_HANDLETYPE)(unsigned long)plane[0].reserved[4];
8890 
8891                if (vdec_msg->msgdata.output_frame.len <=  omxhdr->nAllocLen) {
8892                    omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
8893                    omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
8894                    omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
8895                    omxhdr->nFlags = 0;
8896 
8897                    if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
8898                         omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
8899                         //rc = -1;
8900                    }
8901                    if (omxhdr->nFilledLen) {
8902                        omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
8903                    }
8904                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
8905                        omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
8906                    } else {
8907                        omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
8908                    }
8909 #if NEED_TO_REVISIT
8910                    if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
8911                        omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
8912                    }
8913 #endif
8914                    if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
8915                         omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
8916                         DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
8917                                         omx_ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
8918                    }
8919 
8920                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_DATA_CORRUPT) {
8921                        omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
8922                    }
8923 
8924                    output_respbuf = (struct vdec_output_frameinfo *)\
8925                             omxhdr->pOutputPortPrivate;
8926                    if (!output_respbuf) {
8927                      DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
8928                      return -1;
8929                    }
8930                    output_respbuf->len = vdec_msg->msgdata.output_frame.len;
8931                    output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
8932 
8933                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
8934                        output_respbuf->pic_type = PICTURE_TYPE_I;
8935                    }
8936                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
8937                        output_respbuf->pic_type = PICTURE_TYPE_P;
8938                    }
8939                    if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
8940                        output_respbuf->pic_type = PICTURE_TYPE_B;
8941                    }
8942 
8943                    if (vdec_msg->msgdata.output_frame.len) {
8944                        DEBUG_PRINT_LOW("Processing extradata");
8945                        reconfig_event_sent = omx->handle_extradata(omxhdr);
8946 
8947                        if (omx->m_extradata_info.output_crop_updated) {
8948                            DEBUG_PRINT_LOW("Read FBD crop from output extra data");
8949                            vdec_msg->msgdata.output_frame.framesize.left = omx->m_extradata_info.output_crop_rect.nLeft;
8950                            vdec_msg->msgdata.output_frame.framesize.top = omx->m_extradata_info.output_crop_rect.nTop;
8951                            vdec_msg->msgdata.output_frame.framesize.right = omx->m_extradata_info.output_crop_rect.nWidth;
8952                            vdec_msg->msgdata.output_frame.framesize.bottom = omx->m_extradata_info.output_crop_rect.nHeight;
8953                            vdec_msg->msgdata.output_frame.picsize.frame_width = omx->m_extradata_info.output_width;
8954                            vdec_msg->msgdata.output_frame.picsize.frame_height = omx->m_extradata_info.output_height;
8955                            memcpy(vdec_msg->msgdata.output_frame.misrinfo,
8956                                 omx->m_extradata_info.misr_info, sizeof(vdec_misrinfo));
8957                        } else {
8958                            DEBUG_PRINT_LOW("Read FBD crop from v4l2 reserved fields");
8959                            vdec_msg->msgdata.output_frame.framesize.left = plane[0].reserved[2];
8960                            vdec_msg->msgdata.output_frame.framesize.top = plane[0].reserved[3];
8961                            vdec_msg->msgdata.output_frame.framesize.right = plane[0].reserved[2] + plane[0].reserved[4];
8962                            vdec_msg->msgdata.output_frame.framesize.bottom = plane[0].reserved[3] + plane[0].reserved[5];
8963                            vdec_msg->msgdata.output_frame.picsize.frame_width = plane[0].reserved[6];
8964                            vdec_msg->msgdata.output_frame.picsize.frame_height = plane[0].reserved[7];
8965 
8966                            /* Copy these values back to OMX internal variables to make both handlign same*/
8967 
8968                            omx->m_extradata_info.output_crop_rect.nLeft = vdec_msg->msgdata.output_frame.framesize.left;
8969                            omx->m_extradata_info.output_crop_rect.nTop = vdec_msg->msgdata.output_frame.framesize.top;
8970                            omx->m_extradata_info.output_crop_rect.nWidth = vdec_msg->msgdata.output_frame.framesize.right;
8971                            omx->m_extradata_info.output_crop_rect.nHeight = vdec_msg->msgdata.output_frame.framesize.bottom;
8972                            omx->m_extradata_info.output_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
8973                            omx->m_extradata_info.output_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
8974                        }
8975                    }
8976 
8977                    vdec_msg->msgdata.output_frame.bufferaddr =
8978                        omx_ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
8979 
8980                    DEBUG_PRINT_LOW("[RespBufDone] Fd(%d) Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x)"
8981                            " FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
8982                            omx_ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd,
8983                            omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
8984                            vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
8985                            (unsigned int)vdec_msg->msgdata.output_frame.len,
8986                            vdec_msg->msgdata.output_frame.framesize.left,
8987                            vdec_msg->msgdata.output_frame.framesize.top,
8988                            vdec_msg->msgdata.output_frame.framesize.right,
8989                            vdec_msg->msgdata.output_frame.framesize.bottom);
8990 
8991                    /* Post event if resolution OR crop changed */
8992                    /* filled length will be changed if resolution changed */
8993                    /* Crop parameters can be changed even without resolution change */
8994                    if (omxhdr->nFilledLen
8995                        && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
8996                        || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
8997                        || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
8998                        || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
8999                        || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
9000                        || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
9001                        || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
9002 
9003                        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",
9004                                omx->prev_n_filled_len,
9005                                omx->drv_ctx.video_resolution.frame_width,
9006                                omx->drv_ctx.video_resolution.frame_height,
9007                                omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
9008                                omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
9009                                omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
9010                                vdec_msg->msgdata.output_frame.picsize.frame_height,
9011                                vdec_msg->msgdata.output_frame.framesize.left,
9012                                vdec_msg->msgdata.output_frame.framesize.top,
9013                                vdec_msg->msgdata.output_frame.framesize.right,
9014                                vdec_msg->msgdata.output_frame.framesize.bottom);
9015 
9016                        memcpy(&omx->drv_ctx.frame_size,
9017                                &vdec_msg->msgdata.output_frame.framesize,
9018                                sizeof(struct vdec_framesize));
9019 
9020                        omx->drv_ctx.video_resolution.frame_width =
9021                                vdec_msg->msgdata.output_frame.picsize.frame_width;
9022                        omx->drv_ctx.video_resolution.frame_height =
9023                                vdec_msg->msgdata.output_frame.picsize.frame_height;
9024                        if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
9025                            omx->drv_ctx.video_resolution.stride =
9026                                VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
9027                            omx->drv_ctx.video_resolution.scan_lines =
9028                                VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
9029                        } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
9030                            omx->drv_ctx.video_resolution.stride =
9031                                VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width);
9032                            omx->drv_ctx.video_resolution.scan_lines =
9033                                VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height);
9034                        } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_TP10_UBWC) {
9035                            omx->drv_ctx.video_resolution.stride =
9036                                VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_width);
9037                            omx->drv_ctx.video_resolution.scan_lines =
9038                                VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, omx->drv_ctx.video_resolution.frame_height);
9039                         }
9040                         else if(omx->drv_ctx.output_format == VDEC_YUV_FORMAT_P010_VENUS) {
9041                            omx->drv_ctx.video_resolution.stride =
9042                                VENUS_Y_STRIDE(COLOR_FMT_P010, omx->drv_ctx.video_resolution.frame_width);
9043                            omx->drv_ctx.video_resolution.scan_lines =
9044                                VENUS_Y_SCANLINES(COLOR_FMT_P010, omx->drv_ctx.video_resolution.frame_height);
9045                         }
9046 
9047                        if(!reconfig_event_sent) {
9048                            omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
9049                                            OMX_IndexConfigCommonOutputCrop,
9050                                            OMX_COMPONENT_GENERATE_PORT_RECONFIG);
9051                            reconfig_event_sent = true;
9052                        } else {
9053                            /* Update C2D with new resolution */
9054                            if (!omx->client_buffers.update_buffer_req()) {
9055                                DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
9056                            }
9057                        }
9058                    }
9059 
9060                    if (omxhdr->nFilledLen)
9061                        omx->prev_n_filled_len = omxhdr->nFilledLen;
9062 
9063                    if (!omx->m_enable_android_native_buffers && omx->output_use_buffer && omxhdr->pBuffer &&
9064                        vdec_msg->msgdata.output_frame.bufferaddr)
9065                        memcpy ( omxhdr->pBuffer, (void *)
9066                                ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
9067                                 (unsigned long)vdec_msg->msgdata.output_frame.offset),
9068                                vdec_msg->msgdata.output_frame.len);
9069                } else {
9070                    DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
9071                            (unsigned int)vdec_msg->msgdata.output_frame.len,
9072                            omxhdr->nAllocLen, omx->prev_n_filled_len);
9073                    omxhdr->nFilledLen = 0;
9074                }
9075 
9076                omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
9077                         OMX_COMPONENT_GENERATE_FBD);
9078 
9079             } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
9080                 omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
9081                         OMX_COMPONENT_GENERATE_EOS_DONE);
9082             } else {
9083                 omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
9084                         OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
9085             }
9086             break;
9087         }
9088         case VDEC_MSG_EVT_CONFIG_CHANGED:
9089             DEBUG_PRINT_HIGH("Port settings changed");
9090             omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
9091             omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
9092             omx->isPortReconfigInsufficient = vdec_msg->msgdata.output_frame.flags;
9093             omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
9094                     OMX_COMPONENT_GENERATE_PORT_RECONFIG);
9095             break;
9096         default:
9097             break;
9098     }
9099     return rc;
9100 }
9101 
empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp,OMX_BUFFERHEADERTYPE * buffer)9102 OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
9103         OMX_HANDLETYPE hComp,
9104         OMX_BUFFERHEADERTYPE *buffer
9105         )
9106 {
9107     unsigned address,p2,id;
9108     DEBUG_PRINT_LOW("Empty this arbitrary");
9109 
9110     if (buffer == NULL) {
9111         return OMX_ErrorBadParameter;
9112     }
9113     DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
9114     DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld",
9115             (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp);
9116 
9117     /* return zero length and not an EOS buffer */
9118     /* return buffer if input flush in progress */
9119     if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
9120                 ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
9121         DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
9122         m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
9123         return OMX_ErrorNone;
9124     }
9125 
9126     if (psource_frame == NULL) {
9127         DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp);
9128         psource_frame = buffer;
9129         DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
9130         push_input_buffer (hComp);
9131     } else {
9132         DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
9133         if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL,
9134                     (unsigned)NULL)) {
9135             return OMX_ErrorBadParameter;
9136         }
9137     }
9138 
9139     if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
9140         codec_config_flag = false;
9141     }
9142     return OMX_ErrorNone;
9143 }
9144 
push_input_buffer(OMX_HANDLETYPE hComp)9145 OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
9146 {
9147     unsigned long address,p2,id;
9148     OMX_ERRORTYPE ret = OMX_ErrorNone;
9149 
9150     if (pdest_frame == NULL || psource_frame == NULL) {
9151         /*Check if we have a destination buffer*/
9152         if (pdest_frame == NULL) {
9153             DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
9154             if (m_input_free_q.m_size) {
9155                 m_input_free_q.pop_entry(&address,&p2,&id);
9156                 pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
9157                 pdest_frame->nFilledLen = 0;
9158                 pdest_frame->nTimeStamp = LLONG_MAX;
9159                 DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
9160             }
9161         }
9162 
9163         /*Check if we have a destination buffer*/
9164         if (psource_frame == NULL) {
9165             DEBUG_PRINT_LOW("Get a source buffer from the queue");
9166             if (m_input_pending_q.m_size) {
9167                 m_input_pending_q.pop_entry(&address,&p2,&id);
9168                 psource_frame = (OMX_BUFFERHEADERTYPE *)address;
9169                 DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
9170                         psource_frame->nTimeStamp);
9171                 DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
9172                         (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9173 
9174             }
9175         }
9176 
9177     }
9178 
9179     while ((pdest_frame != NULL) && (psource_frame != NULL)) {
9180         switch (codec_type_parse) {
9181             case CODEC_TYPE_MPEG2:
9182                 ret =  push_input_sc_codec(hComp);
9183                 break;
9184             case CODEC_TYPE_H264:
9185                 ret = push_input_h264(hComp);
9186                 break;
9187             case CODEC_TYPE_HEVC:
9188                 ret = push_input_hevc(hComp);
9189                 break;
9190             default:
9191                 break;
9192         }
9193         if (ret != OMX_ErrorNone) {
9194             DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
9195             omx_report_error ();
9196             break;
9197         }
9198     }
9199 
9200     return ret;
9201 }
9202 
push_input_sc_codec(OMX_HANDLETYPE hComp)9203 OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
9204 {
9205     OMX_U32 partial_frame = 1;
9206     OMX_BOOL generate_ebd = OMX_TRUE;
9207     unsigned long address = 0, p2 = 0, id = 0;
9208 
9209     DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld",
9210             psource_frame,psource_frame->nTimeStamp);
9211     if (m_frame_parser.parse_sc_frame(psource_frame,
9212                 pdest_frame,&partial_frame) == -1) {
9213         DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9214         return OMX_ErrorBadParameter;
9215     }
9216 
9217     if (partial_frame == 0) {
9218         DEBUG_PRINT_LOW("Frame size %u source %p frame count %d",
9219                 (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count);
9220 
9221 
9222         DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp);
9223         /*First Parsed buffer will have only header Hence skip*/
9224         if (frame_count == 0) {
9225             frame_count++;
9226         } else {
9227             pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9228             if (pdest_frame->nFilledLen) {
9229                 /*Push the frame to the Decoder*/
9230                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9231                     return OMX_ErrorBadParameter;
9232                 }
9233                 frame_count++;
9234                 pdest_frame = NULL;
9235 
9236                 if (m_input_free_q.m_size) {
9237                     m_input_free_q.pop_entry(&address,&p2,&id);
9238                     pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9239                     pdest_frame->nFilledLen = 0;
9240                 }
9241             } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
9242                 DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
9243                 m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL,
9244                         (unsigned)NULL);
9245                 pdest_frame = NULL;
9246             }
9247         }
9248     } else {
9249         DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen);
9250         /*Check if Destination Buffer is full*/
9251         if (pdest_frame->nAllocLen ==
9252                 pdest_frame->nFilledLen + pdest_frame->nOffset) {
9253             DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
9254             return OMX_ErrorStreamCorrupt;
9255         }
9256     }
9257 
9258     if (psource_frame->nFilledLen == 0) {
9259         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9260             if (pdest_frame) {
9261                 pdest_frame->nFlags |= psource_frame->nFlags;
9262                 pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
9263                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld",
9264                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9265                 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9266                         (unsigned int)pdest_frame->nFilledLen,frame_count++);
9267                 /*Push the frame to the Decoder*/
9268                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9269                     return OMX_ErrorBadParameter;
9270                 }
9271                 frame_count++;
9272                 pdest_frame = NULL;
9273             } else {
9274                 DEBUG_PRINT_LOW("Last frame in else dest addr") ;
9275                 generate_ebd = OMX_FALSE;
9276             }
9277         }
9278         if (generate_ebd) {
9279             DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
9280             m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9281             psource_frame = NULL;
9282 
9283             if (m_input_pending_q.m_size) {
9284                 DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
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     return OMX_ErrorNone;
9295 }
9296 
push_input_h264(OMX_HANDLETYPE hComp)9297 OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
9298 {
9299     OMX_U32 partial_frame = 1;
9300     unsigned long address = 0, p2 = 0, id = 0;
9301     OMX_BOOL isNewFrame = OMX_FALSE;
9302     OMX_BOOL generate_ebd = OMX_TRUE;
9303 
9304     if (h264_scratch.pBuffer == NULL) {
9305         DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
9306         return OMX_ErrorBadParameter;
9307     }
9308     DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u "
9309             "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal);
9310     DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen);
9311     if (h264_scratch.nFilledLen && look_ahead_nal) {
9312         look_ahead_nal = false;
9313         if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9314                 h264_scratch.nFilledLen) {
9315             memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9316                     h264_scratch.pBuffer,h264_scratch.nFilledLen);
9317             pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9318             DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
9319             h264_scratch.nFilledLen = 0;
9320         } else {
9321             DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
9322             return OMX_ErrorBadParameter;
9323         }
9324     }
9325 
9326     /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result
9327        in EOS flag getting associated with the destination
9328     */
9329     if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) &&
9330             pdest_frame->nFilledLen) {
9331         DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'");
9332         generate_ebd = OMX_FALSE;
9333     }
9334 
9335     if (nal_length == 0) {
9336         DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
9337         if (m_frame_parser.parse_sc_frame(psource_frame,
9338                     &h264_scratch,&partial_frame) == -1) {
9339             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9340             return OMX_ErrorBadParameter;
9341         }
9342     } else {
9343         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
9344         if (m_frame_parser.parse_h264_nallength(psource_frame,
9345                     &h264_scratch,&partial_frame) == -1) {
9346             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9347             return OMX_ErrorBadParameter;
9348         }
9349     }
9350 
9351     if (partial_frame == 0) {
9352         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9353             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9354             nal_count++;
9355             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9356             h264_scratch.nFlags = psource_frame->nFlags;
9357         } else {
9358             DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen);
9359             if (h264_scratch.nFilledLen) {
9360                 h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
9361                         NALU_TYPE_SPS);
9362 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9363                 if (client_extradata & OMX_TIMEINFO_EXTRADATA)
9364                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9365                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
9366                 else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9367                     // If timeinfo is present frame info from SEI is already processed
9368                     h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
9369                             h264_scratch.nFilledLen, NALU_TYPE_SEI);
9370 #endif
9371                 m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9372                 nal_count++;
9373                 if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
9374                     pdest_frame->nTimeStamp = h264_last_au_ts;
9375                     pdest_frame->nFlags = h264_last_au_flags;
9376 #ifdef PANSCAN_HDLR
9377                     if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
9378                         h264_parser->update_panscan_data(h264_last_au_ts);
9379 #endif
9380                 }
9381                 if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
9382                         m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
9383                     h264_last_au_ts = h264_scratch.nTimeStamp;
9384                     h264_last_au_flags = h264_scratch.nFlags;
9385 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9386                     if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9387                         OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
9388                         if (!VALID_TS(h264_last_au_ts))
9389                             h264_last_au_ts = ts_in_sei;
9390                     }
9391 #endif
9392                 } else
9393                     h264_last_au_ts = LLONG_MAX;
9394             }
9395 
9396             if (!isNewFrame) {
9397                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9398                         h264_scratch.nFilledLen) {
9399                     DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u",
9400                             (unsigned int)h264_scratch.nFilledLen);
9401                     memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9402                             h264_scratch.pBuffer,h264_scratch.nFilledLen);
9403                     pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9404                     if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
9405                         pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
9406                     h264_scratch.nFilledLen = 0;
9407                 } else {
9408                     DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
9409                     return OMX_ErrorBadParameter;
9410                 }
9411             } else if(h264_scratch.nFilledLen) {
9412                 look_ahead_nal = true;
9413                 DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu",
9414                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9415                 DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
9416                         (unsigned int)pdest_frame->nFilledLen,frame_count++);
9417 
9418                 if (pdest_frame->nFilledLen == 0) {
9419                     DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
9420                     look_ahead_nal = false;
9421                     if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9422                             h264_scratch.nFilledLen) {
9423                         memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9424                                 h264_scratch.pBuffer,h264_scratch.nFilledLen);
9425                         pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9426                         h264_scratch.nFilledLen = 0;
9427                     } else {
9428                         DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
9429                         return OMX_ErrorBadParameter;
9430                     }
9431                 } else {
9432                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9433                         DEBUG_PRINT_LOW("Reset the EOS Flag");
9434                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9435                     }
9436                     /*Push the frame to the Decoder*/
9437                     if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9438                         return OMX_ErrorBadParameter;
9439                     }
9440                     //frame_count++;
9441                     pdest_frame = NULL;
9442                     if (m_input_free_q.m_size) {
9443                         m_input_free_q.pop_entry(&address,&p2,&id);
9444                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9445                         DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
9446                         pdest_frame->nFilledLen = 0;
9447                         pdest_frame->nFlags = 0;
9448                         pdest_frame->nTimeStamp = LLONG_MAX;
9449                     }
9450                 }
9451             }
9452         }
9453     } else {
9454         DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen);
9455         /*Check if Destination Buffer is full*/
9456         if (h264_scratch.nAllocLen ==
9457                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9458             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9459             return OMX_ErrorStreamCorrupt;
9460         }
9461     }
9462 
9463     if (!psource_frame->nFilledLen) {
9464         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
9465 
9466         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9467             if (pdest_frame) {
9468                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9469                 if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
9470                         h264_scratch.nFilledLen) {
9471                     if(pdest_frame->nFilledLen == 0) {
9472                         /* No residual frame from before, send whatever
9473                          * we have left */
9474                         memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9475                                 h264_scratch.pBuffer, h264_scratch.nFilledLen);
9476                         pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9477                         h264_scratch.nFilledLen = 0;
9478                         pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9479                     } else {
9480                         m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
9481                         if(!isNewFrame) {
9482                             /* Have a residual frame, but we know that the
9483                              * AU in this frame is belonging to whatever
9484                              * frame we had left over.  So append it */
9485                              memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
9486                                      h264_scratch.pBuffer,h264_scratch.nFilledLen);
9487                              pdest_frame->nFilledLen += h264_scratch.nFilledLen;
9488                              h264_scratch.nFilledLen = 0;
9489                              if (h264_last_au_ts != LLONG_MAX)
9490                                  pdest_frame->nTimeStamp = h264_last_au_ts;
9491                         } else {
9492                             /* Completely new frame, let's just push what
9493                              * we have now.  The resulting EBD would trigger
9494                              * another push */
9495                             generate_ebd = OMX_FALSE;
9496                             pdest_frame->nTimeStamp = h264_last_au_ts;
9497                             h264_last_au_ts = h264_scratch.nTimeStamp;
9498                         }
9499                     }
9500                 } else {
9501                     DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
9502                     return OMX_ErrorBadParameter;
9503                 }
9504 
9505                 /* Iff we coalesced two buffers, inherit the flags of both bufs */
9506                 if(generate_ebd == OMX_TRUE) {
9507                      pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9508                 }
9509 
9510                 DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu",
9511                         (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
9512                 DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
9513 #ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
9514                 if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
9515                     OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
9516                     if (!VALID_TS(pdest_frame->nTimeStamp))
9517                         pdest_frame->nTimeStamp = ts_in_sei;
9518                 }
9519 #endif
9520                 /*Push the frame to the Decoder*/
9521                 if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
9522                     return OMX_ErrorBadParameter;
9523                 }
9524                 frame_count++;
9525                 pdest_frame = NULL;
9526             } else {
9527                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9528                         pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9529                 generate_ebd = OMX_FALSE;
9530             }
9531         }
9532     }
9533     if (generate_ebd && !psource_frame->nFilledLen) {
9534         m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
9535         psource_frame = NULL;
9536         if (m_input_pending_q.m_size) {
9537             DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
9538             m_input_pending_q.pop_entry(&address,&p2,&id);
9539             psource_frame = (OMX_BUFFERHEADERTYPE *) address;
9540             DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u",
9541                     (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
9542         }
9543     }
9544     return OMX_ErrorNone;
9545 }
9546 
copy_buffer(OMX_BUFFERHEADERTYPE * pDst,OMX_BUFFERHEADERTYPE * pSrc)9547 OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
9548 {
9549     OMX_ERRORTYPE rc = OMX_ErrorNone;
9550     if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
9551         memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
9552         if (pDst->nTimeStamp == LLONG_MAX) {
9553             pDst->nTimeStamp = pSrc->nTimeStamp;
9554             DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp);
9555         }
9556         pDst->nFilledLen += pSrc->nFilledLen;
9557         pSrc->nFilledLen = 0;
9558     } else {
9559         DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
9560         rc = OMX_ErrorBadParameter;
9561     }
9562     return rc;
9563 }
9564 
push_input_hevc(OMX_HANDLETYPE hComp)9565 OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp)
9566 {
9567     OMX_U32 partial_frame = 1;
9568     unsigned long address,p2,id;
9569     OMX_BOOL isNewFrame = OMX_FALSE;
9570     OMX_BOOL generate_ebd = OMX_TRUE;
9571     OMX_ERRORTYPE rc = OMX_ErrorNone;
9572     if (h264_scratch.pBuffer == NULL) {
9573         DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
9574         return OMX_ErrorBadParameter;
9575     }
9576 
9577     DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \
9578             pdest_frame nFilledLen %u nTimeStamp %lld",
9579             (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9580 
9581     if (h264_scratch.nFilledLen && look_ahead_nal) {
9582         look_ahead_nal = false;
9583         rc = copy_buffer(pdest_frame, &h264_scratch);
9584         if (rc != OMX_ErrorNone) {
9585             return rc;
9586         }
9587     }
9588 
9589     if (nal_length == 0) {
9590         if (m_frame_parser.parse_sc_frame(psource_frame,
9591                     &h264_scratch,&partial_frame) == -1) {
9592             DEBUG_PRINT_ERROR("Error In Parsing Return Error");
9593             return OMX_ErrorBadParameter;
9594         }
9595     } else {
9596         DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
9597         if (m_frame_parser.parse_h264_nallength(psource_frame,
9598                     &h264_scratch,&partial_frame) == -1) {
9599             DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
9600             return OMX_ErrorBadParameter;
9601         }
9602     }
9603 
9604     if (partial_frame == 0) {
9605         if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
9606             DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
9607             nal_count++;
9608             h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
9609             h264_scratch.nFlags = psource_frame->nFlags;
9610         } else {
9611             DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen);
9612             if (h264_scratch.nFilledLen) {
9613                 m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame);
9614                 nal_count++;
9615             }
9616 
9617             if (!isNewFrame) {
9618                 DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \
9619                         nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld",
9620                         (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp,
9621                         (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9622                 rc = copy_buffer(pdest_frame, &h264_scratch);
9623                 if (rc != OMX_ErrorNone) {
9624                     return rc;
9625                 }
9626             } else {
9627                 look_ahead_nal = true;
9628                 if (pdest_frame->nFilledLen == 0) {
9629                     look_ahead_nal = false;
9630                     DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
9631                     rc = copy_buffer(pdest_frame, &h264_scratch);
9632                     if (rc != OMX_ErrorNone) {
9633                         return OMX_ErrorBadParameter;
9634                     }
9635                 } else {
9636                     if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
9637                         pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
9638                     }
9639                     DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \
9640                             nTimeStamp %lld, look_ahead_nal in h264_scratch \
9641                             nFilledLen %u nTimeStamp %lld",
9642                             frame_count++, (unsigned int)pdest_frame->nFilledLen,
9643                             pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen,
9644                             h264_scratch.nTimeStamp);
9645                     if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9646                         return OMX_ErrorBadParameter;
9647                     }
9648                     pdest_frame = NULL;
9649                     if (m_input_free_q.m_size) {
9650                         m_input_free_q.pop_entry(&address, &p2, &id);
9651                         pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
9652                         DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame);
9653                         pdest_frame->nFilledLen = 0;
9654                         pdest_frame->nFlags = 0;
9655                         pdest_frame->nTimeStamp = LLONG_MAX;
9656                     }
9657                 }
9658             }
9659         }
9660     } else {
9661         DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \
9662                 pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \
9663                 nFilledLen %u nTimeStamp %lld",
9664                 (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp,
9665                 (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp,
9666                 (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
9667 
9668         if (h264_scratch.nAllocLen ==
9669                 h264_scratch.nFilledLen + h264_scratch.nOffset) {
9670             DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
9671             return OMX_ErrorStreamCorrupt;
9672         }
9673     }
9674 
9675     if (!psource_frame->nFilledLen) {
9676         DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame);
9677         if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
9678             if (pdest_frame) {
9679                 DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
9680                 rc = copy_buffer(pdest_frame, &h264_scratch);
9681                 if ( rc != OMX_ErrorNone ) {
9682                     return rc;
9683                 }
9684                 pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
9685                 pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
9686                 DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld",
9687                         frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
9688                 if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
9689                     return OMX_ErrorBadParameter;
9690                 }
9691                 frame_count++;
9692                 pdest_frame = NULL;
9693             } else {
9694                 DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
9695                         pdest_frame, (unsigned int)h264_scratch.nFilledLen);
9696                 generate_ebd = OMX_FALSE;
9697             }
9698         }
9699     }
9700 
9701     if (generate_ebd && !psource_frame->nFilledLen) {
9702         m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame);
9703         psource_frame = NULL;
9704         if (m_input_pending_q.m_size) {
9705             m_input_pending_q.pop_entry(&address, &p2, &id);
9706             psource_frame = (OMX_BUFFERHEADERTYPE *)address;
9707             DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld",
9708                     (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp);
9709         }
9710     }
9711     return OMX_ErrorNone;
9712 }
9713 
9714 #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)9715 bool omx_vdec::alloc_map_gbm_memory(OMX_U32 w,OMX_U32 h,int dev_fd,
9716                  struct vdec_gbm *op_buf_gbm_info, int flag)
9717 {
9718 
9719     uint32 flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
9720     struct gbm_device *gbm = NULL;
9721     struct gbm_bo *bo = NULL;
9722     int bo_fd = -1, meta_fd = -1;
9723     if (!op_buf_gbm_info || dev_fd < 0 ) {
9724         DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
9725         return FALSE;
9726     }
9727 
9728     gbm = gbm_create_device(dev_fd);
9729     if (gbm == NULL) {
9730        DEBUG_PRINT_ERROR("create gbm device failed");
9731        return FALSE;
9732     } else {
9733        DEBUG_PRINT_LOW( "Successfully created gbm device");
9734     }
9735     if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC)
9736        flags |= GBM_BO_USAGE_UBWC_ALIGNED_QTI;
9737 
9738     DEBUG_PRINT_LOW("create NV12 gbm_bo with width=%d, height=%d", w, h);
9739     bo = gbm_bo_create(gbm, w, h,GBM_FORMAT_NV12,
9740               flags);
9741 
9742     if (bo == NULL) {
9743       DEBUG_PRINT_ERROR("Create bo failed");
9744       gbm_device_destroy(gbm);
9745       return FALSE;
9746     }
9747 
9748     bo_fd = gbm_bo_get_fd(bo);
9749     if (bo_fd < 0) {
9750       DEBUG_PRINT_ERROR("Get bo fd failed");
9751       gbm_bo_destroy(bo);
9752       gbm_device_destroy(gbm);
9753       return FALSE;
9754     }
9755 
9756     gbm_perform(GBM_PERFORM_GET_METADATA_ION_FD, bo, &meta_fd);
9757     if (meta_fd < 0) {
9758       DEBUG_PRINT_ERROR("Get bo meta fd failed");
9759       gbm_bo_destroy(bo);
9760       gbm_device_destroy(gbm);
9761       return FALSE;
9762     }
9763     op_buf_gbm_info->gbm = gbm;
9764     op_buf_gbm_info->bo = bo;
9765     op_buf_gbm_info->bo_fd = bo_fd;
9766     op_buf_gbm_info->meta_fd = meta_fd;
9767 
9768     DEBUG_PRINT_LOW("allocate gbm bo fd meta fd  %p %d %d",bo,bo_fd,meta_fd);
9769     return TRUE;
9770 }
9771 
free_gbm_memory(struct vdec_gbm * buf_gbm_info)9772 void omx_vdec::free_gbm_memory(struct vdec_gbm *buf_gbm_info)
9773 {
9774     if(!buf_gbm_info) {
9775       DEBUG_PRINT_ERROR(" GBM: free called with invalid fd/allocdata");
9776       return;
9777     }
9778     DEBUG_PRINT_LOW("free gbm bo fd meta fd  %p %d %d",
9779            buf_gbm_info->bo,buf_gbm_info->bo_fd,buf_gbm_info->meta_fd);
9780 
9781     if (buf_gbm_info->bo)
9782        gbm_bo_destroy(buf_gbm_info->bo);
9783     buf_gbm_info->bo = NULL;
9784 
9785     if (buf_gbm_info->gbm)
9786        gbm_device_destroy(buf_gbm_info->gbm);
9787     buf_gbm_info->gbm = NULL;
9788 
9789     buf_gbm_info->bo_fd = -1;
9790     buf_gbm_info->meta_fd = -1;
9791 }
9792 #endif
9793 #ifndef USE_ION
align_pmem_buffers(int pmem_fd,OMX_U32 buffer_size,OMX_U32 alignment)9794 bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
9795         OMX_U32 alignment)
9796 {
9797     struct pmem_allocation allocation;
9798     allocation.size = buffer_size;
9799     allocation.align = clip2(alignment);
9800     if (allocation.align < 4096) {
9801         allocation.align = 4096;
9802     }
9803     if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
9804         DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
9805                 allocation.align, allocation.size);
9806         return false;
9807     }
9808     return true;
9809 }
9810 #endif
9811 #ifdef USE_ION
alloc_map_ion_memory(OMX_U32 buffer_size,vdec_ion * ion_info,int flag)9812 bool omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size, vdec_ion *ion_info, int flag)
9813 
9814 {
9815     int rc = -EINVAL;
9816     int ion_dev_flag;
9817     struct vdec_ion ion_buf_info;
9818 
9819     if (!ion_info || buffer_size <= 0) {
9820         DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
9821         return false;
9822     }
9823 
9824     ion_info->dev_fd = ion_open();
9825     if (ion_info->dev_fd < 0) {
9826         DEBUG_PRINT_ERROR("opening ion device failed with ion_fd = %d", ion_info->dev_fd);
9827         return false;
9828     }
9829 
9830     ion_info->alloc_data.flags = flag;
9831     ion_info->alloc_data.len = buffer_size;
9832 
9833     ion_info->alloc_data.heap_id_mask = ION_HEAP(ION_SYSTEM_HEAP_ID);
9834     if (secure_mode && (ion_info->alloc_data.flags & ION_FLAG_SECURE)) {
9835         ion_info->alloc_data.heap_id_mask = ION_HEAP(MEM_HEAP_ID);
9836     }
9837 
9838     /* Use secure display cma heap for obvious reasons. */
9839     if (ion_info->alloc_data.flags & ION_FLAG_CP_BITSTREAM) {
9840         ion_info->alloc_data.heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
9841     }
9842 
9843     rc = ion_alloc_fd(ion_info->dev_fd, ion_info->alloc_data.len, 0,
9844                       ion_info->alloc_data.heap_id_mask, ion_info->alloc_data.flags,
9845                       &ion_info->data_fd);
9846 
9847     if (rc || ion_info->data_fd < 0) {
9848         DEBUG_PRINT_ERROR("ION ALLOC memory failed");
9849         ion_close(ion_info->dev_fd);
9850         ion_info->data_fd = -1;
9851         ion_info->dev_fd = -1;
9852         return false;
9853     }
9854 
9855     DEBUG_PRINT_HIGH("Alloc ion memory: fd (dev:%d data:%d) len %d flags %#x mask %#x",
9856                      ion_info->dev_fd, ion_info->data_fd, (unsigned int)ion_info->alloc_data.len,
9857                      (unsigned int)ion_info->alloc_data.flags,
9858                      (unsigned int)ion_info->alloc_data.heap_id_mask);
9859 
9860     return true;
9861 }
9862 
free_ion_memory(struct vdec_ion * buf_ion_info)9863 void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
9864 {
9865 
9866     if (!buf_ion_info) {
9867         DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
9868         return;
9869     }
9870     DEBUG_PRINT_HIGH("Free ion memory: mmap fd %d ion_dev fd %d len %d flags %#x mask %#x",
9871         buf_ion_info->data_fd, buf_ion_info->dev_fd,
9872         (unsigned int)buf_ion_info->alloc_data.len,
9873         (unsigned int)buf_ion_info->alloc_data.flags,
9874         (unsigned int)buf_ion_info->alloc_data.heap_id_mask);
9875 
9876     if (buf_ion_info->data_fd >= 0) {
9877         close(buf_ion_info->data_fd);
9878         buf_ion_info->data_fd = -1;
9879     }
9880     if (buf_ion_info->dev_fd >= 0) {
9881         ion_close(buf_ion_info->dev_fd);
9882         buf_ion_info->dev_fd = -1;
9883     }
9884 }
9885 
do_cache_operations(int fd)9886 void omx_vdec::do_cache_operations(int fd)
9887 {
9888     if (fd < 0)
9889         return;
9890 
9891     struct dma_buf_sync dma_buf_sync_data[2];
9892     dma_buf_sync_data[0].flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
9893     dma_buf_sync_data[1].flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
9894 
9895     for(unsigned int i=0; i<2; i++) {
9896         int rc = ioctl(fd, DMA_BUF_IOCTL_SYNC, &dma_buf_sync_data[i]);
9897         if (rc < 0) {
9898             DEBUG_PRINT_ERROR("Failed DMA_BUF_IOCTL_SYNC %s fd : %d", i==0?"start":"end", fd);
9899             return;
9900         }
9901     }
9902 }
9903 
9904 #endif
free_output_buffer_header(bool intermediate)9905 void omx_vdec::free_output_buffer_header(bool intermediate)
9906 {
9907     DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
9908     output_use_buffer = false;
9909     ouput_egl_buffers = false;
9910 
9911     OMX_BUFFERHEADERTYPE  **omx_base_address =
9912         intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
9913     vdec_bufferpayload **omx_ptr_outputbuffer =
9914         intermediate?&drv_ctx.ptr_intermediate_outputbuffer:&drv_ctx.ptr_outputbuffer;
9915     vdec_output_frameinfo **omx_ptr_respbuffer =
9916         intermediate?&drv_ctx.ptr_intermediate_respbuffer:&drv_ctx.ptr_respbuffer;
9917     vdec_ion **omx_op_buf_ion_info =
9918         intermediate?&drv_ctx.op_intermediate_buf_ion_info:&drv_ctx.op_buf_ion_info;
9919 #ifdef USE_GBM
9920     vdec_gbm **omx_op_buf_gbm_info =
9921         intermediate?&drv_ctx.op_intermediate_buf_gbm_info:&drv_ctx.op_buf_gbm_info;
9922 #endif
9923 
9924     if (*omx_base_address) {
9925         free (*omx_base_address);
9926         *omx_base_address = NULL;
9927     }
9928 
9929     if (m_platform_list) {
9930         free(m_platform_list);
9931         m_platform_list = NULL;
9932     }
9933 
9934     if (*omx_ptr_respbuffer) {
9935         free (*omx_ptr_respbuffer);
9936         *omx_ptr_respbuffer = NULL;
9937     }
9938     if (*omx_ptr_outputbuffer) {
9939         free (*omx_ptr_outputbuffer);
9940         *omx_ptr_outputbuffer = NULL;
9941     }
9942 #ifdef USE_GBM
9943     if (*omx_op_buf_gbm_info) {
9944         DEBUG_PRINT_LOW("Free o/p gbm context");
9945         free(*omx_op_buf_gbm_info);
9946         *omx_op_buf_gbm_info = NULL;
9947     }
9948     if (drv_ctx.gbm_device_fd >= 0) {
9949        DEBUG_PRINT_LOW("Close gbm device");
9950        close(drv_ctx.gbm_device_fd);
9951        drv_ctx.gbm_device_fd = -1;
9952     }
9953 
9954 #elif defined USE_ION
9955     if (*omx_op_buf_ion_info) {
9956         DEBUG_PRINT_LOW("Free o/p ion context");
9957         free(*omx_op_buf_ion_info);
9958         *omx_op_buf_ion_info = NULL;
9959     }
9960 #endif
9961     if (intermediate == false && client_buffers.is_color_conversion_enabled()) {
9962         free_output_buffer_header(true);
9963     }
9964 }
9965 
free_input_buffer_header()9966 void omx_vdec::free_input_buffer_header()
9967 {
9968     input_use_buffer = false;
9969     if (arbitrary_bytes) {
9970         if (m_inp_heap_ptr) {
9971             DEBUG_PRINT_LOW("Free input Heap Pointer");
9972             free (m_inp_heap_ptr);
9973             m_inp_heap_ptr = NULL;
9974         }
9975 
9976         if (m_phdr_pmem_ptr) {
9977             DEBUG_PRINT_LOW("Free input pmem header Pointer");
9978             free (m_phdr_pmem_ptr);
9979             m_phdr_pmem_ptr = NULL;
9980         }
9981     }
9982     if (m_inp_mem_ptr) {
9983         DEBUG_PRINT_LOW("Free input pmem Pointer area");
9984         free (m_inp_mem_ptr);
9985         m_inp_mem_ptr = NULL;
9986     }
9987     /* We just freed all the buffer headers, every thing in m_input_free_q,
9988      * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
9989     while (m_input_free_q.m_size) {
9990         unsigned long address, p2, id;
9991         m_input_free_q.pop_entry(&address, &p2, &id);
9992     }
9993     while (m_input_pending_q.m_size) {
9994         unsigned long address, p2, id;
9995         m_input_pending_q.pop_entry(&address, &p2, &id);
9996     }
9997     pdest_frame = NULL;
9998     psource_frame = NULL;
9999     if (drv_ctx.ptr_inputbuffer) {
10000         DEBUG_PRINT_LOW("Free Driver Context pointer");
10001         free (drv_ctx.ptr_inputbuffer);
10002         drv_ctx.ptr_inputbuffer = NULL;
10003     }
10004 #ifdef USE_ION
10005     if (drv_ctx.ip_buf_ion_info) {
10006         DEBUG_PRINT_LOW("Free ion context");
10007         free(drv_ctx.ip_buf_ion_info);
10008         drv_ctx.ip_buf_ion_info = NULL;
10009     }
10010 #endif
10011 }
10012 
free_output_extradata_buffer_header()10013 void omx_vdec::free_output_extradata_buffer_header() {
10014     client_extradata = false;
10015     if (m_client_output_extradata_mem_ptr) {
10016         DEBUG_PRINT_LOW("Free extradata pmem Pointer area");
10017         free(m_client_output_extradata_mem_ptr);
10018         m_client_output_extradata_mem_ptr = NULL;
10019     }
10020 }
10021 
stream_off(OMX_U32 port)10022 int omx_vdec::stream_off(OMX_U32 port)
10023 {
10024     enum v4l2_buf_type btype;
10025     int rc = 0;
10026     enum v4l2_ports v4l2_port = OUTPUT_PORT;
10027     struct v4l2_requestbuffers bufreq;
10028 
10029     if (port == OMX_CORE_INPUT_PORT_INDEX) {
10030         btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10031         v4l2_port = OUTPUT_PORT;
10032     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
10033         btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10034         v4l2_port = CAPTURE_PORT;
10035     } else if (port == OMX_ALL) {
10036         int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
10037         int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
10038 
10039         if (!rc_input)
10040             return rc_input;
10041         else
10042             return rc_output;
10043     }
10044 
10045     if (!streaming[v4l2_port]) {
10046         // already streamed off, warn and move on
10047         DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
10048                 " which is already streamed off", v4l2_port);
10049         return 0;
10050     }
10051 
10052     DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
10053 
10054     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
10055     if (rc) {
10056         /*TODO: How to handle this case */
10057         DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
10058     } else {
10059         streaming[v4l2_port] = false;
10060     }
10061 
10062     if (port == OMX_CORE_INPUT_PORT_INDEX) {
10063         bufreq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10064     } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
10065         bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10066     }
10067 
10068     bufreq.memory = V4L2_MEMORY_USERPTR;
10069     bufreq.count = 0;
10070     rc = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10071     if (rc) {
10072         DEBUG_PRINT_ERROR("Failed to release buffers on %d Port", v4l2_port);
10073     }
10074     return rc;
10075 }
10076 
get_buffer_req(vdec_allocatorproperty * buffer_prop)10077 OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
10078 {
10079     OMX_ERRORTYPE eRet = OMX_ErrorNone;
10080     struct v4l2_control control;
10081     unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
10082     unsigned int final_extra_data_size = 0;
10083     struct v4l2_format fmt;
10084     int ret = 0;
10085     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
10086             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10087 
10088     if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10089         fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10090         fmt.fmt.pix_mp.pixelformat = output_capability;
10091         control.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT;
10092     } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10093         fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10094         fmt.fmt.pix_mp.pixelformat = capture_capability;
10095         control.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
10096     } else {
10097         eRet = OMX_ErrorBadParameter;
10098     }
10099     if (eRet == OMX_ErrorNone) {
10100         ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control);
10101     }
10102     if (ret) {
10103         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
10104         /*TODO: How to handle this case */
10105         eRet = OMX_ErrorInsufficientResources;
10106         return eRet;
10107     }
10108     buffer_prop->actualcount = buffer_prop->mincount = control.value;
10109     DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
10110             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10111 
10112     ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10113 
10114     if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
10115         drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
10116     DEBUG_PRINT_HIGH("Buffer Size = %d, type = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage, fmt.type);
10117 
10118     if (ret) {
10119         /*TODO: How to handle this case */
10120         DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
10121         eRet = OMX_ErrorInsufficientResources;
10122     } else {
10123         int extra_idx = 0;
10124 
10125         buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
10126         buf_size = buffer_prop->buffer_size;
10127         extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
10128         if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
10129             extra_data_size =  fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
10130         } else if (extra_idx >= VIDEO_MAX_PLANES) {
10131             DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
10132             return OMX_ErrorBadParameter;
10133         }
10134 
10135         default_extra_data_size = VENUS_EXTRADATA_SIZE(
10136                 drv_ctx.video_resolution.frame_height,
10137                 drv_ctx.video_resolution.frame_width);
10138         final_extra_data_size = extra_data_size > default_extra_data_size ?
10139             extra_data_size : default_extra_data_size;
10140 
10141         final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
10142             (~(buffer_prop->alignment - 1));
10143 
10144         drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
10145         drv_ctx.extradata_info.count = buffer_prop->actualcount;
10146         drv_ctx.extradata_info.buffer_size = final_extra_data_size;
10147         buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
10148         DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
10149                 buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
10150         if (extra_data_size)
10151             DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
10152                 drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
10153 
10154         if (in_reconfig) // BufReq will be set to driver when port is disabled
10155             buffer_prop->buffer_size = buf_size;
10156         else if (buf_size != buffer_prop->buffer_size) {
10157             buffer_prop->buffer_size = buf_size;
10158             eRet = set_buffer_req(buffer_prop);
10159         }
10160     }
10161     DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
10162             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10163     return eRet;
10164 }
10165 
set_buffer_req(vdec_allocatorproperty * buffer_prop)10166 OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
10167 {
10168     OMX_ERRORTYPE eRet = OMX_ErrorNone;
10169     unsigned buf_size = 0;
10170     struct v4l2_format fmt, c_fmt;
10171     struct v4l2_requestbuffers bufreq;
10172     int ret = 0;
10173     DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
10174             buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
10175     buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
10176     if (buf_size != buffer_prop->buffer_size) {
10177         DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
10178                 (unsigned int)buffer_prop->buffer_size, buf_size);
10179         eRet = OMX_ErrorBadParameter;
10180     } else {
10181         memset(&fmt, 0x0, sizeof(struct v4l2_format));
10182         memset(&c_fmt, 0x0, sizeof(struct v4l2_format));
10183         fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
10184         fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
10185         fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
10186 
10187         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10188             fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10189             fmt.fmt.pix_mp.pixelformat = output_capability;
10190             DEBUG_PRINT_LOW("S_FMT: type %d wxh %dx%d size %d format %x",
10191                 fmt.type, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
10192                 fmt.fmt.pix_mp.plane_fmt[0].sizeimage, fmt.fmt.pix_mp.pixelformat);
10193             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10194         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10195             c_fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10196             c_fmt.fmt.pix_mp.pixelformat = capture_capability;
10197             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &c_fmt);
10198             c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
10199             DEBUG_PRINT_LOW("S_FMT: type %d wxh %dx%d size %d format %x",
10200                 c_fmt.type, c_fmt.fmt.pix_mp.width, c_fmt.fmt.pix_mp.height,
10201                 c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage, c_fmt.fmt.pix_mp.pixelformat);
10202             ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &c_fmt);
10203         } else {
10204             eRet = OMX_ErrorBadParameter;
10205         }
10206         if (ret) {
10207             DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
10208             eRet = OMX_ErrorInsufficientResources;
10209         }
10210 
10211         bufreq.memory = V4L2_MEMORY_USERPTR;
10212         bufreq.count = buffer_prop->actualcount;
10213         if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
10214             bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10215         } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
10216             bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10217         } else {
10218             eRet = OMX_ErrorBadParameter;
10219         }
10220 
10221         if (eRet == OMX_ErrorNone) {
10222             DEBUG_PRINT_LOW("REQBUFS: type %d count %d", bufreq.type, bufreq.count);
10223             ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
10224         }
10225 
10226         if (ret) {
10227             DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
10228             /*TODO: How to handle this case */
10229             eRet = OMX_ErrorInsufficientResources;
10230         } else if (bufreq.count < buffer_prop->actualcount) {
10231             DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
10232                     " on v4l2 port %d to %d (prefers %d)", bufreq.type,
10233                     buffer_prop->actualcount, bufreq.count);
10234             eRet = OMX_ErrorInsufficientResources;
10235         } else {
10236             if (!client_buffers.update_buffer_req()) {
10237                 DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
10238                 eRet = OMX_ErrorInsufficientResources;
10239             }
10240         }
10241     }
10242     return eRet;
10243 }
10244 
update_picture_resolution()10245 OMX_ERRORTYPE omx_vdec::update_picture_resolution()
10246 {
10247     OMX_ERRORTYPE eRet = OMX_ErrorNone;
10248     return eRet;
10249 }
10250 
update_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portDefn)10251 OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
10252 {
10253     OMX_ERRORTYPE eRet = OMX_ErrorNone;
10254     struct v4l2_format fmt;
10255     if (!portDefn) {
10256         DEBUG_PRINT_ERROR("update_portdef: invalid params");
10257         return OMX_ErrorBadParameter;
10258     }
10259     portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
10260     portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
10261     portDefn->eDomain    = OMX_PortDomainVideo;
10262     memset(&fmt, 0x0, sizeof(struct v4l2_format));
10263     if (0 == portDefn->nPortIndex) {
10264         if (secure_mode) {
10265             eRet = get_buffer_req(&drv_ctx.ip_buf);
10266             if (eRet) {
10267                 DEBUG_PRINT_ERROR("%s:get_buffer_req(ip_buf) failed", __func__);
10268                 return eRet;
10269             }
10270         }
10271         portDefn->eDir =  OMX_DirInput;
10272         portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
10273         portDefn->nBufferCountMin    = drv_ctx.ip_buf.mincount;
10274         portDefn->nBufferSize        = drv_ctx.ip_buf.buffer_size;
10275         portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
10276         portDefn->format.video.eCompressionFormat = eCompressionFormat;
10277         //for input port, always report the fps value set by client,
10278         //to distinguish whether client got valid fps from parser.
10279         portDefn->format.video.xFramerate = m_fps_received;
10280         portDefn->bEnabled   = m_inp_bEnabled;
10281         portDefn->bPopulated = m_inp_bPopulated;
10282 
10283         fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10284         fmt.fmt.pix_mp.pixelformat = output_capability;
10285         ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10286     } else if (1 == portDefn->nPortIndex) {
10287         unsigned int buf_size = 0;
10288         int ret = 0;
10289        if (!is_down_scalar_enabled) {
10290            fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10291            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10292            fmt.fmt.pix_mp.pixelformat = capture_capability;
10293            fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10294            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
10295        }
10296 
10297        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10298        fmt.fmt.pix_mp.pixelformat = capture_capability;
10299        ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
10300        if (ret) {
10301            DEBUG_PRINT_ERROR("Get Resolution failed");
10302            return OMX_ErrorHardware;
10303        }
10304        drv_ctx.op_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
10305        if (!client_buffers.update_buffer_req()) {
10306            DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
10307            return OMX_ErrorHardware;
10308        }
10309 
10310         if (!client_buffers.get_buffer_req(buf_size)) {
10311             DEBUG_PRINT_ERROR("update buffer requirements");
10312             return OMX_ErrorHardware;
10313         }
10314         portDefn->nBufferSize = buf_size;
10315         portDefn->eDir =  OMX_DirOutput;
10316         portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
10317         portDefn->nBufferCountMin    = drv_ctx.op_buf.mincount;
10318         portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
10319         if (drv_ctx.frame_rate.fps_denominator > 0)
10320             portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
10321                 drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
10322         else {
10323             DEBUG_PRINT_ERROR("Error: Divide by zero");
10324             return OMX_ErrorBadParameter;
10325         }
10326         portDefn->bEnabled   = m_out_bEnabled;
10327         portDefn->bPopulated = m_out_bPopulated;
10328         if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
10329             DEBUG_PRINT_ERROR("Error in getting color format");
10330             return OMX_ErrorHardware;
10331         }
10332         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
10333         fmt.fmt.pix_mp.pixelformat = capture_capability;
10334     } else if (OMX_CORE_OUTPUT_EXTRADATA_INDEX == portDefn->nPortIndex) {
10335         portDefn->nBufferSize = m_client_out_extradata_info.getSize();
10336         portDefn->nBufferCountMin = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
10337         portDefn->nBufferCountActual = MIN_NUM_INPUT_OUTPUT_EXTRADATA_BUFFERS;
10338         portDefn->eDir =  OMX_DirOutput;
10339         portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
10340         portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
10341         portDefn->format.video.nStride  = drv_ctx.video_resolution.stride;
10342         portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
10343         portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
10344         portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
10345         DEBUG_PRINT_LOW(" get_parameter: Port idx %d nBufSize %u nBufCnt %u",
10346                 (int)portDefn->nPortIndex,
10347                 (unsigned int)portDefn->nBufferSize,
10348                 (unsigned int)portDefn->nBufferCountActual);
10349         return eRet;
10350     } else {
10351         portDefn->eDir = OMX_DirMax;
10352         DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
10353                 (int)portDefn->nPortIndex);
10354         eRet = OMX_ErrorBadPortIndex;
10355     }
10356     if (in_reconfig) {
10357         m_extradata_info.output_crop_rect.nLeft = 0;
10358         m_extradata_info.output_crop_rect.nTop = 0;
10359         m_extradata_info.output_crop_rect.nWidth = fmt.fmt.pix_mp.width;
10360         m_extradata_info.output_crop_rect.nHeight = fmt.fmt.pix_mp.height;
10361     }
10362     update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
10363         fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
10364 
10365     portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
10366     portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
10367     portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
10368     portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
10369 
10370     if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
10371        (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
10372            portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
10373            portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
10374     }
10375     DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
10376             "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
10377             (unsigned int)portDefn->nPortIndex,
10378             (unsigned int)portDefn->format.video.nFrameWidth,
10379             (unsigned int)portDefn->format.video.nFrameHeight,
10380             (int)portDefn->format.video.nStride,
10381             (unsigned int)portDefn->format.video.nSliceHeight,
10382             (unsigned int)portDefn->format.video.eColorFormat,
10383             (unsigned int)portDefn->nBufferSize,
10384             (unsigned int)portDefn->nBufferCountActual);
10385 
10386     return eRet;
10387 }
10388 
allocate_output_headers(bool intermediate)10389 OMX_ERRORTYPE omx_vdec::allocate_output_headers(bool intermediate)
10390 {
10391     OMX_ERRORTYPE eRet = OMX_ErrorNone;
10392     OMX_BUFFERHEADERTYPE *bufHdr = NULL;
10393     unsigned i = 0;
10394 
10395     OMX_BUFFERHEADERTYPE  **omx_base_address =
10396                       intermediate?&m_intermediate_out_mem_ptr:&m_out_mem_ptr;
10397     vdec_bufferpayload **omx_ptr_outputbuffer =
10398         intermediate?&drv_ctx.ptr_intermediate_outputbuffer:&drv_ctx.ptr_outputbuffer;
10399     vdec_output_frameinfo **omx_ptr_respbuffer =
10400         intermediate?&drv_ctx.ptr_intermediate_respbuffer:&drv_ctx.ptr_respbuffer;
10401     vdec_ion **omx_op_buf_ion_info =
10402         intermediate?&drv_ctx.op_intermediate_buf_ion_info:&drv_ctx.op_buf_ion_info;
10403 
10404     if (!*omx_base_address) {
10405         DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation, Cnt %d Sz %d",
10406             drv_ctx.op_buf.actualcount, (unsigned int)drv_ctx.op_buf.buffer_size);
10407         int nBufHdrSize        = 0;
10408         int nPlatformEntrySize = 0;
10409         int nPlatformListSize  = 0;
10410         int nPMEMInfoSize = 0;
10411         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
10412         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
10413         OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
10414 
10415         nBufHdrSize        = drv_ctx.op_buf.actualcount *
10416             sizeof(OMX_BUFFERHEADERTYPE);
10417         nPMEMInfoSize      = drv_ctx.op_buf.actualcount *
10418             sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
10419         nPlatformListSize  = drv_ctx.op_buf.actualcount *
10420             sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
10421         nPlatformEntrySize = drv_ctx.op_buf.actualcount *
10422             sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
10423 
10424         *omx_base_address = (OMX_BUFFERHEADERTYPE  *)calloc(nBufHdrSize,1);
10425         // Alloc mem for platform specific info
10426         char *pPtr=NULL;
10427         pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
10428                 nPMEMInfoSize,1);
10429         *omx_ptr_outputbuffer = (struct vdec_bufferpayload *)    \
10430                        calloc (sizeof(struct vdec_bufferpayload),
10431                                drv_ctx.op_buf.actualcount);
10432         *omx_ptr_respbuffer = (struct vdec_output_frameinfo  *)                         \
10433                      calloc (sizeof (struct vdec_output_frameinfo),
10434                              drv_ctx.op_buf.actualcount);
10435         if (!pPtr || !*omx_ptr_outputbuffer || !*omx_ptr_respbuffer) {
10436             DEBUG_PRINT_ERROR("allocate_output_headers: allocation failed");
10437             free(pPtr); pPtr = NULL;
10438             free(*omx_ptr_outputbuffer); *omx_ptr_outputbuffer = NULL;
10439             free(*omx_ptr_respbuffer); *omx_ptr_respbuffer = NULL;
10440             return OMX_ErrorInsufficientResources;
10441         }
10442 
10443 #ifdef USE_ION
10444         *omx_op_buf_ion_info = (struct vdec_ion * ) \
10445                       calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
10446         if (!*omx_op_buf_ion_info) {
10447             DEBUG_PRINT_ERROR("Failed to alloc output buffer ion info");
10448             free(pPtr); pPtr = NULL;
10449             free(*omx_ptr_outputbuffer); *omx_ptr_outputbuffer = NULL;
10450             free(*omx_ptr_respbuffer); *omx_ptr_respbuffer = NULL;
10451             return OMX_ErrorInsufficientResources;
10452         }
10453 #endif
10454 
10455         if (*omx_base_address && pPtr && *omx_ptr_outputbuffer
10456             && *omx_ptr_respbuffer) {
10457             bufHdr          =  *omx_base_address;
10458             if (m_platform_list) {
10459                 free(m_platform_list);
10460             }
10461             m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
10462             m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
10463                 (((char *) m_platform_list)  + nPlatformListSize);
10464             m_pmem_info     = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
10465                 (((char *) m_platform_entry) + nPlatformEntrySize);
10466             pPlatformList   = m_platform_list;
10467             pPlatformEntry  = m_platform_entry;
10468             pPMEMInfo       = m_pmem_info;
10469 
10470             DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p", *omx_base_address);
10471 
10472             // Settting the entire storage nicely
10473             DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
10474                             *omx_base_address,pPlatformEntry);
10475             DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
10476             for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
10477                 bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
10478                 bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
10479                 // Set the values when we determine the right HxW param
10480                 bufHdr->nAllocLen          = 0;
10481                 bufHdr->nFilledLen         = 0;
10482                 bufHdr->pAppPrivate        = NULL;
10483                 bufHdr->nOutputPortIndex   = OMX_CORE_OUTPUT_PORT_INDEX;
10484                 pPlatformEntry->type       = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
10485                 pPlatformEntry->entry      = pPMEMInfo;
10486                 // Initialize the Platform List
10487                 pPlatformList->nEntries    = 1;
10488                 pPlatformList->entryList   = pPlatformEntry;
10489                 // Keep pBuffer NULL till vdec is opened
10490                 bufHdr->pBuffer            = NULL;
10491                 pPMEMInfo->offset          =  0;
10492                 pPMEMInfo->pmem_fd = -1;
10493                 bufHdr->pPlatformPrivate = pPlatformList;
10494                 (*omx_ptr_outputbuffer)[i].pmem_fd = -1;
10495 #ifdef USE_ION
10496                 (*omx_op_buf_ion_info)[i].data_fd = -1;
10497                 (*omx_op_buf_ion_info)[i].dev_fd = -1;
10498 #endif
10499                 /*Create a mapping between buffers*/
10500                 bufHdr->pOutputPortPrivate = &(*omx_ptr_respbuffer)[i];
10501                 (*omx_ptr_respbuffer)[i].client_data = (void *) \
10502                     &(*omx_ptr_outputbuffer)[i];
10503                 // Move the buffer and buffer header pointers
10504                 bufHdr++;
10505                 pPMEMInfo++;
10506                 pPlatformEntry++;
10507                 pPlatformList++;
10508             }
10509         } else {
10510             DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
10511                               *omx_base_address, pPtr);
10512             if (*omx_base_address) {
10513                 free(*omx_base_address);
10514                 *omx_base_address = NULL;
10515             }
10516             if (pPtr) {
10517                 free(pPtr);
10518                 pPtr = NULL;
10519             }
10520             if (*omx_ptr_outputbuffer) {
10521                 free(*omx_ptr_outputbuffer);
10522                 *omx_ptr_outputbuffer = NULL;
10523             }
10524             if (*omx_ptr_respbuffer) {
10525                 free(*omx_ptr_respbuffer);
10526                 *omx_ptr_respbuffer = NULL;
10527             }
10528 #ifdef USE_ION
10529             if (*omx_op_buf_ion_info) {
10530                 DEBUG_PRINT_LOW("Free o/p ion context");
10531                 free(*omx_op_buf_ion_info);
10532                 *omx_op_buf_ion_info = NULL;
10533             }
10534 #endif
10535             eRet =  OMX_ErrorInsufficientResources;
10536         }
10537     } else {
10538         eRet =  OMX_ErrorInsufficientResources;
10539     }
10540 
10541     if (intermediate == false &&
10542         eRet == OMX_ErrorNone &&
10543         client_buffers.is_color_conversion_enabled()) {
10544         eRet = allocate_output_headers(true);
10545     }
10546 
10547     return eRet;
10548 }
10549 
complete_pending_buffer_done_cbs()10550 void omx_vdec::complete_pending_buffer_done_cbs()
10551 {
10552     unsigned long p1, p2, ident;
10553     omx_cmd_queue tmp_q, pending_bd_q;
10554     pthread_mutex_lock(&m_lock);
10555     // pop all pending GENERATE FDB from ftb queue
10556     while (m_ftb_q.m_size) {
10557         m_ftb_q.pop_entry(&p1,&p2,&ident);
10558         if (ident == OMX_COMPONENT_GENERATE_FBD) {
10559             pending_bd_q.insert_entry(p1,p2,ident);
10560         } else {
10561             tmp_q.insert_entry(p1,p2,ident);
10562         }
10563     }
10564     //return all non GENERATE FDB to ftb queue
10565     while (tmp_q.m_size) {
10566         tmp_q.pop_entry(&p1,&p2,&ident);
10567         m_ftb_q.insert_entry(p1,p2,ident);
10568     }
10569     // pop all pending GENERATE EDB from etb queue
10570     while (m_etb_q.m_size) {
10571         m_etb_q.pop_entry(&p1,&p2,&ident);
10572         if (ident == OMX_COMPONENT_GENERATE_EBD) {
10573             pending_bd_q.insert_entry(p1,p2,ident);
10574         } else {
10575             tmp_q.insert_entry(p1,p2,ident);
10576         }
10577     }
10578     //return all non GENERATE FDB to etb queue
10579     while (tmp_q.m_size) {
10580         tmp_q.pop_entry(&p1,&p2,&ident);
10581         m_etb_q.insert_entry(p1,p2,ident);
10582     }
10583     pthread_mutex_unlock(&m_lock);
10584     // process all pending buffer dones
10585     while (pending_bd_q.m_size) {
10586         pending_bd_q.pop_entry(&p1,&p2,&ident);
10587         switch (ident) {
10588             case OMX_COMPONENT_GENERATE_EBD:
10589                 if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
10590                     DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
10591                     omx_report_error ();
10592                 }
10593                 break;
10594 
10595             case OMX_COMPONENT_GENERATE_FBD:
10596                 if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
10597                     DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
10598                     omx_report_error ();
10599                 }
10600                 break;
10601         }
10602     }
10603 }
10604 
set_frame_rate(OMX_S64 act_timestamp)10605 void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
10606 {
10607     OMX_U32 new_frame_interval = 0;
10608     if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
10609             && llabs(act_timestamp - prev_ts) > 2000) {
10610         new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ?
10611             llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual);
10612         if (new_frame_interval != frm_int || frm_int == 0) {
10613             frm_int = new_frame_interval;
10614             if (frm_int) {
10615                 drv_ctx.frame_rate.fps_numerator = 1e6;
10616                 drv_ctx.frame_rate.fps_denominator = frm_int;
10617                 DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
10618                         (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
10619                         (float)drv_ctx.frame_rate.fps_denominator);
10620                 /* We need to report the difference between this FBD and the previous FBD
10621                  * back to the driver for clock scaling purposes. */
10622                 struct v4l2_outputparm oparm;
10623                 /*XXX: we're providing timing info as seconds per frame rather than frames
10624                  * per second.*/
10625                 oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
10626                 oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
10627 
10628                 struct v4l2_streamparm sparm;
10629                 sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
10630                 sparm.parm.output = oparm;
10631                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
10632                     DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
10633                             performance might be affected");
10634                 }
10635 
10636             }
10637         }
10638     }
10639     prev_ts = act_timestamp;
10640 }
10641 
adjust_timestamp(OMX_S64 & act_timestamp)10642 void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
10643 {
10644     if (rst_prev_ts && VALID_TS(act_timestamp)) {
10645         prev_ts = act_timestamp;
10646         prev_ts_actual = act_timestamp;
10647         rst_prev_ts = false;
10648     } else if (VALID_TS(prev_ts)) {
10649         bool codec_cond = (drv_ctx.timestamp_adjust)?
10650             (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) :
10651             (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual);
10652              prev_ts_actual = act_timestamp; //unadjusted previous timestamp
10653         if (frm_int > 0 && codec_cond) {
10654             DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
10655             act_timestamp = prev_ts + frm_int;
10656             DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
10657             prev_ts = act_timestamp;
10658         } else {
10659             if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) {
10660                 // ensure that timestamps can never step backwards when in display order
10661                 act_timestamp = prev_ts;
10662             }
10663             set_frame_rate(act_timestamp);
10664         }
10665     } else if (frm_int > 0)          // In this case the frame rate was set along
10666     {                               // with the port definition, start ts with 0
10667         act_timestamp = prev_ts = 0;  // and correct if a valid ts is received.
10668         rst_prev_ts = true;
10669     }
10670 }
10671 
convert_color_space_info(OMX_U32 primaries,OMX_U32 range,OMX_U32 transfer,OMX_U32 matrix,ColorAspects * aspects)10672 void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
10673     OMX_U32 transfer, OMX_U32 matrix, ColorAspects *aspects)
10674 {
10675     switch (primaries) {
10676         case MSM_VIDC_BT709_5:
10677             aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
10678             break;
10679         case MSM_VIDC_BT470_6_M:
10680             aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
10681             break;
10682         case MSM_VIDC_BT601_6_625:
10683             aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10684             break;
10685         case MSM_VIDC_BT601_6_525:
10686             aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
10687             break;
10688         case MSM_VIDC_GENERIC_FILM:
10689             aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
10690             break;
10691         case MSM_VIDC_BT2020:
10692             aspects->mPrimaries = ColorAspects::PrimariesBT2020;
10693             break;
10694         case MSM_VIDC_UNSPECIFIED:
10695             //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default
10696         default:
10697             //aspects->mPrimaries = ColorAspects::PrimariesOther;
10698             aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
10699             break;
10700     }
10701 
10702     aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
10703 
10704     switch (transfer) {
10705         case MSM_VIDC_TRANSFER_BT709_5:
10706         case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
10707             aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10708             break;
10709         case MSM_VIDC_TRANSFER_BT_470_6_M:
10710             aspects->mTransfer = ColorAspects::TransferGamma22;
10711             break;
10712         case MSM_VIDC_TRANSFER_BT_470_6_BG:
10713             aspects->mTransfer = ColorAspects::TransferGamma28;
10714             break;
10715         case MSM_VIDC_TRANSFER_SMPTE_240M:
10716             aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10717             break;
10718         case MSM_VIDC_TRANSFER_LINEAR:
10719             aspects->mTransfer = ColorAspects::TransferLinear;
10720             break;
10721         case MSM_VIDC_TRANSFER_IEC_61966:
10722             aspects->mTransfer = ColorAspects::TransferXvYCC;
10723             break;
10724         case MSM_VIDC_TRANSFER_BT_1361:
10725             aspects->mTransfer = ColorAspects::TransferBT1361;
10726             break;
10727         case MSM_VIDC_TRANSFER_SRGB:
10728             aspects->mTransfer = ColorAspects::TransferSRGB;
10729             break;
10730         case MSM_VIDC_TRANSFER_SMPTE_ST2084:
10731             aspects->mTransfer = ColorAspects::TransferST2084;
10732             break;
10733         case MSM_VIDC_TRANSFER_HLG:
10734             aspects->mTransfer = ColorAspects::TransferHLG;
10735             break;
10736         default:
10737             //aspects->mTransfer = ColorAspects::TransferOther;
10738             aspects->mTransfer = m_client_color_space.sAspects.mTransfer;
10739             break;
10740     }
10741 
10742     switch (matrix) {
10743         case MSM_VIDC_MATRIX_BT_709_5:
10744             aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10745             break;
10746         case MSM_VIDC_MATRIX_FCC_47:
10747             aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
10748             break;
10749         case MSM_VIDC_MATRIX_601_6_625:
10750         case MSM_VIDC_MATRIX_601_6_525:
10751             aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10752             break;
10753         case MSM_VIDC_MATRIX_SMPTE_240M:
10754             aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
10755             break;
10756         case MSM_VIDC_MATRIX_BT_2020:
10757             aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10758             break;
10759         case MSM_VIDC_MATRIX_BT_2020_CONST:
10760             aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
10761             break;
10762         default:
10763             //aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
10764             aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
10765             break;
10766     }
10767 }
10768 
print_debug_color_aspects(ColorAspects * a,const char * prefix)10769 void omx_vdec::print_debug_color_aspects(ColorAspects *a, const char *prefix) {
10770     DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d(%s) Range = %d(%s) Tx = %d(%s) Matrix = %d(%s)",
10771                 prefix, a->mPrimaries, asString(a->mPrimaries), a->mRange, asString(a->mRange),
10772                 a->mTransfer, asString(a->mTransfer), a->mMatrixCoeffs, asString(a->mMatrixCoeffs));
10773 
10774 }
10775 
handle_color_space_info(void * data)10776 bool omx_vdec::handle_color_space_info(void *data)
10777 {
10778     ColorAspects tempAspects;
10779     memset(&tempAspects, 0x0, sizeof(ColorAspects));
10780     ColorAspects *aspects = &tempAspects;
10781 
10782     switch(output_capability) {
10783         case V4L2_PIX_FMT_MPEG2:
10784             {
10785                 struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
10786                 seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
10787 
10788                 /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
10789                  * understand this code */
10790 
10791                 if (seqdisp_payload && seqdisp_payload->color_descp) {
10792 
10793                     convert_color_space_info(seqdisp_payload->color_primaries, 0,
10794                             seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
10795                             aspects);
10796                     /* MPEG2 seqdisp payload doesn't give range info. Hence assing the value
10797                      * set by client */
10798                     aspects->mRange = m_client_color_space.sAspects.mRange;
10799                     m_disp_hor_size = seqdisp_payload->disp_width;
10800                     m_disp_vert_size = seqdisp_payload->disp_height;
10801                 }
10802             }
10803             break;
10804         case V4L2_PIX_FMT_H264:
10805         case V4L2_PIX_FMT_HEVC:
10806             {
10807                 struct msm_vidc_vui_display_info_payload *display_info_payload;
10808                 display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
10809 
10810                 /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
10811 
10812                 if (display_info_payload->video_signal_present_flag &&
10813                         display_info_payload->color_description_present_flag) {
10814                     convert_color_space_info(display_info_payload->color_primaries,
10815                             display_info_payload->video_full_range_flag,
10816                             display_info_payload->transfer_characteristics,
10817                             display_info_payload->matrix_coefficients,
10818                             aspects);
10819                 }
10820             }
10821             break;
10822         case V4L2_PIX_FMT_VP8:
10823             {
10824                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10825                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10826                 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
10827                  * to understand this code */
10828 
10829                 if (vpx_color_space_payload->color_space == 0) {
10830                     aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
10831                     aspects->mRange = ColorAspects::RangeLimited;
10832                     aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10833                     aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10834                 } else {
10835                     DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
10836                     break;
10837                 }
10838             }
10839             break;
10840         case V4L2_PIX_FMT_VP9:
10841             {
10842                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
10843                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
10844                 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
10845                  * to understand this code */
10846 
10847                 switch(vpx_color_space_payload->color_space) {
10848                     case MSM_VIDC_CS_BT_601:
10849                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10850                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10851                         aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
10852                         aspects->mRange = m_client_color_space.sAspects.mRange;
10853                         break;
10854                     case MSM_VIDC_CS_BT_709:
10855                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10856                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10857                         aspects->mPrimaries =  ColorAspects::PrimariesBT709_5;
10858                         aspects->mRange = m_client_color_space.sAspects.mRange;
10859                         break;
10860                     case MSM_VIDC_CS_SMPTE_170:
10861                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
10862                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10863                         aspects->mPrimaries =  ColorAspects::PrimariesBT601_6_525;
10864                         aspects->mRange = m_client_color_space.sAspects.mRange;
10865                         break;
10866                     case MSM_VIDC_CS_SMPTE_240:
10867                         aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
10868                         aspects->mTransfer = ColorAspects::TransferSMPTE240M;
10869                         aspects->mPrimaries =  ColorAspects::PrimariesBT601_6_525;
10870                         aspects->mRange = m_client_color_space.sAspects.mRange;
10871                         break;
10872                     case MSM_VIDC_CS_BT_2020:
10873                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
10874                         aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
10875                         aspects->mPrimaries = ColorAspects::PrimariesBT2020;
10876                         aspects->mRange = m_client_color_space.sAspects.mRange;
10877                         break;
10878                     case MSM_VIDC_CS_RESERVED:
10879                         aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
10880                         aspects->mTransfer = ColorAspects::TransferOther;
10881                         aspects->mPrimaries = ColorAspects::PrimariesOther;
10882                         aspects->mRange = m_client_color_space.sAspects.mRange;
10883                         break;
10884                     case MSM_VIDC_CS_RGB:
10885                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
10886                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
10887                         aspects->mPrimaries = ColorAspects::PrimariesOther;
10888                         aspects->mRange = m_client_color_space.sAspects.mRange;
10889                         break;
10890                     default:
10891                         break;
10892                 }
10893             }
10894             break;
10895         default:
10896             break;
10897     }
10898 
10899     print_debug_color_aspects(aspects, "Bitstream");
10900 
10901     if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
10902             m_internal_color_space.sAspects.mTransfer != aspects->mTransfer ||
10903             m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs ||
10904             m_internal_color_space.sAspects.mRange != aspects->mRange) {
10905         memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
10906 
10907         DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to Color Aspects Change");
10908         print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
10909         print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
10910 
10911         post_event(OMX_CORE_OUTPUT_PORT_INDEX,
10912                 OMX_QTIIndexConfigDescribeColorAspects,
10913                 OMX_COMPONENT_GENERATE_PORT_RECONFIG);
10914         return true;
10915     }
10916     return false;
10917 }
10918 
print_debug_hdr_color_info(HDRStaticInfo * hdr_info,const char * prefix)10919 void omx_vdec::print_debug_hdr_color_info(HDRStaticInfo *hdr_info, const char *prefix)
10920 {
10921     if (!hdr_info->mID) {
10922         DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mR.x = %d mR.y = %d", prefix,
10923                          hdr_info->sType1.mR.x, hdr_info->sType1.mR.y);
10924         DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mG.x = %d mG.y = %d", prefix,
10925                          hdr_info->sType1.mG.x, hdr_info->sType1.mG.y);
10926         DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mB.x = %d mB.y = %d", prefix,
10927                          hdr_info->sType1.mB.x, hdr_info->sType1.mB.y);
10928         DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: mW.x = %d mW.y = %d", prefix,
10929                          hdr_info->sType1.mW.x, hdr_info->sType1.mW.y);
10930         DEBUG_PRINT_LOW("%s : HDRstaticinfo MDC: maxDispLum = %d minDispLum = %d", prefix,
10931                          hdr_info->sType1.mMaxDisplayLuminance, hdr_info->sType1.mMinDisplayLuminance);
10932         DEBUG_PRINT_LOW("%s : HDRstaticinfo CLL: CLL = %d FLL = %d", prefix,
10933                         hdr_info->sType1.mMaxContentLightLevel, hdr_info->sType1.mMaxFrameAverageLightLevel);
10934     }
10935 
10936 }
10937 
print_debug_hdr_color_info_mdata(ColorMetaData * color_mdata)10938 void omx_vdec::print_debug_hdr_color_info_mdata(ColorMetaData* color_mdata)
10939 {
10940     DEBUG_PRINT_LOW("setMetaData COLOR_METADATA : color_primaries = %u, range = %u, transfer = %u, matrix = %u",
10941                     color_mdata->colorPrimaries, color_mdata->range,
10942                     color_mdata->transfer, color_mdata->matrixCoefficients);
10943 
10944     for(uint8_t i = 0; i < 3; i++) {
10945         for(uint8_t j = 0; j < 2; j++) {
10946             DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : rgbPrimaries[%d][%d] = %d", i, j, color_mdata->masteringDisplayInfo.primaries.rgbPrimaries[i][j]);
10947         }
10948     }
10949 
10950     DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : whitepoint[0] = %d whitepoint[1] = %d",
10951                     color_mdata->masteringDisplayInfo.primaries.whitePoint[0],
10952                     color_mdata->masteringDisplayInfo.primaries.whitePoint[1]);
10953 
10954     DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxDispLum = %d minDispLum = %d",
10955                     color_mdata->masteringDisplayInfo.maxDisplayLuminance,
10956                     color_mdata->masteringDisplayInfo.minDisplayLuminance);
10957 
10958     DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxCLL = %d maxFLL = %d",
10959                     color_mdata->contentLightLevel.maxContentLightLevel,
10960                     color_mdata->contentLightLevel.minPicAverageLightLevel);
10961 
10962 
10963 }
10964 
handle_content_light_level_info(void * data)10965 bool omx_vdec::handle_content_light_level_info(void* data)
10966 {
10967     struct msm_vidc_content_light_level_sei_payload *light_level_payload =
10968         (msm_vidc_content_light_level_sei_payload*)(data);
10969 
10970     if ((m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel != light_level_payload->nMaxContentLight) ||
10971         (m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel != light_level_payload->nMaxPicAverageLight)) {
10972         m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel = light_level_payload->nMaxContentLight;
10973         m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel = light_level_payload->nMaxPicAverageLight;
10974         return true;
10975     }
10976     return false;
10977 }
10978 
handle_mastering_display_color_info(void * data)10979 bool omx_vdec::handle_mastering_display_color_info(void* data)
10980 {
10981     struct msm_vidc_mastering_display_colour_sei_payload *mastering_display_payload =
10982         (msm_vidc_mastering_display_colour_sei_payload*)(data);
10983     HDRStaticInfo* hdr_info = &m_internal_hdr_info.sInfo;
10984     bool internal_disp_changed_flag = false;
10985 
10986     internal_disp_changed_flag |= (hdr_info->sType1.mR.x != mastering_display_payload->nDisplayPrimariesX[0]) ||
10987         (hdr_info->sType1.mR.y != mastering_display_payload->nDisplayPrimariesY[0]);
10988     internal_disp_changed_flag |= (hdr_info->sType1.mG.x != mastering_display_payload->nDisplayPrimariesX[1]) ||
10989         (hdr_info->sType1.mG.y != mastering_display_payload->nDisplayPrimariesY[1]);
10990     internal_disp_changed_flag |= (hdr_info->sType1.mB.x != mastering_display_payload->nDisplayPrimariesX[2]) ||
10991         (hdr_info->sType1.mB.y != mastering_display_payload->nDisplayPrimariesY[2]);
10992 
10993     internal_disp_changed_flag |= (hdr_info->sType1.mW.x != mastering_display_payload->nWhitePointX) ||
10994         (hdr_info->sType1.mW.y != mastering_display_payload->nWhitePointY);
10995 
10996     /* Maximum Display Luminance from the bitstream is in 0.0001 cd/m2 while the HDRStaticInfo extension
10997        requires it in cd/m2, so dividing by 10000 and rounding the value after division
10998     */
10999     uint16_t max_display_luminance_cd_m2 =
11000         static_cast<int>((mastering_display_payload->nMaxDisplayMasteringLuminance / LUMINANCE_DIV_FACTOR) + 0.5);
11001     internal_disp_changed_flag |= (hdr_info->sType1.mMaxDisplayLuminance != max_display_luminance_cd_m2) ||
11002         (hdr_info->sType1.mMinDisplayLuminance != mastering_display_payload->nMinDisplayMasteringLuminance);
11003 
11004     if (internal_disp_changed_flag) {
11005         hdr_info->sType1.mR.x = mastering_display_payload->nDisplayPrimariesX[0];
11006         hdr_info->sType1.mR.y = mastering_display_payload->nDisplayPrimariesY[0];
11007         hdr_info->sType1.mG.x = mastering_display_payload->nDisplayPrimariesX[1];
11008         hdr_info->sType1.mG.y = mastering_display_payload->nDisplayPrimariesY[1];
11009         hdr_info->sType1.mB.x = mastering_display_payload->nDisplayPrimariesX[2];
11010         hdr_info->sType1.mB.y = mastering_display_payload->nDisplayPrimariesY[2];
11011         hdr_info->sType1.mW.x = mastering_display_payload->nWhitePointX;
11012         hdr_info->sType1.mW.y = mastering_display_payload->nWhitePointY;
11013 
11014         hdr_info->sType1.mMaxDisplayLuminance = max_display_luminance_cd_m2;
11015         hdr_info->sType1.mMinDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance;
11016     }
11017 
11018     return internal_disp_changed_flag;
11019 }
11020 
set_colormetadata_in_handle(ColorMetaData * color_mdata,unsigned int buf_index)11021 void omx_vdec::set_colormetadata_in_handle(ColorMetaData *color_mdata, unsigned int buf_index)
11022 {
11023     private_handle_t *private_handle = NULL;
11024     if (buf_index < drv_ctx.op_buf.actualcount &&
11025         buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
11026         native_buffer[buf_index].privatehandle) {
11027         private_handle = native_buffer[buf_index].privatehandle;
11028     }
11029     if (private_handle) {
11030         setMetaData(private_handle, COLOR_METADATA, (void*)color_mdata);
11031     }
11032 }
11033 
convert_color_aspects_to_metadata(ColorAspects & aspects,ColorMetaData & color_mdata)11034 void omx_vdec::convert_color_aspects_to_metadata(ColorAspects& aspects, ColorMetaData &color_mdata)
11035 {
11036     PrimariesMap::const_iterator primary_it = mPrimariesMap.find(aspects.mPrimaries);
11037     TransferMap::const_iterator transfer_it = mTransferMap.find(aspects.mTransfer);
11038     MatrixCoeffMap::const_iterator matrix_it = mMatrixCoeffMap.find(aspects.mMatrixCoeffs);
11039     RangeMap::const_iterator range_it = mColorRangeMap.find(aspects.mRange);
11040 
11041     if (primary_it == mPrimariesMap.end()) {
11042         DEBUG_PRINT_LOW("No mapping for %d in PrimariesMap, defaulting to unspecified", aspects.mPrimaries);
11043         color_mdata.colorPrimaries = (ColorPrimaries)2;
11044     } else {
11045         color_mdata.colorPrimaries = primary_it->second;
11046     }
11047 
11048     if (transfer_it == mTransferMap.end()) {
11049         DEBUG_PRINT_LOW("No mapping for %d in TransferMap, defaulting to unspecified", aspects.mTransfer);
11050         color_mdata.transfer = (GammaTransfer)2;
11051     } else {
11052         color_mdata.transfer = transfer_it->second;
11053     }
11054 
11055     if (matrix_it == mMatrixCoeffMap.end()) {
11056         DEBUG_PRINT_LOW("No mapping for %d in MatrixCoeffMap, defaulting to unspecified", aspects.mMatrixCoeffs);
11057         color_mdata.matrixCoefficients = (MatrixCoEfficients)2;
11058     } else {
11059         color_mdata.matrixCoefficients = matrix_it->second;
11060     }
11061 
11062     if (range_it == mColorRangeMap.end()) {
11063         DEBUG_PRINT_LOW("No mapping for %d in ColorRangeMap, defaulting to limited range", aspects.mRange);
11064         color_mdata.range = Range_Limited;
11065     } else {
11066         color_mdata.range = range_it->second;
11067     }
11068 }
11069 
convert_hdr_info_to_metadata(HDRStaticInfo & hdr_info,ColorMetaData & color_mdata)11070 void omx_vdec::convert_hdr_info_to_metadata(HDRStaticInfo& hdr_info, ColorMetaData &color_mdata)
11071 {
11072     HDRStaticInfo::Type1 zero_hdr_info;
11073     MasteringDisplay& mastering_display = color_mdata.masteringDisplayInfo;
11074     ContentLightLevel& content_light = color_mdata.contentLightLevel;
11075     bool hdr_info_enabled = false;
11076     memset(&zero_hdr_info, 0, sizeof(HDRStaticInfo::Type1));
11077     hdr_info_enabled = (memcmp(&hdr_info, &zero_hdr_info, sizeof(HDRStaticInfo::Type1))!= 0);
11078 
11079     if (hdr_info_enabled) {
11080         mastering_display.colorVolumeSEIEnabled = true;
11081         mastering_display.primaries.rgbPrimaries[0][0] = hdr_info.sType1.mR.x;
11082         mastering_display.primaries.rgbPrimaries[0][1] = hdr_info.sType1.mR.y;
11083         mastering_display.primaries.rgbPrimaries[1][0] = hdr_info.sType1.mG.x;
11084         mastering_display.primaries.rgbPrimaries[1][1] = hdr_info.sType1.mG.y;
11085         mastering_display.primaries.rgbPrimaries[2][0] = hdr_info.sType1.mB.x;
11086         mastering_display.primaries.rgbPrimaries[2][1] = hdr_info.sType1.mB.y;
11087         mastering_display.primaries.whitePoint[0] = hdr_info.sType1.mW.x;
11088         mastering_display.primaries.whitePoint[1] = hdr_info.sType1.mW.y;
11089         mastering_display.maxDisplayLuminance = hdr_info.sType1.mMaxDisplayLuminance * LUMINANCE_DIV_FACTOR;
11090         mastering_display.minDisplayLuminance = hdr_info.sType1.mMinDisplayLuminance;
11091         content_light.lightLevelSEIEnabled = true;
11092         content_light.maxContentLightLevel = hdr_info.sType1.mMaxContentLightLevel;
11093         content_light.minPicAverageLightLevel = hdr_info.sType1.mMaxFrameAverageLightLevel;
11094     }
11095 
11096 }
11097 
get_preferred_color_aspects(ColorAspects & preferredColorAspects)11098 void omx_vdec::get_preferred_color_aspects(ColorAspects& preferredColorAspects)
11099 {
11100     // For VPX, use client-color if specified.
11101     // For the rest, try to use the stream-color if present
11102     bool preferClientColor = (output_capability == V4L2_PIX_FMT_VP8 ||
11103          output_capability == V4L2_PIX_FMT_VP9);
11104 
11105     const ColorAspects &preferredColor = preferClientColor ?
11106         m_client_color_space.sAspects : m_internal_color_space.sAspects;
11107     const ColorAspects &defaultColor = preferClientColor ?
11108         m_internal_color_space.sAspects : m_client_color_space.sAspects;
11109 
11110     preferredColorAspects.mPrimaries = preferredColor.mPrimaries != ColorAspects::PrimariesUnspecified ?
11111         preferredColor.mPrimaries : defaultColor.mPrimaries;
11112     preferredColorAspects.mTransfer = preferredColor.mTransfer != ColorAspects::TransferUnspecified ?
11113         preferredColor.mTransfer : defaultColor.mTransfer;
11114     preferredColorAspects.mMatrixCoeffs = preferredColor.mMatrixCoeffs != ColorAspects::MatrixUnspecified ?
11115         preferredColor.mMatrixCoeffs : defaultColor.mMatrixCoeffs;
11116     preferredColorAspects.mRange = preferredColor.mRange != ColorAspects::RangeUnspecified ?
11117         preferredColor.mRange : defaultColor.mRange;
11118 
11119 }
11120 
get_preferred_hdr_info(HDRStaticInfo & finalHDRInfo)11121 void omx_vdec::get_preferred_hdr_info(HDRStaticInfo& finalHDRInfo)
11122 {
11123     bool preferClientHDR = (output_capability == V4L2_PIX_FMT_VP9);
11124 
11125     const HDRStaticInfo &preferredHDRInfo = preferClientHDR ?
11126         m_client_hdr_info.sInfo : m_internal_hdr_info.sInfo;
11127     const HDRStaticInfo &defaultHDRInfo = preferClientHDR ?
11128         m_internal_hdr_info.sInfo : m_client_hdr_info.sInfo;
11129     finalHDRInfo.sType1.mR = ((preferredHDRInfo.sType1.mR.x != 0) && (preferredHDRInfo.sType1.mR.y != 0)) ?
11130         preferredHDRInfo.sType1.mR : defaultHDRInfo.sType1.mR;
11131     finalHDRInfo.sType1.mG = ((preferredHDRInfo.sType1.mG.x != 0) && (preferredHDRInfo.sType1.mG.y != 0)) ?
11132         preferredHDRInfo.sType1.mG : defaultHDRInfo.sType1.mG;
11133     finalHDRInfo.sType1.mB = ((preferredHDRInfo.sType1.mB.x != 0) && (preferredHDRInfo.sType1.mB.y != 0)) ?
11134         preferredHDRInfo.sType1.mB : defaultHDRInfo.sType1.mB;
11135     finalHDRInfo.sType1.mW = ((preferredHDRInfo.sType1.mW.x != 0) && (preferredHDRInfo.sType1.mW.y != 0)) ?
11136         preferredHDRInfo.sType1.mW : defaultHDRInfo.sType1.mW;
11137     finalHDRInfo.sType1.mMaxDisplayLuminance = (preferredHDRInfo.sType1.mMaxDisplayLuminance != 0) ?
11138         preferredHDRInfo.sType1.mMaxDisplayLuminance : defaultHDRInfo.sType1.mMaxDisplayLuminance;
11139     finalHDRInfo.sType1.mMinDisplayLuminance = (preferredHDRInfo.sType1.mMinDisplayLuminance != 0) ?
11140         preferredHDRInfo.sType1.mMinDisplayLuminance : defaultHDRInfo.sType1.mMinDisplayLuminance;
11141     finalHDRInfo.sType1.mMaxContentLightLevel = (preferredHDRInfo.sType1.mMaxContentLightLevel != 0) ?
11142         preferredHDRInfo.sType1.mMaxContentLightLevel : defaultHDRInfo.sType1.mMaxContentLightLevel;
11143     finalHDRInfo.sType1.mMaxFrameAverageLightLevel = (preferredHDRInfo.sType1.mMaxFrameAverageLightLevel != 0) ?
11144         preferredHDRInfo.sType1.mMaxFrameAverageLightLevel : defaultHDRInfo.sType1.mMaxFrameAverageLightLevel;
11145 }
11146 
print_debug_hdr10plus_metadata(ColorMetaData & color_mdata)11147 void omx_vdec::print_debug_hdr10plus_metadata(ColorMetaData& color_mdata) {
11148     DEBUG_PRINT_LOW("HDR10+ valid data length: %d", color_mdata.dynamicMetaDataLen);
11149     for (uint32_t i = 0 ; i < color_mdata.dynamicMetaDataLen && i+3 < HDR_DYNAMIC_META_DATA_SZ; i=i+4) {
11150         DEBUG_PRINT_LOW("HDR10+ mdata: %02X %02X %02X %02X", color_mdata.dynamicMetaDataPayload[i],
11151             color_mdata.dynamicMetaDataPayload[i+1],
11152             color_mdata.dynamicMetaDataPayload[i+2],
11153             color_mdata.dynamicMetaDataPayload[i+3]);
11154     }
11155 
11156 }
11157 
handle_extradata(OMX_BUFFERHEADERTYPE * p_buf_hdr)11158 bool omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
11159 {
11160     OMX_OTHER_EXTRADATATYPE *p_sei = NULL, *p_vui = NULL, *p_client_extra = NULL;
11161     OMX_U32 num_conceal_MB = 0;
11162     OMX_TICKS time_stamp = 0;
11163     OMX_U32 frame_rate = 0;
11164     unsigned long consumed_len = 0;
11165     OMX_U32 num_MB_in_frame;
11166     OMX_U32 recovery_sei_flags = 1;
11167     int enable = OMX_InterlaceFrameProgressive;
11168     bool internal_hdr_info_changed_flag = false;
11169     bool reconfig_event_sent = false;
11170     char *p_extradata = NULL;
11171     OMX_OTHER_EXTRADATATYPE *data = NULL;
11172     ColorMetaData color_mdata;
11173 
11174     OMX_BUFFERHEADERTYPE  *omx_base_address =
11175         client_buffers.is_color_conversion_enabled()?
11176                             m_intermediate_out_mem_ptr:m_out_mem_ptr;
11177     vdec_bufferpayload *omx_ptr_outputbuffer =
11178         client_buffers.is_color_conversion_enabled()?
11179                     drv_ctx.ptr_intermediate_outputbuffer:drv_ctx.ptr_outputbuffer;
11180     memset(&color_mdata, 0, sizeof(color_mdata));
11181 
11182     int buf_index = p_buf_hdr - omx_base_address;
11183     if (buf_index >= drv_ctx.extradata_info.count) {
11184         DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)",
11185                 buf_index, drv_ctx.extradata_info.count);
11186         return reconfig_event_sent;
11187     }
11188     struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
11189 
11190     if (omx_ptr_outputbuffer[buf_index].bufferaddr == NULL) {
11191         DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL");
11192         return reconfig_event_sent;
11193     }
11194 
11195     if (!drv_ctx.extradata_info.uaddr) {
11196         DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
11197         return reconfig_event_sent;
11198     }
11199 
11200     if (m_client_output_extradata_mem_ptr &&
11201         m_client_out_extradata_info.getSize() >= drv_ctx.extradata_info.buffer_size) {
11202         p_client_extra = (OMX_OTHER_EXTRADATATYPE *)((m_client_output_extradata_mem_ptr + buf_index)->pBuffer);
11203     }
11204 
11205     p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
11206 
11207     m_extradata_info.output_crop_updated = OMX_FALSE;
11208     data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
11209     if (data) {
11210         while ((((consumed_len + sizeof(struct OMX_OTHER_EXTRADATATYPE)) <
11211                 drv_ctx.extradata_info.buffer_size) && ((consumed_len + data->nSize) <
11212                 drv_ctx.extradata_info.buffer_size))
11213                 && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
11214             DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
11215             switch ((unsigned long)data->eType) {
11216                 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
11217                     struct msm_vidc_interlace_payload *payload;
11218                     payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
11219                     if (payload) {
11220                         DEBUG_PRINT_LOW("Interlace format %#x", payload->format);
11221                         enable = OMX_InterlaceFrameProgressive;
11222                         is_mbaff = payload->format & MSM_VIDC_INTERLACE_FRAME_MBAFF;
11223                         switch (payload->format & 0x1F) {
11224                             case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
11225                                 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11226                                 break;
11227                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
11228                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
11229                                 enable = OMX_InterlaceInterleaveFrameTopFieldFirst;
11230                                 break;
11231                             case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
11232                                 drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
11233                                 enable = OMX_InterlaceInterleaveFrameBottomFieldFirst;
11234                                 break;
11235                             case MSM_VIDC_INTERLACE_FRAME_TOPFIELDFIRST:
11236                                 drv_ctx.interlace = VDEC_InterlaceFrameTopFieldFirst;
11237                                 enable = OMX_InterlaceFrameTopFieldFirst;
11238                                 break;
11239                            case MSM_VIDC_INTERLACE_FRAME_BOTTOMFIELDFIRST:
11240                                 drv_ctx.interlace = VDEC_InterlaceFrameBottomFieldFirst;
11241                                 enable = OMX_InterlaceFrameBottomFieldFirst;
11242                                 break;
11243                             default:
11244                                 DEBUG_PRINT_LOW("default case - set to progressive");
11245                                 drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11246                         }
11247                     }
11248 
11249                     if (m_enable_android_native_buffers) {
11250                         DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d enable:%d",
11251                                         payload->format, enable);
11252 
11253                         setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
11254                                PP_PARAM_INTERLACED, (void*)&enable);
11255 
11256                     }
11257                     if (client_extradata & OMX_INTERLACE_EXTRADATA) {
11258                         if (p_client_extra) {
11259                             append_interlace_extradata(p_client_extra, (payload->format & 0x1F));
11260                             p_client_extra = (OMX_OTHER_EXTRADATATYPE *)
11261                                 (((OMX_U8 *)p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11262                         }
11263                     }
11264                     break;
11265                 case MSM_VIDC_EXTRADATA_FRAME_RATE:
11266                     struct msm_vidc_framerate_payload *frame_rate_payload;
11267                     frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
11268                     frame_rate = frame_rate_payload->frame_rate;
11269                     break;
11270                 case MSM_VIDC_EXTRADATA_TIMESTAMP:
11271                     struct msm_vidc_ts_payload *time_stamp_payload;
11272                     time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
11273                     time_stamp = time_stamp_payload->timestamp_lo;
11274                     time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
11275                     p_buf_hdr->nTimeStamp = time_stamp;
11276                     break;
11277                 case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
11278                     struct msm_vidc_concealmb_payload *conceal_mb_payload;
11279                     conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
11280                     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
11281                             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
11282                     num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
11283                     break;
11284                 case MSM_VIDC_EXTRADATA_INDEX:
11285                     int *etype;
11286                     etype  = (int *)(void *)data->data;
11287                     if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
11288                         struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
11289                         aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
11290                         if (aspect_ratio_payload) {
11291                             ((struct vdec_output_frameinfo *)
11292                              p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
11293                             ((struct vdec_output_frameinfo *)
11294                              p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
11295                         }
11296                     } else if (etype && *etype == MSM_VIDC_EXTRADATA_OUTPUT_CROP) {
11297                         struct msm_vidc_output_crop_payload *output_crop_payload;
11298                         output_crop_payload = (struct msm_vidc_output_crop_payload *)(++etype);
11299                         if (output_crop_payload) {
11300                             m_extradata_info.output_crop_rect.nLeft = output_crop_payload->left;
11301                             m_extradata_info.output_crop_rect.nTop = output_crop_payload->top;
11302                             m_extradata_info.output_crop_rect.nWidth = output_crop_payload->left + output_crop_payload->display_width;
11303                             m_extradata_info.output_crop_rect.nHeight = output_crop_payload->top + output_crop_payload->display_height;
11304                             m_extradata_info.output_width = output_crop_payload->width;
11305                             m_extradata_info.output_height = output_crop_payload->height;
11306                             m_extradata_info.output_crop_updated = OMX_TRUE;
11307                             for(unsigned int m=0; m<output_crop_payload->misr_info[0].misr_set; m++) {
11308                             DEBUG_PRINT_HIGH("MISR0: %x %x %x %x\n",
11309                                 output_crop_payload->misr_info[0].misr_dpb_luma[m],
11310                                 output_crop_payload->misr_info[0].misr_dpb_chroma[m],
11311                                 output_crop_payload->misr_info[0].misr_opb_luma[m],
11312                                 output_crop_payload->misr_info[0].misr_opb_chroma[m]);
11313                             }
11314                             for(unsigned int m=0; m< output_crop_payload->misr_info[1].misr_set; m++) {
11315                                 DEBUG_PRINT_HIGH("MISR1: %x %x %x %x\n",
11316                                                  output_crop_payload->misr_info[1].misr_dpb_luma[m],
11317                                                  output_crop_payload->misr_info[1].misr_dpb_chroma[m],
11318                                                  output_crop_payload->misr_info[1].misr_opb_luma[m],
11319                                                  output_crop_payload->misr_info[1].misr_opb_chroma[m]);
11320                             }
11321                             memcpy(m_extradata_info.misr_info, output_crop_payload->misr_info, 2 * sizeof(msm_vidc_misr_info));
11322                             if (client_extradata & OMX_OUTPUTCROP_EXTRADATA) {
11323                                 if (p_client_extra) {
11324                                     append_outputcrop_extradata(p_client_extra, output_crop_payload);
11325                                     p_client_extra = (OMX_OTHER_EXTRADATATYPE *)(((OMX_U8 *)p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11326                                 }
11327                             }
11328                         }
11329                     }
11330                     break;
11331                 case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
11332                     struct msm_vidc_recoverysei_payload *recovery_sei_payload;
11333                     recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
11334                     recovery_sei_flags = recovery_sei_payload->flags;
11335                     if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
11336                         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
11337                         DEBUG_PRINT_HIGH("***************************************************");
11338                         DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
11339                         DEBUG_PRINT_HIGH("***************************************************");
11340                     }
11341                     break;
11342                case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
11343                     panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
11344                     if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
11345                         DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
11346                         DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
11347                             MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
11348                         return reconfig_event_sent;
11349                     }
11350                     break;
11351                 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
11352                 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
11353                 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
11354                     reconfig_event_sent |= handle_color_space_info((void *)data->data);
11355                     break;
11356                 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
11357                     struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
11358                     s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
11359                     switch (s3d_frame_packing_payload->fpa_type) {
11360                         case MSM_VIDC_FRAMEPACK_SIDE_BY_SIDE:
11361                             if (s3d_frame_packing_payload->content_interprtation_type == 1)
11362                                 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_L_R;
11363                             else if (s3d_frame_packing_payload->content_interprtation_type == 2)
11364                                 stereo_output_mode = HAL_3D_SIDE_BY_SIDE_R_L;
11365                             else {
11366                                 DEBUG_PRINT_ERROR("Unsupported side-by-side framepacking type");
11367                                 stereo_output_mode = HAL_NO_3D;
11368                             }
11369                             break;
11370                         case MSM_VIDC_FRAMEPACK_TOP_BOTTOM:
11371                             stereo_output_mode = HAL_3D_TOP_BOTTOM;
11372                             break;
11373                         default:
11374                             DEBUG_PRINT_ERROR("Unsupported framepacking type");
11375                             stereo_output_mode = HAL_NO_3D;
11376                     }
11377                     DEBUG_PRINT_LOW("setMetaData FRAMEPACKING : fpa_type = %u, content_interprtation_type = %u, stereo_output_mode= %d",
11378                         s3d_frame_packing_payload->fpa_type, s3d_frame_packing_payload->content_interprtation_type, stereo_output_mode);
11379                     if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
11380                         if (p_client_extra) {
11381                             append_framepack_extradata(p_client_extra, s3d_frame_packing_payload);
11382                             p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11383                         }
11384                     }
11385                     break;
11386                 case MSM_VIDC_EXTRADATA_FRAME_QP:
11387                     struct msm_vidc_frame_qp_payload *qp_payload;
11388                     qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
11389                     if (client_extradata & OMX_QP_EXTRADATA) {
11390                         if (p_client_extra) {
11391                             append_qp_extradata(p_client_extra, qp_payload);
11392                             p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11393                         }
11394                     }
11395                     break;
11396                 case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
11397                     struct msm_vidc_frame_bits_info_payload *bits_info_payload;
11398                     bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
11399                     if (client_extradata & OMX_BITSINFO_EXTRADATA) {
11400                         if (p_client_extra) {
11401                             append_bitsinfo_extradata(p_client_extra, bits_info_payload);
11402                             p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11403                         }
11404                     }
11405                     break;
11406                 case MSM_VIDC_EXTRADATA_UBWC_CR_STAT_INFO:
11407                     DEBUG_PRINT_LOW("MSM_VIDC_EXTRADATA_UBWC_CR_STAT_INFO not used. Ignoring.");
11408                     break;
11409                 case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
11410                     if(output_capability == V4L2_PIX_FMT_HEVC) {
11411                         struct msm_vidc_stream_userdata_payload* userdata_payload = (struct msm_vidc_stream_userdata_payload*)data->data;
11412                         // Remove the size of type from msm_vidc_stream_userdata_payload
11413                         uint32_t payload_len = data->nDataSize - sizeof(userdata_payload->type);
11414                         if ((data->nDataSize < sizeof(userdata_payload->type)) ||
11415                             (payload_len > HDR_DYNAMIC_META_DATA_SZ)) {
11416                             DEBUG_PRINT_ERROR("Invalid User extradata size %u for HDR10+", data->nDataSize);
11417                         } else {
11418                             color_mdata.dynamicMetaDataValid = true;
11419                             color_mdata.dynamicMetaDataLen = payload_len;
11420                             memcpy(color_mdata.dynamicMetaDataPayload, userdata_payload->data, payload_len);
11421                             DEBUG_PRINT_HIGH("Copied %u bytes of HDR10+ extradata", payload_len);
11422                         }
11423                     }
11424                     if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
11425                         if (p_client_extra) {
11426                             append_user_extradata(p_client_extra, data);
11427                             p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11428                         }
11429                     }
11430                     break;
11431                 case MSM_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI:
11432 
11433                     internal_hdr_info_changed_flag |= handle_content_light_level_info((void*)data->data);
11434                     break;
11435                 case MSM_VIDC_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI:
11436                     internal_hdr_info_changed_flag |= handle_mastering_display_color_info((void*)data->data);
11437                     break;
11438                 default:
11439                     DEBUG_PRINT_LOW("Unrecognized extradata");
11440                     goto unrecognized_extradata;
11441             }
11442             consumed_len += data->nSize;
11443             data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
11444         }
11445         if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
11446             p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11447             if (p_client_extra) {
11448                 append_frame_info_extradata(p_client_extra,
11449                         num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
11450                         time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
11451                             p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
11452                 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11453             }
11454         }
11455         if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
11456             if (p_client_extra) {
11457                 append_frame_dimension_extradata(p_client_extra);
11458                 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
11459             }
11460         }
11461 
11462         if(internal_hdr_info_changed_flag) {
11463             print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "Internal");
11464             print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "Client");
11465             if(!reconfig_event_sent) {
11466                 DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to HDR Info Change");
11467                 post_event(OMX_CORE_OUTPUT_PORT_INDEX,
11468                            OMX_QTIIndexConfigDescribeHDRColorInfo,
11469                            OMX_COMPONENT_GENERATE_PORT_RECONFIG);
11470                 reconfig_event_sent = true;
11471             }
11472         }
11473 
11474         if (m_enable_android_native_buffers) {
11475                 ColorAspects final_color_aspects;
11476                 HDRStaticInfo final_hdr_info;
11477                 memset(&final_color_aspects, 0, sizeof(final_color_aspects));
11478                 memset(&final_hdr_info, 0, sizeof(final_hdr_info));
11479                 get_preferred_color_aspects(final_color_aspects);
11480 
11481                 /* For VP8, always set the metadata on gralloc handle to 601-LR */
11482                 if (output_capability == V4L2_PIX_FMT_VP8) {
11483                     final_color_aspects.mPrimaries = ColorAspects::PrimariesBT601_6_525;
11484                     final_color_aspects.mRange = ColorAspects::RangeLimited;
11485                     final_color_aspects.mTransfer = ColorAspects::TransferSMPTE170M;
11486                     final_color_aspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
11487                 }
11488                 get_preferred_hdr_info(final_hdr_info);
11489                 convert_color_aspects_to_metadata(final_color_aspects, color_mdata);
11490                 convert_hdr_info_to_metadata(final_hdr_info, color_mdata);
11491                 print_debug_hdr_color_info_mdata(&color_mdata);
11492                 print_debug_hdr10plus_metadata(color_mdata);
11493                 set_colormetadata_in_handle(&color_mdata, buf_index);
11494         }
11495 
11496     }
11497 unrecognized_extradata:
11498     if (client_extradata) {
11499         p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
11500         if (p_client_extra) {
11501             append_terminator_extradata(p_client_extra);
11502         }
11503     }
11504     return reconfig_event_sent;
11505 }
11506 
enable_extradata(OMX_U64 requested_extradata,bool is_internal,bool enable)11507 OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U64 requested_extradata,
11508         bool is_internal, bool enable)
11509 {
11510     OMX_ERRORTYPE ret = OMX_ErrorNone;
11511     struct v4l2_control control;
11512     if (m_state != OMX_StateLoaded) {
11513         DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
11514         return OMX_ErrorIncorrectStateOperation;
11515     }
11516     DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
11517             (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
11518 
11519     if (!is_internal) {
11520         if (enable)
11521             client_extradata |= requested_extradata;
11522         else
11523             client_extradata = client_extradata & ~requested_extradata;
11524     }
11525 
11526     if (enable) {
11527         if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
11528             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11529             control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
11530             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11531                 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
11532                         " Quality of interlaced clips might be impacted.");
11533             }
11534         }
11535         if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
11536             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11537             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
11538             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11539                 DEBUG_PRINT_HIGH("Failed to set framerate extradata");
11540             }
11541             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11542             control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
11543             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11544                 DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
11545             }
11546             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11547             control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
11548             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11549                 DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
11550             }
11551             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11552             control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
11553             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11554                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11555             }
11556             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11557             control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
11558             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11559                 DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11560             }
11561             if (output_capability == V4L2_PIX_FMT_MPEG2) {
11562                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11563                 control.value =  V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
11564                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11565                     DEBUG_PRINT_HIGH("Failed to set panscan extradata");
11566                 }
11567             }
11568         }
11569         if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
11570             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11571             control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
11572             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11573                 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
11574             }
11575         }
11576         if (!secure_mode && (requested_extradata & OMX_FRAMEPACK_EXTRADATA)) {
11577             if (output_capability == V4L2_PIX_FMT_H264) {
11578                 DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
11579                 control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11580                 control.value =  V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
11581                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11582                     DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
11583                 }
11584             } else {
11585                 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
11586             }
11587         }
11588         if (requested_extradata & OMX_QP_EXTRADATA) {
11589             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11590             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
11591             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11592                 DEBUG_PRINT_HIGH("Failed to set QP extradata");
11593             }
11594         }
11595         if (!secure_mode && (requested_extradata & OMX_EXTNUSER_EXTRADATA)) {
11596             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11597             control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
11598             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11599                 DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
11600             }
11601         }
11602 #if NEED_TO_REVISIT
11603         if (requested_extradata & OMX_QP_EXTRADATA) {
11604             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11605             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
11606             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11607                 DEBUG_PRINT_HIGH("Failed to set QP extradata");
11608             }
11609         }
11610 #endif
11611         if (requested_extradata & OMX_OUTPUTCROP_EXTRADATA) {
11612             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11613             control.value = V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP;
11614             DEBUG_PRINT_LOW("Enable output crop extra data");
11615             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11616                 DEBUG_PRINT_HIGH("Failed to set output crop extradata");
11617             }
11618         }
11619         if (requested_extradata & OMX_UBWC_CR_STATS_INFO_EXTRADATA) {
11620             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11621             control.value = V4L2_MPEG_VIDC_EXTRADATA_UBWC_CR_STATS_INFO;
11622             DEBUG_PRINT_LOW("Enable UBWC stats extra data");
11623             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11624                 DEBUG_PRINT_HIGH("Failed to set output crop extradata");
11625             }
11626         }
11627         if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) {
11628             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11629             switch(output_capability) {
11630                 case V4L2_PIX_FMT_H264:
11631                 case V4L2_PIX_FMT_HEVC:
11632                     control.value =  V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY;
11633                     break;
11634                 case V4L2_PIX_FMT_VP8:
11635                 case V4L2_PIX_FMT_VP9:
11636                     control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE;
11637                     break;
11638                 case V4L2_PIX_FMT_MPEG2:
11639                     control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
11640                     break;
11641                 default:
11642                     DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind);
11643                     return ret;
11644             }
11645 
11646             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11647                 DEBUG_PRINT_HIGH("Failed to set Display info extradata");
11648             }
11649         }
11650         if (requested_extradata & OMX_HDR_COLOR_INFO_EXTRADATA) {
11651             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
11652             if (output_capability == V4L2_PIX_FMT_HEVC) {
11653                 control.value = V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI;
11654                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11655                     DEBUG_PRINT_HIGH("Failed to set Display Colour SEI extradata");
11656                 }
11657                 control.value = V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI;
11658                 if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
11659                     DEBUG_PRINT_HIGH("Failed to set Content Light Level SEI extradata");
11660                 }
11661             } else {
11662                 DEBUG_PRINT_HIGH("OMX_HDR_COLOR_INFO_EXTRADATA supported for HEVC only");
11663             }
11664         }
11665     }
11666     ret = get_buffer_req(&drv_ctx.op_buf);
11667     return ret;
11668 }
11669 
count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE * extra)11670 OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11671 {
11672     OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
11673     OMX_U8 *data_ptr = extra->data, data = 0;
11674     while (byte_count < extra->nDataSize) {
11675         data = *data_ptr;
11676         while (data) {
11677             num_MB += (data&0x01);
11678             data >>= 1;
11679         }
11680         data_ptr++;
11681         byte_count++;
11682     }
11683     num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
11684             (drv_ctx.video_resolution.frame_height + 15)) >> 8;
11685     return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
11686 }
11687 
print_debug_extradata(OMX_OTHER_EXTRADATATYPE * extra)11688 void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11689 {
11690     if (!m_debug_extradata || !extra)
11691         return;
11692 
11693 
11694     DEBUG_PRINT_HIGH(
11695             "============== Extra Data ==============\n"
11696             "           Size: %u\n"
11697             "        Version: %u\n"
11698             "      PortIndex: %u\n"
11699             "           Type: %x\n"
11700             "       DataSize: %u",
11701             (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
11702             (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
11703 
11704     if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
11705         OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
11706         DEBUG_PRINT_HIGH(
11707                 "------ Interlace Format ------\n"
11708                 "                Size: %u\n"
11709                 "             Version: %u\n"
11710                 "           PortIndex: %u\n"
11711                 " Is Interlace Format: %d\n"
11712                 "   Interlace Formats: %u\n"
11713                 "=========== End of Interlace ===========",
11714                 (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
11715                 intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
11716     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
11717         OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
11718 
11719         DEBUG_PRINT_HIGH(
11720                 "-------- Frame Format --------\n"
11721                 "             Picture Type: %d\n"
11722                 "           Interlace Type: %d\n"
11723                 " Pan Scan Total Frame Num: %u\n"
11724                 "   Concealed Macro Blocks: %u\n"
11725                 "        Recovery SEI Flag: %u\n"
11726                 "               frame rate: %u\n"
11727                 "               Time Stamp: %llu\n"
11728                 "           Aspect Ratio X: %u\n"
11729                 "           Aspect Ratio Y: %u",
11730                 fminfo->ePicType,
11731                 fminfo->interlaceType,
11732                 (unsigned int)fminfo->panScan.numWindows,
11733                 (unsigned int)fminfo->nConcealedMacroblocks,
11734                 (unsigned int)fminfo->nRecoverySeiFlag,
11735                 (unsigned int)fminfo->nFrameRate,
11736                 fminfo->nTimeStamp,
11737                 (unsigned int)fminfo->aspectRatio.aspectRatioX,
11738                 (unsigned int)fminfo->aspectRatio.aspectRatioY);
11739 
11740         for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
11741             DEBUG_PRINT_HIGH(
11742                     "------------------------------"
11743                     "     Pan Scan Frame Num: %u\n"
11744                     "            Rectangle x: %d\n"
11745                     "            Rectangle y: %d\n"
11746                     "           Rectangle dx: %d\n"
11747                     "           Rectangle dy: %d",
11748                     (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
11749                     (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
11750         }
11751 
11752         DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
11753     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
11754         OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
11755         DEBUG_PRINT_HIGH(
11756                 "------------------ Framepack Format ----------\n"
11757                 "                           id: %u \n"
11758                 "                  cancel_flag: %u \n"
11759                 "                         type: %u \n"
11760                 " quincunx_sampling_flagFormat: %u \n"
11761                 "  content_interpretation_type: %u \n"
11762                 "        spatial_flipping_flag: %u \n"
11763                 "          frame0_flipped_flag: %u \n"
11764                 "             field_views_flag: %u \n"
11765                 " current_frame_is_frame0_flag: %u \n"
11766                 "   frame0_self_contained_flag: %u \n"
11767                 "   frame1_self_contained_flag: %u \n"
11768                 "       frame0_grid_position_x: %u \n"
11769                 "       frame0_grid_position_y: %u \n"
11770                 "       frame1_grid_position_x: %u \n"
11771                 "       frame1_grid_position_y: %u \n"
11772                 "                reserved_byte: %u \n"
11773                 "            repetition_period: %u \n"
11774                 "               extension_flag: %u \n"
11775                 "================== End of Framepack ===========",
11776                 (unsigned int)framepack->id,
11777                 (unsigned int)framepack->cancel_flag,
11778                 (unsigned int)framepack->type,
11779                 (unsigned int)framepack->quincunx_sampling_flag,
11780                 (unsigned int)framepack->content_interpretation_type,
11781                 (unsigned int)framepack->spatial_flipping_flag,
11782                 (unsigned int)framepack->frame0_flipped_flag,
11783                 (unsigned int)framepack->field_views_flag,
11784                 (unsigned int)framepack->current_frame_is_frame0_flag,
11785                 (unsigned int)framepack->frame0_self_contained_flag,
11786                 (unsigned int)framepack->frame1_self_contained_flag,
11787                 (unsigned int)framepack->frame0_grid_position_x,
11788                 (unsigned int)framepack->frame0_grid_position_y,
11789                 (unsigned int)framepack->frame1_grid_position_x,
11790                 (unsigned int)framepack->frame1_grid_position_y,
11791                 (unsigned int)framepack->reserved_byte,
11792                 (unsigned int)framepack->repetition_period,
11793                 (unsigned int)framepack->extension_flag);
11794     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
11795         OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
11796         DEBUG_PRINT_HIGH(
11797                 "---- QP (Frame quantization parameter) ----\n"
11798                 "              Frame QP: %u \n"
11799                 "       Sum of Frame QP: %u \n"
11800                 "     Sum of Skipped QP: %u \n"
11801                 "    Num Skipped Blocks: %u \n"
11802                 "          Total Blocks: %u \n"
11803                 "================ End of QP ================\n",
11804                 (unsigned int)qp->nQP,(unsigned int)qp->nQPSum,
11805                 (unsigned int)qp->nSkipQPSum,(unsigned int)qp->nSkipNumBlocks,
11806                 (unsigned int)qp->nTotalNumBlocks);
11807     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
11808         OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
11809         DEBUG_PRINT_HIGH(
11810                 "--------- Input bits information --------\n"
11811                 "    Header bits: %u \n"
11812                 "     Frame bits: %u \n"
11813                 "===== End of Input bits information =====\n",
11814                 (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
11815     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
11816         OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
11817         OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
11818         OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
11819         OMX_U32 i = 0;
11820         DEBUG_PRINT_HIGH(
11821                 "--------------  Userdata  -------------\n"
11822                 "    Stream userdata type: %u\n"
11823                 "          userdata size: %u\n"
11824                 "    STREAM_USERDATA:",
11825                 (unsigned int)userdata->type, (unsigned int)userdata_size);
11826                 for (i = 0; i < userdata_size; i+=4) {
11827                     DEBUG_PRINT_HIGH("        %x %x %x %x",
11828                         data_ptr[i], data_ptr[i+1],
11829                         data_ptr[i+2], data_ptr[i+3]);
11830                 }
11831         DEBUG_PRINT_HIGH(
11832                 "=========== End of Userdata ===========");
11833     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) {
11834         OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
11835         DEBUG_PRINT_HIGH(
11836                 "--------------  VQZip  -------------\n"
11837                 "    Size: %u\n",
11838                 (unsigned int)vq->nSize);
11839         DEBUG_PRINT_HIGH( "=========== End of VQZip ===========");
11840     } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataOutputCropInfo) {
11841         OMX_QCOM_OUTPUT_CROP *outputcrop_info = (OMX_QCOM_OUTPUT_CROP*)(void *)extra->data;
11842         DEBUG_PRINT_HIGH(
11843             "------------------ output crop ----------\n"
11844             "                         left: %u \n"
11845             "                          top: %u \n"
11846             "                display_width: %u \n"
11847             "               display_height: %u \n"
11848             "                        width: %u \n"
11849             "                       height: %u \n"
11850             "                    frame_num: %u \n"
11851             "                  bit_depth_y: %u \n"
11852             "                  bit_depth_c: %u \n",
11853             (unsigned int)outputcrop_info->left,
11854             (unsigned int)outputcrop_info->top,
11855             (unsigned int)outputcrop_info->display_width,
11856             (unsigned int)outputcrop_info->display_height,
11857             (unsigned int)outputcrop_info->width,
11858             (unsigned int)outputcrop_info->height,
11859             (unsigned int)outputcrop_info->frame_num,
11860             (unsigned int)outputcrop_info->bit_depth_y,
11861             (unsigned int)outputcrop_info->bit_depth_c);
11862         for(unsigned int m=0; m<outputcrop_info->misr_info[0].misr_set; m++) {
11863             DEBUG_PRINT_HIGH(
11864             "     top field: misr_dpb_luma(%d): %u \n"
11865             "   top field: misr_dpb_chroma(%d): %u \n"
11866             "     top field: misr_opb_luma(%d): %u \n"
11867             "   top field: misr_opb_chroma(%d): %u \n",
11868             m, (unsigned int)outputcrop_info->misr_info[0].misr_dpb_luma[m],
11869             m, (unsigned int)outputcrop_info->misr_info[0].misr_dpb_chroma[m],
11870             m, (unsigned int)outputcrop_info->misr_info[0].misr_opb_luma[m],
11871             m, (unsigned int)outputcrop_info->misr_info[0].misr_opb_chroma[m]);
11872         }
11873         for(unsigned int m=0; m<outputcrop_info->misr_info[1].misr_set; m++) {
11874             DEBUG_PRINT_HIGH(
11875             "  bottom field: misr_dpb_luma(%d): %u \n"
11876             "bottom field: misr_dpb_chroma(%d): %u \n"
11877             "  bottom field: misr_opb_luma(%d): %u \n"
11878             "bottom field: misr_opb_chroma(%d): %u \n",
11879             m, (unsigned int)outputcrop_info->misr_info[1].misr_dpb_luma[m],
11880             m, (unsigned int)outputcrop_info->misr_info[1].misr_dpb_chroma[m],
11881             m, (unsigned int)outputcrop_info->misr_info[1].misr_opb_luma[m],
11882             m, (unsigned int)outputcrop_info->misr_info[1].misr_opb_chroma[m]);
11883         }
11884         DEBUG_PRINT_HIGH("================== End of output crop ===========");
11885     } else if (extra->eType == OMX_ExtraDataNone) {
11886         DEBUG_PRINT_HIGH("========== End of Terminator ===========");
11887     } else {
11888         DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
11889     }
11890 }
11891 
append_interlace_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_U32 interlaced_format_type)11892 void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11893         OMX_U32 interlaced_format_type)
11894 {
11895     OMX_STREAMINTERLACEFORMAT *interlace_format;
11896 
11897     if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
11898         return;
11899     }
11900     if (!extra) {
11901        DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input");
11902        return;
11903     }
11904     extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
11905     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11906     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11907     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
11908     extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
11909     interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
11910     interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
11911     interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
11912     interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11913 
11914     if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) {
11915         interlace_format->bInterlaceFormat = OMX_FALSE;
11916         interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
11917         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11918     } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) {
11919         interlace_format->bInterlaceFormat = OMX_TRUE;
11920         interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
11921         drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
11922     } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) {
11923         interlace_format->bInterlaceFormat = OMX_TRUE;
11924         interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
11925         drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
11926     } else if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_TOPFIELDFIRST) {
11927         interlace_format->bInterlaceFormat = OMX_TRUE;
11928         interlace_format->nInterlaceFormats = OMX_InterlaceFrameTopFieldFirst;
11929         drv_ctx.interlace = VDEC_InterlaceFrameTopFieldFirst;
11930     } else if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_BOTTOMFIELDFIRST) {
11931         interlace_format->bInterlaceFormat = OMX_TRUE;
11932         interlace_format->nInterlaceFormats = OMX_InterlaceFrameBottomFieldFirst;
11933         drv_ctx.interlace = VDEC_InterlaceFrameBottomFieldFirst;
11934     } else {
11935         //default case - set to progressive
11936         interlace_format->bInterlaceFormat = OMX_FALSE;
11937         interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
11938         drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
11939     }
11940     print_debug_extradata(extra);
11941 }
11942 
append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE * extra)11943 void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
11944 {
11945     OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
11946     if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
11947         return;
11948     }
11949     extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
11950     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11951     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11952     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
11953     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
11954     frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
11955     frame_dimension->nDecWidth = rectangle.nLeft;
11956     frame_dimension->nDecHeight = rectangle.nTop;
11957     frame_dimension->nActualWidth = rectangle.nWidth;
11958     frame_dimension->nActualHeight = rectangle.nHeight;
11959 }
11960 
fill_aspect_ratio_info(struct vdec_aspectratioinfo * aspect_ratio_info,OMX_QCOM_EXTRADATA_FRAMEINFO * frame_info)11961 void omx_vdec::fill_aspect_ratio_info(
11962         struct vdec_aspectratioinfo *aspect_ratio_info,
11963         OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
11964 {
11965     m_extradata = frame_info;
11966     m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
11967     m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
11968     DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
11969             (unsigned int)m_extradata->aspectRatio.aspectRatioY);
11970 }
11971 
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)11972 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
11973         OMX_U32 num_conceal_mb, OMX_U32 recovery_sei_flag, OMX_U32 picture_type, OMX_U32 frame_rate,
11974         OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
11975         struct vdec_aspectratioinfo *aspect_ratio_info)
11976 {
11977     OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
11978     struct msm_vidc_panscan_window *panscan_window;
11979     if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
11980         return;
11981     }
11982     extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
11983     extra->nVersion.nVersion = OMX_SPEC_VERSION;
11984     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
11985     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
11986     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
11987     frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
11988     switch (picture_type) {
11989         case PICTURE_TYPE_I:
11990             frame_info->ePicType = OMX_VIDEO_PictureTypeI;
11991             break;
11992         case PICTURE_TYPE_P:
11993             frame_info->ePicType = OMX_VIDEO_PictureTypeP;
11994             break;
11995         case PICTURE_TYPE_B:
11996             frame_info->ePicType = OMX_VIDEO_PictureTypeB;
11997             break;
11998         default:
11999             frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
12000     }
12001     if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
12002         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
12003     else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
12004         frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
12005     else if (drv_ctx.interlace == VDEC_InterlaceFrameTopFieldFirst)
12006         frame_info->interlaceType = OMX_QCOM_InterlaceFrameTopFieldFirst;
12007     else if (drv_ctx.interlace == VDEC_InterlaceFrameBottomFieldFirst)
12008         frame_info->interlaceType = OMX_QCOM_InterlaceFrameBottomFieldFirst;
12009     else
12010         frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
12011     memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
12012     frame_info->nConcealedMacroblocks = num_conceal_mb;
12013     frame_info->nRecoverySeiFlag = recovery_sei_flag;
12014     frame_info->nFrameRate = frame_rate;
12015     frame_info->nTimeStamp = time_stamp;
12016     frame_info->panScan.numWindows = 0;
12017     if (output_capability == V4L2_PIX_FMT_MPEG2) {
12018         if (m_disp_hor_size && m_disp_vert_size) {
12019             frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
12020             frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
12021         } else {
12022             frame_info->displayAspectRatio.displayHorizontalSize = 0;
12023             frame_info->displayAspectRatio.displayVerticalSize = 0;
12024         }
12025     }
12026 
12027     if (panscan_payload) {
12028         frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
12029         panscan_window = &panscan_payload->wnd[0];
12030         for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
12031             frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
12032             frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
12033             frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
12034             frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
12035             panscan_window++;
12036         }
12037     }
12038     fill_aspect_ratio_info(aspect_ratio_info, frame_info);
12039     print_debug_extradata(extra);
12040 }
12041 
append_portdef_extradata(OMX_OTHER_EXTRADATATYPE * extra)12042 void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12043 {
12044     OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
12045     extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
12046     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12047     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12048     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
12049     extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
12050     portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
12051     *portDefn = m_port_def;
12052     DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
12053             "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
12054             (unsigned int)portDefn->format.video.nFrameWidth,
12055             (unsigned int)portDefn->format.video.nStride,
12056             (unsigned int)portDefn->format.video.nSliceHeight);
12057 }
12058 
append_outputcrop_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_output_crop_payload * output_crop_payload)12059 void omx_vdec::append_outputcrop_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12060         struct msm_vidc_output_crop_payload *output_crop_payload) {
12061     extra->nSize = OMX_OUTPUTCROP_EXTRADATA_SIZE;
12062     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12063     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12064     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataOutputCropInfo;
12065     extra->nDataSize = sizeof(OMX_QCOM_OUTPUT_CROP);
12066     memcpy(extra->data, output_crop_payload, extra->nDataSize);
12067 
12068     print_debug_extradata(extra);
12069 }
12070 
append_framepack_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_s3d_frame_packing_payload * s3d_frame_packing_payload)12071 void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12072         struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
12073 {
12074     OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
12075     if (18 * sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
12076         DEBUG_PRINT_ERROR("frame packing size mismatch");
12077         return;
12078     }
12079     extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
12080     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12081     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12082     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
12083     extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
12084     framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
12085     framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
12086     framepack->nVersion.nVersion = OMX_SPEC_VERSION;
12087     framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12088     memcpy(&framepack->id, s3d_frame_packing_payload,
12089         sizeof(struct msm_vidc_s3d_frame_packing_payload));
12090     memcpy(&m_frame_pack_arrangement, framepack,
12091         sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
12092     print_debug_extradata(extra);
12093 }
12094 
append_qp_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_qp_payload * qp_payload)12095 void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12096             struct msm_vidc_frame_qp_payload *qp_payload)
12097 {
12098     OMX_QCOM_EXTRADATA_QP * qp = NULL;
12099     if (!qp_payload) {
12100         DEBUG_PRINT_ERROR("QP payload is NULL");
12101         return;
12102     }
12103     extra->nSize = OMX_QP_EXTRADATA_SIZE;
12104     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12105     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12106     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
12107     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
12108     qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
12109     qp->nQP = qp_payload->frame_qp;
12110     qp->nQPSum = qp_payload->qp_sum;
12111     qp->nSkipQPSum = qp_payload->skip_qp_sum;
12112     qp->nSkipNumBlocks = qp_payload->skip_num_blocks;
12113     qp->nTotalNumBlocks = qp_payload->total_num_blocks;
12114     print_debug_extradata(extra);
12115 }
12116 
append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE * extra,struct msm_vidc_frame_bits_info_payload * bits_payload)12117 void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12118             struct msm_vidc_frame_bits_info_payload *bits_payload)
12119 {
12120     OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
12121     if (!bits_payload) {
12122         DEBUG_PRINT_ERROR("bits info payload is NULL");
12123         return;
12124     }
12125     extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
12126     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12127     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12128     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
12129     extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
12130     bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
12131     bits->frame_bits = bits_payload->frame_bits;
12132     bits->header_bits = bits_payload->header_bits;
12133     print_debug_extradata(extra);
12134 }
12135 
append_user_extradata(OMX_OTHER_EXTRADATATYPE * extra,OMX_OTHER_EXTRADATATYPE * p_user)12136 void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
12137             OMX_OTHER_EXTRADATATYPE *p_user)
12138 {
12139     int userdata_size = 0;
12140     struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
12141     userdata_payload =
12142         (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
12143     userdata_size = p_user->nDataSize;
12144     extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
12145     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12146     extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
12147     extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
12148     extra->nDataSize = userdata_size;
12149     if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize))
12150         memcpy(extra->data, p_user->data, extra->nDataSize);
12151     print_debug_extradata(extra);
12152 }
12153 
append_terminator_extradata(OMX_OTHER_EXTRADATATYPE * extra)12154 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
12155 {
12156     if (!client_extradata) {
12157         return;
12158     }
12159     extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
12160     extra->nVersion.nVersion = OMX_SPEC_VERSION;
12161     extra->eType = OMX_ExtraDataNone;
12162     extra->nDataSize = 0;
12163     extra->data[0] = 0;
12164 
12165     print_debug_extradata(extra);
12166 }
12167 
allocate_desc_buffer(OMX_U32 index)12168 OMX_ERRORTYPE  omx_vdec::allocate_desc_buffer(OMX_U32 index)
12169 {
12170     OMX_ERRORTYPE eRet = OMX_ErrorNone;
12171     if (index >= drv_ctx.ip_buf.actualcount) {
12172         DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
12173         return OMX_ErrorInsufficientResources;
12174     }
12175     if (m_desc_buffer_ptr == NULL) {
12176         m_desc_buffer_ptr = (desc_buffer_hdr*) \
12177                     calloc( (sizeof(desc_buffer_hdr)),
12178                             drv_ctx.ip_buf.actualcount);
12179         if (m_desc_buffer_ptr == NULL) {
12180             DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
12181             return OMX_ErrorInsufficientResources;
12182         }
12183     }
12184 
12185     m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
12186     if (m_desc_buffer_ptr[index].buf_addr == NULL) {
12187         DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
12188         return OMX_ErrorInsufficientResources;
12189     }
12190 
12191     return eRet;
12192 }
12193 
insert_demux_addr_offset(OMX_U32 address_offset)12194 void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
12195 {
12196     DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
12197     if (m_demux_entries < 8192) {
12198         m_demux_offsets[m_demux_entries++] = address_offset;
12199     }
12200     return;
12201 }
12202 
extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE * buf_hdr)12203 void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
12204 {
12205     OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
12206     OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
12207     OMX_U32 index = 0;
12208 
12209     m_demux_entries = 0;
12210 
12211     while (index < bytes_to_parse) {
12212         if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
12213                     (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
12214                 ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
12215                  (buf[index+2] == 0x01)) ) {
12216             //Found start code, insert address offset
12217             insert_demux_addr_offset(index);
12218             if (buf[index+2] == 0x01) // 3 byte start code
12219                 index += 3;
12220             else                      //4 byte start code
12221                 index += 4;
12222         } else
12223             index++;
12224     }
12225     DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
12226     return;
12227 }
12228 
handle_demux_data(OMX_BUFFERHEADERTYPE * p_buf_hdr)12229 OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
12230 {
12231     //fix this, handle 3 byte start code, vc1 terminator entry
12232     OMX_U8 *p_demux_data = NULL;
12233     OMX_U32 desc_data = 0;
12234     OMX_U32 start_addr = 0;
12235     OMX_U32 nal_size = 0;
12236     OMX_U32 suffix_byte = 0;
12237     OMX_U32 demux_index = 0;
12238     OMX_U32 buffer_index = 0;
12239 
12240     if (m_desc_buffer_ptr == NULL) {
12241         DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
12242         return OMX_ErrorBadParameter;
12243     }
12244 
12245     buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
12246     if (buffer_index > drv_ctx.ip_buf.actualcount) {
12247         DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
12248         return OMX_ErrorBadParameter;
12249     }
12250 
12251     p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
12252 
12253     if ( ((OMX_U8*)p_demux_data == NULL) ||
12254             ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
12255         DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
12256         return OMX_ErrorBadParameter;
12257     } else {
12258         for (; demux_index < m_demux_entries; demux_index++) {
12259             desc_data = 0;
12260             start_addr = m_demux_offsets[demux_index];
12261             if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
12262                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
12263             } else {
12264                 suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
12265             }
12266             if (demux_index < (m_demux_entries - 1)) {
12267                 nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
12268             } else {
12269                 nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
12270             }
12271             DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
12272                     (unsigned int)start_addr,
12273                     (unsigned int)suffix_byte,
12274                     (unsigned int)nal_size,
12275                     (unsigned int)demux_index);
12276             desc_data = (start_addr >> 3) << 1;
12277             desc_data |= (start_addr & 7) << 21;
12278             desc_data |= suffix_byte << 24;
12279 
12280             memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
12281             memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
12282             memset(p_demux_data + 8, 0, sizeof(OMX_U32));
12283             memset(p_demux_data + 12, 0, sizeof(OMX_U32));
12284 
12285             p_demux_data += 16;
12286         }
12287         //Add zero word to indicate end of descriptors
12288         memset(p_demux_data, 0, sizeof(OMX_U32));
12289 
12290         m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
12291         DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
12292     }
12293     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
12294     m_demux_entries = 0;
12295     DEBUG_PRINT_LOW("Demux table complete!");
12296     return OMX_ErrorNone;
12297 }
12298 
enable_color_conversion(bool enable)12299 void omx_vdec::allocate_color_convert_buf::enable_color_conversion(bool enable) {
12300     if (!omx) {
12301         DEBUG_PRINT_HIGH("Invalid omx_vdec");
12302         return;
12303     }
12304 
12305     if (!omx->in_reconfig)
12306         enabled = enable;
12307 
12308     omx->c2d_enable_pending = enable;
12309 }
12310 
allocate_color_convert_buf()12311 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
12312 {
12313     enabled = false;
12314     client_buffers_disabled = false;
12315     omx = NULL;
12316     init_members();
12317     ColorFormat = OMX_COLOR_FormatMax;
12318     dest_format = YCbCr420P;
12319     m_c2d_width = 0;
12320     m_c2d_height = 0;
12321 
12322     mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12][-1] =
12323                         QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
12324     mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12][VDEC_CODECTYPE_MVC] =
12325                         QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
12326     mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12_UBWC][-1] =
12327                         QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
12328     mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_NV12_TP10_UBWC][-1] =
12329                      QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed;
12330     mMapOutput2DriverColorFormat[VDEC_YUV_FORMAT_P010_VENUS][-1] =
12331                      QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus;
12332 
12333     mMapOutput2Convert.insert( {
12334             {VDEC_YUV_FORMAT_NV12, NV12_128m},
12335             {VDEC_YUV_FORMAT_NV12_UBWC, NV12_UBWC},
12336             {VDEC_YUV_FORMAT_NV12_TP10_UBWC, TP10_UBWC},
12337             {VDEC_YUV_FORMAT_P010_VENUS, YCbCr420_VENUS_P010},
12338         });
12339 }
12340 
set_vdec_client(void * client)12341 void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
12342 {
12343     omx = reinterpret_cast<omx_vdec*>(client);
12344 }
12345 
init_members()12346 void omx_vdec::allocate_color_convert_buf::init_members()
12347 {
12348     allocated_count = 0;
12349     buffer_size_req = 0;
12350     buffer_alignment_req = 0;
12351     m_c2d_width = m_c2d_height = 0;
12352     memset(m_platform_list_client,0,sizeof(m_platform_list_client));
12353     memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
12354     memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
12355     memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
12356 #ifdef USE_ION
12357     memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
12358 #endif
12359     for (int i = 0; i < MAX_COUNT; i++)
12360         pmem_fd[i] = -1;
12361 }
12362 
update_buffer_req()12363 bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
12364 {
12365     bool status = true;
12366     unsigned int src_size = 0, destination_size = 0;
12367     unsigned int height, width;
12368     struct v4l2_format fmt;
12369     OMX_COLOR_FORMATTYPE drv_color_format;
12370 
12371     if (!omx) {
12372         DEBUG_PRINT_ERROR("Invalid client in color convert");
12373         return false;
12374     }
12375     if (!enabled) {
12376         DEBUG_PRINT_HIGH("No color conversion required");
12377         return true;
12378     }
12379     pthread_mutex_lock(&omx->c_lock);
12380 
12381     ColorSubMapping::const_iterator
12382         found =  mMapOutput2Convert.find(omx->drv_ctx.output_format);
12383     if (found == mMapOutput2Convert.end()) {
12384         DEBUG_PRINT_HIGH("%s: Could not find the color conversion "
12385                          "mapping for %#X. Setting to default NV12",
12386                          __func__, omx->drv_ctx.output_format);
12387         src_format = NV12_128m;
12388     } else {
12389         src_format = (ColorConvertFormat) found->second;;
12390     }
12391 
12392     memset(&fmt, 0x0, sizeof(struct v4l2_format));
12393     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
12394     fmt.fmt.pix_mp.pixelformat = omx->capture_capability;
12395     ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
12396     width = fmt.fmt.pix_mp.width;
12397     height =  fmt.fmt.pix_mp.height;
12398 
12399     bool resolution_upgrade = (height > m_c2d_height ||
12400             width > m_c2d_width);
12401     bool is_interlaced = omx->m_progressive != MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
12402     if (resolution_upgrade) {
12403         // resolution upgraded ? ensure we are yet to allocate;
12404         // failing which, c2d buffers will never be reallocated and bad things will happen
12405         if (allocated_count > 0) {
12406             DEBUG_PRINT_ERROR("Cannot change C2D buffer requirements with %d active allocations",
12407                     allocated_count);
12408             status = false;
12409         }
12410     }
12411 
12412     if (status != false) {
12413         if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
12414             (ColorFormat != OMX_COLOR_FormatYUV420Planar &&
12415              ColorFormat != OMX_COLOR_FormatYUV420SemiPlanar &&
12416              ColorFormat != (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m)) {
12417             DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
12418             status = false;
12419         } else {
12420             ColorSubMapping::const_iterator
12421                 found =  mMapOutput2Convert.find(
12422                                                  omx->drv_ctx.output_format);
12423             if (found == mMapOutput2Convert.end()) {
12424                 src_format = NV12_128m;
12425             } else {
12426                 src_format = (ColorConvertFormat) found->second;;
12427             }
12428 
12429             DEBUG_PRINT_INFO("C2D: Set Resolution, Interlace(%s) Conversion(%#X -> %#X)"
12430                              " src(%dX%d) dest(%dX%d)",
12431                              (omx->m_progressive != MSM_VIDC_PIC_STRUCT_PROGRESSIVE) ? "true": "false",
12432                              src_format, dest_format, width,
12433                              omx->m_progressive !=
12434                                   MSM_VIDC_PIC_STRUCT_PROGRESSIVE?(height+1)/2 : height,
12435                              width, height);
12436             status = c2dcc.setResolution(width,
12437                                          omx->m_progressive !=
12438                                          MSM_VIDC_PIC_STRUCT_PROGRESSIVE?
12439                                          (height+1)/2 : height,
12440                                          width, height,
12441                                          src_format, dest_format,
12442                                          0,0);
12443             if (status) {
12444                 src_size = c2dcc.getBuffSize(C2D_INPUT);
12445                 destination_size = c2dcc.getBuffSize(C2D_OUTPUT);
12446 
12447                 if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
12448                     !destination_size) {
12449                     DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
12450                                       "driver size %u destination size %d",
12451                                       src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
12452                                       destination_size);
12453                     buffer_size_req = 0;
12454                     // TODO: make this fatal. Driver is not supposed to quote size
12455                     //  smaller than what C2D needs !!
12456                 } else {
12457                     buffer_size_req = destination_size;
12458                     m_c2d_height = height;
12459                     m_c2d_width = width;
12460                 }
12461             }
12462         }
12463     }
12464     pthread_mutex_unlock(&omx->c_lock);
12465     return status;
12466 }
12467 
set_color_format(OMX_COLOR_FORMATTYPE dest_color_format)12468 bool omx_vdec::allocate_color_convert_buf::set_color_format(
12469         OMX_COLOR_FORMATTYPE dest_color_format)
12470 {
12471     bool status = true, drv_colorformat_c2d_enable = false;
12472     bool dest_color_format_c2d_enable = false;
12473     OMX_COLOR_FORMATTYPE drv_color_format = OMX_COLOR_FormatUnused;
12474     if (!omx) {
12475         DEBUG_PRINT_ERROR("Invalid client in color convert");
12476         return false;
12477     }
12478     pthread_mutex_lock(&omx->c_lock);
12479     status = get_color_format (drv_color_format);
12480 
12481     drv_colorformat_c2d_enable = (drv_color_format != dest_color_format) &&
12482         (drv_color_format != (OMX_COLOR_FORMATTYPE)
12483                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView) &&
12484         (drv_color_format != (OMX_COLOR_FORMATTYPE)
12485                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed) &&
12486         (drv_color_format != (OMX_COLOR_FORMATTYPE)
12487                 QOMX_COLOR_FORMATYUV420SemiPlanarP010Venus);
12488 
12489     dest_color_format_c2d_enable = (dest_color_format != (OMX_COLOR_FORMATTYPE)
12490             QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) &&
12491             (dest_color_format != (OMX_COLOR_FORMATTYPE)
12492                 QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m10bitCompressed);
12493 
12494     if (status && drv_colorformat_c2d_enable && dest_color_format_c2d_enable) {
12495         DEBUG_PRINT_LOW("Enabling C2D");
12496         if (dest_color_format == OMX_COLOR_FormatYUV420Planar ||
12497             dest_color_format == OMX_COLOR_FormatYUV420SemiPlanar ||
12498             (omx->m_progressive != MSM_VIDC_PIC_STRUCT_PROGRESSIVE &&
12499             dest_color_format == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m)) {
12500             ColorFormat = dest_color_format;
12501             if (dest_color_format == OMX_COLOR_FormatYUV420Planar) {
12502                    dest_format = YCbCr420P;
12503             } else if( dest_color_format == OMX_COLOR_FormatYUV420SemiPlanar) {
12504                     dest_format = YCbCr420SP;
12505             } else {
12506                    dest_format = NV12_128m;
12507             }
12508             enable_color_conversion(true);
12509         } else {
12510             DEBUG_PRINT_ERROR("Unsupported output color format for c2d (%d)",
12511                               dest_color_format);
12512             status = false;
12513             enable_color_conversion(false);
12514         }
12515     } else {
12516         enable_color_conversion(false);
12517     }
12518     pthread_mutex_unlock(&omx->c_lock);
12519     return status;
12520 }
12521 
get_il_buf_hdr(OMX_BUFFERHEADERTYPE * bufadd)12522 OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
12523 (OMX_BUFFERHEADERTYPE *bufadd)
12524 {
12525     if (!omx) {
12526         DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
12527         return NULL;
12528     }
12529     if (!is_color_conversion_enabled())
12530         return bufadd;
12531 
12532     OMX_BUFFERHEADERTYPE  *omx_base_address =
12533               is_color_conversion_enabled()?
12534                     omx->m_intermediate_out_mem_ptr:omx->m_out_mem_ptr;
12535 
12536     unsigned index = 0;
12537     index = bufadd - omx_base_address;
12538     if (index < omx->drv_ctx.op_buf.actualcount) {
12539         m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
12540         m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
12541 
12542         omx->m_out_mem_ptr[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
12543         omx->m_out_mem_ptr[index].nTimeStamp = bufadd->nTimeStamp;
12544         bool status = false;
12545         if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
12546             pthread_mutex_lock(&omx->c_lock);
12547             omx->do_cache_operations(omx->drv_ctx.op_intermediate_buf_ion_info[index].data_fd);
12548 
12549             DEBUG_PRINT_INFO("C2D: Start color convertion");
12550             status = c2dcc.convertC2D(
12551                              omx->drv_ctx.ptr_intermediate_outputbuffer[index].pmem_fd,
12552                              bufadd->pBuffer, bufadd->pBuffer,
12553                              omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
12554                              omx->m_out_mem_ptr[index].pBuffer,
12555                              omx->m_out_mem_ptr[index].pBuffer);
12556             omx->do_cache_operations(omx->drv_ctx.op_intermediate_buf_ion_info[index].data_fd);
12557             if (!status) {
12558                 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
12559                 m_out_mem_ptr_client[index].nFilledLen = 0;
12560                 omx->m_out_mem_ptr[index].nFilledLen = 0;
12561                 pthread_mutex_unlock(&omx->c_lock);
12562                 return &omx->m_out_mem_ptr[index];
12563             } else {
12564                 unsigned int filledLen = 0;
12565                 c2dcc.getBuffFilledLen(C2D_OUTPUT, filledLen);
12566                 m_out_mem_ptr_client[index].nFilledLen = filledLen;
12567                 omx->m_out_mem_ptr[index].nFilledLen = filledLen;
12568             }
12569             pthread_mutex_unlock(&omx->c_lock);
12570         } else {
12571             m_out_mem_ptr_client[index].nFilledLen = 0;
12572             omx->m_out_mem_ptr[index].nFilledLen = 0;
12573         }
12574         return &omx->m_out_mem_ptr[index];
12575     }
12576     DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
12577     return NULL;
12578 }
12579 
get_buffer_req(unsigned int & buffer_size)12580     bool omx_vdec::allocate_color_convert_buf::get_buffer_req
12581 (unsigned int &buffer_size)
12582 {
12583     bool status = true;
12584     pthread_mutex_lock(&omx->c_lock);
12585      /* Whenever port mode is set to kPortModeDynamicANWBuffer, Video Frameworks
12586         always uses VideoNativeMetadata and OMX receives buffer type as
12587         grallocsource via storeMetaDataInBuffers_l API. The buffer_size
12588         will be communicated to frameworks via IndexParamPortdefinition. */
12589     if (!enabled)
12590         buffer_size = omx->dynamic_buf_mode ? sizeof(struct VideoNativeMetadata) :
12591                       omx->drv_ctx.op_buf.buffer_size;
12592     else {
12593         buffer_size = c2dcc.getBuffSize(C2D_OUTPUT);
12594     }
12595     pthread_mutex_unlock(&omx->c_lock);
12596     return status;
12597 }
12598 
set_buffer_req(OMX_U32 buffer_size,OMX_U32 actual_count)12599 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::set_buffer_req(
12600         OMX_U32 buffer_size, OMX_U32 actual_count)
12601 {
12602     OMX_U32 expectedSize = is_color_conversion_enabled() ? buffer_size_req : omx->dynamic_buf_mode ?
12603             sizeof(struct VideoDecoderOutputMetaData) : omx->drv_ctx.op_buf.buffer_size;
12604     if (buffer_size < expectedSize) {
12605         DEBUG_PRINT_ERROR("OP Requirements: Client size(%u) insufficient v/s requested(%u)",
12606                 buffer_size, expectedSize);
12607         return OMX_ErrorBadParameter;
12608     }
12609     if (actual_count < omx->drv_ctx.op_buf.mincount) {
12610         DEBUG_PRINT_ERROR("OP Requirements: Client count(%u) insufficient v/s requested(%u)",
12611                 actual_count, omx->drv_ctx.op_buf.mincount);
12612         return OMX_ErrorBadParameter;
12613     }
12614 
12615     if (enabled) {
12616         // disallow changing buffer size/count while we have active allocated buffers
12617         if (allocated_count > 0) {
12618             DEBUG_PRINT_ERROR("Cannot change C2D buffer size from %u to %u with %d active allocations",
12619                     buffer_size_req, buffer_size, allocated_count);
12620             return OMX_ErrorInvalidState;
12621         }
12622 
12623         buffer_size_req = buffer_size;
12624     } else {
12625         if (buffer_size > omx->drv_ctx.op_buf.buffer_size) {
12626             omx->drv_ctx.op_buf.buffer_size = buffer_size;
12627         }
12628     }
12629 
12630     omx->drv_ctx.op_buf.actualcount = actual_count;
12631     omx->drv_ctx.extradata_info.count = omx->drv_ctx.op_buf.actualcount;
12632     omx->drv_ctx.extradata_info.size = omx->drv_ctx.extradata_info.count *
12633             omx->drv_ctx.extradata_info.buffer_size;
12634     return omx->set_buffer_req(&(omx->drv_ctx.op_buf));
12635 }
12636 
is_component_secure()12637 bool omx_vdec::is_component_secure()
12638 {
12639     return secure_mode;
12640 }
12641 
get_color_format(OMX_COLOR_FORMATTYPE & dest_color_format)12642 bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
12643 {
12644     bool status = true;
12645     if (!enabled) {
12646         for (auto& x: mMapOutput2DriverColorFormat) {
12647             DecColorMapping::const_iterator
12648                 found = mMapOutput2DriverColorFormat.find(omx->drv_ctx.output_format);
12649             if (found == mMapOutput2DriverColorFormat.end()) {
12650                 status = false;
12651             } else {
12652                 ColorSubMapping::const_iterator
12653                     subFound = found->second.find(omx->drv_ctx.decoder_format);
12654                 if (subFound == found->second.end()) {
12655                     dest_color_format = (OMX_COLOR_FORMATTYPE)
12656                                              found->second.find(-1)->second;
12657                 } else {
12658                     dest_color_format = (OMX_COLOR_FORMATTYPE) subFound->second;
12659                 }
12660             }
12661         }
12662     } else {
12663         if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
12664             ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
12665             ColorFormat == (OMX_COLOR_FORMATTYPE) QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
12666             dest_color_format = ColorFormat;
12667         } else {
12668             status = false;
12669         }
12670     }
12671     return status;
12672 }
12673 
send_codec_config()12674 void omx_vdec::send_codec_config() {
12675     if (codec_config_flag) {
12676         unsigned long p1 = 0; // Parameter - 1
12677         unsigned long p2 = 0; // Parameter - 2
12678         unsigned long ident = 0;
12679         pthread_mutex_lock(&m_lock);
12680         DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n");
12681         while (m_etb_q.m_size) {
12682             m_etb_q.pop_entry(&p1,&p2,&ident);
12683             if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
12684                 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
12685                     if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
12686                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
12687                         DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure");
12688                         omx_report_error();
12689                     }
12690                 } else {
12691                     DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2);
12692                     m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2);
12693                 }
12694             } else if (ident == OMX_COMPONENT_GENERATE_ETB) {
12695                 if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
12696                     if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\
12697                                 (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
12698                         DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure");
12699                         omx_report_error ();
12700                     }
12701                 } else {
12702                     pending_input_buffers++;
12703                     VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
12704                     DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d",
12705                             (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers);
12706                     empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
12707                 }
12708             } else if (ident == OMX_COMPONENT_GENERATE_EBD) {
12709                 DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p",
12710                         (OMX_BUFFERHEADERTYPE *)p1);
12711                 empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
12712             }
12713         }
12714         pthread_mutex_unlock(&m_lock);
12715     }
12716 }
12717 
perf_control()12718 omx_vdec::perf_control::perf_control()
12719 {
12720     m_perf_control_enable = 0;
12721     m_perf_lib = NULL;
12722     m_perf_handle = 0;
12723     m_perf_lock_acquire = NULL;
12724     m_perf_lock_release = NULL;
12725 }
12726 
~perf_control()12727 omx_vdec::perf_control::~perf_control()
12728 {
12729     if (!m_perf_control_enable)
12730         return;
12731 
12732     if (m_perf_handle && m_perf_lock_release) {
12733         m_perf_lock_release(m_perf_handle);
12734         DEBUG_PRINT_LOW("perflock released");
12735     }
12736     if (m_perf_lib) {
12737         dlclose(m_perf_lib);
12738     }
12739 }
12740 
perf_lock_acquire()12741 int omx_vdec::perf_control::perf_lock_acquire()
12742 {
12743     int arg[2];
12744     if (!m_perf_control_enable)
12745         return 0;
12746 
12747     if (!m_perf_lib) {
12748         DEBUG_PRINT_ERROR("no perf control library");
12749         return -1;
12750     }
12751     if (!m_perf_lock_acquire) {
12752         DEBUG_PRINT_ERROR("NULL perflock acquire");
12753         return -1;
12754     }
12755     if (m_perf_handle) {
12756         DEBUG_PRINT_LOW("perflock already acquired");
12757         return 0;
12758     }
12759     DEBUG_PRINT_HIGH("perflock acquire");
12760     arg[0] = MPCTLV3_VIDEO_DECODE_PB_HINT;
12761     arg[1] = 1;
12762     m_perf_handle = m_perf_lock_acquire(0, 0, arg, sizeof(arg) / sizeof(int));
12763     if (m_perf_handle < 0) {
12764         DEBUG_PRINT_ERROR("perflock acquire failed with error %d", m_perf_handle);
12765         m_perf_handle = 0;
12766         return -1;
12767     }
12768     return 0;
12769 }
12770 
perf_lock_release()12771 void omx_vdec::perf_control::perf_lock_release()
12772 {
12773     if (!m_perf_control_enable)
12774         return;
12775 
12776     if (!m_perf_lib) {
12777         DEBUG_PRINT_ERROR("no perf control library");
12778         return;
12779     }
12780     if (!m_perf_lock_release) {
12781         DEBUG_PRINT_ERROR("NULL perflock release");
12782         return;
12783     }
12784     if (!m_perf_handle) {
12785         DEBUG_PRINT_LOW("perflock already released");
12786         return;
12787     }
12788     DEBUG_PRINT_HIGH("perflock release");
12789     m_perf_lock_release(m_perf_handle);
12790     m_perf_handle = 0;
12791 }
12792 
load_perf_library()12793 bool omx_vdec::perf_control::load_perf_library()
12794 {
12795     char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
12796 
12797     if (!m_perf_control_enable) {
12798         DEBUG_PRINT_HIGH("perf control is not enabled");
12799         return false;
12800     }
12801     if (m_perf_lib) {
12802         DEBUG_PRINT_HIGH("perf lib already opened");
12803         return true;
12804     }
12805 
12806     if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
12807         DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
12808         goto handle_err;
12809     }
12810 
12811     if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
12812         DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
12813         goto handle_err;
12814     } else {
12815         m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
12816         if (m_perf_lock_acquire == NULL) {
12817             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
12818             goto handle_err;
12819         }
12820         m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
12821         if (m_perf_lock_release == NULL) {
12822             DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
12823             goto handle_err;
12824         }
12825     }
12826     return true;
12827 
12828 handle_err:
12829     if (m_perf_lib) {
12830         dlclose(m_perf_lib);
12831     }
12832     m_perf_lib = NULL;
12833     m_perf_lock_acquire = NULL;
12834     m_perf_lock_release = NULL;
12835     return false;
12836 }
12837 
enable_adaptive_playback(unsigned long nMaxFrameWidth,unsigned long nMaxFrameHeight)12838 OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
12839                             unsigned long nMaxFrameHeight)
12840 {
12841 
12842     OMX_ERRORTYPE eRet = OMX_ErrorNone;
12843     int ret = 0;
12844     unsigned long min_res_buf_count = 0;
12845 
12846     eRet = enable_smoothstreaming();
12847     if (eRet != OMX_ErrorNone) {
12848          DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
12849          return eRet;
12850      }
12851 
12852      DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
12853              nMaxFrameWidth,
12854              nMaxFrameHeight);
12855      m_smoothstreaming_mode = true;
12856      m_smoothstreaming_width = nMaxFrameWidth;
12857      m_smoothstreaming_height = nMaxFrameHeight;
12858 
12859      //Get upper limit buffer count for min supported resolution
12860      struct v4l2_format fmt;
12861      fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
12862      fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
12863      fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
12864      fmt.fmt.pix_mp.pixelformat = output_capability;
12865 
12866      ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
12867      if (ret) {
12868          DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
12869                            m_decoder_capability.min_height,
12870                            m_decoder_capability.min_width);
12871          return OMX_ErrorUnsupportedSetting;
12872      }
12873 
12874      eRet = get_buffer_req(&drv_ctx.op_buf);
12875      if (eRet != OMX_ErrorNone) {
12876          DEBUG_PRINT_ERROR("failed to get_buffer_req");
12877          return eRet;
12878      }
12879 
12880      min_res_buf_count = drv_ctx.op_buf.mincount;
12881      DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
12882                      min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
12883 
12884      m_extradata_info.output_crop_rect.nLeft = 0;
12885      m_extradata_info.output_crop_rect.nTop = 0;
12886      m_extradata_info.output_crop_rect.nWidth = m_smoothstreaming_width;
12887      m_extradata_info.output_crop_rect.nHeight = m_smoothstreaming_height;
12888 
12889      update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
12890                        m_smoothstreaming_width, m_smoothstreaming_height);
12891 
12892      //Get upper limit buffer size for max smooth streaming resolution set
12893      fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
12894      fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
12895      fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
12896      fmt.fmt.pix_mp.pixelformat = output_capability;
12897      ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
12898      if (ret) {
12899          DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
12900          return OMX_ErrorUnsupportedSetting;
12901      }
12902 
12903      eRet = get_buffer_req(&drv_ctx.op_buf);
12904      if (eRet != OMX_ErrorNone) {
12905          DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
12906          return eRet;
12907      }
12908      DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
12909                      (unsigned int)drv_ctx.op_buf.buffer_size);
12910 
12911      drv_ctx.op_buf.mincount = min_res_buf_count;
12912      drv_ctx.op_buf.actualcount = min_res_buf_count;
12913      drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size;
12914      eRet = set_buffer_req(&drv_ctx.op_buf);
12915      if (eRet != OMX_ErrorNone) {
12916          DEBUG_PRINT_ERROR("failed to set_buffer_req");
12917          return eRet;
12918      }
12919 
12920      eRet = get_buffer_req(&drv_ctx.op_buf);
12921      if (eRet != OMX_ErrorNone) {
12922          DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
12923          return eRet;
12924      }
12925      DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
12926                       drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
12927      return eRet;
12928 }
12929 
12930 //static
describeColorFormat(OMX_PTR pParam)12931 OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
12932 
12933 #ifndef FLEXYUV_SUPPORTED
12934     return OMX_ErrorUndefined;
12935 #else
12936 
12937     if (pParam == NULL) {
12938         DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
12939         return OMX_ErrorBadParameter;
12940     }
12941 
12942     DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
12943 
12944     MediaImage *img = &(params->sMediaImage);
12945     switch(params->eColorFormat) {
12946         case static_cast <OMX_COLOR_FORMATTYPE> (QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m):
12947         {
12948             img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
12949             img->mNumPlanes = 3;
12950             // mWidth and mHeight represent the W x H of the largest plane
12951             // In our case, this happens to be the Stride x Scanlines of Y plane
12952             img->mWidth = params->nFrameWidth;
12953             img->mHeight = params->nFrameHeight;
12954             size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12955             size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
12956             img->mBitDepth = 8;
12957             //Plane 0 (Y)
12958             img->mPlane[MediaImage::Y].mOffset = 0;
12959             img->mPlane[MediaImage::Y].mColInc = 1;
12960             img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
12961             img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
12962             img->mPlane[MediaImage::Y].mVertSubsampling = 1;
12963             //Plane 1 (U)
12964             img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
12965             img->mPlane[MediaImage::U].mColInc = 2;           //interleaved UV
12966             img->mPlane[MediaImage::U].mRowInc =
12967                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12968             img->mPlane[MediaImage::U].mHorizSubsampling = 2;
12969             img->mPlane[MediaImage::U].mVertSubsampling = 2;
12970             //Plane 2 (V)
12971             img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
12972             img->mPlane[MediaImage::V].mColInc = 2;           //interleaved UV
12973             img->mPlane[MediaImage::V].mRowInc =
12974                     VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
12975             img->mPlane[MediaImage::V].mHorizSubsampling = 2;
12976             img->mPlane[MediaImage::V].mVertSubsampling = 2;
12977             break;
12978         }
12979 
12980         case OMX_COLOR_FormatYUV420Planar:
12981         case OMX_COLOR_FormatYUV420SemiPlanar:
12982             // We need not describe the standard OMX linear formats as these are
12983             // understood by client. Fail this deliberately to let client fill-in
12984             return OMX_ErrorUnsupportedSetting;
12985 
12986         default:
12987             // Rest all formats which are non-linear cannot be described
12988             DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
12989             img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
12990             return OMX_ErrorNone;
12991     };
12992 
12993     DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
12994     DEBUG_PRINT_LOW("  FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
12995     DEBUG_PRINT_LOW("  YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
12996     for (size_t i = 0; i < img->mNumPlanes; ++i) {
12997         DEBUG_PRINT_LOW("  Plane[%zu] : offset=%d / xStep=%d / yStep = %d",
12998                 i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
12999     }
13000     return OMX_ErrorNone;
13001 #endif //FLEXYUV_SUPPORTED
13002 }
13003 
prefetch_buffers(unsigned long prefetch_count,unsigned long prefetch_size,unsigned ioctl_code,unsigned ion_flag)13004 bool omx_vdec::prefetch_buffers(unsigned long prefetch_count,
13005         unsigned long prefetch_size, unsigned ioctl_code, unsigned ion_flag)
13006 {
13007     struct ion_prefetch_data prefetch_data;
13008     struct ion_prefetch_regions regions;
13009     __u64 sizes[prefetch_count];
13010     int rc, ion_fd = ion_open();
13011     if (ion_fd < 0) {
13012         DEBUG_PRINT_ERROR("%s: Ion fd open failed : %d", __func__, ion_fd);
13013         return false;
13014     }
13015 
13016     DEBUG_PRINT_HIGH("%s: prefetch_count : %lu, prefetch_size : %lu, ioctl : %u",
13017             __func__, prefetch_count, prefetch_size, ioctl_code);
13018     for (uint32_t i = 0; i < prefetch_count; i++) {
13019         sizes[i] = prefetch_size;
13020     }
13021 
13022     regions.nr_sizes = prefetch_count;
13023 #if TARGET_ION_ABI_VERSION >= 2
13024     regions.sizes = (__u64)sizes;
13025 #else
13026     regions.sizes = sizes;
13027 #endif
13028     regions.vmid = ion_flag;
13029 
13030     prefetch_data.nr_regions = 1;
13031 #if TARGET_ION_ABI_VERSION >= 2
13032     prefetch_data.regions = (__u64)&regions;
13033 #else
13034     prefetch_data.regions = &regions;
13035 #endif
13036     prefetch_data.heap_id = ION_HEAP(ION_SECURE_HEAP_ID);
13037 
13038     rc = ioctl(ion_fd, ioctl_code, &prefetch_data);
13039     if (rc) {
13040         DEBUG_PRINT_ERROR("%s: Prefetch ioctl failed ioctl : %u, rc : %d, errno : %d",
13041                 __func__, ioctl_code, rc, errno);
13042         rc = false;
13043     } else {
13044         rc = true;
13045     }
13046 
13047     close(ion_fd);
13048     return rc;
13049 }
13050 
13051 // No code beyond this !
13052 
13053 // inline import of vendor-extensions implementation
13054 #include "omx_vdec_extensions.hpp"
13055